Commit 74c3354b authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman
Browse files

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: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/1612702361.lm7fqo56re.astroid@bobo.none
parent 56acfdd8
Loading
Loading
Loading
Loading
+15 −4
Original line number Original line Diff line number Diff line
@@ -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;