From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:37:11
There's a bunch of problems we hit bringing up fwnmi sreset and testing
with mce injection on QEMU. Mostly pseries issues.
This series of fixes applies on top of next-test, the machine
check reconcile patch won't apply cleanly to previous kernels but
it might want to be backported. We can do that after upstreaming.
This doesn't solve all known problems yet, but fwnmi machine check
and system reset injection in QEMU is significantly better. There
will be more to come but these should be ready for review now.
Thanks,
Nick
Nicholas Piggin (12):
powerpc/64s/exceptions: Fix in_mce accounting in unrecoverable path
powerpc/64s/exceptions: Change irq reconcile for NMIs from reusing
_DAR to RESULT
powerpc/64s/exceptions: machine check reconcile irq state
powerpc/pseries/ras: avoid calling rtas_token in NMI paths
powerpc/pseries/ras: FWNMI_VALID off by one
powerpc/pseries/ras: fwnmi avoid modifying r3 in error case
powerpc/pseries/ras: fwnmi sreset should not interlock
powerpc/pseries: limit machine check stack to 4GB
powerpc/pseries: machine check use rtas_call_unlocked with args on
stack
powerpc/64s: machine check interrupt update NMI accounting
powerpc/64s: machine check do not trace real-mode handler
powerpc/64s: system reset do not trace
arch/powerpc/include/asm/firmware.h | 1 +
arch/powerpc/kernel/exceptions-64s.S | 33 +++++++++++---
arch/powerpc/kernel/mce.c | 13 +++++-
arch/powerpc/kernel/process.c | 2 +-
arch/powerpc/kernel/setup_64.c | 15 ++++++-
arch/powerpc/kernel/traps.c | 18 +++-----
arch/powerpc/platforms/pseries/ras.c | 62 +++++++++++++++++++-------
arch/powerpc/platforms/pseries/setup.c | 13 ++++--
8 files changed, 118 insertions(+), 39 deletions(-)
--
2.23.0
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:41:44
A spare interrupt stack slot is needed to save irq state when
reconciling NMIs (sreset and decrementer soft-nmi). _DAR is used
for this, but we want to reconcile machine checks as well, which
do use _DAR. Switch to using RESULT instead, as it's used by
system calls.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:45:51
In the interest of reducing code and possible failures in the
machine check and system reset paths, grab the "ibm,nmi-interlock"
token at init time.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/firmware.h | 1 +
arch/powerpc/platforms/pseries/ras.c | 2 +-
arch/powerpc/platforms/pseries/setup.c | 13 ++++++++++---
3 files changed, 12 insertions(+), 4 deletions(-)
@@ -128,6 +128,7 @@ extern void machine_check_fwnmi(void);/* This is true if we are using the firmware NMI handler (typically LPAR) */externintfwnmi_active;+externintibm_nmi_interlock_token;externunsignedint__start___fw_ftr_fixup,__stop___fw_ftr_fixup;
@@ -83,6 +83,7 @@ unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K);EXPORT_SYMBOL(CMO_PageSize);intfwnmi_active;/* TRUE if an FWNMI handler is present */+intibm_nmi_interlock_token;staticvoidpSeries_show_cpuinfo(structseq_file*m){
@@ -113,9 +114,14 @@ static void __init fwnmi_init(void)structslb_entry*slb_ptr;size_tsize;#endif+intibm_nmi_register_token;-intibm_nmi_register=rtas_token("ibm,nmi-register");-if(ibm_nmi_register==RTAS_UNKNOWN_SERVICE)+ibm_nmi_register_token=rtas_token("ibm,nmi-register");+if(ibm_nmi_register_token==RTAS_UNKNOWN_SERVICE)+return;++ibm_nmi_interlock_token=rtas_token("ibm,nmi-interlock");+if(WARN_ON(ibm_nmi_interlock_token==RTAS_UNKNOWN_SERVICE))return;/* If the kernel's not linked at zero we point the firmware at low
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:47:53
This was discovered developing qemu fwnmi sreset support. This
off-by-one bug means the last 16 bytes of the rtas area can not
be used for a 16 byte save area.
It's not a serious bug, and QEMU implementation has to retain a
workaround for old kernels, but it's good to tighten it.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/platforms/pseries/ras.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:49:36
If there is some error with the fwnmi save area, r3 has already been
modified which doesn't help with debugging.
Only update r3 when to restore the saved value.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/platforms/pseries/ras.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:51:49
PAPR does not specify that fwnmi sreset should be interlocked, and
PowerVM (and therefore now QEMU) do not require it.
These "ibm,nmi-interlock" calls are ignored by firmware, but there
is a possibility that the sreset could have interrupted a machine
check and release the machine check's interlock too early, corrupting
it if another machine check came in.
This is an extremely rare case, but it should be fixed for clarity
and reducing the code executed in the sreset path. Firmware also
does not provide error information for the sreset case to look at, so
remove that comment.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/platforms/pseries/ras.c | 48 ++++++++++++++++++++--------
1 file changed, 34 insertions(+), 14 deletions(-)
@@ -406,6 +406,20 @@ static inline struct rtas_error_log *fwnmi_get_errlog(void)return(structrtas_error_log*)local_paca->mce_data_buf;}+staticunsignedlong*fwnmi_get_savep(structpt_regs*regs)+{+unsignedlongsavep_ra;++/* Mask top two bits */+savep_ra=regs->gpr[3]&~(0x3UL<<62);+if(!VALID_FWNMI_BUFFER(savep_ra)){+printk(KERN_ERR"FWNMI: corrupt r3 0x%016lx\n",regs->gpr[3]);+returnNULL;+}++return__va(savep_ra);+}+/**Gettheerrorinformationforerrorscomingthroughthe*FWNMIvectors.Thept_regs'r3willbeupdatedtoreflect
@@ -423,20 +437,15 @@ static inline struct rtas_error_log *fwnmi_get_errlog(void)*/staticstructrtas_error_log*fwnmi_get_errinfo(structpt_regs*regs){-unsignedlongsavep_ra;unsignedlong*savep;structrtas_error_log*h;-/* Mask top two bits */-savep_ra=regs->gpr[3]&~(0x3UL<<62);--if(!VALID_FWNMI_BUFFER(savep_ra)){-printk(KERN_ERR"FWNMI: corrupt r3 0x%016lx\n",regs->gpr[3]);+savep=fwnmi_get_savep(regs);+if(!savep)returnNULL;-}-savep=__va(savep_ra);-regs->gpr[3]=be64_to_cpu(savep[0]);/* restore original r3 */+/* restore original r3 */+regs->gpr[3]=be64_to_cpu(savep[0]);h=(structrtas_error_log*)&savep[1];/* Use the per cpu buffer from paca to store rtas error log */
@@ -483,11 +492,22 @@ int pSeries_system_reset_exception(struct pt_regs *regs)#endifif(fwnmi_active){-structrtas_error_log*errhdr=fwnmi_get_errinfo(regs);-if(errhdr){-/* XXX Should look at FWNMI information */-}-fwnmi_release_errinfo();+unsignedlong*savep;++/*+*Firmware(PowerVMandKVM)savesr3toasavearealike+*machinecheck,whichisnotexactlywhatPAPR(2.9)+*suggestsbutthereisnowaytodetectotherwise,sothis+*istheinterfacenow.+*+*Systemresetsdonotsaveanyerrorlogorrequirean+*"ibm,nmi-interlock"rtascalltorelease.+*/++savep=fwnmi_get_savep(regs);+/* restore original r3 */+if(savep)+regs->gpr[3]=be64_to_cpu(savep[0]);}if(smp_handle_nmi_ipi(regs))
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:53:33
This allows rtas_args to be put on the machine check stack, which
avoids a lot of complications with re-entrancy deadlocks.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/setup_64.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:55:30
With the previous patch, machine checks can use rtas_call_unlocked
which avoids the rtas spinlock which would deadlock if a machine
check hits while making an rtas call.
This also avoids the complex rtas error logging which has more rtas calls
and includes kmalloc (which can return memory beyond RMA, which would
also crash).
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/platforms/pseries/ras.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:57:55
machine_check_early is taken as an NMI, so nmi_enter is used there.
machine_check_exception is no longer taken as an NMI (it's invoked
via irq_work in the case a machine check hits in kernel mode), so
remove the nmi_enter from that case.
In NMI context, hash faults don't try to refill the hash table, which
can lead to crashes accessing non-pinned kernel pages. System reset
still has this potential problem.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/mce.c | 7 +++++++
arch/powerpc/kernel/process.c | 2 +-
arch/powerpc/kernel/traps.c | 13 +------------
3 files changed, 9 insertions(+), 13 deletions(-)
@@ -823,9 +823,6 @@ int machine_check_generic(struct pt_regs *regs)voidmachine_check_exception(structpt_regs*regs){intrecover=0;-boolnested=in_nmi();-if(!nested)-nmi_enter();__this_cpu_inc(irq_stat.mce_exceptions);
@@ -851,20 +848,12 @@ void machine_check_exception(struct pt_regs *regs)if(check_io_access(regs))gotobail;-if(!nested)-nmi_exit();-die("Machine check",regs,SIGBUS);+bail:/* Must die if the interrupt is not recoverable */if(!(regs->msr&MSR_RI))nmi_panic(regs,"Unrecoverable Machine check");--return;--bail:-if(!nested)-nmi_exit();}voidSMIException(structpt_regs*regs)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 10:59:37
Rather than notrace annotations throughout a significant part of the
machine check code across kernel/ pseries/ and powernv/ which can
easily be broken and is infrequently tested, use paca->ftrace_enabled
to blanket-disable tracing of the real-mode non-maskable handler.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/mce.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-03-25 11:01:59
Similarly to the previous patch, do not trace system reset. This code
is used when there is a crash or hang, and tracing disturbs the system
more and has been known to crash in the crash handling path.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/traps.c | 5 +++++
1 file changed, 5 insertions(+)
@@ -524,6 +527,8 @@ void system_reset_exception(struct pt_regs *regs)if(!nested)nmi_exit();+local_paca->ftrace_enabled=ftrace_enabled;+/* What should we do here? We could issue a shutdown or hard reset. */}
From: Naveen N. Rao <hidden> Date: 2020-03-26 17:26:14
Nicholas Piggin wrote:
Similarly to the previous patch, do not trace system reset. This code
is used when there is a crash or hang, and tracing disturbs the system
more and has been known to crash in the crash handling path.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/traps.c | 5 +++++
1 file changed, 5 insertions(+)
For the ftrace bits:
Acked-by: Naveen N. Rao <redacted>
I suppose we could add helpers to save/restore the state. But, since we
only have these two users as of now, we can revisit that if the need
arises.
- Naveen
On 2020-03-25 20:34:02 Wed, Nicholas Piggin wrote:
In the interest of reducing code and possible failures in the
machine check and system reset paths, grab the "ibm,nmi-interlock"
token at init time.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
@@ -128,6 +128,7 @@ extern void machine_check_fwnmi(void);/* This is true if we are using the firmware NMI handler (typically LPAR) */externintfwnmi_active;+externintibm_nmi_interlock_token;externunsignedint__start___fw_ftr_fixup,__stop___fw_ftr_fixup;
@@ -83,6 +83,7 @@ unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K);EXPORT_SYMBOL(CMO_PageSize);intfwnmi_active;/* TRUE if an FWNMI handler is present */+intibm_nmi_interlock_token;staticvoidpSeries_show_cpuinfo(structseq_file*m){
@@ -113,9 +114,14 @@ static void __init fwnmi_init(void)structslb_entry*slb_ptr;size_tsize;#endif+intibm_nmi_register_token;-intibm_nmi_register=rtas_token("ibm,nmi-register");-if(ibm_nmi_register==RTAS_UNKNOWN_SERVICE)+ibm_nmi_register_token=rtas_token("ibm,nmi-register");+if(ibm_nmi_register_token==RTAS_UNKNOWN_SERVICE)+return;++ibm_nmi_interlock_token=rtas_token("ibm,nmi-interlock");+if(WARN_ON(ibm_nmi_interlock_token==RTAS_UNKNOWN_SERVICE))return;/* If the kernel's not linked at zero we point the firmware at low
On 2020-03-25 20:34:03 Wed, Nicholas Piggin wrote:
quoted hunk
This was discovered developing qemu fwnmi sreset support. This
off-by-one bug means the last 16 bytes of the rtas area can not
be used for a 16 byte save area.
It's not a serious bug, and QEMU implementation has to retain a
workaround for old kernels, but it's good to tighten it.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/platforms/pseries/ras.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
On 2020-03-25 20:34:06 Wed, Nicholas Piggin wrote:
quoted hunk
This allows rtas_args to be put on the machine check stack, which
avoids a lot of complications with re-entrancy deadlocks.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/setup_64.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
Don't you need this as well under CONFIG_PPC_BOOK3S_64 #ifdef ??
Rest looks good.
Reviewed-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Thanks,
-Mahesh.
From: Nicholas Piggin <npiggin@gmail.com> Date: 2020-04-03 10:26:26
Mahesh J Salgaonkar's on March 27, 2020 3:24 pm:
On 2020-03-25 20:34:06 Wed, Nicholas Piggin wrote:
quoted
This allows rtas_args to be put on the machine check stack, which
avoids a lot of complications with re-entrancy deadlocks.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/setup_64.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)