diff options
-rw-r--r-- | target-ppc/cpu-qom.h | 3 | ||||
-rw-r--r-- | target-ppc/mmu-hash64.c | 39 | ||||
-rw-r--r-- | target-ppc/translate_init.c | 22 |
3 files changed, 57 insertions, 7 deletions
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h index 0fad2def0a..286410502f 100644 --- a/target-ppc/cpu-qom.h +++ b/target-ppc/cpu-qom.h @@ -70,18 +70,21 @@ enum powerpc_mmu_t { #define POWERPC_MMU_64 0x00010000 #define POWERPC_MMU_1TSEG 0x00020000 #define POWERPC_MMU_AMR 0x00040000 +#define POWERPC_MMU_64K 0x00080000 /* 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, /* Architecture 2.06 "degraded" (no 1T segments) */ POWERPC_MMU_2_06a = POWERPC_MMU_64 | POWERPC_MMU_AMR | 0x00000003, /* Architecture 2.07 variant */ POWERPC_MMU_2_07 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG + | POWERPC_MMU_64K | POWERPC_MMU_AMR | 0x00000004, /* Architecture 2.07 "degraded" (no 1T segments) */ POWERPC_MMU_2_07a = POWERPC_MMU_64 | POWERPC_MMU_AMR diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 6d6f26c929..3b1357a648 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -450,9 +450,31 @@ void ppc_hash64_stop_access(PowerPCCPU *cpu, uint64_t token) } } +/* Returns the effective page shift or 0. MPSS isn't supported yet so + * this will always be the slb_pshift or 0 + */ +static uint32_t ppc_hash64_pte_size_decode(uint64_t pte1, uint32_t slb_pshift) +{ + switch (slb_pshift) { + case 12: + return 12; + case 16: + if ((pte1 & 0xf000) == 0x1000) { + return 16; + } + return 0; + case 24: + if ((pte1 & 0xff000) == 0) { + return 24; + } + return 0; + } + return 0; +} + static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, - bool secondary, target_ulong ptem, - ppc_hash_pte64_t *pte) + uint32_t slb_pshift, bool secondary, + target_ulong ptem, ppc_hash_pte64_t *pte) { CPUPPCState *env = &cpu->env; int i; @@ -472,6 +494,13 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, if ((pte0 & HPTE64_V_VALID) && (secondary == !!(pte0 & HPTE64_V_SECONDARY)) && HPTE64_V_COMPARE(pte0, ptem)) { + uint32_t pshift = ppc_hash64_pte_size_decode(pte1, slb_pshift); + if (pshift == 0) { + continue; + } + /* We don't do anything with pshift yet as qemu TLB only deals + * with 4K pages anyway + */ pte->pte0 = pte0; pte->pte1 = pte1; ppc_hash64_stop_access(cpu, token); @@ -525,7 +554,8 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu, " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx " hash=" TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, vsid, ptem, hash); - pte_offset = ppc_hash64_pteg_search(cpu, hash, 0, ptem, pte); + pte_offset = ppc_hash64_pteg_search(cpu, hash, slb->sps->page_shift, + 0, ptem, pte); if (pte_offset == -1) { /* Secondary PTEG lookup */ @@ -535,7 +565,8 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu, " hash=" TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, vsid, ptem, ~hash); - pte_offset = ppc_hash64_pteg_search(cpu, ~hash, 1, ptem, pte); + pte_offset = ppc_hash64_pteg_search(cpu, ~hash, slb->sps->page_shift, 1, + ptem, pte); } return pte_offset; diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 55d1bfac97..843f19b748 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -10293,8 +10293,8 @@ static void ppc_cpu_initfn(Object *obj) if (pcc->sps) { env->sps = *pcc->sps; } else if (env->mmu_model & POWERPC_MMU_64) { - /* Use default sets of page sizes */ - static const struct ppc_segment_page_sizes defsps = { + /* 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, @@ -10306,7 +10306,23 @@ static void ppc_cpu_initfn(Object *obj) }, }, }; - env->sps = defsps; + 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) */ |