The code to track the CPPR values added by commit 49bd3647134ea47420067aea8d1401e722bf2aac ("powerpc/pseries: Track previous CPPR values to correctly EOI interrupts") broke kexec on pseries because the kexec code in xics.c calls xics_set_cpu_priority() before the IPI has been EOI'ed. This wasn't a problem previously but it now triggers a BUG_ON in xics_set_cpu_priority() because os_cppr->index isn't 0:
Oops: Exception in kernel mode, sig: 5 [#1] SMP NR_CPUS=128 NUMA kernel BUG at arch/powerpc/platforms/pseries/xics.c:791! pSeries Modules linked in: ehea dm_mirror dm_region_hash dm_log dm_zero dm_snapshot parport_pc parport dm_multipath autofs4 NIP: c0000000000461bc LR: c000000000046260 CTR: c00000000004bc08 REGS: c00000000fffb770 TRAP: 0700 Not tainted (2.6.33-rc6-autokern1) MSR: 8000000000021032 <ME,CE,IR,DR> CR: 48000022 XER: 00000001 TASK = c000000000aef700[0] 'swapper' THREAD: c000000000bcc000 CPU: 0 GPR00: 0000000000000001 c00000000fffb9f0 c000000000bcc9e8 0000000000000000 GPR04: 0000000000000000 0000000000000000 00000000000000dc 0000000000000002 GPR08: c0000000040036e8 c000000004002e40 0000000000000898 0000000000000000 GPR12: 0000000000000002 c000000000bf8480 0000000003500000 c000000000792f28 GPR16: c0000000007915e0 0000000000000000 0000000000419000 0000000003da8990 GPR20: c0000000008a8990 0000000000000010 c000000000ae92c0 0000000000000010 GPR24: 0000000000000000 c000000000be2380 0000000000000000 0000000000200200 GPR28: 0000000000000001 0000000000000001 c000000000b249e8 0000000000000000 NIP [c0000000000461bc] .xics_set_cpu_priority+0x38/0xb8 LR [c000000000046260] .xics_teardown_cpu+0x24/0xa4 Call Trace: [c00000000fffb9f0] [00000000ffffebf3] 0xffffebf3 (unreliable) [c00000000fffba60] [c000000000046260] .xics_teardown_cpu+0x24/0xa4 [c00000000fffbae0] [c000000000046330] .xics_kexec_teardown_cpu+0x18/0xb4 [c00000000fffbb60] [c00000000004a150] .pseries_kexec_cpu_down_xics+0x20/0x38 [c00000000fffbbf0] [c00000000002e5b8] .kexec_smp_down+0x48/0x7c [c00000000fffbc70] [c0000000000b2dd0] .generic_smp_call_function_interrupt+0xf4/0x1b4 [c00000000fffbd20] [c00000000002aed0] .smp_message_recv+0x48/0x100 [c00000000fffbda0] [c000000000046ae0] .xics_ipi_dispatch+0x84/0x148 [c00000000fffbe30] [c0000000000d62dc] .handle_IRQ_event+0xc8/0x248 [c00000000fffbf00] [c0000000000d8eb4] .handle_percpu_irq+0x80/0xf4 [c00000000fffbf90] [c000000000029048] .call_handle_irq+0x1c/0x2c [c000000000bcfa30] [c00000000000ec84] .do_IRQ+0x1b8/0x2a4 [c000000000bcfae0] [c000000000004804] hardware_interrupt_entry+0x1c/0x98 Fix this problem by setting the index on the CPPR stack to 0 before calling xics_set_cpu_priority() in xics_teardown_cpu(). Also make it clear that we only want to set the priority when there's just one CPPR value in the stack, and enforce it by updating the value of os_cppr->stack[0] rather than os_cppr->stack[os_cppr->index]. While we're at it change the BUG_ON to a WARN_ON. Reported-by: Anton Blanchard <an...@samba.org> Signed-off-by: Mark Nelson <ma...@au1.ibm.com> --- Ben, if it's not too late for 2.6.33 this would be really nice to have as without it we can't kexec on pseries. arch/powerpc/platforms/pseries/xics.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) Index: upstream/arch/powerpc/platforms/pseries/xics.c =================================================================== --- upstream.orig/arch/powerpc/platforms/pseries/xics.c +++ upstream/arch/powerpc/platforms/pseries/xics.c @@ -784,9 +784,13 @@ static void xics_set_cpu_priority(unsign { struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); - BUG_ON(os_cppr->index != 0); + /* + * we only really want to set the priority when there's + * just one cppr value on the stack + */ + WARN_ON(os_cppr->index != 0); - os_cppr->stack[os_cppr->index] = cppr; + os_cppr->stack[0] = cppr; if (firmware_has_feature(FW_FEATURE_LPAR)) lpar_cppr_info(cppr); @@ -821,8 +825,14 @@ void xics_setup_cpu(void) void xics_teardown_cpu(void) { + struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); int cpu = smp_processor_id(); + /* + * we have to reset the cppr index to 0 because we're + * not going to return from the IPI + */ + os_cppr->index = 0; xics_set_cpu_priority(0); /* Clear any pending IPI request */ _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev