summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-09-10 15:08:34 +0000
committerEdgar E. Iglesias <edgar.iglesias@gmail.com>2010-09-15 16:18:33 +0200
commit41557447d30eeb944e42069513df13585f5e6c7f (patch)
tree5c4382b8e922a57aab31d9b169b6fa3bf97b849d
parentf844c817d726cd2bdb431aa41c8217891ede2eaf (diff)
downloadqemu-41557447d30eeb944e42069513df13585f5e6c7f.tar.gz
qemu-41557447d30eeb944e42069513df13585f5e6c7f.tar.bz2
qemu-41557447d30eeb944e42069513df13585f5e6c7f.zip
PPC: Redesign interrupt trigger path
According to the Book3S spec, the interrupt context starts with an MSR value that is rather simple. If we leave out the HV case, it's almost always 0. To reflect this, let's redesign the way that MSR value gets calculated. Using this, we also squash the bug where MSR_POW can slip through into the interrupt handler MSR. Reported-by: Thomas Monjalon <thomas.monjalon@openwide.fr> Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
-rw-r--r--target-ppc/helper.c80
1 files changed, 29 insertions, 51 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index a7ec1f458d..f865d7ae4c 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2073,18 +2073,24 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
" => %08x (%02x)\n", env->nip, excp, env->error_code);
- msr = env->msr;
- new_msr = msr;
+
+ /* new srr1 value excluding must-be-zero bits */
+ msr = env->msr & ~0x783f0000ULL;
+
+ /* new interrupt handler msr */
+ new_msr = env->msr & ((target_ulong)1 << MSR_ME);
+
+ /* target registers */
srr0 = SPR_SRR0;
srr1 = SPR_SRR1;
asrr0 = -1;
asrr1 = -1;
+
switch (excp) {
case POWERPC_EXCP_NONE:
/* Should never happen */
return;
case POWERPC_EXCP_CRITICAL: /* Critical input */
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
switch (excp_model) {
case POWERPC_EXCP_40x:
srr0 = SPR_40x_SRR2;
@@ -2115,12 +2121,14 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
env->halted = 1;
env->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
- new_msr &= ~((target_ulong)1 << MSR_RI);
- new_msr &= ~((target_ulong)1 << MSR_ME);
if (0) {
/* XXX: find a suitable condition to enable the hypervisor mode */
new_msr |= (target_ulong)MSR_HVB;
}
+
+ /* machine check exceptions don't have ME set */
+ new_msr &= ~((target_ulong)1 << MSR_ME);
+
/* XXX: should also have something loaded in DAR / DSISR */
switch (excp_model) {
case POWERPC_EXCP_40x:
@@ -2140,25 +2148,21 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
case POWERPC_EXCP_DSI: /* Data storage exception */
LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
"\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
goto store_next;
case POWERPC_EXCP_ISI: /* Instruction storage exception */
LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
"\n", msr, env->nip);
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
msr |= env->error_code;
goto store_next;
case POWERPC_EXCP_EXTERNAL: /* External input */
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes0 == 1)
new_msr |= (target_ulong)MSR_HVB;
goto store_next;
case POWERPC_EXCP_ALIGN: /* Alignment exception */
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
/* XXX: this is false */
@@ -2174,7 +2178,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
env->error_code = 0;
return;
}
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
msr |= 0x00100000;
@@ -2184,19 +2187,16 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
break;
case POWERPC_EXCP_INVAL:
LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
msr |= 0x00080000;
break;
case POWERPC_EXCP_PRIV:
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
msr |= 0x00040000;
break;
case POWERPC_EXCP_TRAP:
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
msr |= 0x00020000;
@@ -2209,7 +2209,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
}
goto store_current;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
goto store_current;
@@ -2226,23 +2225,19 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
}
}
dump_syscall(env);
- new_msr &= ~((target_ulong)1 << MSR_RI);
lev = env->error_code;
if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
new_msr |= (target_ulong)MSR_HVB;
goto store_next;
case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
- new_msr &= ~((target_ulong)1 << MSR_RI);
goto store_current;
case POWERPC_EXCP_DECR: /* Decrementer exception */
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
goto store_next;
case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
/* FIT on 4xx */
LOG_EXCP("FIT exception\n");
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
goto store_next;
case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
LOG_EXCP("WDT exception\n");
@@ -2254,13 +2249,10 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
default:
break;
}
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
goto store_next;
case POWERPC_EXCP_DTLB: /* Data TLB error */
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
goto store_next;
case POWERPC_EXCP_ITLB: /* Instruction TLB error */
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
goto store_next;
case POWERPC_EXCP_DEBUG: /* Debug interrupt */
switch (excp_model) {
@@ -2277,7 +2269,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
cpu_abort(env, "Debug exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
goto store_current;
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
/* XXX: TODO */
@@ -2290,7 +2281,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
"is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
- new_msr &= ~((target_ulong)1 << MSR_RI);
/* XXX: TODO */
cpu_abort(env,
"Performance counter exception is not implemented yet !\n");
@@ -2314,19 +2304,23 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
"is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_RESET: /* System reset exception */
- new_msr &= ~((target_ulong)1 << MSR_RI);
+ if (msr_pow) {
+ /* indicate that we resumed from power save mode */
+ msr |= 0x10000;
+ } else {
+ new_msr &= ~((target_ulong)1 << MSR_ME);
+ }
+
if (0) {
/* XXX: find a suitable condition to enable the hypervisor mode */
new_msr |= (target_ulong)MSR_HVB;
}
goto store_next;
case POWERPC_EXCP_DSEG: /* Data segment exception */
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
goto store_next;
case POWERPC_EXCP_ISEG: /* Instruction segment exception */
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
goto store_next;
@@ -2334,9 +2328,9 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
new_msr |= (target_ulong)MSR_HVB;
+ new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
goto store_next;
case POWERPC_EXCP_TRACE: /* Trace exception */
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
goto store_next;
@@ -2344,30 +2338,32 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
new_msr |= (target_ulong)MSR_HVB;
+ new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
goto store_next;
case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
new_msr |= (target_ulong)MSR_HVB;
+ new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
goto store_next;
case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
new_msr |= (target_ulong)MSR_HVB;
+ new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
goto store_next;
case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
new_msr |= (target_ulong)MSR_HVB;
+ new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
goto store_next;
case POWERPC_EXCP_VPU: /* Vector unavailable exception */
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
goto store_current;
case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
LOG_EXCP("PIT exception\n");
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
goto store_next;
case POWERPC_EXCP_IO: /* IO error exception */
/* XXX: TODO */
@@ -2383,7 +2379,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
"is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
if (lpes1 == 0) /* XXX: check this */
new_msr |= (target_ulong)MSR_HVB;
switch (excp_model) {
@@ -2402,7 +2397,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
}
break;
case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
if (lpes1 == 0) /* XXX: check this */
new_msr |= (target_ulong)MSR_HVB;
switch (excp_model) {
@@ -2421,7 +2415,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
}
break;
case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
- new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
if (lpes1 == 0) /* XXX: check this */
new_msr |= (target_ulong)MSR_HVB;
switch (excp_model) {
@@ -2525,7 +2518,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
"is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
- new_msr &= ~((target_ulong)1 << MSR_RI);
if (lpes1 == 0)
new_msr |= (target_ulong)MSR_HVB;
/* XXX: TODO */
@@ -2579,23 +2571,11 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
/* If we disactivated any translation, flush TLBs */
if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
tlb_flush(env, 1);
- /* reload MSR with correct bits */
- new_msr &= ~((target_ulong)1 << MSR_EE);
- new_msr &= ~((target_ulong)1 << MSR_PR);
- new_msr &= ~((target_ulong)1 << MSR_FP);
- new_msr &= ~((target_ulong)1 << MSR_FE0);
- new_msr &= ~((target_ulong)1 << MSR_SE);
- new_msr &= ~((target_ulong)1 << MSR_BE);
- new_msr &= ~((target_ulong)1 << MSR_FE1);
- new_msr &= ~((target_ulong)1 << MSR_IR);
- new_msr &= ~((target_ulong)1 << MSR_DR);
-#if 0 /* Fix this: not on all targets */
- new_msr &= ~((target_ulong)1 << MSR_PMM);
-#endif
- if (msr_ile)
+
+ if (msr_ile) {
new_msr |= (target_ulong)1 << MSR_LE;
- else
- new_msr &= ~((target_ulong)1 << MSR_LE);
+ }
+
/* Jump to handler */
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
@@ -2606,14 +2586,12 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
#if defined(TARGET_PPC64)
if (excp_model == POWERPC_EXCP_BOOKE) {
if (!msr_icm) {
- new_msr &= ~((target_ulong)1 << MSR_CM);
vector = (uint32_t)vector;
} else {
new_msr |= (target_ulong)1 << MSR_CM;
}
} else {
if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
- new_msr &= ~((target_ulong)1 << MSR_SF);
vector = (uint32_t)vector;
} else {
new_msr |= (target_ulong)1 << MSR_SF;