diff options
Diffstat (limited to 'target/ppc')
| -rw-r--r-- | target/ppc/arch_dump.c | 2 | ||||
| -rw-r--r-- | target/ppc/cpu.h | 25 | ||||
| -rw-r--r-- | target/ppc/cpu_init.c | 2 | ||||
| -rw-r--r-- | target/ppc/excp_helper.c | 185 |
4 files changed, 76 insertions, 138 deletions
diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c index bb392f6d88..993740897d 100644 --- a/target/ppc/arch_dump.c +++ b/target/ppc/arch_dump.c @@ -237,7 +237,7 @@ int cpu_get_dump_info(ArchDumpInfo *info, info->d_machine = PPC_ELF_MACHINE; info->d_class = ELFCLASS; - if (ppc_interrupts_little_endian(cpu)) { + if (ppc_interrupts_little_endian(cpu, cpu->env.has_hv_mode)) { info->d_endian = ELFDATA2LSB; } else { info->d_endian = ELFDATA2MSB; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index f20d4ffa6d..f99cd0ea92 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -2728,20 +2728,29 @@ static inline bool ppc_has_spr(PowerPCCPU *cpu, int spr) return cpu->env.spr_cb[spr].name != NULL; } -static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu) +#if !defined(CONFIG_USER_ONLY) +static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu, bool hv) { PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); + CPUPPCState *env = &cpu->env; + bool ile; + + if (hv && env->has_hv_mode) { + if (is_isa300(pcc)) { + ile = !!(env->spr[SPR_HID0] & HID0_POWER9_HILE); + } else { + ile = !!(env->spr[SPR_HID0] & HID0_HILE); + } - /* - * Only models that have an LPCR and know about LPCR_ILE can do little - * endian. - */ - if (pcc->lpcr_mask & LPCR_ILE) { - return !!(cpu->env.spr[SPR_LPCR] & LPCR_ILE); + } else if (pcc->lpcr_mask & LPCR_ILE) { + ile = !!(env->spr[SPR_LPCR] & LPCR_ILE); + } else { + ile = !!(msr_ile); } - return false; + return ile; } +#endif void dump_mmu(CPUPPCState *env); diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index cc93bff3fa..e30e86fe9d 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6953,10 +6953,12 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data) PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX | + PPC_FLOAT_EXT | PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_64B | + PPC_POPCNTB | PPC_SEGMENT_64B | PPC_SLBI; pcc->insns_flags2 = PPC2_FP_CVT_S64; pcc->msr_mask = (1ull << MSR_SF) | diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index a779dc936a..bc646c67a0 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -30,8 +30,6 @@ #include "exec/cpu_ldst.h" #endif -/* #define DEBUG_SOFTWARE_TLB */ - /*****************************************************************************/ /* Exception processing */ #if !defined(CONFIG_USER_ONLY) @@ -135,6 +133,39 @@ static void dump_hcall(CPUPPCState *env) env->nip); } +static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) +{ + const char *es; + target_ulong *miss, *cmp; + int en; + + if (!qemu_loglevel_mask(CPU_LOG_MMU)) { + return; + } + + if (excp == POWERPC_EXCP_IFTLB) { + es = "I"; + en = 'I'; + miss = &env->spr[SPR_IMISS]; + cmp = &env->spr[SPR_ICMP]; + } else { + if (excp == POWERPC_EXCP_DLTLB) { + es = "DL"; + } else { + es = "DS"; + } + en = 'D'; + miss = &env->spr[SPR_DMISS]; + cmp = &env->spr[SPR_DCMP]; + } + qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " + TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " + TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, + env->spr[SPR_HASH1], env->spr[SPR_HASH2], + env->error_code); +} + + static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, target_ulong *msr) { @@ -365,7 +396,7 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt */ -static void powerpc_excp(PowerPCCPU *cpu, int excp) +static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -669,23 +700,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ env->spr[SPR_BOOKE_ESR] = ESR_SPV; break; - case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "Embedded floating point data exception " - "is not implemented yet !\n"); - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "Embedded floating point round exception " - "is not implemented yet !\n"); - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ - /* XXX: TODO */ - cpu_abort(cs, - "Performance counter exception is not implemented yet !\n"); - break; case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ break; case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ @@ -750,19 +764,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ trace_ppc_excp_print("PIT"); break; - case POWERPC_EXCP_IO: /* IO error exception */ - /* XXX: TODO */ - cpu_abort(cs, "601 IO error exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_RUNM: /* Run mode exception */ - /* XXX: TODO */ - cpu_abort(cs, "601 run mode exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_EMUL: /* Emulation trap exception */ - /* XXX: TODO */ - cpu_abort(cs, "602 emulation trap exception " - "is not implemented yet !\n"); - break; case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ @@ -777,34 +778,8 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) } /* fall through */ case POWERPC_EXCP_7x5: -#if defined(DEBUG_SOFTWARE_TLB) - if (qemu_log_enabled()) { - const char *es; - target_ulong *miss, *cmp; - int en; - - if (excp == POWERPC_EXCP_IFTLB) { - es = "I"; - en = 'I'; - miss = &env->spr[SPR_IMISS]; - cmp = &env->spr[SPR_ICMP]; - } else { - if (excp == POWERPC_EXCP_DLTLB) { - es = "DL"; - } else { - es = "DS"; - } - en = 'D'; - miss = &env->spr[SPR_DMISS]; - cmp = &env->spr[SPR_DCMP]; - } - qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " - TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " - TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, - env->spr[SPR_HASH1], env->spr[SPR_HASH2], - env->error_code); - } -#endif + ppc_excp_debug_sw_tlb(env, excp); + msr |= env->crf[0] << 28; msr |= env->error_code; /* key, D/I, S/L bits */ /* Set way using a LRU mechanism */ @@ -815,56 +790,25 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) break; } break; + case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ + case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ + case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ + case POWERPC_EXCP_IO: /* IO error exception */ + case POWERPC_EXCP_RUNM: /* Run mode exception */ + case POWERPC_EXCP_EMUL: /* Emulation trap exception */ case POWERPC_EXCP_FPA: /* Floating-point assist exception */ - /* XXX: TODO */ - cpu_abort(cs, "Floating point assist exception " - "is not implemented yet !\n"); - break; case POWERPC_EXCP_DABR: /* Data address breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "DABR exception is not implemented yet !\n"); - break; case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "IABR exception is not implemented yet !\n"); - break; case POWERPC_EXCP_SMI: /* System management interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "SMI exception is not implemented yet !\n"); - break; case POWERPC_EXCP_THERM: /* Thermal interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "Thermal management exception " - "is not implemented yet !\n"); - break; case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ - /* XXX: TODO */ - cpu_abort(cs, - "Performance counter exception is not implemented yet !\n"); - break; case POWERPC_EXCP_VPUA: /* Vector assist exception */ - /* XXX: TODO */ - cpu_abort(cs, "VPU assist exception is not implemented yet !\n"); - break; case POWERPC_EXCP_SOFTP: /* Soft patch exception */ - /* XXX: TODO */ - cpu_abort(cs, - "970 soft-patch exception is not implemented yet !\n"); - break; case POWERPC_EXCP_MAINT: /* Maintenance exception */ - /* XXX: TODO */ - cpu_abort(cs, - "970 maintenance exception is not implemented yet !\n"); - break; case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "Maskable external exception " - "is not implemented yet !\n"); - break; case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "Non maskable external exception " - "is not implemented yet !\n"); + cpu_abort(cs, "%s exception not implemented\n", + powerpc_excp_name(excp)); break; default: excp_invalid: @@ -888,36 +832,9 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) * Sort out endianness of interrupt, this differs depending on the * CPU, the HV mode, etc... */ -#ifdef TARGET_PPC64 - if (excp_model == POWERPC_EXCP_POWER7) { - if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (excp_model == POWERPC_EXCP_POWER8) { - if (new_msr & MSR_HVB) { - if (env->spr[SPR_HID0] & HID0_HILE) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (env->spr[SPR_LPCR] & LPCR_ILE) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (excp_model == POWERPC_EXCP_POWER9 || - excp_model == POWERPC_EXCP_POWER10) { - if (new_msr & MSR_HVB) { - if (env->spr[SPR_HID0] & HID0_POWER9_HILE) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (env->spr[SPR_LPCR] & LPCR_ILE) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (msr_ile) { + if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { new_msr |= (target_ulong)1 << MSR_LE; } -#else - if (msr_ile) { - new_msr |= (target_ulong)1 << MSR_LE; - } -#endif #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_BOOKE) { @@ -950,6 +867,16 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) powerpc_set_excp_state(cpu, vector, new_msr); } +static void powerpc_excp(PowerPCCPU *cpu, int excp) +{ + CPUPPCState *env = &cpu->env; + + switch (env->excp_model) { + default: + powerpc_excp_legacy(cpu, excp); + } +} + void ppc_cpu_do_interrupt(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -1126,7 +1053,7 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) */ msr = (1ULL << MSR_ME); msr |= env->msr & (1ULL << MSR_SF); - if (ppc_interrupts_little_endian(cpu)) { + if (ppc_interrupts_little_endian(cpu, false)) { msr |= (1ULL << MSR_LE); } |