diff options
Diffstat (limited to 'target/ppc/excp_helper.c')
-rw-r--r-- | target/ppc/excp_helper.c | 130 |
1 files changed, 87 insertions, 43 deletions
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index f052979664..a988ba15f4 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -67,19 +67,31 @@ static inline void dump_syscall(CPUPPCState *env) ppc_dump_gpr(env, 8), env->nip); } +static inline void dump_syscall_vectored(CPUPPCState *env) +{ + qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 + " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 + " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 + " nip=" TARGET_FMT_lx "\n", + ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), + ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), + ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7), + ppc_dump_gpr(env, 8), env->nip); +} + static inline void dump_hcall(CPUPPCState *env) { qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 - " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 - " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 - " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 + " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 + " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 + " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 " nip=" TARGET_FMT_lx "\n", ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4), - ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), - ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), - ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), - ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), - env->nip); + ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), + ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), + ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), + ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), + env->nip); } static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, @@ -89,7 +101,7 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, env->resume_as_sreset = false; /* Pretend to be returning from doze always as we don't lose state */ - *msr |= (0x1ull << (63 - 47)); + *msr |= SRR1_WS_NOLOSS; /* Machine checks are sent normally */ if (excp == POWERPC_EXCP_MCHECK) { @@ -97,25 +109,25 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, } switch (excp) { case POWERPC_EXCP_RESET: - *msr |= 0x4ull << (63 - 45); + *msr |= SRR1_WAKERESET; break; case POWERPC_EXCP_EXTERNAL: - *msr |= 0x8ull << (63 - 45); + *msr |= SRR1_WAKEEE; break; case POWERPC_EXCP_DECR: - *msr |= 0x6ull << (63 - 45); + *msr |= SRR1_WAKEDEC; break; case POWERPC_EXCP_SDOOR: - *msr |= 0x5ull << (63 - 45); + *msr |= SRR1_WAKEDBELL; break; case POWERPC_EXCP_SDOOR_HV: - *msr |= 0x3ull << (63 - 45); + *msr |= SRR1_WAKEHDBELL; break; case POWERPC_EXCP_HV_MAINT: - *msr |= 0xaull << (63 - 45); + *msr |= SRR1_WAKEHMI; break; case POWERPC_EXCP_HVIRT: - *msr |= 0x9ull << (63 - 45); + *msr |= SRR1_WAKEHVI; break; default: cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", @@ -185,7 +197,7 @@ 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, lev, ail; + int srr0, srr1, asrr0, asrr1, lev = -1, ail; bool lpes0; qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx @@ -421,6 +433,13 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) new_msr |= (target_ulong)MSR_HVB; } break; + case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ + lev = env->error_code; + dump_syscall_vectored(env); + env->nip += 4; + new_msr |= env->msr & ((target_ulong)1 << MSR_EE); + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + break; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ case POWERPC_EXCP_DECR: /* Decrementer exception */ @@ -724,12 +743,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) break; } - /* Save PC */ - env->spr[srr0] = env->nip; - - /* Save MSR */ - env->spr[srr1] = msr; - /* Sanity check */ if (!(env->msr_mask & MSR_HVB)) { if (new_msr & MSR_HVB) { @@ -742,14 +755,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } } - /* If any alternate SRR register are defined, duplicate saved values */ - if (asrr0 != -1) { - env->spr[asrr0] = env->spr[srr0]; - } - if (asrr1 != -1) { - env->spr[asrr1] = env->spr[srr1]; - } - /* * Sort out endianness of interrupt, this differs depending on the * CPU, the HV mode, etc... @@ -784,14 +789,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif - /* Jump to handler */ - vector = env->excp_vectors[excp]; - if (vector == (target_ulong)-1ULL) { - cpu_abort(cs, "Raised an exception without defined vector %d\n", - excp); - } - vector |= env->excp_prefix; - /* * AIL only works if there is no HV transition and we are running * with translations enabled @@ -800,10 +797,21 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) { ail = 0; } - /* Handle AIL */ - if (ail) { - new_msr |= (1 << MSR_IR) | (1 << MSR_DR); - vector |= ppc_excp_vector_offset(cs, ail); + + vector = env->excp_vectors[excp]; + if (vector == (target_ulong)-1ULL) { + cpu_abort(cs, "Raised an exception without defined vector %d\n", + excp); + } + + vector |= env->excp_prefix; + + /* If any alternate SRR register are defined, duplicate saved values */ + if (asrr0 != -1) { + env->spr[asrr0] = env->nip; + } + if (asrr1 != -1) { + env->spr[asrr1] = msr; } #if defined(TARGET_PPC64) @@ -823,6 +831,37 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif + if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { + /* Save PC */ + env->spr[srr0] = env->nip; + + /* Save MSR */ + env->spr[srr1] = msr; + + /* Handle AIL */ + if (ail) { + new_msr |= (1 << MSR_IR) | (1 << MSR_DR); + vector |= ppc_excp_vector_offset(cs, ail); + } + +#if defined(TARGET_PPC64) + } else { + /* scv AIL is a little different */ + if (ail) { + new_msr |= (1 << MSR_IR) | (1 << MSR_DR); + } + if (ail == AIL_C000_0000_0000_4000) { + vector |= 0xc000000000003000ull; + } else { + vector |= 0x0000000000017000ull; + } + vector += lev * 0x20; + + env->lr = env->nip; + env->ctr = msr; +#endif + } + powerpc_set_excp_state(cpu, vector, new_msr); } @@ -1160,6 +1199,11 @@ void helper_rfid(CPUPPCState *env) do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]); } +void helper_rfscv(CPUPPCState *env) +{ + do_rfi(env, env->lr, env->ctr); +} + void helper_hrfid(CPUPPCState *env) { do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); |