mailweb.openeuler.org
Manage this list

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

Kernel

Threads by month
  • ----- 2025 -----
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2021 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2020 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2019 -----
  • December
kernel@openeuler.org

  • 59 participants
  • 20035 discussions
[openeuler:OLK-6.6 2059/2059] drivers/crypto/ccp/hygon/tdm-kernel-guard.c:151:5: sparse: sparse: symbol 'tdm_service_run' was not declared. Should it be static?
by kernel test robot 25 Mar '25

25 Mar '25
tree: https://gitee.com/openeuler/kernel.git OLK-6.6 head: 0278be80a99934144f0e708459f3475248f280c4 commit: 3ad98583441f7c8a2553e1e8d6340ed4397033e2 [2059/2059] crypto: tdm: Support dynamic protection for SCT and IDT by HYGON TDM config: x86_64-randconfig-121-20250325 (https://download.01.org/0day-ci/archive/20250325/202503251859.zDW2wWzp-lkp@…) compiler: gcc-11 (Debian 11.3.0-12) 11.3.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250325/202503251859.zDW2wWzp-lkp@…) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp(a)intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202503251859.zDW2wWzp-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/crypto/ccp/hygon/tdm-kernel-guard.c:151:5: sparse: sparse: symbol 'tdm_service_run' was not declared. Should it be static? >> drivers/crypto/ccp/hygon/tdm-kernel-guard.c:212:5: sparse: sparse: symbol 'tdm_service_exit' was not declared. Should it be static? vim +/tdm_service_run +151 drivers/crypto/ccp/hygon/tdm-kernel-guard.c 150 > 151 int tdm_service_run(struct tdm_security_enhance *data) 152 { 153 int ret = 0; 154 struct addr_range_info *addr_range = NULL; 155 156 // Allocate memory for addr_range 157 addr_range = kzalloc(sizeof(struct addr_range_info) + sizeof(struct addr_info), GFP_KERNEL); 158 if (!addr_range) { 159 ret = -DYN_ERR_MEM; 160 pr_err("addr_range kzalloc memory failed\n"); 161 goto end; 162 } 163 164 // Fill in addr_range 165 addr_range->count = 1; 166 addr_range->addr[0].addr_start = data->vaddr; 167 addr_range->addr[0].length = data->size; 168 data->mem_range = addr_range; 169 170 // Context configuration 171 data->context |= TASK_CREATE_VADDR; 172 173 // Allocate memory for authcode 174 data->authcode = kzalloc(sizeof(struct authcode_2b) + AUTHCODE_MAX, GFP_KERNEL); 175 if (!data->authcode) { 176 ret = -DYN_ERR_MEM; 177 pr_err("authcode_2b kzalloc memory failed\n"); 178 goto free_addr_range_info; 179 } 180 181 data->authcode->len = AUTHCODE_MAX; 182 183 // Measurement data configuration 184 data->mdata.hash_algo = HASH_ALGO_SM3; 185 data->mdata.period_ms = 0; 186 ret = calc_expected_hash((uint8_t *)data->vaddr, data->size, 187 data->mdata.expected_measurement); 188 if (ret) { 189 pr_err("calculate expected hash failed!\n"); 190 goto free_authcode; 191 } 192 193 // Create and start tdm task 194 ret = tdm_task_create_and_run(data); 195 if (ret) { 196 pr_err("tdm_task_create_and_run failed!\n"); 197 goto free_authcode; 198 } 199 200 return ret; 201 202 free_authcode: 203 kfree(data->authcode); 204 data->authcode = NULL; 205 free_addr_range_info: 206 kfree(data->mem_range); 207 data->mem_range = NULL; 208 end: 209 return ret; 210 } 211 > 212 int tdm_service_exit(struct tdm_security_enhance *data) 213 { 214 int ret = 0; 215 int task_status = 0; 216 217 task_status = psp_startstop_measure_task(data->task_id, data->authcode, false); 218 if (task_status < 0) { 219 ret = task_status; 220 pr_err("task_id %d stop failed with 0x%x\n", data->task_id, ret); 221 goto end; 222 } 223 224 // Waiting for the task to end 225 msleep(40); 226 227 psp_destroy_measure_task(data->task_id, data->authcode); 228 229 kfree(data->authcode); 230 data->authcode = NULL; 231 kfree(data->mem_range); 232 data->mem_range = NULL; 233 end: 234 return ret; 235 } 236 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
1 0
0 0
[openeuler:OLK-6.6] BUILD SUCCESS 0278be80a99934144f0e708459f3475248f280c4
by kernel test robot 25 Mar '25

25 Mar '25
tree/branch: https://gitee.com/openeuler/kernel.git OLK-6.6 branch HEAD: 0278be80a99934144f0e708459f3475248f280c4 !15477 PCI: rcar-ep: Fix incorrect variable used when calling devm_request_mem_region() Warning ids grouped by kconfigs: recent_errors |-- arm64-allmodconfig | |-- arch-arm64-kvm-virtcca_cvm.c:warning:no-previous-prototype-for-function-virtcca_get_tmi_version | |-- drivers-coda-coda_pci.c:warning:Excess-function-parameter-pdev-description-in-virtcca_pci_get_rom_size | |-- drivers-coda-coda_pci.c:warning:Function-parameter-or-member-p-not-described-in-virtcca_pci_get_rom_size | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- arm64-allnoconfig | |-- kismet:WARNING:unmet-direct-dependencies-detected-for-HALTPOLL_CPUIDLE-when-selected-by-ARM64 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- arm64-defconfig | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- arm64-randconfig-001-20250324 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- arm64-randconfig-002-20250324 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- arm64-randconfig-003-20250324 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- arm64-randconfig-052-20250324 | |-- Documentation-devicetree-bindings-dma-snps-dw-axi-dmac.yaml:snps-priority:multiple-incompatible-types:uint32-array | `-- Documentation-devicetree-bindings-net-snps-dwmac.yaml:snps-priority:multiple-incompatible-types:uint32 |-- arm64-randconfig-053-20250324 | |-- Documentation-devicetree-bindings-dma-snps-dw-axi-dmac.yaml:snps-priority:multiple-incompatible-types:uint32-array | `-- Documentation-devicetree-bindings-net-snps-dwmac.yaml:snps-priority:multiple-incompatible-types:uint32 |-- arm64-randconfig-054-20250324 | |-- Documentation-devicetree-bindings-dma-snps-dw-axi-dmac.yaml:snps-priority:multiple-incompatible-types:uint32-array | `-- Documentation-devicetree-bindings-net-snps-dwmac.yaml:snps-priority:multiple-incompatible-types:uint32 |-- loongarch-allmodconfig | |-- arch-loongarch-mm-cache.c:warning:variable-way_size-set-but-not-used | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- loongarch-allnoconfig | |-- arch-loongarch-mm-cache.c:warning:variable-way_size-set-but-not-used | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- loongarch-allyesconfig | |-- arch-loongarch-mm-cache.c:warning:variable-way_size-set-but-not-used | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- loongarch-defconfig | |-- arch-loongarch-mm-cache.c:warning:variable-way_size-set-but-not-used | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- loongarch-randconfig-001-20250324 | |-- arch-loongarch-mm-cache.c:warning:variable-way_size-set-but-not-used | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- loongarch-randconfig-002-20250324 | |-- arch-loongarch-mm-cache.c:warning:variable-way_size-set-but-not-used | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-allnoconfig | |-- kismet:WARNING:unmet-direct-dependencies-detected-for-ACPI_HOTPLUG_IGNORE_OSC-when-selected-by-X86 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-allyesconfig | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-buildonly-randconfig-001-20250324 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-buildonly-randconfig-002-20250324 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-buildonly-randconfig-003-20250324 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-buildonly-randconfig-004-20250324 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-buildonly-randconfig-005-20250324 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-buildonly-randconfig-006-20250324 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-defconfig | |-- mm-memory.c:warning:variable-nr_pages-set-but-not-used | `-- mm-mempolicy.c:warning:writing-byte-into-a-region-of-size |-- x86_64-randconfig-101-20250325 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-randconfig-102-20250325 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-randconfig-103-20250325 | |-- mm-memory.c:warning:variable-nr_pages-set-but-not-used | `-- mm-mempolicy.c:warning:writing-byte-into-a-region-of-size |-- x86_64-randconfig-104-20250325 | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-randconfig-121-20250325 | |-- mm-memblock.c:sparse:sparse:symbol-memblock_alloc_range_nid_flags-was-not-declared.-Should-it-be-static | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-randconfig-122-20250325 | |-- include-linux-userfaultfd_k.h:sparse:sparse:incorrect-type-in-argument-(different-base-types)-expected-restricted-uffd_flags_t-usertype-flags-got-unsigned-int-enum-mfill_atomic_mode-mode | |-- include-linux-userfaultfd_k.h:sparse:sparse:restricted-uffd_flags_t-degrades-to-integer | |-- mm-memblock.c:sparse:sparse:symbol-memblock_alloc_range_nid_flags-was-not-declared.-Should-it-be-static | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used |-- x86_64-randconfig-123-20250325 | |-- mm-memblock.c:sparse:sparse:symbol-memblock_alloc_range_nid_flags-was-not-declared.-Should-it-be-static | `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used `-- x86_64-randconfig-161-20250324 |-- mm-kasan-kasan_test.c-rcu_uaf_reclaim()-error:dereferencing-freed-memory-fp-(line-) `-- mm-memory.c:warning:variable-nr_pages-set-but-not-used elapsed time: 1445m configs tested: 21 configs skipped: 123 The following configs have been built successfully. More configs may be tested in the coming days. tested configs: arm64 allmodconfig clang-19 arm64 allnoconfig gcc-14.2.0 arm64 defconfig gcc-14.2.0 arm64 randconfig-001-20250324 gcc-8.5.0 arm64 randconfig-002-20250324 clang-14 arm64 randconfig-003-20250324 clang-21 arm64 randconfig-004-20250324 gcc-6.5.0 loongarch allmodconfig gcc-14.2.0 loongarch allnoconfig gcc-14.2.0 loongarch defconfig gcc-14.2.0 loongarch randconfig-001-20250324 gcc-14.2.0 loongarch randconfig-002-20250324 gcc-14.2.0 x86_64 allnoconfig clang-20 x86_64 allyesconfig clang-20 x86_64 buildonly-randconfig-001-20250324 clang-20 x86_64 buildonly-randconfig-002-20250324 gcc-12 x86_64 buildonly-randconfig-003-20250324 clang-20 x86_64 buildonly-randconfig-004-20250324 clang-20 x86_64 buildonly-randconfig-005-20250324 clang-20 x86_64 buildonly-randconfig-006-20250324 clang-20 x86_64 defconfig gcc-11 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
1 0
0 0
[PATCH openEuler-1.0-LTS] ALSA: oss: Fix PCM OSS buffer allocation overflow
by Jinjiang Tu 25 Mar '25

25 Mar '25
From: Takashi Iwai <tiwai(a)suse.de> stable inclusion from stable-v4.19.237 commit a63af1baf0a5e11827db60e3127f87e437cab6e5 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBP1SP CVE: CVE-2022-49292 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- commit efb6402c3c4a7c26d97c92d70186424097b6e366 upstream. We've got syzbot reports hitting INT_MAX overflow at vmalloc() allocation that is called from snd_pcm_plug_alloc(). Although we apply the restrictions to input parameters, it's based only on the hw_params of the underlying PCM device. Since the PCM OSS layer allocates a temporary buffer for the data conversion, the size may become unexpectedly large when more channels or higher rates is given; in the reported case, it went over INT_MAX, hence it hits WARN_ON(). This patch is an attempt to avoid such an overflow and an allocation for too large buffers. First off, it adds the limit of 1MB as the upper bound for period bytes. This must be large enough for all use cases, and we really don't want to handle a larger temporary buffer than this size. The size check is performed at two places, where the original period bytes is calculated and where the plugin buffer size is calculated. In addition, the driver uses array_size() and array3_size() for multiplications to catch overflows for the converted period size and buffer bytes. Reported-by: syzbot+72732c532ac1454eeee9(a)syzkaller.appspotmail.com Suggested-by: Linus Torvalds <torvalds(a)linux-foundation.org> Cc: <stable(a)vger.kernel.org> Link: https://lore.kernel.org/r/00000000000085b1b305da5a66f3@google.com Link: https://lore.kernel.org/r/20220318082036.29699-1-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai(a)suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org> Signed-off-by: Jinjiang Tu <tujinjiang(a)huawei.com> --- sound/core/oss/pcm_oss.c | 12 ++++++++---- sound/core/oss/pcm_plugin.c | 5 ++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 7f434a37d860..f22d239eebe4 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -789,6 +789,11 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, if (oss_period_size < 16) return -EINVAL; + + /* don't allocate too large period; 1MB period must be enough */ + if (oss_period_size > 1024 * 1024) + return -ENOMEM; + runtime->oss.period_bytes = oss_period_size; runtime->oss.period_frames = 1; runtime->oss.periods = oss_periods; @@ -1053,10 +1058,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) goto failure; } #endif - oss_period_size *= oss_frame_size; - - oss_buffer_size = oss_period_size * runtime->oss.periods; - if (oss_buffer_size < 0) { + oss_period_size = array_size(oss_period_size, oss_frame_size); + oss_buffer_size = array_size(oss_period_size, runtime->oss.periods); + if (oss_buffer_size <= 0) { err = -EINVAL; goto failure; } diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 31cb2acf8afc..624aca32fe69 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -61,7 +61,10 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t } if ((width = snd_pcm_format_physical_width(format->format)) < 0) return width; - size = frames * format->channels * width; + size = array3_size(frames, format->channels, width); + /* check for too large period size once again */ + if (size > 1024 * 1024) + return -ENOMEM; if (snd_BUG_ON(size % 8)) return -ENXIO; size /= 8; -- 2.43.0
2 1
0 0
[PATCH openEuler-1.0-LTS] ASoC: atmel: Add missing of_node_put() in at91sam9g20ek_audio_probe
by Jinjiang Tu 25 Mar '25

25 Mar '25
From: Miaoqian Lin <linmq006(a)gmail.com> stable inclusion from stable-v4.19.238 commit b0c56a0071116a37c24df998166c22a7e4684626 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBP3W0 CVE: CVE-2022-49243 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- [ Upstream commit f590797fa3c1bccdd19e55441592a23b46aef449 ] This node pointer is returned by of_parse_phandle() with refcount incremented in this function. Calling of_node_put() to avoid the refcount leak. Fixes: 531f67e41dcd ("ASoC: at91sam9g20ek-wm8731: convert to dt support") Signed-off-by: Miaoqian Lin <linmq006(a)gmail.com> Reviewed-by: Codrin Ciubotariu <codrin.ciubotariu(a)microchip.com> Link: https://lore.kernel.org/r/20220307124539.1743-1-linmq006@gmail.com Signed-off-by: Mark Brown <broonie(a)kernel.org> Signed-off-by: Sasha Levin <sashal(a)kernel.org> Signed-off-by: Jinjiang Tu <tujinjiang(a)huawei.com> --- sound/soc/atmel/sam9g20_wm8731.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 98f93e79c654..5041f43ee5f7 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -225,6 +225,7 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev) cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); if (!cpu_np) { dev_err(&pdev->dev, "dai and pcm info missing\n"); + of_node_put(codec_np); return -EINVAL; } at91sam9g20ek_dai.cpu_of_node = cpu_np; -- 2.43.0
2 1
0 0
Re: [PATCH OLK-6.6 v2 2/3] arm64: entry: Support hardware xint
by Jinjie Ruan 25 Mar '25

25 Mar '25
On 2025/3/25 15:00, Liao, Chang wrote: > > > 在 2025/3/24 21:53, Jinjie Ruan 写道: >> hulk inclusion >> category: feature >> bugzilla: https://gitee.com/openeuler/release-management/issues/IBV2E4 >> >> -------------------------------- >> >> Support hardware xint. Hardware xint provides a separate entry for >> interrupt handling, so we can use it to customize and respond to >> interrupts relatively quickly. >> >> Signed-off-by: Jinjie Ruan <ruanjinjie(a)huawei.com> >> --- >> v2: >> - Reuse the xint set and check logic in xint 1.0. >> - Introduce fast_handle_xint(). >> - Rename enable_xint_xcall() to enable_xfunc(). >> - Rename test_has_xint_xcall() to test_has_xfunc(). >> - Fix a typo, Harware -> Hardware. >> - Add a blank line after declarations in el0t_64_xint_handler(). >> --- >> arch/arm64/Kconfig | 7 +++ >> arch/arm64/include/asm/sysreg.h | 4 ++ >> arch/arm64/kernel/cpufeature.c | 75 ++++++++++++++++++++++++- >> arch/arm64/kernel/entry-common.c | 35 +++++++++--- >> arch/arm64/kernel/entry.S | 40 +++++++++++++- >> arch/arm64/tools/cpucaps | 2 +- >> drivers/irqchip/irq-gic-v3.c | 89 ++++++++++++++++++++++++++++-- >> include/linux/irqchip/arm-gic-v3.h | 6 +- >> kernel/irq/debugfs.c | 6 +- >> kernel/irq/internals.h | 3 +- >> 10 files changed, 244 insertions(+), 23 deletions(-) >> >> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig >> index 9da9d58f1c02..57d05cfbd29e 100644 >> --- a/arch/arm64/Kconfig >> +++ b/arch/arm64/Kconfig >> @@ -1717,6 +1717,13 @@ config ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG >> config ARCH_SUPPORTS_CRASH_DUMP >> def_bool y >> >> +config ARCH_SUPPORTS_XINT >> + bool "Hardware xint support" >> + default n >> + depends on ARM64_NMI >> + depends on ARM_GIC_V3 >> + depends on !COMPAT >> + >> config TRANS_TABLE >> def_bool y >> depends on HIBERNATION || KEXEC_CORE >> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h >> index 435634a703c6..b34e8cc4476b 100644 >> --- a/arch/arm64/include/asm/sysreg.h >> +++ b/arch/arm64/include/asm/sysreg.h >> @@ -269,6 +269,10 @@ >> #define SYS_REVIDR_EL1 sys_reg(3, 0, 0, 0, 6) >> >> #define SYS_ACTLR_EL1 sys_reg(3, 0, 1, 0, 1) >> + >> +#define ACTLR_ELx_XINT_SHIFT 21 >> +#define ACTLR_ELx_XINT (BIT(ACTLR_ELx_XINT_SHIFT)) >> + > > I don't think sysreg.h is the best place for those ACTLR_ELx bits. This header's > more about the actual uint32 upcode of system register. not the details of the fields. > And since ACTLR_ELx fields vary implementation. I think we should put them in a new > heade, actlr.h like kernel does with esr.h. > > >> #define SYS_RGSR_EL1 sys_reg(3, 0, 1, 0, 5) >> #define SYS_GCR_EL1 sys_reg(3, 0, 1, 0, 6) >> >> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c >> index a1736e9044da..b4de05241f7d 100644 >> --- a/arch/arm64/kernel/cpufeature.c >> +++ b/arch/arm64/kernel/cpufeature.c >> @@ -2406,8 +2406,12 @@ static bool has_xcall_support(const struct arm64_cpu_capabilities *entry, int __ >> } >> #endif >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> bool is_xint_support; >> +bool hw_xint_support; >> +#endif >> + >> +#ifdef CONFIG_FAST_IRQ >> static int __init xint_setup(char *str) >> { >> if (!cpus_have_cap(ARM64_HAS_GIC_CPUIF_SYSREGS)) >> @@ -2424,6 +2428,66 @@ static bool has_xint_support(const struct arm64_cpu_capabilities *entry, int __u >> } >> #endif >> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +static bool test_has_xfunc(void) > > test_has_xfunc is a bit strange, could we just use has_arch_xint_support()? > >> +{ >> + u64 new, old = read_sysreg(actlr_el1); >> + >> + write_sysreg(old | ACTLR_ELx_XINT, actlr_el1); >> + isb(); >> + new = read_sysreg(actlr_el1); >> + if (new & ACTLR_ELx_XINT) { >> + write_sysreg(old, actlr_el1); >> + hw_xint_support = true; >> + return true; >> + } >> + >> + return false; >> +} >> + >> +static void enable_xfunc(void) > > Could we use cpu_enable_arch_xint()? it is not hard to find some helper functions > in this file has similar role as this. > >> +{ >> + u64 actlr_el1, actlr_el2; >> + u64 el; >> + >> + el = read_sysreg(CurrentEL); >> + if (el == CurrentEL_EL2) { >> + actlr_el2 = read_sysreg(actlr_el2); >> + actlr_el2 |= ACTLR_ELx_XINT; >> + write_sysreg(actlr_el2, actlr_el2); >> + isb(); >> + actlr_el2 = read_sysreg(actlr_el2); >> + pr_info("actlr_el2: %llx, cpu:%d\n", actlr_el2, smp_processor_id()); >> + } >> + >> + actlr_el1 = read_sysreg(actlr_el1); >> + actlr_el1 |= ACTLR_ELx_XINT; >> + write_sysreg(actlr_el1, actlr_el1); >> + isb(); >> + actlr_el1 = read_sysreg(actlr_el1); >> + pr_info("actlr_el1: %llx, cpu:%d\n", actlr_el1, smp_processor_id()); >> +} >> + >> +static bool test_has_xint(const struct arm64_cpu_capabilities *entry, int scope) >> +{ >> + if (!IS_ENABLED(CONFIG_ARM64_NMI)) >> + pr_info("CONFIG_ARM64_NMI disabled, using XINTs for guests only\n"); >> +#ifdef CONFIG_ARM64_PSEUDO_NMI >> + else if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && enable_pseudo_nmi) { >> + pr_info("Pseudo NMI enabled, not using architected XINT\n"); >> + return false; >> + } >> +#endif >> + >> + return test_has_xfunc(); >> +} > > Fold this function into has_arch_xint_support(). > >> + >> +static void xint_enable(const struct arm64_cpu_capabilities *__unused) >> +{ >> + enable_xfunc(); > > Fold this function into cpu_enable_arch_xint(). > >> +} >> +#endif >> + >> static const struct arm64_cpu_capabilities arm64_features[] = { >> { >> .capability = ARM64_ALWAYS_BOOT, >> @@ -2971,6 +3035,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = { >> .type = ARM64_CPUCAP_SYSTEM_FEATURE, >> .matches = has_xint_support, >> }, >> +#endif >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + { >> + .desc = "Hardware xint Support", > > Mind the ppercase for first letter. > >> + .capability = ARM64_HAS_HW_XINT, >> + .type = ARM64_CPUCAP_SYSTEM_FEATURE, >> + .matches = test_has_xint, >> + .cpu_enable = xint_enable, >> + }, >> #endif > > I really can't recall why we add "Xint support" data into arm64_feature array before. > Just to be clear, "Xint support' is a software solution, it's about making interrupt > handler faster. It's not tied to any particular CPU feature. "Hardware Xint Support" > would means something different, like a real CPU feature. So I think we should take > it out from the arm64_feature array upon CPU can support a hardware xint entry. > >> {}, >> }; >> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c >> index 4602c107c40a..d09029dfcf02 100644 >> --- a/arch/arm64/kernel/entry-common.c >> +++ b/arch/arm64/kernel/entry-common.c >> @@ -6,6 +6,9 @@ >> */ >> >> #include <linux/context_tracking.h> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +#include <linux/irqchip/arm-gic-v3.h> >> +#endif >> #include <linux/kasan.h> >> #include <linux/linkage.h> >> #include <linux/lockdep.h> >> @@ -607,7 +610,7 @@ static void noinstr el0_xint(struct pt_regs *regs, u64 nmi_flag, >> } >> >> >> -asmlinkage void noinstr el0t_64_xint_handler(struct pt_regs *regs) >> +asmlinkage void noinstr el0t_64_sw_xint_handler(struct pt_regs *regs) >> { >> el0_xint(regs, ISR_EL1_IS, handle_arch_irq, handle_arch_nmi_irq); >> } >> @@ -966,6 +969,30 @@ asmlinkage void noinstr el0t_64_error_handler(struct pt_regs *regs) >> __el0_error_handler_common(regs); >> } >> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +asmlinkage void noinstr el0t_64_xint_handler(struct pt_regs *regs) >> +{ >> + u32 irqnr = read_sysreg_s(SYS_ICC_HPPIR1_EL1); >> + >> + if (gic_irqnr_is_special(irqnr)) >> + return; >> + >> + if (is_xint(irqnr)) >> + fast_handle_xint(regs, irqnr); >> + else >> + el0t_64_irq_handler(regs); >> +} > > Could we register fast_handle_xint() in gic-v3 driver, like kernel does for gic_handle_irq() > and gic_handle_nmi_irq(). By checking the return value, it still has chance to fall through > to the regular irq handler. 这里做不到,一旦ACK了,就没法回头了 > >> +#else >> +#ifdef CONFIG_AARCH32_EL0 >> +asmlinkage void noinstr el0t_32_irq_handler(struct pt_regs *regs) >> +{ >> + __el0_irq_handler_common(regs); >> +} >> +#else /* CONFIG_AARCH32_EL0 */ >> +UNHANDLED(el0t, 32, irq) >> +#endif >> +#endif >> + >> #ifdef CONFIG_AARCH32_EL0 >> static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr) >> { >> @@ -1028,11 +1055,6 @@ asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs) >> } >> } >> >> -asmlinkage void noinstr el0t_32_irq_handler(struct pt_regs *regs) >> -{ >> - __el0_irq_handler_common(regs); >> -} >> - >> asmlinkage void noinstr el0t_32_fiq_handler(struct pt_regs *regs) >> { >> __el0_fiq_handler_common(regs); >> @@ -1044,7 +1066,6 @@ asmlinkage void noinstr el0t_32_error_handler(struct pt_regs *regs) >> } >> #else /* CONFIG_AARCH32_EL0 */ >> UNHANDLED(el0t, 32, sync) >> -UNHANDLED(el0t, 32, irq) >> UNHANDLED(el0t, 32, fiq) >> UNHANDLED(el0t, 32, error) >> #endif /* CONFIG_AARCH32_EL0 */ >> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S >> index da3809632f0f..046225fa2f90 100644 >> --- a/arch/arm64/kernel/entry.S >> +++ b/arch/arm64/kernel/entry.S >> @@ -565,7 +565,11 @@ SYM_CODE_START(vectors) >> kernel_ventry 0, t, 64, error // Error 64-bit EL0 >> >> kernel_ventry 0, t, 32, sync // Synchronous 32-bit EL0 >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + kernel_ventry 0, t, 64, xint // XINT 64-bit EL0 >> +#else >> kernel_ventry 0, t, 32, irq // IRQ 32-bit EL0 >> +#endif >> kernel_ventry 0, t, 32, fiq // FIQ 32-bit EL0 >> kernel_ventry 0, t, 32, error // Error 32-bit EL0 >> SYM_CODE_END(vectors) >> @@ -696,7 +700,7 @@ SYM_CODE_END(__bad_stack) >> kernel_entry 0, 64 >> #endif >> mov x0, sp >> - bl el0t_64_xint_handler >> + bl el0t_64_sw_xint_handler >> #ifdef CONFIG_SECURITY_FEATURE_BYPASS >> kernel_exit 0, xint >> #else >> @@ -729,6 +733,18 @@ SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label) >> check_xint_pre_kernel_entry >> .Lskip_check_xint\@: >> .endif >> +#endif >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + .if \el == 0 && \regsize == 64 && \label == xint >> + alternative_if_not ARM64_HAS_HW_XINT >> + b .Lskip_hw_xint\@ >> + alternative_else_nop_endif >> + kernel_entry 0, 64, xint >> + mov x0, sp >> + bl el0t_64_xint_handler >> + kernel_exit 0, xint > > Could we fold the assembly code on else branch into its own macro? > Let's give a the macro an name that has similar style with the ones > we uses in the code braced by CONFIG_FAST_IRQ/SYSCALL. > >> +.Lskip_hw_xint\@: >> + .endif >> #endif >> kernel_entry \el, \regsize >> mov x0, sp >> @@ -760,7 +776,11 @@ SYM_CODE_END(el\el\ht\()_\regsize\()_\label) >> entry_handler 0, t, 64, error >> >> entry_handler 0, t, 32, sync >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + entry_handler 0, t, 64, xint >> +#else >> entry_handler 0, t, 32, irq >> +#endif >> entry_handler 0, t, 32, fiq >> entry_handler 0, t, 32, error >> >> @@ -905,7 +925,14 @@ alternative_else_nop_endif >> .rept 4 >> tramp_ventry .Lvector_start\@, 64, \kpti, \bhb >> .endr >> - .rept 4 >> + >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + tramp_ventry .Lvector_start\@, 64, \kpti, \bhb >> +#else >> + tramp_ventry .Lvector_start\@, 32, \kpti, \bhb >> +#endif >> + >> + .rept 3 >> tramp_ventry .Lvector_start\@, 32, \kpti, \bhb >> .endr >> .endm >> @@ -955,7 +982,14 @@ SYM_CODE_END(tramp_exit) >> .rept 4 >> tramp_ventry .Lvector_start\@, 64, 0, \bhb >> .endr >> - .rept 4 >> + >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + tramp_ventry .Lvector_start\@, 64, 0, \bhb >> +#else >> + tramp_ventry .Lvector_start\@, 32, 0, \bhb >> +#endif >> + >> + .rept 3 > >> tramp_ventry .Lvector_start\@, 32, 0, \bhb >> .endr >> .endm >> diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps >> index f2ddced689b5..b1f109f17e4f 100644 >> --- a/arch/arm64/tools/cpucaps >> +++ b/arch/arm64/tools/cpucaps >> @@ -110,7 +110,7 @@ WORKAROUND_HISI_HIP08_RU_PREFETCH >> WORKAROUND_HISILICON_1980005 >> HAS_XCALL >> HAS_XINT >> -KABI_RESERVE_3 >> +HAS_HW_XINT >> KABI_RESERVE_4 >> KABI_RESERVE_5 >> KABI_RESERVE_6 >> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c >> index 4cc8b95d533f..32ffdf06f61e 100644 >> --- a/drivers/irqchip/irq-gic-v3.c >> +++ b/drivers/irqchip/irq-gic-v3.c >> @@ -35,7 +35,7 @@ >> >> #include "irq-gic-common.h" >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> #include "../../../kernel/irq/internals.h" >> #endif >> >> @@ -828,7 +828,7 @@ static bool gic_rpr_is_nmi_prio(void) >> return unlikely(gic_read_rpr() == GICD_INT_RPR_PRI(GICD_INT_NMI_PRI)); >> } >> >> -static bool gic_irqnr_is_special(u32 irqnr) >> +bool gic_irqnr_is_special(u32 irqnr) >> { >> return irqnr >= 1020 && irqnr <= 1023; >> } > > Please don't do this, left it static. > >> @@ -993,7 +993,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs >> __gic_handle_irq_from_irqson(regs); >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +DECLARE_BITMAP(irqnr_nmi_map, 1024); >> +#endif >> + >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> DECLARE_BITMAP(irqnr_xint_map, 1024); >> >> static bool can_set_xint(unsigned int hwirq) >> @@ -1002,12 +1006,18 @@ static bool can_set_xint(unsigned int hwirq) >> __get_intid_range(hwirq) == SPI_RANGE) >> return true; >> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + if (hw_xint_support && __get_intid_range(hwirq) == PPI_RANGE) >> + return true; >> +#endif >> + >> return false; >> } >> >> static bool xint_transform(int irqno, enum xint_op op) >> { >> struct irq_data *data = irq_get_irq_data(irqno); >> + struct irq_desc *desc; >> int hwirq; >> >> while (data->parent_data) >> @@ -1018,14 +1028,29 @@ static bool xint_transform(int irqno, enum xint_op op) >> if (!can_set_xint(hwirq)) >> return false; >> >> + desc = irq_data_to_desc(data); >> + >> switch (op) { >> case IRQ_TO_XINT: >> set_bit(hwirq, irqnr_xint_map); >> xint_add_debugfs_entry(irqno); >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + if (has_v3_3_nmi() && hw_xint_support && !irq_is_nmi(desc)) { >> + gic_irq_enable_nmi(data); >> + set_bit(hwirq, irqnr_nmi_map); >> + } >> +#endif >> return true; >> case XINT_TO_IRQ: >> clear_bit(hwirq, irqnr_xint_map); >> xint_remove_debugfs_entry(irqno); >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + if (has_v3_3_nmi() && hw_xint_support && irq_is_nmi(desc) && >> + test_bit(hwirq, irqnr_nmi_map)) { >> + gic_irq_disable_nmi(data); >> + clear_bit(hwirq, irqnr_nmi_map); >> + } >> +#endif >> return false; >> case XINT_SET_CHECK: >> return test_bit(hwirq, irqnr_xint_map); >> @@ -1096,7 +1121,7 @@ static const struct proc_ops xint_proc_ops = { >> >> void register_irqchip_proc(struct irq_desc *desc, void *irqp) >> { >> - if (!is_xint_support) >> + if (!is_xint_support && !hw_xint_support) >> return; >> >> /* create /proc/irq/<irq>/xint */ >> @@ -1105,12 +1130,63 @@ void register_irqchip_proc(struct irq_desc *desc, void *irqp) >> >> void unregister_irqchip_proc(struct irq_desc *desc) >> { >> - if (!is_xint_support) >> + if (!is_xint_support && !hw_xint_support) >> return; >> >> remove_proc_entry("xint", desc->dir); >> } >> -#endif /* CONFIG_FAST_IRQ */ >> +#endif >> + >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +bool is_xint(unsigned long hwirq) >> +{ >> + return test_bit(hwirq, irqnr_xint_map); >> +} >> + >> +static bool is_spi(unsigned long hwirq) >> +{ >> + if (__get_intid_range(hwirq) == SPI_RANGE || >> + __get_intid_range(hwirq) == ESPI_RANGE) >> + return true; >> + >> + return false; >> +} >> + >> +void fast_handle_xint(struct pt_regs *regs, u32 irqnr) >> +{ >> + struct pt_regs *old_regs; >> + struct irq_domain *domain; >> + struct irqaction *action; >> + struct irq_desc *desc; >> + struct irq_data *data; >> + >> + arch_nmi_enter(); >> + BUG_ON(in_nmi() == NMI_MASK); >> + __preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); >> + old_regs = set_irq_regs(regs); >> + >> + domain = irq_get_default_host(); >> + data = radix_tree_lookup(&domain->revmap_tree, irqnr); >> + >> + desc = irq_data_to_desc(data); >> + action = desc->action; >> + >> + gic_read_nmiar(); >> + write_gicreg(irqnr, ICC_EOIR1_EL1); >> + isb(); >> + >> + if (is_spi(irqnr)) >> + action->handler(data->irq, action->dev_id); >> + else >> + action->handler(data->irq, raw_cpu_ptr(action->percpu_dev_id)); >> + gic_write_dir(irqnr); >> + >> + set_irq_regs(old_regs); >> + BUG_ON(!in_nmi()); >> + __preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); >> + arch_nmi_exit(); >> +} >> +#endif >> >> static u32 gic_get_pribits(void) >> { >> @@ -2358,6 +2434,7 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base, >> goto out_free; >> } >> >> + irq_set_default_host(gic_data.domain); >> irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED); >> >> gic_data.has_rss = !!(typer & GICD_TYPER_RSS); >> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h >> index 548b8a5c46cf..3c0f04b86c15 100644 >> --- a/include/linux/irqchip/arm-gic-v3.h >> +++ b/include/linux/irqchip/arm-gic-v3.h >> @@ -721,8 +721,9 @@ static inline enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq) >> } >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> extern bool is_xint_support; >> +extern bool hw_xint_support; >> >> enum xint_op { >> XINT_TO_IRQ, >> @@ -733,6 +734,9 @@ enum xint_op { >> >> void register_irqchip_proc(struct irq_desc *desc, void *irqp); >> void unregister_irqchip_proc(struct irq_desc *desc); >> +bool gic_irqnr_is_special(u32 irqnr); >> +bool is_xint(unsigned long hwirq); >> +void fast_handle_xint(struct pt_regs *regs, u32 irqnr); >> #endif >> #endif >> >> diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c >> index dc94c360b54b..2152125f8ae2 100644 >> --- a/kernel/irq/debugfs.c >> +++ b/kernel/irq/debugfs.c >> @@ -242,7 +242,7 @@ void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc) >> &dfs_irq_ops); >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> static struct dentry *xint_dir; >> >> void xint_add_debugfs_entry(unsigned int irq) >> @@ -281,8 +281,8 @@ static int __init irq_debugfs_init(void) >> >> irq_dir = debugfs_create_dir("irqs", root_dir); >> >> -#ifdef CONFIG_FAST_IRQ >> - if (is_xint_support) >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> + if (is_xint_support || hw_xint_support) >> xint_dir = debugfs_create_dir("xints", root_dir); >> #endif >> >> diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h >> index 2fb08139a9e4..1c64854102f5 100644 >> --- a/kernel/irq/internals.h >> +++ b/kernel/irq/internals.h >> @@ -506,8 +506,9 @@ static inline void irq_remove_debugfs_entry(struct irq_desc *desc) >> kfree(desc->dev_name); >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> extern bool is_xint_support; >> +extern bool hw_xint_support; >> >> void xint_add_debugfs_entry(unsigned int irq); >> void xint_remove_debugfs_entry(unsigned int irq); >
1 0
0 0
[PATCH openEuler-1.0-LTS] macsec: fix UAF bug for real_dev
by Wang Liang 25 Mar '25

25 Mar '25
From: Ziyang Xuan <william.xuanziyang(a)huawei.com> mainline inclusion from mainline-v5.19-rc1 commit 196a888ca6571deb344468e1d7138e3273206335 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBP2L3 CVE: CVE-2022-49390 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- Create a new macsec device but not get reference to real_dev. That can not ensure that real_dev is freed after macsec. That will trigger the UAF bug for real_dev as following: ================================================================== BUG: KASAN: use-after-free in macsec_get_iflink+0x5f/0x70 drivers/net/macsec.c:3662 Call Trace: ... macsec_get_iflink+0x5f/0x70 drivers/net/macsec.c:3662 dev_get_iflink+0x73/0xe0 net/core/dev.c:637 default_operstate net/core/link_watch.c:42 [inline] rfc2863_policy+0x233/0x2d0 net/core/link_watch.c:54 linkwatch_do_dev+0x2a/0x150 net/core/link_watch.c:161 Allocated by task 22209: ... alloc_netdev_mqs+0x98/0x1100 net/core/dev.c:10549 rtnl_create_link+0x9d7/0xc00 net/core/rtnetlink.c:3235 veth_newlink+0x20e/0xa90 drivers/net/veth.c:1748 Freed by task 8: ... kfree+0xd6/0x4d0 mm/slub.c:4552 kvfree+0x42/0x50 mm/util.c:615 device_release+0x9f/0x240 drivers/base/core.c:2229 kobject_cleanup lib/kobject.c:673 [inline] kobject_release lib/kobject.c:704 [inline] kref_put include/linux/kref.h:65 [inline] kobject_put+0x1c8/0x540 lib/kobject.c:721 netdev_run_todo+0x72e/0x10b0 net/core/dev.c:10327 After commit faab39f63c1f ("net: allow out-of-order netdev unregistration") and commit e5f80fcf869a ("ipv6: give an IPv6 dev to blackhole_netdev"), we can add dev_hold_track() in macsec_dev_init() and dev_put_track() in macsec_free_netdev() to fix the problem. Fixes: 2bce1ebed17d ("macsec: fix refcnt leak in module exit routine") Reported-by: syzbot+d0e94b65ac259c29ce7a(a)syzkaller.appspotmail.com Signed-off-by: Ziyang Xuan <william.xuanziyang(a)huawei.com> Link: https://lore.kernel.org/r/20220531074500.1272846-1-william.xuanziyang@huawe… Signed-off-by: Paolo Abeni <pabeni(a)redhat.com> Conflicts: drivers/net/macsec.c [conflicts due to not mergered 4d92b95ff2f9 ("net: add net device refcount tracker infrastructure")] Signed-off-by: Wang Liang <wangliang74(a)huawei.com> --- drivers/net/macsec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 10a8ef2d025a..a0f565814d30 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2783,6 +2783,9 @@ static int macsec_dev_init(struct net_device *dev) if (is_zero_ether_addr(dev->broadcast)) memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len); + /* Get macsec's reference to real_dev */ + dev_hold(real_dev); + return 0; } @@ -3009,6 +3012,8 @@ static void macsec_free_netdev(struct net_device *dev) free_percpu(macsec->stats); free_percpu(macsec->secy.tx_sc.stats); + /* Get rid of the macsec's reference to real_dev */ + dev_put(macsec->real_dev); } static void macsec_setup(struct net_device *dev) -- 2.34.1
2 1
0 0
Re: [PATCH OLK-6.6 v2 2/3] arm64: entry: Support hardware xint
by Jinjie Ruan 25 Mar '25

25 Mar '25
On 2025/3/25 15:00, Liao, Chang wrote: > > > 在 2025/3/24 21:53, Jinjie Ruan 写道: >> hulk inclusion >> category: feature >> bugzilla: https://gitee.com/openeuler/release-management/issues/IBV2E4 >> >> -------------------------------- >> >> Support hardware xint. Hardware xint provides a separate entry for >> interrupt handling, so we can use it to customize and respond to >> interrupts relatively quickly. >> >> Signed-off-by: Jinjie Ruan <ruanjinjie(a)huawei.com> >> --- >> v2: >> - Reuse the xint set and check logic in xint 1.0. >> - Introduce fast_handle_xint(). >> - Rename enable_xint_xcall() to enable_xfunc(). >> - Rename test_has_xint_xcall() to test_has_xfunc(). >> - Fix a typo, Harware -> Hardware. >> - Add a blank line after declarations in el0t_64_xint_handler(). >> --- >> arch/arm64/Kconfig | 7 +++ >> arch/arm64/include/asm/sysreg.h | 4 ++ >> arch/arm64/kernel/cpufeature.c | 75 ++++++++++++++++++++++++- >> arch/arm64/kernel/entry-common.c | 35 +++++++++--- >> arch/arm64/kernel/entry.S | 40 +++++++++++++- >> arch/arm64/tools/cpucaps | 2 +- >> drivers/irqchip/irq-gic-v3.c | 89 ++++++++++++++++++++++++++++-- >> include/linux/irqchip/arm-gic-v3.h | 6 +- >> kernel/irq/debugfs.c | 6 +- >> kernel/irq/internals.h | 3 +- >> 10 files changed, 244 insertions(+), 23 deletions(-) >> >> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig >> index 9da9d58f1c02..57d05cfbd29e 100644 >> --- a/arch/arm64/Kconfig >> +++ b/arch/arm64/Kconfig >> @@ -1717,6 +1717,13 @@ config ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG >> config ARCH_SUPPORTS_CRASH_DUMP >> def_bool y >> >> +config ARCH_SUPPORTS_XINT >> + bool "Hardware xint support" >> + default n >> + depends on ARM64_NMI >> + depends on ARM_GIC_V3 >> + depends on !COMPAT >> + >> config TRANS_TABLE >> def_bool y >> depends on HIBERNATION || KEXEC_CORE >> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h >> index 435634a703c6..b34e8cc4476b 100644 >> --- a/arch/arm64/include/asm/sysreg.h >> +++ b/arch/arm64/include/asm/sysreg.h >> @@ -269,6 +269,10 @@ >> #define SYS_REVIDR_EL1 sys_reg(3, 0, 0, 0, 6) >> >> #define SYS_ACTLR_EL1 sys_reg(3, 0, 1, 0, 1) >> + >> +#define ACTLR_ELx_XINT_SHIFT 21 >> +#define ACTLR_ELx_XINT (BIT(ACTLR_ELx_XINT_SHIFT)) >> + > > I don't think sysreg.h is the best place for those ACTLR_ELx bits. This header's > more about the actual uint32 upcode of system register. not the details of the fields. > And since ACTLR_ELx fields vary implementation. I think we should put them in a new > heade, actlr.h like kernel does with esr.h. > > >> #define SYS_RGSR_EL1 sys_reg(3, 0, 1, 0, 5) >> #define SYS_GCR_EL1 sys_reg(3, 0, 1, 0, 6) >> >> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c >> index a1736e9044da..b4de05241f7d 100644 >> --- a/arch/arm64/kernel/cpufeature.c >> +++ b/arch/arm64/kernel/cpufeature.c >> @@ -2406,8 +2406,12 @@ static bool has_xcall_support(const struct arm64_cpu_capabilities *entry, int __ >> } >> #endif >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> bool is_xint_support; >> +bool hw_xint_support; >> +#endif >> + >> +#ifdef CONFIG_FAST_IRQ >> static int __init xint_setup(char *str) >> { >> if (!cpus_have_cap(ARM64_HAS_GIC_CPUIF_SYSREGS)) >> @@ -2424,6 +2428,66 @@ static bool has_xint_support(const struct arm64_cpu_capabilities *entry, int __u >> } >> #endif >> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +static bool test_has_xfunc(void) > > test_has_xfunc is a bit strange, could we just use has_arch_xint_support()? > >> +{ >> + u64 new, old = read_sysreg(actlr_el1); >> + >> + write_sysreg(old | ACTLR_ELx_XINT, actlr_el1); >> + isb(); >> + new = read_sysreg(actlr_el1); >> + if (new & ACTLR_ELx_XINT) { >> + write_sysreg(old, actlr_el1); >> + hw_xint_support = true; >> + return true; >> + } >> + >> + return false; >> +} >> + >> +static void enable_xfunc(void) > > Could we use cpu_enable_arch_xint()? it is not hard to find some helper functions > in this file has similar role as this. > >> +{ >> + u64 actlr_el1, actlr_el2; >> + u64 el; >> + >> + el = read_sysreg(CurrentEL); >> + if (el == CurrentEL_EL2) { >> + actlr_el2 = read_sysreg(actlr_el2); >> + actlr_el2 |= ACTLR_ELx_XINT; >> + write_sysreg(actlr_el2, actlr_el2); >> + isb(); >> + actlr_el2 = read_sysreg(actlr_el2); >> + pr_info("actlr_el2: %llx, cpu:%d\n", actlr_el2, smp_processor_id()); >> + } >> + >> + actlr_el1 = read_sysreg(actlr_el1); >> + actlr_el1 |= ACTLR_ELx_XINT; >> + write_sysreg(actlr_el1, actlr_el1); >> + isb(); >> + actlr_el1 = read_sysreg(actlr_el1); >> + pr_info("actlr_el1: %llx, cpu:%d\n", actlr_el1, smp_processor_id()); >> +} >> + >> +static bool test_has_xint(const struct arm64_cpu_capabilities *entry, int scope) >> +{ >> + if (!IS_ENABLED(CONFIG_ARM64_NMI)) >> + pr_info("CONFIG_ARM64_NMI disabled, using XINTs for guests only\n"); >> +#ifdef CONFIG_ARM64_PSEUDO_NMI >> + else if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && enable_pseudo_nmi) { >> + pr_info("Pseudo NMI enabled, not using architected XINT\n"); >> + return false; >> + } >> +#endif >> + >> + return test_has_xfunc(); >> +} > > Fold this function into has_arch_xint_support(). > >> + >> +static void xint_enable(const struct arm64_cpu_capabilities *__unused) >> +{ >> + enable_xfunc(); > > Fold this function into cpu_enable_arch_xint(). > >> +} >> +#endif >> + >> static const struct arm64_cpu_capabilities arm64_features[] = { >> { >> .capability = ARM64_ALWAYS_BOOT, >> @@ -2971,6 +3035,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = { >> .type = ARM64_CPUCAP_SYSTEM_FEATURE, >> .matches = has_xint_support, >> }, >> +#endif >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + { >> + .desc = "Hardware xint Support", > > Mind the ppercase for first letter. > >> + .capability = ARM64_HAS_HW_XINT, >> + .type = ARM64_CPUCAP_SYSTEM_FEATURE, >> + .matches = test_has_xint, >> + .cpu_enable = xint_enable, >> + }, >> #endif > > I really can't recall why we add "Xint support" data into arm64_feature array before. > Just to be clear, "Xint support' is a software solution, it's about making interrupt > handler faster. It's not tied to any particular CPU feature. "Hardware Xint Support" > would means something different, like a real CPU feature. So I think we should take > it out from the arm64_feature array upon CPU can support a hardware xint entry. > >> {}, >> }; >> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c >> index 4602c107c40a..d09029dfcf02 100644 >> --- a/arch/arm64/kernel/entry-common.c >> +++ b/arch/arm64/kernel/entry-common.c >> @@ -6,6 +6,9 @@ >> */ >> >> #include <linux/context_tracking.h> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +#include <linux/irqchip/arm-gic-v3.h> >> +#endif >> #include <linux/kasan.h> >> #include <linux/linkage.h> >> #include <linux/lockdep.h> >> @@ -607,7 +610,7 @@ static void noinstr el0_xint(struct pt_regs *regs, u64 nmi_flag, >> } >> >> >> -asmlinkage void noinstr el0t_64_xint_handler(struct pt_regs *regs) >> +asmlinkage void noinstr el0t_64_sw_xint_handler(struct pt_regs *regs) >> { >> el0_xint(regs, ISR_EL1_IS, handle_arch_irq, handle_arch_nmi_irq); >> } >> @@ -966,6 +969,30 @@ asmlinkage void noinstr el0t_64_error_handler(struct pt_regs *regs) >> __el0_error_handler_common(regs); >> } >> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +asmlinkage void noinstr el0t_64_xint_handler(struct pt_regs *regs) >> +{ >> + u32 irqnr = read_sysreg_s(SYS_ICC_HPPIR1_EL1); >> + >> + if (gic_irqnr_is_special(irqnr)) >> + return; >> + >> + if (is_xint(irqnr)) >> + fast_handle_xint(regs, irqnr); >> + else >> + el0t_64_irq_handler(regs); >> +} > > Could we register fast_handle_xint() in gic-v3 driver, like kernel does for gic_handle_irq() > and gic_handle_nmi_irq(). By checking the return value, it still has chance to fall through > to the regular irq handler. > >> +#else >> +#ifdef CONFIG_AARCH32_EL0 >> +asmlinkage void noinstr el0t_32_irq_handler(struct pt_regs *regs) >> +{ >> + __el0_irq_handler_common(regs); >> +} >> +#else /* CONFIG_AARCH32_EL0 */ >> +UNHANDLED(el0t, 32, irq) >> +#endif >> +#endif >> + >> #ifdef CONFIG_AARCH32_EL0 >> static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr) >> { >> @@ -1028,11 +1055,6 @@ asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs) >> } >> } >> >> -asmlinkage void noinstr el0t_32_irq_handler(struct pt_regs *regs) >> -{ >> - __el0_irq_handler_common(regs); >> -} >> - >> asmlinkage void noinstr el0t_32_fiq_handler(struct pt_regs *regs) >> { >> __el0_fiq_handler_common(regs); >> @@ -1044,7 +1066,6 @@ asmlinkage void noinstr el0t_32_error_handler(struct pt_regs *regs) >> } >> #else /* CONFIG_AARCH32_EL0 */ >> UNHANDLED(el0t, 32, sync) >> -UNHANDLED(el0t, 32, irq) >> UNHANDLED(el0t, 32, fiq) >> UNHANDLED(el0t, 32, error) >> #endif /* CONFIG_AARCH32_EL0 */ >> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S >> index da3809632f0f..046225fa2f90 100644 >> --- a/arch/arm64/kernel/entry.S >> +++ b/arch/arm64/kernel/entry.S >> @@ -565,7 +565,11 @@ SYM_CODE_START(vectors) >> kernel_ventry 0, t, 64, error // Error 64-bit EL0 >> >> kernel_ventry 0, t, 32, sync // Synchronous 32-bit EL0 >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + kernel_ventry 0, t, 64, xint // XINT 64-bit EL0 >> +#else >> kernel_ventry 0, t, 32, irq // IRQ 32-bit EL0 >> +#endif >> kernel_ventry 0, t, 32, fiq // FIQ 32-bit EL0 >> kernel_ventry 0, t, 32, error // Error 32-bit EL0 >> SYM_CODE_END(vectors) >> @@ -696,7 +700,7 @@ SYM_CODE_END(__bad_stack) >> kernel_entry 0, 64 >> #endif >> mov x0, sp >> - bl el0t_64_xint_handler >> + bl el0t_64_sw_xint_handler >> #ifdef CONFIG_SECURITY_FEATURE_BYPASS >> kernel_exit 0, xint >> #else >> @@ -729,6 +733,18 @@ SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label) >> check_xint_pre_kernel_entry >> .Lskip_check_xint\@: >> .endif >> +#endif >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + .if \el == 0 && \regsize == 64 && \label == xint >> + alternative_if_not ARM64_HAS_HW_XINT >> + b .Lskip_hw_xint\@ >> + alternative_else_nop_endif >> + kernel_entry 0, 64, xint >> + mov x0, sp >> + bl el0t_64_xint_handler >> + kernel_exit 0, xint > > Could we fold the assembly code on else branch into its own macro? > Let's give a the macro an name that has similar style with the ones > we uses in the code braced by CONFIG_FAST_IRQ/SYSCALL. 软件方案需要检查,硬件方案不需要这些检查逻辑,从xcall/xint这个入口进来就确定了是xcall/xint > >> +.Lskip_hw_xint\@: >> + .endif >> #endif >> kernel_entry \el, \regsize >> mov x0, sp >> @@ -760,7 +776,11 @@ SYM_CODE_END(el\el\ht\()_\regsize\()_\label) >> entry_handler 0, t, 64, error >> >> entry_handler 0, t, 32, sync >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + entry_handler 0, t, 64, xint >> +#else >> entry_handler 0, t, 32, irq >> +#endif >> entry_handler 0, t, 32, fiq >> entry_handler 0, t, 32, error >> >> @@ -905,7 +925,14 @@ alternative_else_nop_endif >> .rept 4 >> tramp_ventry .Lvector_start\@, 64, \kpti, \bhb >> .endr >> - .rept 4 >> + >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + tramp_ventry .Lvector_start\@, 64, \kpti, \bhb >> +#else >> + tramp_ventry .Lvector_start\@, 32, \kpti, \bhb >> +#endif >> + >> + .rept 3 >> tramp_ventry .Lvector_start\@, 32, \kpti, \bhb >> .endr >> .endm >> @@ -955,7 +982,14 @@ SYM_CODE_END(tramp_exit) >> .rept 4 >> tramp_ventry .Lvector_start\@, 64, 0, \bhb >> .endr >> - .rept 4 >> + >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + tramp_ventry .Lvector_start\@, 64, 0, \bhb >> +#else >> + tramp_ventry .Lvector_start\@, 32, 0, \bhb >> +#endif >> + >> + .rept 3 > >> tramp_ventry .Lvector_start\@, 32, 0, \bhb >> .endr >> .endm >> diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps >> index f2ddced689b5..b1f109f17e4f 100644 >> --- a/arch/arm64/tools/cpucaps >> +++ b/arch/arm64/tools/cpucaps >> @@ -110,7 +110,7 @@ WORKAROUND_HISI_HIP08_RU_PREFETCH >> WORKAROUND_HISILICON_1980005 >> HAS_XCALL >> HAS_XINT >> -KABI_RESERVE_3 >> +HAS_HW_XINT >> KABI_RESERVE_4 >> KABI_RESERVE_5 >> KABI_RESERVE_6 >> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c >> index 4cc8b95d533f..32ffdf06f61e 100644 >> --- a/drivers/irqchip/irq-gic-v3.c >> +++ b/drivers/irqchip/irq-gic-v3.c >> @@ -35,7 +35,7 @@ >> >> #include "irq-gic-common.h" >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> #include "../../../kernel/irq/internals.h" >> #endif >> >> @@ -828,7 +828,7 @@ static bool gic_rpr_is_nmi_prio(void) >> return unlikely(gic_read_rpr() == GICD_INT_RPR_PRI(GICD_INT_NMI_PRI)); >> } >> >> -static bool gic_irqnr_is_special(u32 irqnr) >> +bool gic_irqnr_is_special(u32 irqnr) >> { >> return irqnr >= 1020 && irqnr <= 1023; >> } > > Please don't do this, left it static. > >> @@ -993,7 +993,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs >> __gic_handle_irq_from_irqson(regs); >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +DECLARE_BITMAP(irqnr_nmi_map, 1024); >> +#endif >> + >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> DECLARE_BITMAP(irqnr_xint_map, 1024); >> >> static bool can_set_xint(unsigned int hwirq) >> @@ -1002,12 +1006,18 @@ static bool can_set_xint(unsigned int hwirq) >> __get_intid_range(hwirq) == SPI_RANGE) >> return true; >> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + if (hw_xint_support && __get_intid_range(hwirq) == PPI_RANGE) >> + return true; >> +#endif >> + >> return false; >> } >> >> static bool xint_transform(int irqno, enum xint_op op) >> { >> struct irq_data *data = irq_get_irq_data(irqno); >> + struct irq_desc *desc; >> int hwirq; >> >> while (data->parent_data) >> @@ -1018,14 +1028,29 @@ static bool xint_transform(int irqno, enum xint_op op) >> if (!can_set_xint(hwirq)) >> return false; >> >> + desc = irq_data_to_desc(data); >> + >> switch (op) { >> case IRQ_TO_XINT: >> set_bit(hwirq, irqnr_xint_map); >> xint_add_debugfs_entry(irqno); >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + if (has_v3_3_nmi() && hw_xint_support && !irq_is_nmi(desc)) { >> + gic_irq_enable_nmi(data); >> + set_bit(hwirq, irqnr_nmi_map); >> + } >> +#endif >> return true; >> case XINT_TO_IRQ: >> clear_bit(hwirq, irqnr_xint_map); >> xint_remove_debugfs_entry(irqno); >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + if (has_v3_3_nmi() && hw_xint_support && irq_is_nmi(desc) && >> + test_bit(hwirq, irqnr_nmi_map)) { >> + gic_irq_disable_nmi(data); >> + clear_bit(hwirq, irqnr_nmi_map); >> + } >> +#endif >> return false; >> case XINT_SET_CHECK: >> return test_bit(hwirq, irqnr_xint_map); >> @@ -1096,7 +1121,7 @@ static const struct proc_ops xint_proc_ops = { >> >> void register_irqchip_proc(struct irq_desc *desc, void *irqp) >> { >> - if (!is_xint_support) >> + if (!is_xint_support && !hw_xint_support) >> return; >> >> /* create /proc/irq/<irq>/xint */ >> @@ -1105,12 +1130,63 @@ void register_irqchip_proc(struct irq_desc *desc, void *irqp) >> >> void unregister_irqchip_proc(struct irq_desc *desc) >> { >> - if (!is_xint_support) >> + if (!is_xint_support && !hw_xint_support) >> return; >> >> remove_proc_entry("xint", desc->dir); >> } >> -#endif /* CONFIG_FAST_IRQ */ >> +#endif >> + >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +bool is_xint(unsigned long hwirq) >> +{ >> + return test_bit(hwirq, irqnr_xint_map); >> +} >> + >> +static bool is_spi(unsigned long hwirq) >> +{ >> + if (__get_intid_range(hwirq) == SPI_RANGE || >> + __get_intid_range(hwirq) == ESPI_RANGE) >> + return true; >> + >> + return false; >> +} >> + >> +void fast_handle_xint(struct pt_regs *regs, u32 irqnr) >> +{ >> + struct pt_regs *old_regs; >> + struct irq_domain *domain; >> + struct irqaction *action; >> + struct irq_desc *desc; >> + struct irq_data *data; >> + >> + arch_nmi_enter(); >> + BUG_ON(in_nmi() == NMI_MASK); >> + __preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); >> + old_regs = set_irq_regs(regs); >> + >> + domain = irq_get_default_host(); >> + data = radix_tree_lookup(&domain->revmap_tree, irqnr); >> + >> + desc = irq_data_to_desc(data); >> + action = desc->action; >> + >> + gic_read_nmiar(); >> + write_gicreg(irqnr, ICC_EOIR1_EL1); >> + isb(); >> + >> + if (is_spi(irqnr)) >> + action->handler(data->irq, action->dev_id); >> + else >> + action->handler(data->irq, raw_cpu_ptr(action->percpu_dev_id)); >> + gic_write_dir(irqnr); >> + >> + set_irq_regs(old_regs); >> + BUG_ON(!in_nmi()); >> + __preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); >> + arch_nmi_exit(); >> +} >> +#endif >> >> static u32 gic_get_pribits(void) >> { >> @@ -2358,6 +2434,7 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base, >> goto out_free; >> } >> >> + irq_set_default_host(gic_data.domain); >> irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED); >> >> gic_data.has_rss = !!(typer & GICD_TYPER_RSS); >> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h >> index 548b8a5c46cf..3c0f04b86c15 100644 >> --- a/include/linux/irqchip/arm-gic-v3.h >> +++ b/include/linux/irqchip/arm-gic-v3.h >> @@ -721,8 +721,9 @@ static inline enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq) >> } >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> extern bool is_xint_support; >> +extern bool hw_xint_support; >> >> enum xint_op { >> XINT_TO_IRQ, >> @@ -733,6 +734,9 @@ enum xint_op { >> >> void register_irqchip_proc(struct irq_desc *desc, void *irqp); >> void unregister_irqchip_proc(struct irq_desc *desc); >> +bool gic_irqnr_is_special(u32 irqnr); >> +bool is_xint(unsigned long hwirq); >> +void fast_handle_xint(struct pt_regs *regs, u32 irqnr); >> #endif >> #endif >> >> diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c >> index dc94c360b54b..2152125f8ae2 100644 >> --- a/kernel/irq/debugfs.c >> +++ b/kernel/irq/debugfs.c >> @@ -242,7 +242,7 @@ void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc) >> &dfs_irq_ops); >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> static struct dentry *xint_dir; >> >> void xint_add_debugfs_entry(unsigned int irq) >> @@ -281,8 +281,8 @@ static int __init irq_debugfs_init(void) >> >> irq_dir = debugfs_create_dir("irqs", root_dir); >> >> -#ifdef CONFIG_FAST_IRQ >> - if (is_xint_support) >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> + if (is_xint_support || hw_xint_support) >> xint_dir = debugfs_create_dir("xints", root_dir); >> #endif >> >> diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h >> index 2fb08139a9e4..1c64854102f5 100644 >> --- a/kernel/irq/internals.h >> +++ b/kernel/irq/internals.h >> @@ -506,8 +506,9 @@ static inline void irq_remove_debugfs_entry(struct irq_desc *desc) >> kfree(desc->dev_name); >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> extern bool is_xint_support; >> +extern bool hw_xint_support; >> >> void xint_add_debugfs_entry(unsigned int irq); >> void xint_remove_debugfs_entry(unsigned int irq); >
1 0
0 0
Re: [PATCH OLK-6.6 v2 2/3] arm64: entry: Support hardware xint
by Jinjie Ruan 25 Mar '25

25 Mar '25
On 2025/3/25 15:00, Liao, Chang wrote: > > > 在 2025/3/24 21:53, Jinjie Ruan 写道: >> hulk inclusion >> category: feature >> bugzilla: https://gitee.com/openeuler/release-management/issues/IBV2E4 >> >> -------------------------------- >> >> Support hardware xint. Hardware xint provides a separate entry for >> interrupt handling, so we can use it to customize and respond to >> interrupts relatively quickly. >> >> Signed-off-by: Jinjie Ruan <ruanjinjie(a)huawei.com> >> --- >> v2: >> - Reuse the xint set and check logic in xint 1.0. >> - Introduce fast_handle_xint(). >> - Rename enable_xint_xcall() to enable_xfunc(). >> - Rename test_has_xint_xcall() to test_has_xfunc(). >> - Fix a typo, Harware -> Hardware. >> - Add a blank line after declarations in el0t_64_xint_handler(). >> --- >> arch/arm64/Kconfig | 7 +++ >> arch/arm64/include/asm/sysreg.h | 4 ++ >> arch/arm64/kernel/cpufeature.c | 75 ++++++++++++++++++++++++- >> arch/arm64/kernel/entry-common.c | 35 +++++++++--- >> arch/arm64/kernel/entry.S | 40 +++++++++++++- >> arch/arm64/tools/cpucaps | 2 +- >> drivers/irqchip/irq-gic-v3.c | 89 ++++++++++++++++++++++++++++-- >> include/linux/irqchip/arm-gic-v3.h | 6 +- >> kernel/irq/debugfs.c | 6 +- >> kernel/irq/internals.h | 3 +- >> 10 files changed, 244 insertions(+), 23 deletions(-) >> >> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig >> index 9da9d58f1c02..57d05cfbd29e 100644 >> --- a/arch/arm64/Kconfig >> +++ b/arch/arm64/Kconfig >> @@ -1717,6 +1717,13 @@ config ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG >> config ARCH_SUPPORTS_CRASH_DUMP >> def_bool y >> >> +config ARCH_SUPPORTS_XINT >> + bool "Hardware xint support" >> + default n >> + depends on ARM64_NMI >> + depends on ARM_GIC_V3 >> + depends on !COMPAT >> + >> config TRANS_TABLE >> def_bool y >> depends on HIBERNATION || KEXEC_CORE >> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h >> index 435634a703c6..b34e8cc4476b 100644 >> --- a/arch/arm64/include/asm/sysreg.h >> +++ b/arch/arm64/include/asm/sysreg.h >> @@ -269,6 +269,10 @@ >> #define SYS_REVIDR_EL1 sys_reg(3, 0, 0, 0, 6) >> >> #define SYS_ACTLR_EL1 sys_reg(3, 0, 1, 0, 1) >> + >> +#define ACTLR_ELx_XINT_SHIFT 21 >> +#define ACTLR_ELx_XINT (BIT(ACTLR_ELx_XINT_SHIFT)) >> + > > I don't think sysreg.h is the best place for those ACTLR_ELx bits. This header's > more about the actual uint32 upcode of system register. not the details of the fields. > And since ACTLR_ELx fields vary implementation. I think we should put them in a new > heade, actlr.h like kernel does with esr.h. > > >> #define SYS_RGSR_EL1 sys_reg(3, 0, 1, 0, 5) >> #define SYS_GCR_EL1 sys_reg(3, 0, 1, 0, 6) >> >> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c >> index a1736e9044da..b4de05241f7d 100644 >> --- a/arch/arm64/kernel/cpufeature.c >> +++ b/arch/arm64/kernel/cpufeature.c >> @@ -2406,8 +2406,12 @@ static bool has_xcall_support(const struct arm64_cpu_capabilities *entry, int __ >> } >> #endif >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> bool is_xint_support; >> +bool hw_xint_support; >> +#endif >> + >> +#ifdef CONFIG_FAST_IRQ >> static int __init xint_setup(char *str) >> { >> if (!cpus_have_cap(ARM64_HAS_GIC_CPUIF_SYSREGS)) >> @@ -2424,6 +2428,66 @@ static bool has_xint_support(const struct arm64_cpu_capabilities *entry, int __u >> } >> #endif >> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +static bool test_has_xfunc(void) > > test_has_xfunc is a bit strange, could we just use has_arch_xint_support()? > >> +{ >> + u64 new, old = read_sysreg(actlr_el1); >> + >> + write_sysreg(old | ACTLR_ELx_XINT, actlr_el1); >> + isb(); >> + new = read_sysreg(actlr_el1); >> + if (new & ACTLR_ELx_XINT) { >> + write_sysreg(old, actlr_el1); >> + hw_xint_support = true; >> + return true; >> + } >> + >> + return false; >> +} >> + >> +static void enable_xfunc(void) > > Could we use cpu_enable_arch_xint()? it is not hard to find some helper functions > in this file has similar role as this. > >> +{ >> + u64 actlr_el1, actlr_el2; >> + u64 el; >> + >> + el = read_sysreg(CurrentEL); >> + if (el == CurrentEL_EL2) { >> + actlr_el2 = read_sysreg(actlr_el2); >> + actlr_el2 |= ACTLR_ELx_XINT; >> + write_sysreg(actlr_el2, actlr_el2); >> + isb(); >> + actlr_el2 = read_sysreg(actlr_el2); >> + pr_info("actlr_el2: %llx, cpu:%d\n", actlr_el2, smp_processor_id()); >> + } >> + >> + actlr_el1 = read_sysreg(actlr_el1); >> + actlr_el1 |= ACTLR_ELx_XINT; >> + write_sysreg(actlr_el1, actlr_el1); >> + isb(); >> + actlr_el1 = read_sysreg(actlr_el1); >> + pr_info("actlr_el1: %llx, cpu:%d\n", actlr_el1, smp_processor_id()); >> +} >> + >> +static bool test_has_xint(const struct arm64_cpu_capabilities *entry, int scope) >> +{ >> + if (!IS_ENABLED(CONFIG_ARM64_NMI)) >> + pr_info("CONFIG_ARM64_NMI disabled, using XINTs for guests only\n"); >> +#ifdef CONFIG_ARM64_PSEUDO_NMI >> + else if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && enable_pseudo_nmi) { >> + pr_info("Pseudo NMI enabled, not using architected XINT\n"); >> + return false; >> + } >> +#endif >> + >> + return test_has_xfunc(); >> +} > > Fold this function into has_arch_xint_support(). > >> + >> +static void xint_enable(const struct arm64_cpu_capabilities *__unused) >> +{ >> + enable_xfunc(); > > Fold this function into cpu_enable_arch_xint(). > >> +} >> +#endif >> + >> static const struct arm64_cpu_capabilities arm64_features[] = { >> { >> .capability = ARM64_ALWAYS_BOOT, >> @@ -2971,6 +3035,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = { >> .type = ARM64_CPUCAP_SYSTEM_FEATURE, >> .matches = has_xint_support, >> }, >> +#endif >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + { >> + .desc = "Hardware xint Support", > > Mind the ppercase for first letter. > >> + .capability = ARM64_HAS_HW_XINT, >> + .type = ARM64_CPUCAP_SYSTEM_FEATURE, >> + .matches = test_has_xint, >> + .cpu_enable = xint_enable, >> + }, >> #endif > > I really can't recall why we add "Xint support" data into arm64_feature array before. > Just to be clear, "Xint support' is a software solution, it's about making interrupt > handler faster. It's not tied to any particular CPU feature. "Hardware Xint Support" > would means something different, like a real CPU feature. So I think we should take > it out from the arm64_feature array upon CPU can support a hardware xint entry. 这个在实现xcall/xint 1.0代码的时候,是为了和后面硬件xcall/xint的检测代码兼容吧,当时检视意见是统一和xcall一样这样做 @邹贻鹏 > >> {}, >> }; >> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c >> index 4602c107c40a..d09029dfcf02 100644 >> --- a/arch/arm64/kernel/entry-common.c >> +++ b/arch/arm64/kernel/entry-common.c >> @@ -6,6 +6,9 @@ >> */ >> >> #include <linux/context_tracking.h> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +#include <linux/irqchip/arm-gic-v3.h> >> +#endif >> #include <linux/kasan.h> >> #include <linux/linkage.h> >> #include <linux/lockdep.h> >> @@ -607,7 +610,7 @@ static void noinstr el0_xint(struct pt_regs *regs, u64 nmi_flag, >> } >> >> >> -asmlinkage void noinstr el0t_64_xint_handler(struct pt_regs *regs) >> +asmlinkage void noinstr el0t_64_sw_xint_handler(struct pt_regs *regs) >> { >> el0_xint(regs, ISR_EL1_IS, handle_arch_irq, handle_arch_nmi_irq); >> } >> @@ -966,6 +969,30 @@ asmlinkage void noinstr el0t_64_error_handler(struct pt_regs *regs) >> __el0_error_handler_common(regs); >> } >> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +asmlinkage void noinstr el0t_64_xint_handler(struct pt_regs *regs) >> +{ >> + u32 irqnr = read_sysreg_s(SYS_ICC_HPPIR1_EL1); >> + >> + if (gic_irqnr_is_special(irqnr)) >> + return; >> + >> + if (is_xint(irqnr)) >> + fast_handle_xint(regs, irqnr); >> + else >> + el0t_64_irq_handler(regs); >> +} > > Could we register fast_handle_xint() in gic-v3 driver, like kernel does for gic_handle_irq() > and gic_handle_nmi_irq(). By checking the return value, it still has chance to fall through > to the regular irq handler. > >> +#else >> +#ifdef CONFIG_AARCH32_EL0 >> +asmlinkage void noinstr el0t_32_irq_handler(struct pt_regs *regs) >> +{ >> + __el0_irq_handler_common(regs); >> +} >> +#else /* CONFIG_AARCH32_EL0 */ >> +UNHANDLED(el0t, 32, irq) >> +#endif >> +#endif >> + >> #ifdef CONFIG_AARCH32_EL0 >> static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr) >> { >> @@ -1028,11 +1055,6 @@ asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs) >> } >> } >> >> -asmlinkage void noinstr el0t_32_irq_handler(struct pt_regs *regs) >> -{ >> - __el0_irq_handler_common(regs); >> -} >> - >> asmlinkage void noinstr el0t_32_fiq_handler(struct pt_regs *regs) >> { >> __el0_fiq_handler_common(regs); >> @@ -1044,7 +1066,6 @@ asmlinkage void noinstr el0t_32_error_handler(struct pt_regs *regs) >> } >> #else /* CONFIG_AARCH32_EL0 */ >> UNHANDLED(el0t, 32, sync) >> -UNHANDLED(el0t, 32, irq) >> UNHANDLED(el0t, 32, fiq) >> UNHANDLED(el0t, 32, error) >> #endif /* CONFIG_AARCH32_EL0 */ >> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S >> index da3809632f0f..046225fa2f90 100644 >> --- a/arch/arm64/kernel/entry.S >> +++ b/arch/arm64/kernel/entry.S >> @@ -565,7 +565,11 @@ SYM_CODE_START(vectors) >> kernel_ventry 0, t, 64, error // Error 64-bit EL0 >> >> kernel_ventry 0, t, 32, sync // Synchronous 32-bit EL0 >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + kernel_ventry 0, t, 64, xint // XINT 64-bit EL0 >> +#else >> kernel_ventry 0, t, 32, irq // IRQ 32-bit EL0 >> +#endif >> kernel_ventry 0, t, 32, fiq // FIQ 32-bit EL0 >> kernel_ventry 0, t, 32, error // Error 32-bit EL0 >> SYM_CODE_END(vectors) >> @@ -696,7 +700,7 @@ SYM_CODE_END(__bad_stack) >> kernel_entry 0, 64 >> #endif >> mov x0, sp >> - bl el0t_64_xint_handler >> + bl el0t_64_sw_xint_handler >> #ifdef CONFIG_SECURITY_FEATURE_BYPASS >> kernel_exit 0, xint >> #else >> @@ -729,6 +733,18 @@ SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label) >> check_xint_pre_kernel_entry >> .Lskip_check_xint\@: >> .endif >> +#endif >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + .if \el == 0 && \regsize == 64 && \label == xint >> + alternative_if_not ARM64_HAS_HW_XINT >> + b .Lskip_hw_xint\@ >> + alternative_else_nop_endif >> + kernel_entry 0, 64, xint >> + mov x0, sp >> + bl el0t_64_xint_handler >> + kernel_exit 0, xint > > Could we fold the assembly code on else branch into its own macro? > Let's give a the macro an name that has similar style with the ones > we uses in the code braced by CONFIG_FAST_IRQ/SYSCALL. > >> +.Lskip_hw_xint\@: >> + .endif >> #endif >> kernel_entry \el, \regsize >> mov x0, sp >> @@ -760,7 +776,11 @@ SYM_CODE_END(el\el\ht\()_\regsize\()_\label) >> entry_handler 0, t, 64, error >> >> entry_handler 0, t, 32, sync >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + entry_handler 0, t, 64, xint >> +#else >> entry_handler 0, t, 32, irq >> +#endif >> entry_handler 0, t, 32, fiq >> entry_handler 0, t, 32, error >> >> @@ -905,7 +925,14 @@ alternative_else_nop_endif >> .rept 4 >> tramp_ventry .Lvector_start\@, 64, \kpti, \bhb >> .endr >> - .rept 4 >> + >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + tramp_ventry .Lvector_start\@, 64, \kpti, \bhb >> +#else >> + tramp_ventry .Lvector_start\@, 32, \kpti, \bhb >> +#endif >> + >> + .rept 3 >> tramp_ventry .Lvector_start\@, 32, \kpti, \bhb >> .endr >> .endm >> @@ -955,7 +982,14 @@ SYM_CODE_END(tramp_exit) >> .rept 4 >> tramp_ventry .Lvector_start\@, 64, 0, \bhb >> .endr >> - .rept 4 >> + >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + tramp_ventry .Lvector_start\@, 64, 0, \bhb >> +#else >> + tramp_ventry .Lvector_start\@, 32, 0, \bhb >> +#endif >> + >> + .rept 3 > >> tramp_ventry .Lvector_start\@, 32, 0, \bhb >> .endr >> .endm >> diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps >> index f2ddced689b5..b1f109f17e4f 100644 >> --- a/arch/arm64/tools/cpucaps >> +++ b/arch/arm64/tools/cpucaps >> @@ -110,7 +110,7 @@ WORKAROUND_HISI_HIP08_RU_PREFETCH >> WORKAROUND_HISILICON_1980005 >> HAS_XCALL >> HAS_XINT >> -KABI_RESERVE_3 >> +HAS_HW_XINT >> KABI_RESERVE_4 >> KABI_RESERVE_5 >> KABI_RESERVE_6 >> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c >> index 4cc8b95d533f..32ffdf06f61e 100644 >> --- a/drivers/irqchip/irq-gic-v3.c >> +++ b/drivers/irqchip/irq-gic-v3.c >> @@ -35,7 +35,7 @@ >> >> #include "irq-gic-common.h" >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> #include "../../../kernel/irq/internals.h" >> #endif >> >> @@ -828,7 +828,7 @@ static bool gic_rpr_is_nmi_prio(void) >> return unlikely(gic_read_rpr() == GICD_INT_RPR_PRI(GICD_INT_NMI_PRI)); >> } >> >> -static bool gic_irqnr_is_special(u32 irqnr) >> +bool gic_irqnr_is_special(u32 irqnr) >> { >> return irqnr >= 1020 && irqnr <= 1023; >> } > > Please don't do this, left it static. > >> @@ -993,7 +993,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs >> __gic_handle_irq_from_irqson(regs); >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +DECLARE_BITMAP(irqnr_nmi_map, 1024); >> +#endif >> + >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> DECLARE_BITMAP(irqnr_xint_map, 1024); >> >> static bool can_set_xint(unsigned int hwirq) >> @@ -1002,12 +1006,18 @@ static bool can_set_xint(unsigned int hwirq) >> __get_intid_range(hwirq) == SPI_RANGE) >> return true; >> >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + if (hw_xint_support && __get_intid_range(hwirq) == PPI_RANGE) >> + return true; >> +#endif >> + >> return false; >> } >> >> static bool xint_transform(int irqno, enum xint_op op) >> { >> struct irq_data *data = irq_get_irq_data(irqno); >> + struct irq_desc *desc; >> int hwirq; >> >> while (data->parent_data) >> @@ -1018,14 +1028,29 @@ static bool xint_transform(int irqno, enum xint_op op) >> if (!can_set_xint(hwirq)) >> return false; >> >> + desc = irq_data_to_desc(data); >> + >> switch (op) { >> case IRQ_TO_XINT: >> set_bit(hwirq, irqnr_xint_map); >> xint_add_debugfs_entry(irqno); >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + if (has_v3_3_nmi() && hw_xint_support && !irq_is_nmi(desc)) { >> + gic_irq_enable_nmi(data); >> + set_bit(hwirq, irqnr_nmi_map); >> + } >> +#endif >> return true; >> case XINT_TO_IRQ: >> clear_bit(hwirq, irqnr_xint_map); >> xint_remove_debugfs_entry(irqno); >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> + if (has_v3_3_nmi() && hw_xint_support && irq_is_nmi(desc) && >> + test_bit(hwirq, irqnr_nmi_map)) { >> + gic_irq_disable_nmi(data); >> + clear_bit(hwirq, irqnr_nmi_map); >> + } >> +#endif >> return false; >> case XINT_SET_CHECK: >> return test_bit(hwirq, irqnr_xint_map); >> @@ -1096,7 +1121,7 @@ static const struct proc_ops xint_proc_ops = { >> >> void register_irqchip_proc(struct irq_desc *desc, void *irqp) >> { >> - if (!is_xint_support) >> + if (!is_xint_support && !hw_xint_support) >> return; >> >> /* create /proc/irq/<irq>/xint */ >> @@ -1105,12 +1130,63 @@ void register_irqchip_proc(struct irq_desc *desc, void *irqp) >> >> void unregister_irqchip_proc(struct irq_desc *desc) >> { >> - if (!is_xint_support) >> + if (!is_xint_support && !hw_xint_support) >> return; >> >> remove_proc_entry("xint", desc->dir); >> } >> -#endif /* CONFIG_FAST_IRQ */ >> +#endif >> + >> +#ifdef CONFIG_ARCH_SUPPORTS_XINT >> +bool is_xint(unsigned long hwirq) >> +{ >> + return test_bit(hwirq, irqnr_xint_map); >> +} >> + >> +static bool is_spi(unsigned long hwirq) >> +{ >> + if (__get_intid_range(hwirq) == SPI_RANGE || >> + __get_intid_range(hwirq) == ESPI_RANGE) >> + return true; >> + >> + return false; >> +} >> + >> +void fast_handle_xint(struct pt_regs *regs, u32 irqnr) >> +{ >> + struct pt_regs *old_regs; >> + struct irq_domain *domain; >> + struct irqaction *action; >> + struct irq_desc *desc; >> + struct irq_data *data; >> + >> + arch_nmi_enter(); >> + BUG_ON(in_nmi() == NMI_MASK); >> + __preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); >> + old_regs = set_irq_regs(regs); >> + >> + domain = irq_get_default_host(); >> + data = radix_tree_lookup(&domain->revmap_tree, irqnr); >> + >> + desc = irq_data_to_desc(data); >> + action = desc->action; >> + >> + gic_read_nmiar(); >> + write_gicreg(irqnr, ICC_EOIR1_EL1); >> + isb(); >> + >> + if (is_spi(irqnr)) >> + action->handler(data->irq, action->dev_id); >> + else >> + action->handler(data->irq, raw_cpu_ptr(action->percpu_dev_id)); >> + gic_write_dir(irqnr); >> + >> + set_irq_regs(old_regs); >> + BUG_ON(!in_nmi()); >> + __preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); >> + arch_nmi_exit(); >> +} >> +#endif >> >> static u32 gic_get_pribits(void) >> { >> @@ -2358,6 +2434,7 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base, >> goto out_free; >> } >> >> + irq_set_default_host(gic_data.domain); >> irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED); >> >> gic_data.has_rss = !!(typer & GICD_TYPER_RSS); >> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h >> index 548b8a5c46cf..3c0f04b86c15 100644 >> --- a/include/linux/irqchip/arm-gic-v3.h >> +++ b/include/linux/irqchip/arm-gic-v3.h >> @@ -721,8 +721,9 @@ static inline enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq) >> } >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> extern bool is_xint_support; >> +extern bool hw_xint_support; >> >> enum xint_op { >> XINT_TO_IRQ, >> @@ -733,6 +734,9 @@ enum xint_op { >> >> void register_irqchip_proc(struct irq_desc *desc, void *irqp); >> void unregister_irqchip_proc(struct irq_desc *desc); >> +bool gic_irqnr_is_special(u32 irqnr); >> +bool is_xint(unsigned long hwirq); >> +void fast_handle_xint(struct pt_regs *regs, u32 irqnr); >> #endif >> #endif >> >> diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c >> index dc94c360b54b..2152125f8ae2 100644 >> --- a/kernel/irq/debugfs.c >> +++ b/kernel/irq/debugfs.c >> @@ -242,7 +242,7 @@ void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc) >> &dfs_irq_ops); >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> static struct dentry *xint_dir; >> >> void xint_add_debugfs_entry(unsigned int irq) >> @@ -281,8 +281,8 @@ static int __init irq_debugfs_init(void) >> >> irq_dir = debugfs_create_dir("irqs", root_dir); >> >> -#ifdef CONFIG_FAST_IRQ >> - if (is_xint_support) >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> + if (is_xint_support || hw_xint_support) >> xint_dir = debugfs_create_dir("xints", root_dir); >> #endif >> >> diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h >> index 2fb08139a9e4..1c64854102f5 100644 >> --- a/kernel/irq/internals.h >> +++ b/kernel/irq/internals.h >> @@ -506,8 +506,9 @@ static inline void irq_remove_debugfs_entry(struct irq_desc *desc) >> kfree(desc->dev_name); >> } >> >> -#ifdef CONFIG_FAST_IRQ >> +#if defined(CONFIG_FAST_IRQ) || defined(CONFIG_ARCH_SUPPORTS_XINT) >> extern bool is_xint_support; >> +extern bool hw_xint_support; >> >> void xint_add_debugfs_entry(unsigned int irq); >> void xint_remove_debugfs_entry(unsigned int irq); >
1 0
0 0
[openeuler:openEuler-1.0-LTS 1513/1513] mm/page_ext.o: warning: objtool: missing symbol for section .init.text
by kernel test robot 25 Mar '25

25 Mar '25
tree: https://gitee.com/openeuler/kernel.git openEuler-1.0-LTS head: 3e8e3ea77f0dd528b080f91d615144093b741003 commit: 5f0e34d2aceec67c169be7599d82f0e8519c37f7 [1513/1513] mm/sparsemem: fix 'mem_section' will never be NULL gcc 12 warning config: x86_64-buildonly-randconfig-005-20250324 (https://download.01.org/0day-ci/archive/20250325/202503251400.xG2WACIP-lkp@…) compiler: clang version 20.1.1 (https://github.com/llvm/llvm-project 424c2d9b7e4de40d0804dd374721e6411c27d1d1) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250325/202503251400.xG2WACIP-lkp@…) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp(a)intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202503251400.xG2WACIP-lkp@intel.com/ All warnings (new ones prefixed by >>): >> mm/page_ext.o: warning: objtool: missing symbol for section .init.text -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
1 0
0 0
[PATCH OLK-6.6] btrfs: do proper folio cleanup when cow_file_range() failed
by Zizhi Wo 25 Mar '25

25 Mar '25
From: Qu Wenruo <wqu(a)suse.com> stable inclusion from stable-v6.13.2 commit 692cf71173bb41395c855acbbbe197d3aedfa5d4 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBPBJV CVE: CVE-2024-57976 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- commit 06f364284794f149d2abc167c11d556cf20c954b upstream. [BUG] When testing with COW fixup marked as BUG_ON() (this is involved with the new pin_user_pages*() change, which should not result new out-of-band dirty pages), I hit a crash triggered by the BUG_ON() from hitting COW fixup path. This BUG_ON() happens just after a failed btrfs_run_delalloc_range(): BTRFS error (device dm-2): failed to run delalloc range, root 348 ino 405 folio 65536 submit_bitmap 6-15 start 90112 len 106496: -28 ------------[ cut here ]------------ kernel BUG at fs/btrfs/extent_io.c:1444! Internal error: Oops - BUG: 00000000f2000800 [#1] SMP CPU: 0 UID: 0 PID: 434621 Comm: kworker/u24:8 Tainted: G OE 6.12.0-rc7-custom+ #86 Hardware name: QEMU KVM Virtual Machine, BIOS unknown 2/2/2022 Workqueue: events_unbound btrfs_async_reclaim_data_space [btrfs] pc : extent_writepage_io+0x2d4/0x308 [btrfs] lr : extent_writepage_io+0x2d4/0x308 [btrfs] Call trace: extent_writepage_io+0x2d4/0x308 [btrfs] extent_writepage+0x218/0x330 [btrfs] extent_write_cache_pages+0x1d4/0x4b0 [btrfs] btrfs_writepages+0x94/0x150 [btrfs] do_writepages+0x74/0x190 filemap_fdatawrite_wbc+0x88/0xc8 start_delalloc_inodes+0x180/0x3b0 [btrfs] btrfs_start_delalloc_roots+0x174/0x280 [btrfs] shrink_delalloc+0x114/0x280 [btrfs] flush_space+0x250/0x2f8 [btrfs] btrfs_async_reclaim_data_space+0x180/0x228 [btrfs] process_one_work+0x164/0x408 worker_thread+0x25c/0x388 kthread+0x100/0x118 ret_from_fork+0x10/0x20 Code: aa1403e1 9402f3ef aa1403e0 9402f36f (d4210000) ---[ end trace 0000000000000000 ]--- [CAUSE] That failure is mostly from cow_file_range(), where we can hit -ENOSPC. Although the -ENOSPC is already a bug related to our space reservation code, let's just focus on the error handling. For example, we have the following dirty range [0, 64K) of an inode, with 4K sector size and 4K page size: 0 16K 32K 48K 64K |///////////////////////////////////////| |#######################################| Where |///| means page are still dirty, and |###| means the extent io tree has EXTENT_DELALLOC flag. - Enter extent_writepage() for page 0 - Enter btrfs_run_delalloc_range() for range [0, 64K) - Enter cow_file_range() for range [0, 64K) - Function btrfs_reserve_extent() only reserved one 16K extent So we created extent map and ordered extent for range [0, 16K) 0 16K 32K 48K 64K |////////|//////////////////////////////| |<- OE ->|##############################| And range [0, 16K) has its delalloc flag cleared. But since we haven't yet submit any bio, involved 4 pages are still dirty. - Function btrfs_reserve_extent() returns with -ENOSPC Now we have to run error cleanup, which will clear all EXTENT_DELALLOC* flags and clear the dirty flags for the remaining ranges: 0 16K 32K 48K 64K |////////| | | | | Note that range [0, 16K) still has its pages dirty. - Some time later, writeback is triggered again for the range [0, 16K) since the page range still has dirty flags. - btrfs_run_delalloc_range() will do nothing because there is no EXTENT_DELALLOC flag. - extent_writepage_io() finds page 0 has no ordered flag Which falls into the COW fixup path, triggering the BUG_ON(). Unfortunately this error handling bug dates back to the introduction of btrfs. Thankfully with the abuse of COW fixup, at least it won't crash the kernel. [FIX] Instead of immediately unlocking the extent and folios, we keep the extent and folios locked until either erroring out or the whole delalloc range finished. When the whole delalloc range finished without error, we just unlock the whole range with PAGE_SET_ORDERED (and PAGE_UNLOCK for !keep_locked cases), with EXTENT_DELALLOC and EXTENT_LOCKED cleared. And the involved folios will be properly submitted, with their dirty flags cleared during submission. For the error path, it will be a little more complex: - The range with ordered extent allocated (range (1)) We only clear the EXTENT_DELALLOC and EXTENT_LOCKED, as the remaining flags are cleaned up by btrfs_mark_ordered_io_finished()->btrfs_finish_one_ordered(). For folios we finish the IO (clear dirty, start writeback and immediately finish the writeback) and unlock the folios. - The range with reserved extent but no ordered extent (range(2)) - The range we never touched (range(3)) For both range (2) and range(3) the behavior is not changed. Now even if cow_file_range() failed halfway with some successfully reserved extents/ordered extents, we will keep all folios clean, so there will be no future writeback triggered on them. CC: stable(a)vger.kernel.org Fixes: 524272607e88 ("btrfs: Handle delalloc error correctly to avoid ordered extent hang") Reviewed-by: Boris Burkov <boris(a)bur.io> Signed-off-by: Qu Wenruo <wqu(a)suse.com> Signed-off-by: David Sterba <dsterba(a)suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org> Conflicts: fs/btrfs/inode.c [Some context conflicts are encountered when adapting: 1. ram_size -> cur_size: 5599f39356c6 ("btrfs: simplify range tracking in cow_file_range()"), just simplify the process and do not affect the logic. 2. There is no lock_extent related code: 0ab540995ae0 ("btrfs: push lock_extent into cow_file_range_inline")\a0766d8f35d8 ("btrfs: push extent lock into cow_file_range"), this is to narrow the scope of lock, but does not affect this patch. 3. extent_clear_unlock_delalloc() missed a parameter named "cached": 6b0a63a4fa31 ("btrfs: add a cached state to extent_clear_unlock_delalloc"), does not affect this patch.] Signed-off-by: Zizhi Wo <wozizhi(a)huawei.com> --- fs/btrfs/inode.c | 54 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 71902110c2fe..862cc8703bf0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1356,6 +1356,17 @@ static noinline int cow_file_range(struct btrfs_inode *inode, alloc_hint = get_extent_allocation_hint(inode, start, num_bytes); + /* + * We're not doing compressed IO, don't unlock the first page (which + * the caller expects to stay locked), don't clear any dirty bits and + * don't set any writeback bits. + * + * Do set the Ordered (Private2) bit so we know this page was properly + * setup for writepage. + */ + page_ops = (keep_locked ? 0 : PAGE_UNLOCK); + page_ops |= PAGE_SET_ORDERED; + /* * Relocation relies on the relocated extents to have exactly the same * size as the original extents. Normally writeback for relocation data @@ -1456,21 +1467,6 @@ static noinline int cow_file_range(struct btrfs_inode *inode, btrfs_dec_block_group_reservations(fs_info, ins.objectid); - /* - * We're not doing compressed IO, don't unlock the first page - * (which the caller expects to stay locked), don't clear any - * dirty bits and don't set any writeback bits - * - * Do set the Ordered (Private2) bit so we know this page was - * properly setup for writepage. - */ - page_ops = (keep_locked ? 0 : PAGE_UNLOCK); - page_ops |= PAGE_SET_ORDERED; - - extent_clear_unlock_delalloc(inode, start, start + ram_size - 1, - locked_page, - EXTENT_LOCKED | EXTENT_DELALLOC, - page_ops); if (num_bytes < cur_alloc_size) num_bytes = 0; else @@ -1487,6 +1483,8 @@ static noinline int cow_file_range(struct btrfs_inode *inode, if (ret) goto out_unlock; } + extent_clear_unlock_delalloc(inode, orig_start, end, locked_page, + EXTENT_LOCKED | EXTENT_DELALLOC, page_ops); done: if (done_offset) *done_offset = end; @@ -1507,29 +1505,31 @@ static noinline int cow_file_range(struct btrfs_inode *inode, * We process each region below. */ - clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | - EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV; - page_ops = PAGE_UNLOCK | PAGE_START_WRITEBACK | PAGE_END_WRITEBACK; - /* * For the range (1). We have already instantiated the ordered extents * for this region. They are cleaned up by * btrfs_cleanup_ordered_extents() in e.g, - * btrfs_run_delalloc_range(). EXTENT_LOCKED | EXTENT_DELALLOC are - * already cleared in the above loop. And, EXTENT_DELALLOC_NEW | - * EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV are handled by the cleanup - * function. + * btrfs_run_delalloc_range(). + * EXTENT_DELALLOC_NEW | EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV + * are also handled by the cleanup function. * - * However, in case of @keep_locked, we still need to unlock the pages - * (except @locked_page) to ensure all the pages are unlocked. + * So here we only clear EXTENT_LOCKED and EXTENT_DELALLOC flag, and + * finish the writeback of the involved folios, which will be never submitted. */ - if (keep_locked && orig_start < start) { + if (orig_start < start) { + clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC; + page_ops = PAGE_UNLOCK | PAGE_START_WRITEBACK | PAGE_END_WRITEBACK; + if (!locked_page) mapping_set_error(inode->vfs_inode.i_mapping, ret); extent_clear_unlock_delalloc(inode, orig_start, start - 1, - locked_page, 0, page_ops); + locked_page, clear_bits, page_ops); } + clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | + EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV; + page_ops = PAGE_UNLOCK | PAGE_START_WRITEBACK | PAGE_END_WRITEBACK; + /* * For the range (2). If we reserved an extent for our delalloc range * (or a subrange) and failed to create the respective ordered extent, -- 2.39.2
2 1
0 0
  • ← Newer
  • 1
  • ...
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • ...
  • 2004
  • Older →

HyperKitty Powered by HyperKitty