From: Nicholas Piggin <npiggin@gmail.com> Date: 2017-07-04 10:09:28
These are a few independent patches I've accumulated that improve
system reset handling a bit. The first 2 at least should be quite
straight forward and hopefully can be merged for 4.13.
Thanks,
Nick
Nicholas Piggin (3):
powerpc: do not call ppc_md.panic in panic notifier if fadump not used
powerpc/pseries/le: work around a firmware quirk
powerpc: do not send system reset request through the oops path
arch/powerpc/kernel/setup-common.c | 15 +++++++-----
arch/powerpc/kernel/traps.c | 47 ++++++++++++++++++++++++------------
arch/powerpc/platforms/pseries/ras.c | 15 ++++++++++++
3 files changed, 55 insertions(+), 22 deletions(-)
--
2.11.0
From: Nicholas Piggin <npiggin@gmail.com> Date: 2017-07-04 10:09:32
If fadump is not registered, and no other crash or debug handlers are
registered, the powerpc panic handler stops the guest before the generic
panic code can push out debug information to the console.
Without this patch, system reset injection to a guest causes the guest to
silently stop. Afterwards, we get the expected oops trace.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/setup-common.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
@@ -707,12 +707,15 @@ EXPORT_SYMBOL(check_legacy_ioport);staticintppc_panic_event(structnotifier_block*this,unsignedlongevent,void*ptr){-/*-*Iffirmware-assisteddumphasbeenregisteredthentrigger-*firmware-assisteddumpandletfirmwarehandleeverythingelse.-*/-crash_fadump(NULL,ptr);-ppc_md.panic(ptr);/* May not return */+if(is_fadump_active()){+/*+*Iffirmware-assisteddumphasbeenregisteredthentrigger+*firmware-assisteddumpandletfirmwarehandleeverything+*else.+*/+crash_fadump(NULL,ptr);+ppc_md.panic(ptr);/* May not return */+}returnNOTIFY_DONE;}
From: Nicholas Piggin <npiggin@gmail.com> Date: 2017-07-04 10:09:36
Some PowerVM firmware when delivering a system reset interrupt to a
little endian OS will mess up SRR registers. They are byteswapped, and
SRR1 is incorrect. An example from a crash:
NIP: 14dd0900000000c0
MSR: 1000000200000080
It's possible to detect this pattern in SRR1 (that would never happen in
normal operation), and at least fix the NIP. After this patch, the same
interrupt reports NIP properly:
NIP [c00000000009dd14] plpar_hcall_norets+0x1c/0x28
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/platforms/pseries/ras.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2017-07-04 10:09:40
A system reset is a request to crash / debug the system rather than
necessarily caused by encountering a BUG. So there is no need to
serialize all CPUs behind the die lock, adding taints to all subsequent
traces beyond the first, breaking console locks, etc.
The system reset is NMI context which has its own printk buffers to
prevent output being interleaved. Then it's better to have all
secondaries print out their debug as quickly as possible and the primary
will flush out all printk buffers during panic().
So remove the 0x100 path from die, and move it into system_reset. Name
the crash/dump reasons "System Reset".
This gives "not tained" traces when crashing an untainted kernel. It
also gives the panic reason as "System Reset" as opposed to "Fatal
exception in interrupt" (or "die oops" for fadump).
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/traps.c | 47 ++++++++++++++++++++++++++++++---------------
1 file changed, 31 insertions(+), 16 deletions(-)
@@ -294,17 +282,44 @@ void system_reset_exception(struct pt_regs *regs)gotoout;}-die("System Reset",regs,SIGABRT);+if(debugger(regs))+gotoout;++/*+*Asystemresetisarequesttodump,sowealwayssend+*itthroughthecrashdumpcode(iffadumporkdumpare+*registered).+*/+crash_fadump(regs,"System Reset");++crash_kexec(regs);++/*+*Wearen'ttheprimarycrashCPU.Weneedtosendit+*toaholdingpatterntoavoiditendingupinthepanic+*code.+*/+crash_kexec_secondary(regs);++/*+*Nodebuggerorcrashdumpregistered,printlogsthen+*panic.+*/+__die("System Reset",regs,SIGABRT);++mdelay(2*MSEC_PER_SEC);/* Wait a little while for others to print */+add_taint(TAINT_DIE,LOCKDEP_NOW_UNRELIABLE);+nmi_panic(regs,"System Reset");out:#ifdef CONFIG_PPC_BOOK3S_64BUG_ON(get_paca()->in_nmi==0);if(get_paca()->in_nmi>1)-panic("Unrecoverable nested System Reset");+nmi_panic(regs,"Unrecoverable nested System Reset");#endif/* Must die if the interrupt is not recoverable */if(!(regs->msr&MSR_RI))-panic("Unrecoverable System Reset");+nmi_panic(regs,"Unrecoverable System Reset");if(!nested)nmi_exit();
If fadump is not registered, and no other crash or debug handlers are
registered, the powerpc panic handler stops the guest before the generic
panic code can push out debug information to the console.
Without this patch, system reset injection to a guest causes the guest to
silently stop. Afterwards, we get the expected oops trace.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/setup-common.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
@@ -707,12 +707,15 @@ EXPORT_SYMBOL(check_legacy_ioport);staticintppc_panic_event(structnotifier_block*this,unsignedlongevent,void*ptr){-/*-*Iffirmware-assisteddumphasbeenregisteredthentrigger-*firmware-assisteddumpandletfirmwarehandleeverythingelse.-*/-crash_fadump(NULL,ptr);-ppc_md.panic(ptr);/* May not return */+if(is_fadump_active()){
Should it be !fw_dump.dump_registered check ? The function crash_dump()
already checks for !fw_dump.dump_registered before proceeding. If fadump
has not been registered then the crash_dump() will return immediately
without doing anything and then fall through next line ppc_md.panic(ptr).
fadump active is always false in the first kernel (production kernel).
Hence is_fadump_active() check here would stop triggering fadump even if
it is registered.
fadump active is true only during second kernel (dump capture kernel)
that boots after fadump crash when firmware exports 'ibm,kernel-dump'
device tree node indicating dump data is available.
Thanks,
-Mahesh.
+ /*
+ * If firmware-assisted dump has been registered then trigger
+ * firmware-assisted dump and let firmware handle everything
+ * else.
+ */
+ crash_fadump(NULL, ptr);
+ ppc_md.panic(ptr); /* May not return */
+ }
return NOTIFY_DONE;
}
@@ -707,12 +707,15 @@ EXPORT_SYMBOL(check_legacy_ioport);staticintppc_panic_event(structnotifier_block*this,unsignedlongevent,void*ptr){-/*-*Iffirmware-assisteddumphasbeenregisteredthentrigger-*firmware-assisteddumpandletfirmwarehandleeverythingelse.-*/-crash_fadump(NULL,ptr);-ppc_md.panic(ptr);/* May not return */+if(is_fadump_active()){+/*+*Iffirmware-assisteddumphasbeenregisteredthentrigger+*firmware-assisteddumpandletfirmwarehandleeverything+*else.+*/+crash_fadump(NULL,ptr);
As Mahesh pointed out the check for fadump active is not correct.
+ ppc_md.panic(ptr); /* May not return */
But I wonder if this is the real problem?
AFAICS we only have two users of ppc_md.panic(), ps3 and pseries.
At least on ps3 it has nothing to do with fadump, so skipping it like
you've done is not right.
On pseries it uses rtas_os_term() which tells the HV that we "terminated
normal operation", unless you're doing fadump it's supposed to return
and shouldn't stop the regular panic path. Though maybe that's not true
in practice.
It sounds like what we need to do is have a look at the panic flow and
decide whether ppc_md.panic is useful at all, and if so is it called in
the right place.
cheers
@@ -707,12 +707,15 @@ EXPORT_SYMBOL(check_legacy_ioport);staticintppc_panic_event(structnotifier_block*this,unsignedlongevent,void*ptr){-/*-*Iffirmware-assisteddumphasbeenregisteredthentrigger-*firmware-assisteddumpandletfirmwarehandleeverythingelse.-*/-crash_fadump(NULL,ptr);-ppc_md.panic(ptr);/* May not return */+if(is_fadump_active()){+/*+*Iffirmware-assisteddumphasbeenregisteredthentrigger+*firmware-assisteddumpandletfirmwarehandleeverything+*else.+*/+crash_fadump(NULL,ptr);
As Mahesh pointed out the check for fadump active is not correct.
Yep, I misread that code.
quoted
+ ppc_md.panic(ptr); /* May not return */
But I wonder if this is the real problem?
AFAICS we only have two users of ppc_md.panic(), ps3 and pseries.
At least on ps3 it has nothing to do with fadump, so skipping it like
you've done is not right.
But the call has to do with fadump -- at least that's what the comment
implies. ps3 does not want to panic here (it's .panic is just a hang).
It wants to go via the normal panic path and flush printk buffers etc.
On pseries it uses rtas_os_term() which tells the HV that we "terminated
normal operation", unless you're doing fadump it's supposed to return
and shouldn't stop the regular panic path. Though maybe that's not true
in practice.
It sounds like what we need to do is have a look at the panic flow and
decide whether ppc_md.panic is useful at all, and if so is it called in
the right place.
Yeah I would say you're probably right. The panic handling could possibly
go into the fadump code itself too, if it's relatively common across all
platforms that use it. It can register its own panic handler, no need for
this generic one.
Thanks,
Nick