From: Sumit Garg sumit.garg@linaro.org
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8PLUM?from=project-issue CVE: NA Reference: https://lore.kernel.org/all/1604317487-14543-5-git-send-email-sumit.garg@lin...
-------------------------------------------------
Add a boolean return to arch_trigger_cpumask_backtrace() to support a use-case where a particular architecture detects at runtime if it supports NMI backtrace or it would like to fallback to default implementation using SMP cross-calls.
Currently such an architecture example is arm64 supporting pseudo NMIs feature which is only available on platforms which have support for GICv3 or later version.
Signed-off-by: Sumit Garg sumit.garg@linaro.org Signed-off-by: Wei Li liwei391@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Signed-off-by: Ruan Jinjie ruanjinjie@huawei.com Signed-off-by: Liao Chen liaochen4@huawei.com --- arch/arm/include/asm/irq.h | 2 +- arch/arm/kernel/smp.c | 3 ++- arch/arm64/kernel/Makefile | 2 +- arch/mips/include/asm/irq.h | 2 +- arch/mips/kernel/process.c | 3 ++- arch/powerpc/include/asm/irq.h | 2 +- arch/powerpc/include/asm/nmi.h | 6 ++++++ arch/powerpc/kernel/stacktrace.c | 3 ++- arch/sparc/include/asm/irq_64.h | 2 +- arch/sparc/kernel/process_64.c | 4 +++- arch/x86/include/asm/irq.h | 2 +- arch/x86/kernel/apic/hw_nmi.c | 3 ++- include/linux/nmi.h | 12 ++++-------- 13 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h index 26c1d2ced4ce..d7635f746100 100644 --- a/arch/arm/include/asm/irq.h +++ b/arch/arm/include/asm/irq.h @@ -31,7 +31,7 @@ void handle_IRQ(unsigned int, struct pt_regs *); #ifdef CONFIG_SMP #include <linux/cpumask.h>
-extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask, +extern bool arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu); #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace #endif diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 3431c0553f45..9ffc6c2536fa 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -846,7 +846,8 @@ static void raise_nmi(cpumask_t *mask) __ipi_send_mask(ipi_desc[IPI_CPU_BACKTRACE], mask); }
-void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) +bool arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) { nmi_trigger_cpumask_backtrace(mask, exclude_cpu, raise_nmi); + return true; } diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 59fa5d6e6f3e..187685f57980 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -34,7 +34,7 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \ cpufeature.o alternative.o cacheinfo.o \ smp.o smp_spin_table.o topology.o smccc-call.o \ syscall.o proton-pack.o idreg-override.o idle.o \ - patching.o + patching.o ipi_nmi.o
obj-$(CONFIG_AARCH32_EL0) += binfmt_elf32.o sys32.o signal32.o \ sys_compat.o diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index 3a848e7e69f7..7923ba290e2d 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -76,7 +76,7 @@ extern int cp0_fdc_irq;
extern int get_c0_fdc_int(void);
-void arch_trigger_cpumask_backtrace(const struct cpumask *mask, +bool arch_trigger_cpumask_backtrace(const struct cpumask *mask, int exclude_cpu); #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 5387ed0a5186..e2e57dde2570 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -750,9 +750,10 @@ static void raise_backtrace(cpumask_t *mask) } }
-void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) +bool arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) { nmi_trigger_cpumask_backtrace(mask, exclude_cpu, raise_backtrace); + return true; }
int mips_get_process_fp_mode(struct task_struct *task) diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index ba1a5974e714..3acfa52e436b 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h @@ -54,7 +54,7 @@ void __do_IRQ(struct pt_regs *regs); int irq_choose_cpu(const struct cpumask *mask);
#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_NMI_IPI) -extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask, +extern bool arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu); #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace #endif diff --git a/arch/powerpc/include/asm/nmi.h b/arch/powerpc/include/asm/nmi.h index 49a75340c3e0..f74ef55ac986 100644 --- a/arch/powerpc/include/asm/nmi.h +++ b/arch/powerpc/include/asm/nmi.h @@ -9,6 +9,12 @@ void watchdog_hardlockup_set_timeout_pct(u64 pct); static inline void watchdog_hardlockup_set_timeout_pct(u64 pct) {} #endif
+#ifdef CONFIG_NMI_IPI +extern bool arch_trigger_cpumask_backtrace(const cpumask_t *mask, + int exclude_cpu); +#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace +#endif + extern void hv_nmi_check_nonrecoverable(struct pt_regs *regs);
#endif /* _ASM_NMI_H */ diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c index e6a958a5da27..3d1c373c1cee 100644 --- a/arch/powerpc/kernel/stacktrace.c +++ b/arch/powerpc/kernel/stacktrace.c @@ -204,8 +204,9 @@ static void raise_backtrace_ipi(cpumask_t *mask) } }
-void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) +bool arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) { nmi_trigger_cpumask_backtrace(mask, exclude_cpu, raise_backtrace_ipi); + return true; } #endif /* defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_NMI_IPI) */ diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index 8c4c0c87f998..4daf26697100 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h @@ -86,7 +86,7 @@ static inline unsigned long get_softint(void) return retval; }
-void arch_trigger_cpumask_backtrace(const struct cpumask *mask, +bool arch_trigger_cpumask_backtrace(const struct cpumask *mask, int exclude_cpu); #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index 529adfecd58c..5bcb86ec0c07 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -236,7 +236,7 @@ static void __global_reg_poll(struct global_reg_snapshot *gp) } }
-void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) +bool arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) { struct thread_info *tp = current_thread_info(); struct pt_regs *regs = get_irq_regs(); @@ -291,6 +291,8 @@ void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags); + + return true; }
#ifdef CONFIG_MAGIC_SYSRQ diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 836c170d3087..e1cadd9a439d 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -41,7 +41,7 @@ extern void __handle_irq(struct irq_desc *desc, struct pt_regs *regs); extern void init_ISA_irqs(void);
#ifdef CONFIG_X86_LOCAL_APIC -void arch_trigger_cpumask_backtrace(const struct cpumask *mask, +bool arch_trigger_cpumask_backtrace(const struct cpumask *mask, int exclude_cpu);
#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c index 45af535c44a0..3c7ebee0d491 100644 --- a/arch/x86/kernel/apic/hw_nmi.c +++ b/arch/x86/kernel/apic/hw_nmi.c @@ -36,10 +36,11 @@ static void nmi_raise_cpu_backtrace(cpumask_t *mask) __apic_send_IPI_mask(mask, NMI_VECTOR); }
-void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) +bool arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) { nmi_trigger_cpumask_backtrace(mask, exclude_cpu, nmi_raise_cpu_backtrace); + return true; }
static int nmi_cpu_backtrace_handler(unsigned int cmd, struct pt_regs *regs) diff --git a/include/linux/nmi.h b/include/linux/nmi.h index 7bd446acad24..692f2759be55 100644 --- a/include/linux/nmi.h +++ b/include/linux/nmi.h @@ -157,26 +157,22 @@ static inline void touch_nmi_watchdog(void) #ifdef arch_trigger_cpumask_backtrace static inline bool trigger_all_cpu_backtrace(void) { - arch_trigger_cpumask_backtrace(cpu_online_mask, -1); - return true; + return arch_trigger_cpumask_backtrace(cpu_online_mask, -1); }
static inline bool trigger_allbutcpu_cpu_backtrace(int exclude_cpu) { - arch_trigger_cpumask_backtrace(cpu_online_mask, exclude_cpu); - return true; + return arch_trigger_cpumask_backtrace(cpu_online_mask, exclude_cpu); }
static inline bool trigger_cpumask_backtrace(struct cpumask *mask) { - arch_trigger_cpumask_backtrace(mask, -1); - return true; + return arch_trigger_cpumask_backtrace(mask, -1); }
static inline bool trigger_single_cpu_backtrace(int cpu) { - arch_trigger_cpumask_backtrace(cpumask_of(cpu), -1); - return true; + return arch_trigger_cpumask_backtrace(cpumask_of(cpu), -1); }
/* generic implementation */