X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/3978f4612e7aa90469f6b1e0a04524833e77fbc6..765b842adec4c5a359e69ca08785553599f71496:/target-ppc/excp_helper.c diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index 1a593f6f3f..4250106b34 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -17,7 +17,8 @@ * License along with this library; if not, see . */ #include "cpu.h" -#include "helper.h" +#include "exec/helper-proto.h" +#include "exec/cpu_ldst.h" #include "helper_regs.h" @@ -33,20 +34,25 @@ /*****************************************************************************/ /* PowerPC Hypercall emulation */ -void (*cpu_ppc_hypercall)(CPUPPCState *); +void (*cpu_ppc_hypercall)(PowerPCCPU *); /*****************************************************************************/ /* Exception processing */ #if defined(CONFIG_USER_ONLY) -void do_interrupt(CPUPPCState *env) +void ppc_cpu_do_interrupt(CPUState *cs) { - env->exception_index = POWERPC_EXCP_NONE; + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + cs->exception_index = POWERPC_EXCP_NONE; env->error_code = 0; } -void ppc_hw_interrupt(CPUPPCState *env) +static void ppc_hw_interrupt(CPUPPCState *env) { - env->exception_index = POWERPC_EXCP_NONE; + CPUState *cs = CPU(ppc_env_get_cpu(env)); + + cs->exception_index = POWERPC_EXCP_NONE; env->error_code = 0; } #else /* defined(CONFIG_USER_ONLY) */ @@ -63,8 +69,10 @@ static inline void dump_syscall(CPUPPCState *env) /* Note that this function should be greatly optimized * when called with a constant excp, from ppc_hw_interrupt */ -static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) +static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) { + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; target_ulong msr, new_msr, vector; int srr0, srr1, asrr0, asrr1; int lpes0, lpes1, lev; @@ -83,7 +91,11 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) " => %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); @@ -126,8 +138,8 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) fprintf(stderr, "Machine check while not allowed. " "Entering checkstop state\n"); } - env->halted = 1; - env->interrupt_request |= CPU_INTERRUPT_EXITTB; + cs->halted = 1; + cs->interrupt_request |= CPU_INTERRUPT_EXITTB; } if (0) { /* XXX: find a suitable condition to enable the hypervisor mode */ @@ -144,6 +156,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) 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; @@ -169,9 +182,15 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) msr |= env->error_code; goto store_next; case POWERPC_EXCP_EXTERNAL: /* External input */ + cs = CPU(cpu); + 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(cs->as, env->mpic_iack); + } goto store_next; case POWERPC_EXCP_ALIGN: /* Alignment exception */ if (lpes1 == 0) { @@ -181,13 +200,13 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) /* Get rS/rD and rA from faulting opcode */ env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4)) & 0x03FF0000) >> 16; - goto store_current; + goto store_next; case POWERPC_EXCP_PROGRAM: /* Program exception */ switch (env->error_code & ~0xF) { case POWERPC_EXCP_FP: if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { LOG_EXCP("Ignore floating point exception\n"); - env->exception_index = POWERPC_EXCP_NONE; + cs->exception_index = POWERPC_EXCP_NONE; env->error_code = 0; return; } @@ -224,7 +243,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) break; default: /* Should never occur */ - cpu_abort(env, "Invalid program exception %d. Aborting\n", + cpu_abort(cs, "Invalid program exception %d. Aborting\n", env->error_code); break; } @@ -238,7 +257,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) 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)) { @@ -274,6 +293,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) 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; @@ -283,26 +303,26 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) break; } /* XXX: TODO */ - cpu_abort(env, "Debug exception is not implemented yet !\n"); + cpu_abort(cs, "Debug exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */ env->spr[SPR_BOOKE_ESR] = ESR_SPV; goto store_current; case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ /* XXX: TODO */ - cpu_abort(env, "Embedded floating point data exception " + cpu_abort(cs, "Embedded floating point data exception " "is not implemented yet !\n"); env->spr[SPR_BOOKE_ESR] = ESR_SPV; goto store_next; case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ /* XXX: TODO */ - cpu_abort(env, "Embedded floating point round exception " + cpu_abort(cs, "Embedded floating point round exception " "is not implemented yet !\n"); env->spr[SPR_BOOKE_ESR] = ESR_SPV; goto store_next; case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ /* XXX: TODO */ - cpu_abort(env, + cpu_abort(cs, "Performance counter exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ @@ -374,20 +394,30 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) new_msr |= (target_ulong)MSR_HVB; } goto store_current; + case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ + if (lpes1 == 0) { + new_msr |= (target_ulong)MSR_HVB; + } + goto store_current; + case POWERPC_EXCP_FU: /* Facility unavailable exception */ + 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"); goto store_next; case POWERPC_EXCP_IO: /* IO error exception */ /* XXX: TODO */ - cpu_abort(env, "601 IO error exception is not implemented yet !\n"); + cpu_abort(cs, "601 IO error exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_RUNM: /* Run mode exception */ /* XXX: TODO */ - cpu_abort(env, "601 run mode exception is not implemented yet !\n"); + cpu_abort(cs, "601 run mode exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_EMUL: /* Emulation trap exception */ /* XXX: TODO */ - cpu_abort(env, "602 emulation trap exception " + cpu_abort(cs, "602 emulation trap exception " "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ @@ -405,7 +435,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) case POWERPC_EXCP_74xx: goto tlb_miss_74xx; default: - cpu_abort(env, "Invalid instruction TLB miss exception\n"); + cpu_abort(cs, "Invalid instruction TLB miss exception\n"); break; } break; @@ -424,7 +454,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) case POWERPC_EXCP_74xx: goto tlb_miss_74xx; default: - cpu_abort(env, "Invalid data load TLB miss exception\n"); + cpu_abort(cs, "Invalid data load TLB miss exception\n"); break; } break; @@ -510,30 +540,30 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) msr |= env->error_code; /* key bit */ break; default: - cpu_abort(env, "Invalid data store TLB miss exception\n"); + cpu_abort(cs, "Invalid data store TLB miss exception\n"); break; } goto store_next; case POWERPC_EXCP_FPA: /* Floating-point assist exception */ /* XXX: TODO */ - cpu_abort(env, "Floating point assist exception " + cpu_abort(cs, "Floating point assist exception " "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_DABR: /* Data address breakpoint */ /* XXX: TODO */ - cpu_abort(env, "DABR exception is not implemented yet !\n"); + cpu_abort(cs, "DABR exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ /* XXX: TODO */ - cpu_abort(env, "IABR exception is not implemented yet !\n"); + cpu_abort(cs, "IABR exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_SMI: /* System management interrupt */ /* XXX: TODO */ - cpu_abort(env, "SMI exception is not implemented yet !\n"); + cpu_abort(cs, "SMI exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_THERM: /* Thermal interrupt */ /* XXX: TODO */ - cpu_abort(env, "Thermal management exception " + cpu_abort(cs, "Thermal management exception " "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ @@ -541,36 +571,36 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) new_msr |= (target_ulong)MSR_HVB; } /* XXX: TODO */ - cpu_abort(env, + cpu_abort(cs, "Performance counter exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_VPUA: /* Vector assist exception */ /* XXX: TODO */ - cpu_abort(env, "VPU assist exception is not implemented yet !\n"); + cpu_abort(cs, "VPU assist exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_SOFTP: /* Soft patch exception */ /* XXX: TODO */ - cpu_abort(env, + cpu_abort(cs, "970 soft-patch exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_MAINT: /* Maintenance exception */ /* XXX: TODO */ - cpu_abort(env, + cpu_abort(cs, "970 maintenance exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ /* XXX: TODO */ - cpu_abort(env, "Maskable external exception " + cpu_abort(cs, "Maskable external exception " "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ /* XXX: TODO */ - cpu_abort(env, "Non maskable external exception " + cpu_abort(cs, "Non maskable external exception " "is not implemented yet !\n"); goto store_next; default: excp_invalid: - cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp); + cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); break; store_current: /* save current instruction location */ @@ -590,19 +620,32 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) if (asrr1 != -1) { env->spr[asrr1] = env->spr[srr1]; } - /* If we disactivated any translation, flush TLBs */ - if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) { - tlb_flush(env, 1); + + if (env->spr[SPR_LPCR] & LPCR_AIL) { + new_msr |= (1 << MSR_IR) | (1 << MSR_DR); + } else if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) { + /* If we disactivated any translation, flush TLBs */ + tlb_flush(cs, 1); } +#ifdef TARGET_PPC64 + if (excp_model == POWERPC_EXCP_POWER7) { + if (env->spr[SPR_LPCR] & LPCR_ILE) { + new_msr |= (target_ulong)1 << MSR_LE; + } + } else if (msr_ile) { + new_msr |= (target_ulong)1 << MSR_LE; + } +#else if (msr_ile) { new_msr |= (target_ulong)1 << MSR_LE; } +#endif /* Jump to handler */ vector = env->excp_vectors[excp]; if (vector == (target_ulong)-1ULL) { - cpu_abort(env, "Raised an exception without defined vector %d\n", + cpu_abort(cs, "Raised an exception without defined vector %d\n", excp); } vector |= env->excp_prefix; @@ -629,7 +672,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) hreg_compute_hflags(env); env->nip = vector; /* Reset exception state */ - env->exception_index = POWERPC_EXCP_NONE; + cs->exception_index = POWERPC_EXCP_NONE; env->error_code = 0; if ((env->mmu_model == POWERPC_MMU_BOOKE) || @@ -637,41 +680,46 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) /* XXX: The BookE changes address space when switching modes, we should probably implement that as different MMU indexes, but for the moment we do it the slow way and flush all. */ - tlb_flush(env, 1); + tlb_flush(cs, 1); } } -void do_interrupt(CPUPPCState *env) +void ppc_cpu_do_interrupt(CPUState *cs) { - powerpc_excp(env, env->excp_model, env->exception_index); + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + powerpc_excp(cpu, env->excp_model, cs->exception_index); } -void ppc_hw_interrupt(CPUPPCState *env) +static void ppc_hw_interrupt(CPUPPCState *env) { + 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)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); return; } /* Machine check exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK); return; } #if 0 /* TODO */ /* External debug exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG); return; } #endif @@ -684,8 +732,7 @@ void ppc_hw_interrupt(CPUPPCState *env) if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) { /* Hypervisor decrementer exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { - env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); return; } } @@ -698,7 +745,7 @@ void ppc_hw_interrupt(CPUPPCState *env) #if 0 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT); #endif - powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL); return; } } @@ -706,30 +753,32 @@ void ppc_hw_interrupt(CPUPPCState *env) /* Watchdog timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI); return; } /* Fixed interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT); return; } /* Programmable interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT); return; } /* Decrementer exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) { - env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR); + if (ppc_decr_clear_on_delivery(env)) { + env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); + } + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR); return; } /* External interrupt */ @@ -740,29 +789,52 @@ void ppc_hw_interrupt(CPUPPCState *env) #if 0 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT); #endif - powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM); return; } /* Thermal interrupt */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM); return; } } } + +void ppc_cpu_do_system_reset(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); +} #endif /* !CONFIG_USER_ONLY */ +bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + if (interrupt_request & CPU_INTERRUPT_HARD) { + ppc_hw_interrupt(env); + if (env->pending_interrupts == 0) { + cs->interrupt_request &= ~CPU_INTERRUPT_HARD; + } + return true; + } + return false; +} + #if defined(DEBUG_OP) static void cpu_dump_rfi(target_ulong RA, target_ulong msr) { @@ -777,12 +849,14 @@ static void cpu_dump_rfi(target_ulong RA, target_ulong msr) void helper_raise_exception_err(CPUPPCState *env, uint32_t exception, uint32_t error_code) { + CPUState *cs = CPU(ppc_env_get_cpu(env)); + #if 0 printf("Raise exception %3x code : %d\n", exception, error_code); #endif - env->exception_index = exception; + cs->exception_index = exception; env->error_code = error_code; - cpu_loop_exit(env); + cpu_loop_exit(cs); } void helper_raise_exception(CPUPPCState *env, uint32_t exception) @@ -793,9 +867,12 @@ void helper_raise_exception(CPUPPCState *env, uint32_t exception) #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); } } @@ -803,6 +880,8 @@ void helper_store_msr(CPUPPCState *env, target_ulong 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; @@ -827,13 +906,18 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr, /* 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) @@ -860,20 +944,22 @@ void helper_40x_rfci(CPUPPCState *env) 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 @@ -953,16 +1039,19 @@ void helper_msgsnd(target_ulong rb) { int irq = dbell2irq(rb); int pir = rb & DBELL_PIRTAG_MASK; - CPUPPCState *cenv; + CPUState *cs; if (irq < 0) { return; } - for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) { + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *cenv = &cpu->env; + if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) { cenv->pending_interrupts |= 1 << irq; - cpu_interrupt(cenv, CPU_INTERRUPT_HARD); + cpu_interrupt(cs, CPU_INTERRUPT_HARD); } } }