Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

LoongArch: Handle percpu handler address for ORC unwinder

After commit 4cd641a79e69 ("LoongArch: Remove unnecessary checks for ORC
unwinder"), the system can not boot normally under some configs (such as
enable KASAN), there are many error messages "cannot find unwind pc".

The kernel boots normally with the defconfig, so no problem found out at
the first time. Here is one way to reproduce:

cd linux
make mrproper defconfig -j"$(nproc)"
scripts/config -e KASAN
make olddefconfig all -j"$(nproc)"
sudo make modules_install
sudo make install
sudo reboot

The address that can not unwind is not a valid kernel address which is
between "pcpu_handlers[cpu]" and "pcpu_handlers[cpu] + vec_sz" due to
the code of eentry was copied to the new area of pcpu_handlers[cpu] in
setup_tlb_handler(), handle this special case to get the valid address
to unwind normally.

Cc: stable@vger.kernel.org
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

authored by

Tiezhu Yang and committed by
Huacai Chen
055c7e75 77403a06

+19
+3
arch/loongarch/include/asm/setup.h
··· 7 7 #define _LOONGARCH_SETUP_H 8 8 9 9 #include <linux/types.h> 10 + #include <linux/threads.h> 10 11 #include <asm/sections.h> 11 12 #include <uapi/asm/setup.h> 12 13 ··· 15 14 16 15 extern unsigned long eentry; 17 16 extern unsigned long tlbrentry; 17 + extern unsigned long pcpu_handlers[NR_CPUS]; 18 + extern long exception_handlers[VECSIZE * 128 / sizeof(long)]; 18 19 extern char init_command_line[COMMAND_LINE_SIZE]; 19 20 extern void tlb_init(int cpu); 20 21 extern void cpu_cache_init(void);
+16
arch/loongarch/kernel/unwind_orc.c
··· 352 352 { 353 353 extern unsigned long eentry; 354 354 355 + #if defined(CONFIG_NUMA) && !defined(CONFIG_PREEMPT_RT) 356 + int cpu; 357 + int vec_sz = sizeof(exception_handlers); 358 + 359 + for_each_possible_cpu(cpu) { 360 + if (!pcpu_handlers[cpu]) 361 + continue; 362 + 363 + if (ra >= pcpu_handlers[cpu] && 364 + ra < pcpu_handlers[cpu] + vec_sz) { 365 + ra = ra + eentry - pcpu_handlers[cpu]; 366 + break; 367 + } 368 + } 369 + #endif 370 + 355 371 if (ra >= eentry && ra < eentry + EXCCODE_INT_END * VECSIZE) { 356 372 unsigned long func; 357 373 unsigned long type = (ra - eentry) / VECSIZE;