aboutsummaryrefslogtreecommitdiff
path: root/target/ppc
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2024-03-19 16:01:46 +1000
committerNicholas Piggin <npiggin@gmail.com>2024-03-30 18:50:25 +1000
commit434531619fecd5ff9a08e548ed87b2b73c29cf3e (patch)
tree2c15630389ad38bb4a7f4e2a1bbbb23723cce211 /target/ppc
parented399ade3c85adf82fe507339560693e83a27020 (diff)
downloadqemu-434531619fecd5ff9a08e548ed87b2b73c29cf3e.zip
qemu-434531619fecd5ff9a08e548ed87b2b73c29cf3e.tar.gz
qemu-434531619fecd5ff9a08e548ed87b2b73c29cf3e.tar.bz2
target/ppc: Do not clear MSR[ME] on MCE interrupts to supervisor
Hardware clears the MSR[ME] bit when delivering a machine check interrupt, so that is what QEMU does. The spapr environment runs in supervisor mode though, and receives machine check interrupts after they are processed by the hypervisor, and MSR[ME] must always be enabled in supervisor mode (otherwise it could checkstop the system). So MSR[ME] must not be cleared when delivering machine checks to the supervisor. The fix to prevent supervisor mode from modifying MSR[ME] also prevented it from re-enabling the incorrectly cleared MSR[ME] bit when returning from handling the interrupt. Before that fix, the problem was not very noticable with well-behaved code. So the Fixes tag is not strictly correct, but practically they go together. Found by kvm-unit-tests machine check tests (not yet upstream). Fixes: 678b6f1af75ef ("target/ppc: Prevent supervisor from modifying MSR[ME]") Reviewed-by: Harsh Prateek Bora <harshpb@linux.ibm.com> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Diffstat (limited to 'target/ppc')
-rw-r--r--target/ppc/excp_helper.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 80f584f..674c05a 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1345,9 +1345,10 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
* clear (e.g., see FWNMI in PAPR).
*/
new_msr |= (target_ulong)MSR_HVB;
+
+ /* HV machine check exceptions don't have ME set */
+ new_msr &= ~((target_ulong)1 << MSR_ME);
}
- /* machine check exceptions don't have ME set */
- new_msr &= ~((target_ulong)1 << MSR_ME);
msr |= env->error_code;
break;