powerpc/pseries/mce: restore msr before returning from handler
The pseries real-mode machine check handler can enable the MMU, and return from the handler with the MMU still enabled. This works, but real-mode handler wrapper exit handlers want to rely on the MMU being in real-mode. So change the pseries handler to restore the MSR after it has finished virtual mode tasks. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/1612702361.lm7fqo56re.astroid@bobo.none
This commit is contained in:
parent
56acfdd8bf
commit
74c3354bc1
@ -717,6 +717,7 @@ static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)
|
|||||||
struct pseries_errorlog *pseries_log;
|
struct pseries_errorlog *pseries_log;
|
||||||
struct pseries_mc_errorlog *mce_log = NULL;
|
struct pseries_mc_errorlog *mce_log = NULL;
|
||||||
int disposition = rtas_error_disposition(errp);
|
int disposition = rtas_error_disposition(errp);
|
||||||
|
unsigned long msr;
|
||||||
u8 error_type;
|
u8 error_type;
|
||||||
|
|
||||||
if (!rtas_error_extended(errp))
|
if (!rtas_error_extended(errp))
|
||||||
@ -742,9 +743,21 @@ static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)
|
|||||||
* SLB multihit is done by now.
|
* SLB multihit is done by now.
|
||||||
*/
|
*/
|
||||||
out:
|
out:
|
||||||
mtmsr(mfmsr() | MSR_IR | MSR_DR);
|
msr = mfmsr();
|
||||||
|
mtmsr(msr | MSR_IR | MSR_DR);
|
||||||
|
|
||||||
disposition = mce_handle_err_virtmode(regs, errp, mce_log,
|
disposition = mce_handle_err_virtmode(regs, errp, mce_log,
|
||||||
disposition);
|
disposition);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queue irq work to log this rtas event later.
|
||||||
|
* irq_work_queue uses per-cpu variables, so do this in virt
|
||||||
|
* mode as well.
|
||||||
|
*/
|
||||||
|
irq_work_queue(&mce_errlog_process_work);
|
||||||
|
|
||||||
|
mtmsr(msr);
|
||||||
|
|
||||||
return disposition;
|
return disposition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -860,10 +873,8 @@ long pseries_machine_check_realmode(struct pt_regs *regs)
|
|||||||
* virtual mode.
|
* virtual mode.
|
||||||
*/
|
*/
|
||||||
disposition = mce_handle_error(regs, errp);
|
disposition = mce_handle_error(regs, errp);
|
||||||
fwnmi_release_errinfo();
|
|
||||||
|
|
||||||
/* Queue irq work to log this rtas event later. */
|
fwnmi_release_errinfo();
|
||||||
irq_work_queue(&mce_errlog_process_work);
|
|
||||||
|
|
||||||
if (disposition == RTAS_DISP_FULLY_RECOVERED)
|
if (disposition == RTAS_DISP_FULLY_RECOVERED)
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user