diff options
Diffstat (limited to 'target/ppc')
-rw-r--r-- | target/ppc/cpu-qom.h | 27 | ||||
-rw-r--r-- | target/ppc/cpu.h | 30 | ||||
-rw-r--r-- | target/ppc/gdbstub.c | 14 | ||||
-rw-r--r-- | target/ppc/kvm.c | 41 | ||||
-rw-r--r-- | target/ppc/machine.c | 23 | ||||
-rw-r--r-- | target/ppc/mmu-hash64.c | 152 | ||||
-rw-r--r-- | target/ppc/mmu-hash64.h | 48 | ||||
-rw-r--r-- | target/ppc/mmu_helper.c | 24 | ||||
-rw-r--r-- | target/ppc/translate.c | 14 | ||||
-rw-r--r-- | target/ppc/translate_init.c | 137 |
10 files changed, 256 insertions, 254 deletions
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index deaa46a14b..433a71e484 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -68,34 +68,17 @@ enum powerpc_mmu_t { /* PowerPC 601 MMU model (specific BATs format) */ POWERPC_MMU_601 = 0x0000000A, #define POWERPC_MMU_64 0x00010000 -#define POWERPC_MMU_1TSEG 0x00020000 -#define POWERPC_MMU_AMR 0x00040000 -#define POWERPC_MMU_64K 0x00080000 -#define POWERPC_MMU_V3 0x00100000 /* ISA V3.00 MMU Support */ /* 64 bits PowerPC MMU */ POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001, /* Architecture 2.03 and later (has LPCR) */ POWERPC_MMU_2_03 = POWERPC_MMU_64 | 0x00000002, /* Architecture 2.06 variant */ - POWERPC_MMU_2_06 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG - | POWERPC_MMU_64K - | POWERPC_MMU_AMR | 0x00000003, + POWERPC_MMU_2_06 = POWERPC_MMU_64 | 0x00000003, /* Architecture 2.07 variant */ - POWERPC_MMU_2_07 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG - | POWERPC_MMU_64K - | POWERPC_MMU_AMR | 0x00000004, + POWERPC_MMU_2_07 = POWERPC_MMU_64 | 0x00000004, /* Architecture 3.00 variant */ - POWERPC_MMU_3_00 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG - | POWERPC_MMU_64K - | POWERPC_MMU_AMR | POWERPC_MMU_V3 - | 0x00000005, + POWERPC_MMU_3_00 = POWERPC_MMU_64 | 0x00000005, }; -#define POWERPC_MMU_VER(x) ((x) & (POWERPC_MMU_64 | 0xFFFF)) -#define POWERPC_MMU_VER_64B POWERPC_MMU_VER(POWERPC_MMU_64B) -#define POWERPC_MMU_VER_2_03 POWERPC_MMU_VER(POWERPC_MMU_2_03) -#define POWERPC_MMU_VER_2_06 POWERPC_MMU_VER(POWERPC_MMU_2_06) -#define POWERPC_MMU_VER_2_07 POWERPC_MMU_VER(POWERPC_MMU_2_07) -#define POWERPC_MMU_VER_3_00 POWERPC_MMU_VER(POWERPC_MMU_3_00) /*****************************************************************************/ /* Exception model */ @@ -164,7 +147,7 @@ enum powerpc_input_t { PPC_FLAGS_INPUT_RCPU, }; -struct ppc_segment_page_sizes; +typedef struct PPCHash64Options PPCHash64Options; /** * PowerPCCPUClass: @@ -198,7 +181,7 @@ typedef struct PowerPCCPUClass { uint32_t flags; int bfd_mach; uint32_t l1_dcache_size, l1_icache_size; - const struct ppc_segment_page_sizes *sps; + const PPCHash64Options *hash64_opts; struct ppc_radix_page_info *radix_page_info; void (*init_proc)(CPUPPCState *env); int (*check_pow)(CPUPPCState *env); diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index c621a6bd5e..8c9e03f54d 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -327,11 +327,13 @@ union ppc_tlb_t { #define TLB_MAS 3 #endif +typedef struct PPCHash64SegmentPageSizes PPCHash64SegmentPageSizes; + typedef struct ppc_slb_t ppc_slb_t; struct ppc_slb_t { uint64_t esid; uint64_t vsid; - const struct ppc_one_seg_page_size *sps; + const PPCHash64SegmentPageSizes *sps; }; #define MAX_SLB_ENTRIES 64 @@ -948,28 +950,8 @@ enum { #define DBELL_PROCIDTAG_MASK PPC_BITMASK(44, 63) -/*****************************************************************************/ -/* Segment page size information, used by recent hash MMUs - * The format of this structure mirrors kvm_ppc_smmu_info - */ - #define PPC_PAGE_SIZES_MAX_SZ 8 -struct ppc_one_page_size { - uint32_t page_shift; /* Page shift (or 0) */ - uint32_t pte_enc; /* Encoding in the HPTE (>>12) */ -}; - -struct ppc_one_seg_page_size { - uint32_t page_shift; /* Base page shift of segment (or 0) */ - uint32_t slb_enc; /* SLB encoding for BookS */ - struct ppc_one_page_size enc[PPC_PAGE_SIZES_MAX_SZ]; -}; - -struct ppc_segment_page_sizes { - struct ppc_one_seg_page_size sps[PPC_PAGE_SIZES_MAX_SZ]; -}; - struct ppc_radix_page_info { uint32_t count; uint32_t entries[PPC_PAGE_SIZES_MAX_SZ]; @@ -1043,7 +1025,6 @@ struct CPUPPCState { #if defined(TARGET_PPC64) /* PowerPC 64 SLB area */ ppc_slb_t slb[MAX_SLB_ENTRIES]; - int32_t slb_nr; /* tcg TLB needs flush (deferred slb inval instruction typically) */ #endif /* segment registers */ @@ -1106,10 +1087,8 @@ struct CPUPPCState { uint64_t insns_flags; uint64_t insns_flags2; #if defined(TARGET_PPC64) - struct ppc_segment_page_sizes sps; ppc_slb_t vrma_slb; target_ulong rmls; - bool ci_large_pages; #endif #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) @@ -1227,6 +1206,7 @@ struct PowerPCCPU { PPCVirtualHypervisor *vhyp; Object *intc; int32_t node_id; /* NUMA node this CPU belongs to */ + PPCHash64Options *hash64_opts; /* Fields related to migration compatibility hacks */ bool pre_2_8_migration; @@ -1235,6 +1215,8 @@ struct PowerPCCPU { uint64_t mig_insns_flags2; uint32_t mig_nb_BATs; bool pre_2_10_migration; + bool pre_2_13_migration; + int32_t mig_slb_nr; }; static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env) diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c index 7a338136a8..b6f6693583 100644 --- a/target/ppc/gdbstub.c +++ b/target/ppc/gdbstub.c @@ -37,10 +37,10 @@ static int ppc_gdb_register_len_apple(int n) case 65+32: /* msr */ case 67+32: /* lr */ case 68+32: /* ctr */ - case 69+32: /* xer */ case 70+32: /* fpscr */ return 8; case 66+32: /* cr */ + case 69+32: /* xer */ return 4; default: return 0; @@ -61,6 +61,8 @@ static int ppc_gdb_register_len(int n) return 8; case 66: /* cr */ + case 69: + /* xer */ return 4; case 64: /* nip */ @@ -70,8 +72,6 @@ static int ppc_gdb_register_len(int n) /* lr */ case 68: /* ctr */ - case 69: - /* xer */ return sizeof(target_ulong); case 70: /* fpscr */ @@ -152,7 +152,7 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) gdb_get_regl(mem_buf, env->ctr); break; case 69: - gdb_get_regl(mem_buf, env->xer); + gdb_get_reg32(mem_buf, env->xer); break; case 70: gdb_get_reg32(mem_buf, env->fpscr); @@ -208,7 +208,7 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n) gdb_get_reg64(mem_buf, env->ctr); break; case 69 + 32: - gdb_get_reg64(mem_buf, env->xer); + gdb_get_reg32(mem_buf, env->xer); break; case 70 + 32: gdb_get_reg64(mem_buf, env->fpscr); @@ -259,7 +259,7 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) env->ctr = ldtul_p(mem_buf); break; case 69: - env->xer = ldtul_p(mem_buf); + env->xer = ldl_p(mem_buf); break; case 70: /* fpscr */ @@ -309,7 +309,7 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n) env->ctr = ldq_p(mem_buf); break; case 69 + 32: - env->xer = ldq_p(mem_buf); + env->xer = ldl_p(mem_buf); break; case 70 + 32: /* fpscr */ diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 79a436a384..6de59c5b21 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -302,12 +302,12 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu, /* HV KVM has backing store size restrictions */ info->flags = KVM_PPC_PAGE_SIZES_REAL; - if (env->mmu_model & POWERPC_MMU_1TSEG) { + if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { info->flags |= KVM_PPC_1T_SEGMENTS; } - if (POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_06 || - POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_07) { + if (env->mmu_model == POWERPC_MMU_2_06 || + env->mmu_model == POWERPC_MMU_2_07) { info->slb_size = 32; } else { info->slb_size = 64; @@ -321,8 +321,8 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu, i++; /* 64K on MMU 2.06 and later */ - if (POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_06 || - POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_07) { + if (env->mmu_model == POWERPC_MMU_2_06 || + env->mmu_model == POWERPC_MMU_2_07) { info->sps[i].page_shift = 16; info->sps[i].slb_enc = 0x110; info->sps[i].enc[0].page_shift = 16; @@ -425,7 +425,6 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) static bool has_smmu_info; CPUPPCState *env = &cpu->env; int iq, ik, jq, jk; - bool has_64k_pages = false; /* We only handle page sizes for 64-bit server guests for now */ if (!(env->mmu_model & POWERPC_MMU_64)) { @@ -443,13 +442,17 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) } /* Convert to QEMU form */ - memset(&env->sps, 0, sizeof(env->sps)); + memset(cpu->hash64_opts->sps, 0, sizeof(*cpu->hash64_opts->sps)); /* If we have HV KVM, we need to forbid CI large pages if our * host page size is smaller than 64K. */ if (smmu_info.flags & KVM_PPC_PAGE_SIZES_REAL) { - env->ci_large_pages = getpagesize() >= 0x10000; + if (getpagesize() >= 0x10000) { + cpu->hash64_opts->flags |= PPC_HASH64_CI_LARGEPAGE; + } else { + cpu->hash64_opts->flags &= ~PPC_HASH64_CI_LARGEPAGE; + } } /* @@ -457,7 +460,7 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) * the selected CPU has with the capabilities that KVM supports. */ for (ik = iq = 0; ik < KVM_PPC_PAGE_SIZES_MAX_SZ; ik++) { - struct ppc_one_seg_page_size *qsps = &env->sps.sps[iq]; + PPCHash64SegmentPageSizes *qsps = &cpu->hash64_opts->sps[iq]; struct kvm_ppc_one_seg_page_size *ksps = &smmu_info.sps[ik]; if (!kvm_valid_page_size(smmu_info.flags, max_cpu_page_size, @@ -471,9 +474,6 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) ksps->enc[jk].page_shift)) { continue; } - if (ksps->enc[jk].page_shift == 16) { - has_64k_pages = true; - } qsps->enc[jq].page_shift = ksps->enc[jk].page_shift; qsps->enc[jq].pte_enc = ksps->enc[jk].pte_enc; if (++jq >= PPC_PAGE_SIZES_MAX_SZ) { @@ -484,27 +484,16 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) break; } } - env->slb_nr = smmu_info.slb_size; + cpu->hash64_opts->slb_size = smmu_info.slb_size; if (!(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) { - env->mmu_model &= ~POWERPC_MMU_1TSEG; - } - if (!has_64k_pages) { - env->mmu_model &= ~POWERPC_MMU_64K; + cpu->hash64_opts->flags &= ~PPC_HASH64_1TSEG; } } bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path) { Object *mem_obj = object_resolve_path(obj_path, NULL); - char *mempath = object_property_get_str(mem_obj, "mem-path", NULL); - long pagesize; - - if (mempath) { - pagesize = qemu_mempath_getpagesize(mempath); - g_free(mempath); - } else { - pagesize = getpagesize(); - } + long pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(mem_obj)); return pagesize >= max_cpu_page_size; } diff --git a/target/ppc/machine.c b/target/ppc/machine.c index 0634cdb295..3d6434a006 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -18,6 +18,9 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) unsigned int i, j; target_ulong sdr1; uint32_t fpscr; +#if defined(TARGET_PPC64) + int32_t slb_nr; +#endif target_ulong xer; for (i = 0; i < 32; i++) @@ -49,7 +52,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) qemu_get_sbe32s(f, &env->access_type); #if defined(TARGET_PPC64) qemu_get_betls(f, &env->spr[SPR_ASR]); - qemu_get_sbe32s(f, &env->slb_nr); + qemu_get_sbe32s(f, &slb_nr); #endif qemu_get_betls(f, &sdr1); for (i = 0; i < 32; i++) @@ -146,6 +149,15 @@ static bool cpu_pre_2_8_migration(void *opaque, int version_id) return cpu->pre_2_8_migration; } +#if defined(TARGET_PPC64) +static bool cpu_pre_2_13_migration(void *opaque, int version_id) +{ + PowerPCCPU *cpu = opaque; + + return cpu->pre_2_13_migration; +} +#endif + static int cpu_pre_save(void *opaque) { PowerPCCPU *cpu = opaque; @@ -203,6 +215,11 @@ static int cpu_pre_save(void *opaque) cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2; cpu->mig_nb_BATs = env->nb_BATs; } + if (cpu->pre_2_13_migration) { + if (cpu->hash64_opts) { + cpu->mig_slb_nr = cpu->hash64_opts->slb_size; + } + } return 0; } @@ -478,7 +495,7 @@ static int slb_post_load(void *opaque, int version_id) /* We've pulled in the raw esid and vsid values from the migration * stream, but we need to recompute the page size pointers */ - for (i = 0; i < env->slb_nr; i++) { + for (i = 0; i < cpu->hash64_opts->slb_size; i++) { if (ppc_store_slb(cpu, i, env->slb[i].esid, env->slb[i].vsid) < 0) { /* Migration source had bad values in its SLB */ return -1; @@ -495,7 +512,7 @@ static const VMStateDescription vmstate_slb = { .needed = slb_needed, .post_load = slb_post_load, .fields = (VMStateField[]) { - VMSTATE_INT32_EQUAL(env.slb_nr, PowerPCCPU, NULL), + VMSTATE_INT32_TEST(mig_slb_nr, PowerPCCPU, cpu_pre_2_13_migration), VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, MAX_SLB_ENTRIES), VMSTATE_END_OF_LIST() } diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index c9b72b7429..7e0adecfd9 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -52,7 +52,7 @@ static ppc_slb_t *slb_lookup(PowerPCCPU *cpu, target_ulong eaddr) esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V; esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V; - for (n = 0; n < env->slb_nr; n++) { + for (n = 0; n < cpu->hash64_opts->slb_size; n++) { ppc_slb_t *slb = &env->slb[n]; LOG_SLB("%s: slot %d %016" PRIx64 " %016" @@ -80,7 +80,7 @@ void dump_slb(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu) cpu_synchronize_state(CPU(cpu)); cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n"); - for (i = 0; i < env->slb_nr; i++) { + for (i = 0; i < cpu->hash64_opts->slb_size; i++) { slbe = env->slb[i].esid; slbv = env->slb[i].vsid; if (slbe == 0 && slbv == 0) { @@ -93,10 +93,11 @@ void dump_slb(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu) void helper_slbia(CPUPPCState *env) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); int n; /* XXX: Warning: slbia never invalidates the first segment */ - for (n = 1; n < env->slb_nr; n++) { + for (n = 1; n < cpu->hash64_opts->slb_size; n++) { ppc_slb_t *slb = &env->slb[n]; if (slb->esid & SLB_ESID_V) { @@ -148,10 +149,10 @@ int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot, { CPUPPCState *env = &cpu->env; ppc_slb_t *slb = &env->slb[slot]; - const struct ppc_one_seg_page_size *sps = NULL; + const PPCHash64SegmentPageSizes *sps = NULL; int i; - if (slot >= env->slb_nr) { + if (slot >= cpu->hash64_opts->slb_size) { return -1; /* Bad slot number */ } if (esid & ~(SLB_ESID_ESID | SLB_ESID_V)) { @@ -160,12 +161,12 @@ int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot, if (vsid & (SLB_VSID_B & ~SLB_VSID_B_1T)) { return -1; /* Bad segment size */ } - if ((vsid & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) { + if ((vsid & SLB_VSID_B) && !(ppc_hash64_has(cpu, PPC_HASH64_1TSEG))) { return -1; /* 1T segment on MMU that doesn't support it */ } for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { - const struct ppc_one_seg_page_size *sps1 = &env->sps.sps[i]; + const PPCHash64SegmentPageSizes *sps1 = &cpu->hash64_opts->sps[i]; if (!sps1->page_shift) { break; @@ -202,7 +203,7 @@ static int ppc_load_slb_esid(PowerPCCPU *cpu, target_ulong rb, int slot = rb & 0xfff; ppc_slb_t *slb = &env->slb[slot]; - if (slot >= env->slb_nr) { + if (slot >= cpu->hash64_opts->slb_size) { return -1; } @@ -217,7 +218,7 @@ static int ppc_load_slb_vsid(PowerPCCPU *cpu, target_ulong rb, int slot = rb & 0xfff; ppc_slb_t *slb = &env->slb[slot]; - if (slot >= env->slb_nr) { + if (slot >= cpu->hash64_opts->slb_size) { return -1; } @@ -369,7 +370,7 @@ static int ppc_hash64_amr_prot(PowerPCCPU *cpu, ppc_hash_pte64_t pte) int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; /* Only recent MMUs implement Virtual Page Class Key Protection */ - if (!(env->mmu_model & POWERPC_MMU_AMR)) { + if (!ppc_hash64_has(cpu, PPC_HASH64_AMR)) { return prot; } @@ -451,8 +452,8 @@ void ppc_hash64_unmap_hptes(PowerPCCPU *cpu, const ppc_hash_pte64_t *hptes, false, n * HASH_PTE_SIZE_64); } -static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps, - uint64_t pte0, uint64_t pte1) +static unsigned hpte_page_shift(const PPCHash64SegmentPageSizes *sps, + uint64_t pte0, uint64_t pte1) { int i; @@ -466,7 +467,7 @@ static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps, } for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { - const struct ppc_one_page_size *ps = &sps->enc[i]; + const PPCHash64PageSize *ps = &sps->enc[i]; uint64_t mask; if (!ps->page_shift) { @@ -489,7 +490,7 @@ static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps, } static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, - const struct ppc_one_seg_page_size *sps, + const PPCHash64SegmentPageSizes *sps, target_ulong ptem, ppc_hash_pte64_t *pte, unsigned *pshift) { @@ -543,7 +544,7 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu, CPUPPCState *env = &cpu->env; hwaddr hash, ptex; uint64_t vsid, epnmask, epn, ptem; - const struct ppc_one_seg_page_size *sps = slb->sps; + const PPCHash64SegmentPageSizes *sps = slb->sps; /* The SLB store path should prevent any bad page size encodings * getting in there, so: */ @@ -552,7 +553,7 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu, /* If ISL is set in LPCR we need to clamp the page size to 4K */ if (env->spr[SPR_LPCR] & LPCR_ISL) { /* We assume that when using TCG, 4k is first entry of SPS */ - sps = &env->sps.sps[0]; + sps = &cpu->hash64_opts->sps[0]; assert(sps->page_shift == 12); } @@ -605,7 +606,6 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu, unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, uint64_t pte0, uint64_t pte1) { - CPUPPCState *env = &cpu->env; int i; if (!(pte0 & HPTE64_V_LARGE)) { @@ -617,7 +617,7 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, * this gives an unambiguous result. */ for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { - const struct ppc_one_seg_page_size *sps = &env->sps.sps[i]; + const PPCHash64SegmentPageSizes *sps = &cpu->hash64_opts->sps[i]; unsigned shift; if (!sps->page_shift) { @@ -633,9 +633,9 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, return 0; } -static void ppc_hash64_set_isi(CPUState *cs, CPUPPCState *env, - uint64_t error_code) +static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code) { + CPUPPCState *env = &POWERPC_CPU(cs)->env; bool vpm; if (msr_ir) { @@ -659,9 +659,9 @@ static void ppc_hash64_set_isi(CPUState *cs, CPUPPCState *env, env->error_code = error_code; } -static void ppc_hash64_set_dsi(CPUState *cs, CPUPPCState *env, uint64_t dar, - uint64_t dsisr) +static void ppc_hash64_set_dsi(CPUState *cs, uint64_t dar, uint64_t dsisr) { + CPUPPCState *env = &POWERPC_CPU(cs)->env; bool vpm; if (msr_dr) { @@ -741,13 +741,13 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, } else { /* The access failed, generate the approriate interrupt */ if (rwx == 2) { - ppc_hash64_set_isi(cs, env, SRR1_PROTFAULT); + ppc_hash64_set_isi(cs, SRR1_PROTFAULT); } else { int dsisr = DSISR_PROTFAULT; if (rwx == 1) { dsisr |= DSISR_ISSTORE; } - ppc_hash64_set_dsi(cs, env, eaddr, dsisr); + ppc_hash64_set_dsi(cs, eaddr, dsisr); } return 1; } @@ -762,7 +762,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, slb = slb_lookup(cpu, eaddr); if (!slb) { /* No entry found, check if in-memory segment tables are in use */ - if ((env->mmu_model & POWERPC_MMU_V3) && ppc64_use_proc_tbl(cpu)) { + if (ppc64_use_proc_tbl(cpu)) { /* TODO - Unsupported */ error_report("Segment Table Support Unimplemented"); exit(1); @@ -783,7 +783,7 @@ skip_slb_search: /* 3. Check for segment level no-execute violation */ if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) { - ppc_hash64_set_isi(cs, env, SRR1_NOEXEC_GUARD); + ppc_hash64_set_isi(cs, SRR1_NOEXEC_GUARD); return 1; } @@ -791,13 +791,13 @@ skip_slb_search: ptex = ppc_hash64_htab_lookup(cpu, slb, eaddr, &pte, &apshift); if (ptex == -1) { if (rwx == 2) { - ppc_hash64_set_isi(cs, env, SRR1_NOPTE); + ppc_hash64_set_isi(cs, SRR1_NOPTE); } else { int dsisr = DSISR_NOPTE; if (rwx == 1) { dsisr |= DSISR_ISSTORE; } - ppc_hash64_set_dsi(cs, env, eaddr, dsisr); + ppc_hash64_set_dsi(cs, eaddr, dsisr); } return 1; } @@ -824,7 +824,7 @@ skip_slb_search: if (PAGE_EXEC & ~amr_prot) { srr1 |= SRR1_IAMR; /* Access violates virt pg class key prot */ } - ppc_hash64_set_isi(cs, env, srr1); + ppc_hash64_set_isi(cs, srr1); } else { int dsisr = 0; if (need_prot[rwx] & ~pp_prot) { @@ -836,7 +836,7 @@ skip_slb_search: if (need_prot[rwx] & ~amr_prot) { dsisr |= DSISR_AMR; } - ppc_hash64_set_dsi(cs, env, eaddr, dsisr); + ppc_hash64_set_dsi(cs, eaddr, dsisr); } return 1; } @@ -942,8 +942,9 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex, cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH; } -void ppc_hash64_update_rmls(CPUPPCState *env) +void ppc_hash64_update_rmls(PowerPCCPU *cpu) { + CPUPPCState *env = &cpu->env; uint64_t lpcr = env->spr[SPR_LPCR]; /* @@ -976,9 +977,10 @@ void ppc_hash64_update_rmls(CPUPPCState *env) } } -void ppc_hash64_update_vrma(CPUPPCState *env) +void ppc_hash64_update_vrma(PowerPCCPU *cpu) { - const struct ppc_one_seg_page_size *sps = NULL; + CPUPPCState *env = &cpu->env; + const PPCHash64SegmentPageSizes *sps = NULL; target_ulong esid, vsid, lpcr; ppc_slb_t *slb = &env->vrma_slb; uint32_t vrmasd; @@ -1002,8 +1004,8 @@ void ppc_hash64_update_vrma(CPUPPCState *env) vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP); esid = SLB_ESID_V; - for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { - const struct ppc_one_seg_page_size *sps1 = &env->sps.sps[i]; + for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { + const PPCHash64SegmentPageSizes *sps1 = &cpu->hash64_opts->sps[i]; if (!sps1->page_shift) { break; @@ -1028,11 +1030,12 @@ void ppc_hash64_update_vrma(CPUPPCState *env) void helper_store_lpcr(CPUPPCState *env, target_ulong val) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); uint64_t lpcr = 0; /* Filter out bits */ - switch (POWERPC_MMU_VER(env->mmu_model)) { - case POWERPC_MMU_VER_64B: /* 970 */ + switch (env->mmu_model) { + case POWERPC_MMU_64B: /* 970 */ if (val & 0x40) { lpcr |= LPCR_LPES0; } @@ -1058,26 +1061,26 @@ void helper_store_lpcr(CPUPPCState *env, target_ulong val) * to dig HRMOR out of HID5 */ break; - case POWERPC_MMU_VER_2_03: /* P5p */ + case POWERPC_MMU_2_03: /* P5p */ lpcr = val & (LPCR_RMLS | LPCR_ILE | LPCR_LPES0 | LPCR_LPES1 | LPCR_RMI | LPCR_HDICE); break; - case POWERPC_MMU_VER_2_06: /* P7 */ + case POWERPC_MMU_2_06: /* P7 */ lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE | LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2 | LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_LPES1 | LPCR_HDICE); break; - case POWERPC_MMU_VER_2_07: /* P8 */ + case POWERPC_MMU_2_07: /* P8 */ lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE | LPCR_AIL | LPCR_ONL | LPCR_P8_PECE0 | LPCR_P8_PECE1 | LPCR_P8_PECE2 | LPCR_P8_PECE3 | LPCR_P8_PECE4 | LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_HDICE); break; - case POWERPC_MMU_VER_3_00: /* P9 */ + case POWERPC_MMU_3_00: /* P9 */ lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | @@ -1089,6 +1092,69 @@ void helper_store_lpcr(CPUPPCState *env, target_ulong val) ; } env->spr[SPR_LPCR] = lpcr; - ppc_hash64_update_rmls(env); - ppc_hash64_update_vrma(env); + ppc_hash64_update_rmls(cpu); + ppc_hash64_update_vrma(cpu); +} + +void ppc_hash64_init(PowerPCCPU *cpu) +{ + CPUPPCState *env = &cpu->env; + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); + + if (!pcc->hash64_opts) { + assert(!(env->mmu_model & POWERPC_MMU_64)); + return; + } + + cpu->hash64_opts = g_memdup(pcc->hash64_opts, sizeof(*cpu->hash64_opts)); } + +void ppc_hash64_finalize(PowerPCCPU *cpu) +{ + g_free(cpu->hash64_opts); +} + +const PPCHash64Options ppc_hash64_opts_basic = { + .flags = 0, + .slb_size = 64, + .sps = { + { .page_shift = 12, /* 4K */ + .slb_enc = 0, + .enc = { { .page_shift = 12, .pte_enc = 0 } } + }, + { .page_shift = 24, /* 16M */ + .slb_enc = 0x100, + .enc = { { .page_shift = 24, .pte_enc = 0 } } + }, + }, +}; + +const PPCHash64Options ppc_hash64_opts_POWER7 = { + .flags = PPC_HASH64_1TSEG | PPC_HASH64_AMR | PPC_HASH64_CI_LARGEPAGE, + .slb_size = 32, + .sps = { + { + .page_shift = 12, /* 4K */ + .slb_enc = 0, + .enc = { { .page_shift = 12, .pte_enc = 0 }, + { .page_shift = 16, .pte_enc = 0x7 }, + { .page_shift = 24, .pte_enc = 0x38 }, }, + }, + { + .page_shift = 16, /* 64K */ + .slb_enc = SLB_VSID_64K, + .enc = { { .page_shift = 16, .pte_enc = 0x1 }, + { .page_shift = 24, .pte_enc = 0x8 }, }, + }, + { + .page_shift = 24, /* 16M */ + .slb_enc = SLB_VSID_16M, + .enc = { { .page_shift = 24, .pte_enc = 0 }, }, + }, + { + .page_shift = 34, /* 16G */ + .slb_enc = SLB_VSID_16G, + .enc = { { .page_shift = 34, .pte_enc = 0x3 }, }, + }, + } +}; diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h index d297b97d37..d5fc03441d 100644 --- a/target/ppc/mmu-hash64.h +++ b/target/ppc/mmu-hash64.h @@ -17,8 +17,10 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong pte0, target_ulong pte1); unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, uint64_t pte0, uint64_t pte1); -void ppc_hash64_update_vrma(CPUPPCState *env); -void ppc_hash64_update_rmls(CPUPPCState *env); +void ppc_hash64_update_vrma(PowerPCCPU *cpu); +void ppc_hash64_update_rmls(PowerPCCPU *cpu); +void ppc_hash64_init(PowerPCCPU *cpu); +void ppc_hash64_finalize(PowerPCCPU *cpu); #endif /* @@ -134,6 +136,48 @@ static inline uint64_t ppc_hash64_hpte1(PowerPCCPU *cpu, return ldq_p(&(hptes[i].pte1)); } +/* + * MMU Options + */ + +struct PPCHash64PageSize { + uint32_t page_shift; /* Page shift (or 0) */ + uint32_t pte_enc; /* Encoding in the HPTE (>>12) */ +}; +typedef struct PPCHash64PageSize PPCHash64PageSize; + +struct PPCHash64SegmentPageSizes { + uint32_t page_shift; /* Base page shift of segment (or 0) */ + uint32_t slb_enc; /* SLB encoding for BookS */ + PPCHash64PageSize enc[PPC_PAGE_SIZES_MAX_SZ]; +}; + +struct PPCHash64Options { +#define PPC_HASH64_1TSEG 0x00001 +#define PPC_HASH64_AMR 0x00002 +#define PPC_HASH64_CI_LARGEPAGE 0x00004 + unsigned flags; + unsigned slb_size; + PPCHash64SegmentPageSizes sps[PPC_PAGE_SIZES_MAX_SZ]; +}; + +extern const PPCHash64Options ppc_hash64_opts_basic; +extern const PPCHash64Options ppc_hash64_opts_POWER7; + +static inline bool ppc_hash64_has(PowerPCCPU *cpu, unsigned feature) +{ + return !!(cpu->hash64_opts->flags & feature); +} + #endif /* CONFIG_USER_ONLY */ +#if defined(CONFIG_USER_ONLY) || !defined(TARGET_PPC64) +static inline void ppc_hash64_init(PowerPCCPU *cpu) +{ +} +static inline void ppc_hash64_finalize(PowerPCCPU *cpu) +{ +} +#endif + #endif /* MMU_HASH64_H */ diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 5568d1642b..8075b7149a 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -1266,7 +1266,7 @@ static void mmu6xx_dump_mmu(FILE *f, fprintf_function cpu_fprintf, void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env) { - switch (POWERPC_MMU_VER(env->mmu_model)) { + switch (env->mmu_model) { case POWERPC_MMU_BOOKE: mmubooke_dump_mmu(f, cpu_fprintf, env); break; @@ -1278,13 +1278,13 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env) mmu6xx_dump_mmu(f, cpu_fprintf, env); break; #if defined(TARGET_PPC64) - case POWERPC_MMU_VER_64B: - case POWERPC_MMU_VER_2_03: - case POWERPC_MMU_VER_2_06: - case POWERPC_MMU_VER_2_07: + case POWERPC_MMU_64B: + case POWERPC_MMU_2_03: + case POWERPC_MMU_2_06: + case POWERPC_MMU_2_07: dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env)); break; - case POWERPC_MMU_VER_3_00: + case POWERPC_MMU_3_00: if (ppc64_radix_guest(ppc_env_get_cpu(env))) { /* TODO - Unsupported */ } else { @@ -1423,14 +1423,14 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) CPUPPCState *env = &cpu->env; mmu_ctx_t ctx; - switch (POWERPC_MMU_VER(env->mmu_model)) { + switch (env->mmu_model) { #if defined(TARGET_PPC64) - case POWERPC_MMU_VER_64B: - case POWERPC_MMU_VER_2_03: - case POWERPC_MMU_VER_2_06: - case POWERPC_MMU_VER_2_07: + case POWERPC_MMU_64B: + case POWERPC_MMU_2_03: + case POWERPC_MMU_2_06: + case POWERPC_MMU_2_07: return ppc_hash64_get_phys_page_debug(cpu, addr); - case POWERPC_MMU_VER_3_00: + case POWERPC_MMU_3_00: if (ppc64_radix_guest(ppc_env_get_cpu(env))) { return ppc_radix64_get_phys_page_debug(cpu, addr); } else { diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 3457d29f8e..3beaa1e2f0 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -6561,7 +6561,7 @@ GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE), GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206), GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ), GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC), -GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC), +GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x01800001, PPC_ALTIVEC), GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC), GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI), GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA), @@ -7121,17 +7121,17 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, if (env->spr_cb[SPR_LPCR].name) cpu_fprintf(f, " LPCR " TARGET_FMT_lx "\n", env->spr[SPR_LPCR]); - switch (POWERPC_MMU_VER(env->mmu_model)) { + switch (env->mmu_model) { case POWERPC_MMU_32B: case POWERPC_MMU_601: case POWERPC_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_74xx: #if defined(TARGET_PPC64) - case POWERPC_MMU_VER_64B: - case POWERPC_MMU_VER_2_03: - case POWERPC_MMU_VER_2_06: - case POWERPC_MMU_VER_2_07: - case POWERPC_MMU_VER_3_00: + case POWERPC_MMU_64B: + case POWERPC_MMU_2_03: + case POWERPC_MMU_2_06: + case POWERPC_MMU_2_07: + case POWERPC_MMU_3_00: #endif if (env->spr_cb[SPR_SDR1].name) { /* SDR1 Exists */ cpu_fprintf(f, " SDR1 " TARGET_FMT_lx " ", env->spr[SPR_SDR1]); diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c index 391b94b97d..808f6c1a08 100644 --- a/target/ppc/translate_init.c +++ b/target/ppc/translate_init.c @@ -8195,9 +8195,6 @@ static void init_proc_970(CPUPPCState *env) gen_spr_970_dbg(env); /* env variables */ -#if !defined(CONFIG_USER_ONLY) - env->slb_nr = 64; -#endif env->dcache_line_size = 128; env->icache_line_size = 128; @@ -8242,6 +8239,7 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data) pcc->mmu_model = POWERPC_MMU_64B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; + pcc->hash64_opts = &ppc_hash64_opts_basic; #endif pcc->excp_model = POWERPC_EXCP_970; pcc->bus_model = PPC_FLAGS_INPUT_970; @@ -8271,9 +8269,6 @@ static void init_proc_power5plus(CPUPPCState *env) gen_spr_power5p_ear(env); /* env variables */ -#if !defined(CONFIG_USER_ONLY) - env->slb_nr = 64; -#endif env->dcache_line_size = 128; env->icache_line_size = 128; @@ -8319,6 +8314,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data) pcc->mmu_model = POWERPC_MMU_2_03; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; + pcc->hash64_opts = &ppc_hash64_opts_basic; #endif pcc->excp_model = POWERPC_EXCP_970; pcc->bus_model = PPC_FLAGS_INPUT_970; @@ -8368,36 +8364,6 @@ static Property powerpc_servercpu_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -#ifdef CONFIG_SOFTMMU -static const struct ppc_segment_page_sizes POWER7_POWER8_sps = { - .sps = { - { - .page_shift = 12, /* 4K */ - .slb_enc = 0, - .enc = { { .page_shift = 12, .pte_enc = 0 }, - { .page_shift = 16, .pte_enc = 0x7 }, - { .page_shift = 24, .pte_enc = 0x38 }, }, - }, - { - .page_shift = 16, /* 64K */ - .slb_enc = SLB_VSID_64K, - .enc = { { .page_shift = 16, .pte_enc = 0x1 }, - { .page_shift = 24, .pte_enc = 0x8 }, }, - }, - { - .page_shift = 24, /* 16M */ - .slb_enc = SLB_VSID_16M, - .enc = { { .page_shift = 24, .pte_enc = 0 }, }, - }, - { - .page_shift = 34, /* 16G */ - .slb_enc = SLB_VSID_16G, - .enc = { { .page_shift = 34, .pte_enc = 0x3 }, }, - }, - } -}; -#endif /* CONFIG_SOFTMMU */ - static void init_proc_POWER7(CPUPPCState *env) { /* Common Registers */ @@ -8417,10 +8383,6 @@ static void init_proc_POWER7(CPUPPCState *env) gen_spr_power7_book4(env); /* env variables */ -#if !defined(CONFIG_USER_ONLY) - env->slb_nr = 32; -#endif - env->ci_large_pages = true; env->dcache_line_size = 128; env->icache_line_size = 128; @@ -8526,7 +8488,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) pcc->mmu_model = POWERPC_MMU_2_06; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; - pcc->sps = &POWER7_POWER8_sps; + pcc->hash64_opts = &ppc_hash64_opts_POWER7; #endif pcc->excp_model = POWERPC_EXCP_POWER7; pcc->bus_model = PPC_FLAGS_INPUT_POWER7; @@ -8572,10 +8534,6 @@ static void init_proc_POWER8(CPUPPCState *env) gen_spr_power8_rpr(env); /* env variables */ -#if !defined(CONFIG_USER_ONLY) - env->slb_nr = 32; -#endif - env->ci_large_pages = true; env->dcache_line_size = 128; env->icache_line_size = 128; @@ -8698,7 +8656,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) pcc->mmu_model = POWERPC_MMU_2_07; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; - pcc->sps = &POWER7_POWER8_sps; + pcc->hash64_opts = &ppc_hash64_opts_POWER7; #endif pcc->excp_model = POWERPC_EXCP_POWER8; pcc->bus_model = PPC_FLAGS_INPUT_POWER7; @@ -8773,10 +8731,6 @@ static void init_proc_POWER9(CPUPPCState *env) KVM_REG_PPC_PSSCR, 0); /* env variables */ -#if !defined(CONFIG_USER_ONLY) - env->slb_nr = 32; -#endif - env->ci_large_pages = true; env->dcache_line_size = 128; env->icache_line_size = 128; @@ -8893,7 +8847,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault; /* segment page size remain the same */ - pcc->sps = &POWER7_POWER8_sps; + pcc->hash64_opts = &ppc_hash64_opts_POWER7; pcc->radix_page_info = &POWER9_radix_page_info; #endif pcc->excp_model = POWERPC_EXCP_POWER8; @@ -8920,12 +8874,11 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp) cpu->vhyp = vhyp; - /* PAPR always has exception vectors in RAM not ROM. To ensure this, - * MSR[IP] should never be set. - * - * We also disallow setting of MSR_HV + /* + * With a virtual hypervisor mode we never allow the CPU to go + * hypervisor mode itself */ - env->msr_mask &= ~((1ull << MSR_EP) | MSR_HVB); + env->msr_mask &= ~MSR_HVB; /* Set emulated LPCR to not send interrupts to hypervisor. Note that * under KVM, the actual HW LPCR will be set differently by KVM itself, @@ -8975,8 +8928,8 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp) env->spr[SPR_AMOR] = amor->default_value = 0xffffffffffffffffull; /* Update some env bits based on new LPCR value */ - ppc_hash64_update_rmls(env); - ppc_hash64_update_vrma(env); + ppc_hash64_update_rmls(cpu); + ppc_hash64_update_vrma(cpu); /* Tell KVM that we're in PAPR mode */ if (kvm_enabled()) { @@ -9726,7 +9679,7 @@ static inline bool ppc_cpu_is_valid(PowerPCCPUClass *pcc) #endif } -static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) +static void ppc_cpu_realize(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); PowerPCCPU *cpu = POWERPC_CPU(dev); @@ -9749,14 +9702,7 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) } } -#if defined(TARGET_PPCEMB) - if (!ppc_cpu_is_valid(pcc)) { - error_setg(errp, "CPU does not possess a BookE or 4xx MMU. " - "Please use qemu-system-ppc or qemu-system-ppc64 instead " - "or choose another CPU model."); - goto unrealize; - } -#endif + assert(ppc_cpu_is_valid(pcc)); create_ppc_opcodes(cpu, &local_err); if (local_err != NULL) { @@ -9952,7 +9898,7 @@ unrealize: cpu_exec_unrealizefn(cs); } -static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp) +static void ppc_cpu_unrealize(DeviceState *dev, Error **errp) { PowerPCCPU *cpu = POWERPC_CPU(dev); PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); @@ -10438,7 +10384,7 @@ static bool ppc_cpu_is_big_endian(CPUState *cs) } #endif -static void ppc_cpu_initfn(Object *obj) +static void ppc_cpu_instance_init(Object *obj) { CPUState *cs = CPU(obj); PowerPCCPU *cpu = POWERPC_CPU(obj); @@ -10471,42 +10417,14 @@ static void ppc_cpu_initfn(Object *obj) env->has_hv_mode = !!(env->msr_mask & MSR_HVB); #endif -#if defined(TARGET_PPC64) - if (pcc->sps) { - env->sps = *pcc->sps; - } else if (env->mmu_model & POWERPC_MMU_64) { - /* Use default sets of page sizes. We don't support MPSS */ - static const struct ppc_segment_page_sizes defsps_4k = { - .sps = { - { .page_shift = 12, /* 4K */ - .slb_enc = 0, - .enc = { { .page_shift = 12, .pte_enc = 0 } } - }, - { .page_shift = 24, /* 16M */ - .slb_enc = 0x100, - .enc = { { .page_shift = 24, .pte_enc = 0 } } - }, - }, - }; - static const struct ppc_segment_page_sizes defsps_64k = { - .sps = { - { .page_shift = 12, /* 4K */ - .slb_enc = 0, - .enc = { { .page_shift = 12, .pte_enc = 0 } } - }, - { .page_shift = 16, /* 64K */ - .slb_enc = 0x110, - .enc = { { .page_shift = 16, .pte_enc = 1 } } - }, - { .page_shift = 24, /* 16M */ - .slb_enc = 0x100, - .enc = { { .page_shift = 24, .pte_enc = 0 } } - }, - }, - }; - env->sps = (env->mmu_model & POWERPC_MMU_64K) ? defsps_64k : defsps_4k; - } -#endif /* defined(TARGET_PPC64) */ + ppc_hash64_init(cpu); +} + +static void ppc_cpu_instance_finalize(Object *obj) +{ + PowerPCCPU *cpu = POWERPC_CPU(obj); + + ppc_hash64_finalize(cpu); } static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr) @@ -10552,6 +10470,8 @@ static Property ppc_cpu_properties[] = { DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, false), DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration, false), + DEFINE_PROP_BOOL("pre-2.13-migration", PowerPCCPU, pre_2_13_migration, + false), DEFINE_PROP_END_OF_LIST(), }; @@ -10561,9 +10481,9 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) CPUClass *cc = CPU_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc); - device_class_set_parent_realize(dc, ppc_cpu_realizefn, + device_class_set_parent_realize(dc, ppc_cpu_realize, &pcc->parent_realize); - device_class_set_parent_unrealize(dc, ppc_cpu_unrealizefn, + device_class_set_parent_unrealize(dc, ppc_cpu_unrealize, &pcc->parent_unrealize); pcc->pvr_match = ppc_pvr_match_default; pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always; @@ -10623,7 +10543,8 @@ static const TypeInfo ppc_cpu_type_info = { .name = TYPE_POWERPC_CPU, .parent = TYPE_CPU, .instance_size = sizeof(PowerPCCPU), - .instance_init = ppc_cpu_initfn, + .instance_init = ppc_cpu_instance_init, + .instance_finalize = ppc_cpu_instance_finalize, .abstract = true, .class_size = sizeof(PowerPCCPUClass), .class_init = ppc_cpu_class_init, |