summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-ppc/excp_helper.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 53c407576b..808760bf53 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -213,7 +213,12 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
cs->halted = 1;
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
- new_msr |= (target_ulong)MSR_HVB;
+ if (env->msr_mask & MSR_HVB) {
+ /* ISA specifies HV, but can be delivered to guest with HV clear
+ * (e.g., see FWNMI in PAPR).
+ */
+ new_msr |= (target_ulong)MSR_HVB;
+ }
ail = 0;
/* machine check exceptions don't have ME set */
@@ -391,8 +396,17 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
msr |= 0x10000;
new_msr |= ((target_ulong)1 << MSR_ME);
}
-
- new_msr |= (target_ulong)MSR_HVB;
+ if (env->msr_mask & MSR_HVB) {
+ /* ISA specifies HV, but can be delivered to guest with HV clear
+ * (e.g., see FWNMI in PAPR, NMI injection in QEMU).
+ */
+ new_msr |= (target_ulong)MSR_HVB;
+ } else {
+ if (msr_pow) {
+ cpu_abort(cs, "Trying to deliver power-saving system reset "
+ "exception %d with no HV support\n", excp);
+ }
+ }
ail = 0;
break;
case POWERPC_EXCP_DSEG: /* Data segment exception */
@@ -609,9 +623,15 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
env->spr[srr1] = msr;
/* Sanity check */
- if (!(env->msr_mask & MSR_HVB) && (srr0 == SPR_HSRR0)) {
- cpu_abort(cs, "Trying to deliver HV exception %d with "
- "no HV support\n", excp);
+ if (!(env->msr_mask & MSR_HVB)) {
+ if (new_msr & MSR_HVB) {
+ cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
+ "no HV support\n", excp);
+ }
+ if (srr0 == SPR_HSRR0) {
+ cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
+ "no HV support\n", excp);
+ }
}
/* If any alternate SRR register are defined, duplicate saved values */