From 851f615186597fc6b70e5aa6536868866ff4bee9 Mon Sep 17 00:00:00 2001 From: Oscar Salvador Date: Apr 25 2024 07:33:29 +0000 Subject: Merge remote-tracking branch 'origin/users/msuchanek/SLE15-SP5/for-next' into SLE15-SP5 Pull powerpc fixes from Michal Suchanek --- diff --git a/patches.suse/powerpc-64s-Fix-unrecoverable-MCE-calling-async-hand.patch b/patches.suse/powerpc-64s-Fix-unrecoverable-MCE-calling-async-hand.patch index 5ca4690..991b1ef 100644 --- a/patches.suse/powerpc-64s-Fix-unrecoverable-MCE-calling-async-hand.patch +++ b/patches.suse/powerpc-64s-Fix-unrecoverable-MCE-calling-async-hand.patch @@ -1,15 +1,12 @@ -From d7a8e38999fbd6910516e44cb43f9f4317e54f73 Mon Sep 17 00:00:00 2001 +From f08fb25bc66986b0952724530a640d9970fa52c1 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Tue, 5 Oct 2021 00:56:42 +1000 -Subject: [PATCH] powerpc/64s: Fix unrecoverable MCE calling async handler from NMI -Mime-version: 1.0 -Content-type: text/plain; charset=UTF-8 -Content-transfer-encoding: 8bit -Git-commit: f08fb25bc66986b0952724530a640d9970fa52c1 -Patch-mainline: v5.15-rc5 -References: stable-5.14.12 +Subject: [PATCH] powerpc/64s: Fix unrecoverable MCE calling async handler from + NMI -[ Upstream commit f08fb25bc66986b0952724530a640d9970fa52c1 ] +References: stable-5.14.12 +Patch-mainline: v5.15-rc5 +Git-commit: f08fb25bc66986b0952724530a640d9970fa52c1 The machine check handler is not considered NMI on 64s. The early handler is the true NMI handler, and then it schedules the @@ -33,9 +30,7 @@ Signed-off-by: Nicholas Piggin Tested-by: Cédric Le Goater Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20211004145642.1331214-6-npiggin@gmail.com -Signed-off-by: Sasha Levin Acked-by: Takashi Iwai - --- arch/powerpc/include/asm/interrupt.h | 5 ++--- arch/powerpc/kernel/exceptions-64s.S | 8 +++++-- @@ -43,10 +38,10 @@ Acked-by: Takashi Iwai 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h -index 6b800d3e2681..a925dbc5833c 100644 +index b894b7169706..a1d238255f07 100644 --- a/arch/powerpc/include/asm/interrupt.h +++ b/arch/powerpc/include/asm/interrupt.h -@@ -525,10 +525,9 @@ static __always_inline long ____##func(struct pt_regs *regs) +@@ -528,10 +528,9 @@ static __always_inline long ____##func(struct pt_regs *regs) /* kernel/traps.c */ DECLARE_INTERRUPT_HANDLER_NMI(system_reset_exception); #ifdef CONFIG_PPC_BOOK3S_64 @@ -86,10 +81,10 @@ index 024d9231f88c..eaf1f72131a1 100644 bl machine_check_exception diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c -index 4ac85ab15ad7..08356ec9bfed 100644 +index e453b666613b..11741703d26e 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c -@@ -797,24 +797,22 @@ void die_mce(const char *str, struct pt_regs *regs, long err) +@@ -796,24 +796,22 @@ void die_mce(const char *str, struct pt_regs *regs, long err) * do_exit() checks for in_interrupt() and panics in that case, so * exit the irq/nmi before calling die. */ @@ -122,9 +117,9 @@ index 4ac85ab15ad7..08356ec9bfed 100644 { int recover = 0; -@@ -848,12 +846,19 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception) +@@ -847,12 +845,19 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception) /* Must die if the interrupt is not recoverable */ - if (!(regs->msr & MSR_RI)) + if (regs_is_unrecoverable(regs)) die_mce("Unrecoverable Machine check", regs, SIGBUS); +} @@ -146,5 +141,5 @@ index 4ac85ab15ad7..08356ec9bfed 100644 DEFINE_INTERRUPT_HANDLER(SMIException) /* async? */ -- -2.26.2 +2.44.0 diff --git a/patches.suse/powerpc-Avoid-nmi_enter-nmi_exit-in-real-mode-interr.patch b/patches.suse/powerpc-Avoid-nmi_enter-nmi_exit-in-real-mode-interr.patch new file mode 100644 index 0000000..83c7b33 --- /dev/null +++ b/patches.suse/powerpc-Avoid-nmi_enter-nmi_exit-in-real-mode-interr.patch @@ -0,0 +1,116 @@ +From 0db880fc865ffb522141ced4bfa66c12ab1fbb70 Mon Sep 17 00:00:00 2001 +From: Mahesh Salgaonkar +Date: Wed, 10 Apr 2024 10:00:06 +0530 +Subject: [PATCH] powerpc: Avoid nmi_enter/nmi_exit in real mode interrupt. + +References: bsc#1221645 ltc#205739 bsc#1223191 +Patch-mainline: queued +Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git +Git-commit: 0db880fc865ffb522141ced4bfa66c12ab1fbb70 + +nmi_enter()/nmi_exit() touches per cpu variables which can lead to kernel +crash when invoked during real mode interrupt handling (e.g. early HMI/MCE +interrupt handler) if percpu allocation comes from vmalloc area. + +Early HMI/MCE handlers are called through DEFINE_INTERRUPT_HANDLER_NMI() +wrapper which invokes nmi_enter/nmi_exit calls. We don't see any issue when +percpu allocation is from the embedded first chunk. However with +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK enabled there are chances where percpu +allocation can come from the vmalloc area. + +With kernel command line "percpu_alloc=page" we can force percpu allocation +to come from vmalloc area and can see kernel crash in machine_check_early: + +[ 1.215714] NIP [c000000000e49eb4] rcu_nmi_enter+0x24/0x110 +[ 1.215717] LR [c0000000000461a0] machine_check_early+0xf0/0x2c0 +[ 1.215719] --- interrupt: 200 +[ 1.215720] [c000000fffd73180] [0000000000000000] 0x0 (unreliable) +[ 1.215722] [c000000fffd731b0] [0000000000000000] 0x0 +[ 1.215724] [c000000fffd73210] [c000000000008364] machine_check_early_common+0x134/0x1f8 + +Fix this by avoiding use of nmi_enter()/nmi_exit() in real mode if percpu +first chunk is not embedded. + +Reviewed-by: Christophe Leroy +Tested-by: Shirisha Ganta +Signed-off-by: Mahesh Salgaonkar +Signed-off-by: Michael Ellerman +Link: https://msgid.link/20240410043006.81577-1-mahesh@linux.ibm.com +Acked-by: Michal Suchanek +--- + arch/powerpc/include/asm/interrupt.h | 10 ++++++++++ + arch/powerpc/include/asm/percpu.h | 10 ++++++++++ + arch/powerpc/kernel/setup_64.c | 2 ++ + 3 files changed, 22 insertions(+) + +diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h +index 7b610864b364..2d6c886b40f4 100644 +--- a/arch/powerpc/include/asm/interrupt.h ++++ b/arch/powerpc/include/asm/interrupt.h +@@ -336,6 +336,14 @@ static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct inte + if (IS_ENABLED(CONFIG_KASAN)) + return; + ++ /* ++ * Likewise, do not use it in real mode if percpu first chunk is not ++ * embedded. With CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK enabled there ++ * are chances where percpu allocation can come from vmalloc area. ++ */ ++ if (percpu_first_chunk_is_paged) ++ return; ++ + /* Otherwise, it should be safe to call it */ + nmi_enter(); + } +@@ -351,6 +359,8 @@ static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct inter + // no nmi_exit for a pseries hash guest taking a real mode exception + } else if (IS_ENABLED(CONFIG_KASAN)) { + // no nmi_exit for KASAN in real mode ++ } else if (percpu_first_chunk_is_paged) { ++ // no nmi_exit if percpu first chunk is not embedded + } else { + nmi_exit(); + } +diff --git a/arch/powerpc/include/asm/percpu.h b/arch/powerpc/include/asm/percpu.h +index 8e5b7d0b851c..634970ce13c6 100644 +--- a/arch/powerpc/include/asm/percpu.h ++++ b/arch/powerpc/include/asm/percpu.h +@@ -15,6 +15,16 @@ + #endif /* CONFIG_SMP */ + #endif /* __powerpc64__ */ + ++#if defined(CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK) && defined(CONFIG_SMP) ++#include ++DECLARE_STATIC_KEY_FALSE(__percpu_first_chunk_is_paged); ++ ++#define percpu_first_chunk_is_paged \ ++ (static_key_enabled(&__percpu_first_chunk_is_paged.key)) ++#else ++#define percpu_first_chunk_is_paged false ++#endif /* CONFIG_PPC64 && CONFIG_SMP */ ++ + #include + + #include +diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -834,6 +834,7 @@ static __init int pcpu_cpu_to_node(int cpu) + + unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; + EXPORT_SYMBOL(__per_cpu_offset); ++DEFINE_STATIC_KEY_FALSE(__percpu_first_chunk_is_paged); + + static void __init pcpu_populate_pte(unsigned long addr) + { +@@ -876,6 +877,7 @@ void __init setup_per_cpu_areas(void) + if (rc < 0) + panic("cannot initialize percpu area (err=%d)", rc); + ++ static_key_enable(&__percpu_first_chunk_is_paged.key); + delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; + for_each_possible_cpu(cpu) { + __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu]; +-- +2.44.0 + diff --git a/patches.suse/powerpc-Refactor-verification-of-MSR_RI.patch b/patches.suse/powerpc-Refactor-verification-of-MSR_RI.patch new file mode 100644 index 0000000..b4159a6 --- /dev/null +++ b/patches.suse/powerpc-Refactor-verification-of-MSR_RI.patch @@ -0,0 +1,291 @@ +From 806c0e6e7e97adc17389c8dc1f52d4736f49299b Mon Sep 17 00:00:00 2001 +From: Christophe Leroy +Date: Mon, 23 Aug 2021 08:24:21 +0000 +Subject: [PATCH] powerpc: Refactor verification of MSR_RI + +References: bsc#1223191 +Patch-mainline: v5.15-rc1 +Git-commit: 806c0e6e7e97adc17389c8dc1f52d4736f49299b + +40x and BOOKE don't have MSR_RI therefore all tests involving +MSR_RI may be problematic on those plateforms. + +Create helpers to check or set MSR_RI in regs, and use them +in common code. + +Missing commit 133c17a1788d ("powerpc: Remove MSR_PR check in interrupt_exit_{user/kernel}_prepare()") + +Signed-off-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/c2fb93708196734f4176dda334aaa3055f213b89.1629707037.git.christophe.leroy@csgroup.eu +Acked-by: Michal Suchanek +--- + arch/powerpc/include/asm/ptrace.h | 23 +++++++++++++++++++ + arch/powerpc/kernel/interrupt.c | 9 +++----- + arch/powerpc/kernel/traps.c | 8 +++---- + arch/powerpc/mm/book3s64/slb.c | 2 +- + arch/powerpc/platforms/embedded6xx/holly.c | 2 +- + .../platforms/embedded6xx/mpc7448_hpc2.c | 2 +- + arch/powerpc/platforms/pasemi/idle.c | 2 +- + arch/powerpc/platforms/powernv/opal.c | 2 +- + arch/powerpc/platforms/pseries/ras.c | 2 +- + arch/powerpc/sysdev/fsl_rio.c | 2 +- + arch/powerpc/xmon/xmon.c | 16 +++---------- + 11 files changed, 40 insertions(+), 30 deletions(-) + +diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h +index 5114ddba6f16..f9c235c1d6ce 100644 +--- a/arch/powerpc/include/asm/ptrace.h ++++ b/arch/powerpc/include/asm/ptrace.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #ifndef __ASSEMBLY__ + struct pt_regs +@@ -272,6 +273,28 @@ static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) + regs->gpr[3] = rc; + } + ++static inline bool cpu_has_msr_ri(void) ++{ ++ return !IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x); ++} ++ ++static inline bool regs_is_unrecoverable(struct pt_regs *regs) ++{ ++ return unlikely(cpu_has_msr_ri() && !(regs->msr & MSR_RI)); ++} ++ ++static inline void regs_set_recoverable(struct pt_regs *regs) ++{ ++ if (cpu_has_msr_ri()) ++ regs_set_return_msr(regs, regs->msr | MSR_RI); ++} ++ ++static inline void regs_set_unrecoverable(struct pt_regs *regs) ++{ ++ if (cpu_has_msr_ri()) ++ regs_set_return_msr(regs, regs->msr & ~MSR_RI); ++} ++ + #define arch_has_single_step() (1) + #define arch_has_block_step() (true) + #define ARCH_HAS_USER_SINGLE_STEP_REPORT +diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c +--- a/arch/powerpc/kernel/interrupt.c ++++ b/arch/powerpc/kernel/interrupt.c +@@ -92,8 +92,7 @@ notrace long system_call_exception(long r3, long r4, long r5, + CT_WARN_ON(ct_state() == CONTEXT_KERNEL); + user_exit_irqoff(); + +- if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x)) +- BUG_ON(!(regs->msr & MSR_RI)); ++ BUG_ON(regs_is_unrecoverable(regs)); + BUG_ON(!(regs->msr & MSR_PR)); + BUG_ON(arch_irq_disabled_regs(regs)); + +@@ -462,8 +461,7 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs) + { + unsigned long ret; + +- if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x)) +- BUG_ON(!(regs->msr & MSR_RI)); ++ BUG_ON(regs_is_unrecoverable(regs)); + BUG_ON(!(regs->msr & MSR_PR)); + BUG_ON(arch_irq_disabled_regs(regs)); + CT_WARN_ON(ct_state() == CONTEXT_USER); +@@ -494,8 +492,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs) + bool stack_store = current_thread_info()->flags & + _TIF_EMULATE_STACK_STORE; + +- if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x) && +- unlikely(!(regs->msr & MSR_RI))) ++ if (regs_is_unrecoverable(regs)) + unrecoverable_exception(regs); + BUG_ON(regs->msr & MSR_PR); + /* +diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c +index 5463d201d465..3a344f5265c2 100644 +--- a/arch/powerpc/kernel/traps.c ++++ b/arch/powerpc/kernel/traps.c +@@ -428,7 +428,7 @@ void hv_nmi_check_nonrecoverable(struct pt_regs *regs) + return; + + nonrecoverable: +- regs_set_return_msr(regs, regs->msr & ~MSR_RI); ++ regs_set_unrecoverable(regs); + #endif + } + DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception) +@@ -498,7 +498,7 @@ DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception) + die("Unrecoverable nested System Reset", regs, SIGABRT); + #endif + /* Must die if the interrupt is not recoverable */ +- if (!(regs->msr & MSR_RI)) { ++ if (regs_is_unrecoverable(regs)) { + /* For the reason explained in die_mce, nmi_exit before die */ + nmi_exit(); + die("Unrecoverable System Reset", regs, SIGABRT); +@@ -550,7 +550,7 @@ static inline int check_io_access(struct pt_regs *regs) + printk(KERN_DEBUG "%s bad port %lx at %p\n", + (*nip & 0x100)? "OUT to": "IN from", + regs->gpr[rb] - _IO_BASE, nip); +- regs_set_return_msr(regs, regs->msr | MSR_RI); ++ regs_set_recoverable(regs); + regs_set_return_ip(regs, extable_fixup(entry)); + return 1; + } +@@ -840,7 +840,7 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception) + + bail: + /* Must die if the interrupt is not recoverable */ +- if (!(regs->msr & MSR_RI)) ++ if (regs_is_unrecoverable(regs)) + die_mce("Unrecoverable Machine check", regs, SIGBUS); + + #ifdef CONFIG_PPC_BOOK3S_64 +diff --git a/arch/powerpc/mm/book3s64/slb.c b/arch/powerpc/mm/book3s64/slb.c +index c91bd85eb90e..f0037bcc47a0 100644 +--- a/arch/powerpc/mm/book3s64/slb.c ++++ b/arch/powerpc/mm/book3s64/slb.c +@@ -822,7 +822,7 @@ DEFINE_INTERRUPT_HANDLER_RAW(do_slb_fault) + /* IRQs are not reconciled here, so can't check irqs_disabled */ + VM_WARN_ON(mfmsr() & MSR_EE); + +- if (unlikely(!(regs->msr & MSR_RI))) ++ if (regs_is_unrecoverable(regs)) + return -EINVAL; + + /* +diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c +index 85521b3e7098..7a85b117f7a4 100644 +--- a/arch/powerpc/platforms/embedded6xx/holly.c ++++ b/arch/powerpc/platforms/embedded6xx/holly.c +@@ -251,7 +251,7 @@ static int ppc750_machine_check_exception(struct pt_regs *regs) + /* Are we prepared to handle this fault */ + if ((entry = search_exception_tables(regs->nip)) != NULL) { + tsi108_clear_pci_cfg_error(); +- regs_set_return_msr(regs, regs->msr | MSR_RI); ++ regs_set_recoverable(regs); + regs_set_return_ip(regs, extable_fixup(entry)); + return 1; + } +diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +index d8da6a483e59..9eb9abb5bce2 100644 +--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c ++++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +@@ -173,7 +173,7 @@ static int mpc7448_machine_check_exception(struct pt_regs *regs) + /* Are we prepared to handle this fault */ + if ((entry = search_exception_tables(regs->nip)) != NULL) { + tsi108_clear_pci_cfg_error(); +- regs_set_return_msr(regs, regs->msr | MSR_RI); ++ regs_set_recoverable(regs); + regs_set_return_ip(regs, extable_fixup(entry)); + return 1; + } +diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c +index 9b88e3cded7d..2a5b84268b77 100644 +--- a/arch/powerpc/platforms/pasemi/idle.c ++++ b/arch/powerpc/platforms/pasemi/idle.c +@@ -58,7 +58,7 @@ static int pasemi_system_reset_exception(struct pt_regs *regs) + restore_astate(hard_smp_processor_id()); + + /* everything handled */ +- regs_set_return_msr(regs, regs->msr | MSR_RI); ++ regs_set_recoverable(regs); + return 1; + } + +diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c +index 2835376e61a4..e9d18519e650 100644 +--- a/arch/powerpc/platforms/powernv/opal.c ++++ b/arch/powerpc/platforms/powernv/opal.c +@@ -588,7 +588,7 @@ static int opal_recover_mce(struct pt_regs *regs, + { + int recovered = 0; + +- if (!(regs->msr & MSR_RI)) { ++ if (regs_is_unrecoverable(regs)) { + /* If MSR_RI isn't set, we cannot recover */ + pr_err("Machine check interrupt unrecoverable: MSR(RI=0)\n"); + recovered = 0; +diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c +index 167f2e1b8d39..56092dccfdb8 100644 +--- a/arch/powerpc/platforms/pseries/ras.c ++++ b/arch/powerpc/platforms/pseries/ras.c +@@ -783,7 +783,7 @@ static int recover_mce(struct pt_regs *regs, struct machine_check_event *evt) + { + int recovered = 0; + +- if (!(regs->msr & MSR_RI)) { ++ if (regs_is_unrecoverable(regs)) { + /* If MSR_RI isn't set, we cannot recover */ + pr_err("Machine check interrupt unrecoverable: MSR(RI=0)\n"); + recovered = 0; +diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c +index 5a95b8ea23d8..ff7906b48ca1 100644 +--- a/arch/powerpc/sysdev/fsl_rio.c ++++ b/arch/powerpc/sysdev/fsl_rio.c +@@ -108,7 +108,7 @@ int fsl_rio_mcheck_exception(struct pt_regs *regs) + __func__); + out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), + 0); +- regs_set_return_msr(regs, regs->msr | MSR_RI); ++ regs_set_recoverable(regs); + regs_set_return_ip(regs, extable_fixup(entry)); + return 1; + } +diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c +index ead460b80905..dd8241c009e5 100644 +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -482,16 +482,6 @@ static inline void get_output_lock(void) {} + static inline void release_output_lock(void) {} + #endif + +-static inline int unrecoverable_excp(struct pt_regs *regs) +-{ +-#if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E) +- /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */ +- return 0; +-#else +- return ((regs->msr & MSR_RI) == 0); +-#endif +-} +- + static void xmon_touch_watchdogs(void) + { + touch_softlockup_watchdog_sync(); +@@ -565,7 +555,7 @@ static int xmon_core(struct pt_regs *regs, volatile int fromipi) + bp = NULL; + if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) + bp = at_breakpoint(regs->nip); +- if (bp || unrecoverable_excp(regs)) ++ if (bp || regs_is_unrecoverable(regs)) + fromipi = 0; + + if (!fromipi) { +@@ -577,7 +567,7 @@ static int xmon_core(struct pt_regs *regs, volatile int fromipi) + cpu, BP_NUM(bp)); + xmon_print_symbol(regs->nip, " ", ")\n"); + } +- if (unrecoverable_excp(regs)) ++ if (regs_is_unrecoverable(regs)) + printf("WARNING: exception is not recoverable, " + "can't continue\n"); + release_output_lock(); +@@ -693,7 +683,7 @@ static int xmon_core(struct pt_regs *regs, volatile int fromipi) + printf("Stopped at breakpoint %tx (", BP_NUM(bp)); + xmon_print_symbol(regs->nip, " ", ")\n"); + } +- if (unrecoverable_excp(regs)) ++ if (regs_is_unrecoverable(regs)) + printf("WARNING: exception is not recoverable, " + "can't continue\n"); + remove_bpts(); +-- +2.44.0 + diff --git a/patches.suse/powerpc-kasan-Don-t-instrument-non-maskable-or-raw-i.patch b/patches.suse/powerpc-kasan-Don-t-instrument-non-maskable-or-raw-i.patch new file mode 100644 index 0000000..b6d8cf7 --- /dev/null +++ b/patches.suse/powerpc-kasan-Don-t-instrument-non-maskable-or-raw-i.patch @@ -0,0 +1,269 @@ +From 5352090a999570c6e8a701bcb755fd91e8c5a2cd Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Wed, 18 May 2022 20:06:17 +1000 +Subject: [PATCH] powerpc/kasan: Don't instrument non-maskable or raw + interrupts + +References: bsc#1223191 +Patch-mainline: v5.19-rc1 +Git-commit: 5352090a999570c6e8a701bcb755fd91e8c5a2cd + +Disable address sanitization for raw and non-maskable interrupt +handlers, because they can run in real mode, where we cannot access +the shadow memory. (Note that kasan_arch_is_ready() doesn't test for +real mode, since it is a static branch for speed, and in any case not +all the entry points to the generic KASAN code are protected by +kasan_arch_is_ready guards.) + +The changes to interrupt_nmi_enter/exit_prepare() look larger than +they actually are. The changes are equivalent to adding +!IS_ENABLED(CONFIG_KASAN) to the conditions for calling nmi_enter() or +nmi_exit() in real mode. That is, the code is equivalent to using the +following condition for calling nmi_enter/exit: + + if (((!IS_ENABLED(CONFIG_PPC_BOOK3S_64) || + !firmware_has_feature(FW_FEATURE_LPAR) || + radix_enabled()) && + !IS_ENABLED(CONFIG_KASAN) || + (mfmsr() & MSR_DR)) + +That unwieldy condition has been split into several statements with +comments, for easier reading. + +The nmi_ipi_lock functions that call atomic functions (i.e., +nmi_ipi_lock_start(), nmi_ipi_lock() and nmi_ipi_unlock()), besides +being marked noinstr, now call arch_atomic_* functions instead of +atomic_* functions because with KASAN enabled, the atomic_* functions +are wrappers which explicitly do address sanitization on their +arguments. Since we are trying to avoid address sanitization, we have +to use the lower-level arch_atomic_* versions. + +In hv_nmi_check_nonrecoverable(), the regs_set_unrecoverable() call +has been open-coded so as to avoid having to either trust the inlining +or mark regs_set_unrecoverable() as noinstr. + +[paulus@ozlabs.org: combined a few work-in-progress commits of + Daniel's and wrote the commit message.] + +Signed-off-by: Daniel Axtens +Signed-off-by: Paul Mackerras +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/YoTFGaKM8Pd46PIK@cleo +Acked-by: Michal Suchanek +--- + arch/powerpc/include/asm/interrupt.h | 52 +++++++++++++++++++++------- + arch/powerpc/kernel/smp.c | 22 ++++++------ + arch/powerpc/kernel/traps.c | 6 ++-- + arch/powerpc/lib/Makefile | 3 ++ + arch/powerpc/platforms/powernv/smp.c | 2 +- + 5 files changed, 59 insertions(+), 26 deletions(-) + +diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h +index f964ef5c57d8..b14f54d789d2 100644 +--- a/arch/powerpc/include/asm/interrupt.h ++++ b/arch/powerpc/include/asm/interrupt.h +@@ -324,22 +324,46 @@ static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct inte + } + #endif + ++ /* If data relocations are enabled, it's safe to use nmi_enter() */ ++ if (mfmsr() & MSR_DR) { ++ nmi_enter(); ++ return; ++ } ++ + /* +- * Do not use nmi_enter() for pseries hash guest taking a real-mode ++ * But do not use nmi_enter() for pseries hash guest taking a real-mode + * NMI because not everything it touches is within the RMA limit. + */ +- if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) || +- !firmware_has_feature(FW_FEATURE_LPAR) || +- radix_enabled() || (mfmsr() & MSR_DR)) +- nmi_enter(); ++ if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && ++ firmware_has_feature(FW_FEATURE_LPAR) && ++ !radix_enabled()) ++ return; ++ ++ /* ++ * Likewise, don't use it if we have some form of instrumentation (like ++ * KASAN shadow) that is not safe to access in real mode (even on radix) ++ */ ++ if (IS_ENABLED(CONFIG_KASAN)) ++ return; ++ ++ /* Otherwise, it should be safe to call it */ ++ nmi_enter(); + } + + static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state) + { +- if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) || +- !firmware_has_feature(FW_FEATURE_LPAR) || +- radix_enabled() || (mfmsr() & MSR_DR)) ++ if (mfmsr() & MSR_DR) { ++ // nmi_exit if relocations are on + nmi_exit(); ++ } else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && ++ firmware_has_feature(FW_FEATURE_LPAR) && ++ !radix_enabled()) { ++ // no nmi_exit for a pseries hash guest taking a real mode exception ++ } else if (IS_ENABLED(CONFIG_KASAN)) { ++ // no nmi_exit for KASAN in real mode ++ } else { ++ nmi_exit(); ++ } + + /* + * nmi does not call nap_adjust_return because nmi should not create +@@ -407,7 +431,8 @@ static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct inter + * Specific handlers may have additional restrictions. + */ + #define DEFINE_INTERRUPT_HANDLER_RAW(func) \ +-static __always_inline long ____##func(struct pt_regs *regs); \ ++static __always_inline __no_sanitize_address __no_kcsan long \ ++____##func(struct pt_regs *regs); \ + \ + interrupt_handler long func(struct pt_regs *regs) \ + { \ +@@ -421,7 +446,8 @@ interrupt_handler long func(struct pt_regs *regs) \ + } \ + NOKPROBE_SYMBOL(func); \ + \ +-static __always_inline long ____##func(struct pt_regs *regs) ++static __always_inline __no_sanitize_address __no_kcsan long \ ++____##func(struct pt_regs *regs) + + /** + * DECLARE_INTERRUPT_HANDLER - Declare synchronous interrupt handler function +@@ -541,7 +567,8 @@ static __always_inline void ____##func(struct pt_regs *regs) + * body with a pair of curly brackets. + */ + #define DEFINE_INTERRUPT_HANDLER_NMI(func) \ +-static __always_inline long ____##func(struct pt_regs *regs); \ ++static __always_inline __no_sanitize_address __no_kcsan long \ ++____##func(struct pt_regs *regs); \ + \ + interrupt_handler long func(struct pt_regs *regs) \ + { \ +@@ -558,7 +585,8 @@ interrupt_handler long func(struct pt_regs *regs) \ + } \ + NOKPROBE_SYMBOL(func); \ + \ +-static __always_inline long ____##func(struct pt_regs *regs) ++static __always_inline __no_sanitize_address __no_kcsan long \ ++____##func(struct pt_regs *regs) + + + /* Interrupt handlers */ +diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c +index 4c4511b6a75d..4335efcb3184 100644 +--- a/arch/powerpc/kernel/smp.c ++++ b/arch/powerpc/kernel/smp.c +@@ -411,32 +411,32 @@ static struct cpumask nmi_ipi_pending_mask; + static bool nmi_ipi_busy = false; + static void (*nmi_ipi_function)(struct pt_regs *) = NULL; + +-static void nmi_ipi_lock_start(unsigned long *flags) ++noinstr static void nmi_ipi_lock_start(unsigned long *flags) + { + raw_local_irq_save(*flags); + hard_irq_disable(); +- while (atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) { ++ while (arch_atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) { + raw_local_irq_restore(*flags); +- spin_until_cond(atomic_read(&__nmi_ipi_lock) == 0); ++ spin_until_cond(arch_atomic_read(&__nmi_ipi_lock) == 0); + raw_local_irq_save(*flags); + hard_irq_disable(); + } + } + +-static void nmi_ipi_lock(void) ++noinstr static void nmi_ipi_lock(void) + { +- while (atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) +- spin_until_cond(atomic_read(&__nmi_ipi_lock) == 0); ++ while (arch_atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) ++ spin_until_cond(arch_atomic_read(&__nmi_ipi_lock) == 0); + } + +-static void nmi_ipi_unlock(void) ++noinstr static void nmi_ipi_unlock(void) + { + smp_mb(); +- WARN_ON(atomic_read(&__nmi_ipi_lock) != 1); +- atomic_set(&__nmi_ipi_lock, 0); ++ WARN_ON(arch_atomic_read(&__nmi_ipi_lock) != 1); ++ arch_atomic_set(&__nmi_ipi_lock, 0); + } + +-static void nmi_ipi_unlock_end(unsigned long *flags) ++noinstr static void nmi_ipi_unlock_end(unsigned long *flags) + { + nmi_ipi_unlock(); + raw_local_irq_restore(*flags); +@@ -445,7 +445,7 @@ static void nmi_ipi_unlock_end(unsigned long *flags) + /* + * Platform NMI handler calls this to ack + */ +-int smp_handle_nmi_ipi(struct pt_regs *regs) ++noinstr int smp_handle_nmi_ipi(struct pt_regs *regs) + { + void (*fn)(struct pt_regs *) = NULL; + unsigned long flags; +diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c +index a08bb7cefdc5..3aaa50e5c72f 100644 +--- a/arch/powerpc/kernel/traps.c ++++ b/arch/powerpc/kernel/traps.c +@@ -393,7 +393,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) + * Builds that do not support KVM could take this second option to increase + * the recoverability of NMIs. + */ +-void hv_nmi_check_nonrecoverable(struct pt_regs *regs) ++noinstr void hv_nmi_check_nonrecoverable(struct pt_regs *regs) + { + #ifdef CONFIG_PPC_POWERNV + unsigned long kbase = (unsigned long)_stext; +@@ -433,7 +433,9 @@ void hv_nmi_check_nonrecoverable(struct pt_regs *regs) + return; + + nonrecoverable: +- regs_set_unrecoverable(regs); ++ regs->msr &= ~MSR_RI; ++ local_paca->hsrr_valid = 0; ++ local_paca->srr_valid = 0; + #endif + } + DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception) +diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile +index 5d1881d2e39a..8560c912186d 100644 +--- a/arch/powerpc/lib/Makefile ++++ b/arch/powerpc/lib/Makefile +@@ -13,6 +13,9 @@ CFLAGS_REMOVE_feature-fixups.o = $(CC_FLAGS_FTRACE) + + KASAN_SANITIZE_code-patching.o := n + KASAN_SANITIZE_feature-fixups.o := n ++# restart_table.o contains functions called in the NMI interrupt path ++# which can be in real mode. Disable KASAN. ++KASAN_SANITIZE_restart_table.o := n + + ifdef CONFIG_KASAN + CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING +diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c +index cbb67813cd5d..9e1a25398f98 100644 +--- a/arch/powerpc/platforms/powernv/smp.c ++++ b/arch/powerpc/platforms/powernv/smp.c +@@ -345,7 +345,7 @@ static void __init pnv_smp_probe(void) + } + } + +-static int pnv_system_reset_exception(struct pt_regs *regs) ++noinstr static int pnv_system_reset_exception(struct pt_regs *regs) + { + if (smp_handle_nmi_ipi(regs)) + return 1; +-- +2.44.0 + diff --git a/series.conf b/series.conf index 268117e..3a0d3e4 100644 --- a/series.conf +++ b/series.conf @@ -4394,6 +4394,7 @@ patches.suse/powerpc-perf-Use-stack-siar-instead-of-mfspr.patch patches.suse/powerpc-perf-Drop-the-case-of-returning-0-as-instruc.patch patches.suse/powerpc-perf-Fix-the-check-for-SIAR-value.patch + patches.suse/powerpc-Refactor-verification-of-MSR_RI.patch patches.suse/KVM-PPC-Book3S-HV-Fix-copy_tofrom_guest-routines.patch patches.suse/KVM-PPC-Book3S-HV-Nested-Reflect-guest-PMU-in-use-to.patch patches.suse/powerpc-doc-Fix-htmldocs-errors.patch @@ -28680,6 +28681,7 @@ patches.suse/powerpc-powernv-Get-L1D-flush-requirements-from-devi.patch patches.suse/powerpc-powernv-Get-STF-barrier-requirements-from-de.patch patches.suse/powerpc-ftrace-Remove-ftrace-init-tramp-once-kernel-.patch + patches.suse/powerpc-kasan-Don-t-instrument-non-maskable-or-raw-i.patch patches.suse/powerpc-perf-Fix-the-threshold-compare-group-constraint-for-power10.patch patches.suse/powerpc-perf-Fix-the-threshold-compare-group-constra.patch patches.suse/powerpc-xics-fix-refcount-leak-in-icp_opal_init.patch @@ -46241,6 +46243,9 @@ patches.suse/iommu-vt-d-Allocate-local-memory-for-page-request-qu.patch patches.suse/nilfs2-fix-OOB-in-nilfs_set_de_type.patch + # powerpc/linux next + patches.suse/powerpc-Avoid-nmi_enter-nmi_exit-in-real-mode-interr.patch + # out-of-tree patches patches.suse/cifs-Fix-UAF-in-cifs_demultiplex_thread-.patch patches.suse/raid1-fix-use-after-free-for-original-bio-in-raid1_w.patch