/*****************************************************************************/
/* PowerPC Hypercall emulation */
-void (*cpu_ppc_hypercall)(CPUPPCState *);
+void (*cpu_ppc_hypercall)(PowerPCCPU *);
/*****************************************************************************/
/* Exception processing */
static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
{
CPUPPCState *env = &cpu->env;
+ CPUState *cs;
target_ulong msr, new_msr, vector;
int srr0, srr1, asrr0, asrr1;
int lpes0, lpes1, lev;
" => %08x (%02x)\n", env->nip, excp, env->error_code);
/* new srr1 value excluding must-be-zero bits */
- msr = env->msr & ~0x783f0000ULL;
+ if (excp_model == POWERPC_EXCP_BOOKE) {
+ msr = env->msr;
+ } else {
+ msr = env->msr & ~0x783f0000ULL;
+ }
/* new interrupt handler msr */
new_msr = env->msr & ((target_ulong)1 << MSR_ME);
fprintf(stderr, "Machine check while not allowed. "
"Entering checkstop state\n");
}
- env->halted = 1;
- env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ cs = CPU(cpu);
+ cs->halted = 1;
+ cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
if (0) {
/* XXX: find a suitable condition to enable the hypervisor mode */
srr1 = SPR_40x_SRR3;
break;
case POWERPC_EXCP_BOOKE:
+ /* FIXME: choose one or the other based on CPU type */
srr0 = SPR_BOOKE_MCSRR0;
srr1 = SPR_BOOKE_MCSRR1;
asrr0 = SPR_BOOKE_CSRR0;
if (lpes0 == 1) {
new_msr |= (target_ulong)MSR_HVB;
}
+ if (env->mpic_proxy) {
+ /* IACK the IRQ on delivery */
+ env->spr[SPR_BOOKE_EPR] = ldl_phys(env->mpic_iack);
+ }
goto store_next;
case POWERPC_EXCP_ALIGN: /* Alignment exception */
if (lpes1 == 0) {
dump_syscall(env);
lev = env->error_code;
if ((lev == 1) && cpu_ppc_hypercall) {
- cpu_ppc_hypercall(env);
+ cpu_ppc_hypercall(cpu);
return;
}
if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
case POWERPC_EXCP_DEBUG: /* Debug interrupt */
switch (excp_model) {
case POWERPC_EXCP_BOOKE:
+ /* FIXME: choose one or the other based on CPU type */
srr0 = SPR_BOOKE_DSRR0;
srr1 = SPR_BOOKE_DSRR1;
asrr0 = SPR_BOOKE_CSRR0;
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
int hdice;
-
#if 0
+ CPUState *cs = CPU(cpu);
+
qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
- __func__, env, env->pending_interrupts,
- env->interrupt_request, (int)msr_me, (int)msr_ee);
+ __func__, env, env->pending_interrupts,
+ cs->interrupt_request, (int)msr_me, (int)msr_ee);
#endif
/* External reset */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
#if !defined(CONFIG_USER_ONLY)
void helper_store_msr(CPUPPCState *env, target_ulong val)
{
+ CPUState *cs;
+
val = hreg_store_msr(env, val, 0);
if (val != 0) {
- env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ cs = CPU(ppc_env_get_cpu(env));
+ cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
helper_raise_exception(env, val);
}
}
static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
target_ulong msrm, int keep_msrh)
{
+ CPUState *cs = CPU(ppc_env_get_cpu(env));
+
#if defined(TARGET_PPC64)
if (msr_is_64bit(env, msr)) {
nip = (uint64_t)nip;
/* No need to raise an exception here,
* as rfi is always the last insn of a TB
*/
- env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
void helper_rfi(CPUPPCState *env)
{
- do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
- ~((target_ulong)0x783F0000), 1);
+ if (env->excp_model == POWERPC_EXCP_BOOKE) {
+ do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+ ~((target_ulong)0), 0);
+ } else {
+ do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+ ~((target_ulong)0x783F0000), 1);
+ }
}
#if defined(TARGET_PPC64)
void helper_rfci(CPUPPCState *env)
{
- do_rfi(env, env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
- ~((target_ulong)0x3FFF0000), 0);
+ do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
+ ~((target_ulong)0), 0);
}
void helper_rfdi(CPUPPCState *env)
{
- do_rfi(env, env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
- ~((target_ulong)0x3FFF0000), 0);
+ /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
+ do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
+ ~((target_ulong)0), 0);
}
void helper_rfmci(CPUPPCState *env)
{
- do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
- ~((target_ulong)0x3FFF0000), 0);
+ /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
+ do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
+ ~((target_ulong)0), 0);
}
#endif