diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/ppc/cpu.h | 11 | ||||
-rw-r--r-- | target/ppc/machine.c | 1 | ||||
-rw-r--r-- | target/ppc/mmu-hash32.c | 14 | ||||
-rw-r--r-- | target/ppc/mmu-hash32.h | 26 | ||||
-rw-r--r-- | target/ppc/mmu-hash64.c | 35 | ||||
-rw-r--r-- | target/ppc/mmu-hash64.h | 13 | ||||
-rw-r--r-- | target/ppc/mmu_helper.c | 31 |
7 files changed, 71 insertions, 60 deletions
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 051298b40f..aaf79f52b9 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -306,14 +306,6 @@ union ppc_tlb_t { #define TLB_MAS 3 #endif -#define SDR_32_HTABORG 0xFFFF0000UL -#define SDR_32_HTABMASK 0x000001FFUL - -#if defined(TARGET_PPC64) -#define SDR_64_HTABORG 0xFFFFFFFFFFFC0000ULL -#define SDR_64_HTABSIZE 0x000000000000001FULL -#endif /* defined(TARGET_PPC64 */ - typedef struct ppc_slb_t ppc_slb_t; struct ppc_slb_t { uint64_t esid; @@ -1006,9 +998,6 @@ struct CPUPPCState { /* tcg TLB needs flush (deferred slb inval instruction typically) */ #endif /* segment registers */ - hwaddr htab_base; - /* mask used to normalize hash value to PTEG index */ - hwaddr htab_mask; target_ulong sr[32]; /* externally stored hash table */ uint8_t *external_htab; diff --git a/target/ppc/machine.c b/target/ppc/machine.c index df9f7a4e05..1ccbc8a960 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -229,7 +229,6 @@ static int cpu_post_load(void *opaque, int version_id) } if (!env->external_htab) { - /* Restore htab_base and htab_mask variables */ ppc_store_sdr1(env, env->spr[SPR_SDR1]); } diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c index 29bace622a..03ae3c1279 100644 --- a/target/ppc/mmu-hash32.c +++ b/target/ppc/mmu-hash32.c @@ -304,9 +304,9 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash) { - CPUPPCState *env = &cpu->env; + target_ulong mask = ppc_hash32_hpt_mask(cpu); - return (hash * HASH_PTEG_SIZE_32) & env->htab_mask; + return (hash * HASH_PTEG_SIZE_32) & mask; } static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off, @@ -339,7 +339,6 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu, target_ulong sr, target_ulong eaddr, ppc_hash_pte32_t *pte) { - CPUPPCState *env = &cpu->env; hwaddr pteg_off, pte_offset; hwaddr hash; uint32_t vsid, pgidx, ptem; @@ -353,21 +352,22 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu, qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx " hash " TARGET_FMT_plx "\n", - env->htab_base, env->htab_mask, hash); + ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash); /* Primary PTEG lookup */ qemu_log_mask(CPU_LOG_MMU, "0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx " vsid=%" PRIx32 " ptem=%" PRIx32 " hash=" TARGET_FMT_plx "\n", - env->htab_base, env->htab_mask, vsid, ptem, hash); + ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), + vsid, ptem, hash); pteg_off = get_pteg_offset32(cpu, hash); pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 0, ptem, pte); if (pte_offset == -1) { /* Secondary PTEG lookup */ qemu_log_mask(CPU_LOG_MMU, "1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx " vsid=%" PRIx32 " api=%" PRIx32 - " hash=" TARGET_FMT_plx "\n", env->htab_base, - env->htab_mask, vsid, ptem, ~hash); + " hash=" TARGET_FMT_plx "\n", ppc_hash32_hpt_base(cpu), + ppc_hash32_hpt_mask(cpu), vsid, ptem, ~hash); pteg_off = get_pteg_offset32(cpu, ~hash); pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 1, ptem, pte); } diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h index 5b9fb08d1a..2ed4888a19 100644 --- a/target/ppc/mmu-hash32.h +++ b/target/ppc/mmu-hash32.h @@ -44,6 +44,8 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw, /* * Hash page table definitions */ +#define SDR_32_HTABORG 0xFFFF0000UL +#define SDR_32_HTABMASK 0x000001FFUL #define HPTES_PER_GROUP 8 #define HASH_PTE_SIZE_32 8 @@ -65,42 +67,54 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw, #define HPTE32_R_WIMG 0x00000078 #define HPTE32_R_PP 0x00000003 +static inline hwaddr ppc_hash32_hpt_base(PowerPCCPU *cpu) +{ + return cpu->env.spr[SPR_SDR1] & SDR_32_HTABORG; +} + +static inline hwaddr ppc_hash32_hpt_mask(PowerPCCPU *cpu) +{ + return ((cpu->env.spr[SPR_SDR1] & SDR_32_HTABMASK) << 16) | 0xFFFF; +} + static inline target_ulong ppc_hash32_load_hpte0(PowerPCCPU *cpu, hwaddr pte_offset) { CPUPPCState *env = &cpu->env; + target_ulong base = ppc_hash32_hpt_base(cpu); assert(!env->external_htab); /* Not supported on 32-bit for now */ - return ldl_phys(CPU(cpu)->as, env->htab_base + pte_offset); + return ldl_phys(CPU(cpu)->as, base + pte_offset); } static inline target_ulong ppc_hash32_load_hpte1(PowerPCCPU *cpu, hwaddr pte_offset) { + target_ulong base = ppc_hash32_hpt_base(cpu); CPUPPCState *env = &cpu->env; assert(!env->external_htab); /* Not supported on 32-bit for now */ - return ldl_phys(CPU(cpu)->as, - env->htab_base + pte_offset + HASH_PTE_SIZE_32 / 2); + return ldl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2); } static inline void ppc_hash32_store_hpte0(PowerPCCPU *cpu, hwaddr pte_offset, target_ulong pte0) { CPUPPCState *env = &cpu->env; + target_ulong base = ppc_hash32_hpt_base(cpu); assert(!env->external_htab); /* Not supported on 32-bit for now */ - stl_phys(CPU(cpu)->as, env->htab_base + pte_offset, pte0); + stl_phys(CPU(cpu)->as, base + pte_offset, pte0); } static inline void ppc_hash32_store_hpte1(PowerPCCPU *cpu, hwaddr pte_offset, target_ulong pte1) { CPUPPCState *env = &cpu->env; + target_ulong base = ppc_hash32_hpt_base(cpu); assert(!env->external_htab); /* Not supported on 32-bit for now */ - stl_phys(CPU(cpu)->as, - env->htab_base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1); + stl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1); } typedef struct { diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index f503c69410..38a6912203 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -304,15 +304,13 @@ void ppc_hash64_set_sdr1(PowerPCCPU *cpu, target_ulong value, CPUPPCState *env = &cpu->env; target_ulong htabsize = value & SDR_64_HTABSIZE; - env->spr[SPR_SDR1] = value; if (htabsize > 28) { error_setg(errp, "Invalid HTABSIZE 0x" TARGET_FMT_lx" stored in SDR1", htabsize); - htabsize = 28; + return; } - env->htab_mask = (1ULL << (htabsize + 18 - 7)) - 1; - env->htab_base = value & SDR_64_HTABORG; + env->spr[SPR_SDR1] = value; } void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift, @@ -333,10 +331,6 @@ void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift, return; } - /* Not strictly necessary, but makes it clearer that an external - * htab is in use when debugging */ - env->htab_base = -1; - if (kvm_enabled()) { if (kvmppc_put_books_sregs(cpu) < 0) { error_setg(errp, "Unable to update SDR1 in KVM"); @@ -450,10 +444,11 @@ const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu, * accessible PTEG. */ hptes = (ppc_hash_pte64_t *)(cpu->env.external_htab + pte_offset); - } else if (cpu->env.htab_base) { + } else if (ppc_hash64_hpt_base(cpu)) { + hwaddr base = ppc_hash64_hpt_base(cpu); hwaddr plen = n * HASH_PTE_SIZE_64; - hptes = address_space_map(CPU(cpu)->as, cpu->env.htab_base + pte_offset, - &plen, false); + hptes = address_space_map(CPU(cpu)->as, base + pte_offset, + &plen, false); if (plen < (n * HASH_PTE_SIZE_64)) { hw_error("%s: Unable to map all requested HPTEs\n", __func__); } @@ -514,13 +509,12 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, target_ulong ptem, ppc_hash_pte64_t *pte, unsigned *pshift) { - CPUPPCState *env = &cpu->env; int i; const ppc_hash_pte64_t *pteg; target_ulong pte0, pte1; target_ulong ptex; - ptex = (hash & env->htab_mask) * HPTES_PER_GROUP; + ptex = (hash & ppc_hash64_hpt_mask(cpu)) * HPTES_PER_GROUP; pteg = ppc_hash64_map_hptes(cpu, ptex, HPTES_PER_GROUP); if (!pteg) { return -1; @@ -598,14 +592,15 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu, qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx " hash " TARGET_FMT_plx "\n", - env->htab_base, env->htab_mask, hash); + ppc_hash64_hpt_base(cpu), ppc_hash64_hpt_mask(cpu), hash); /* Primary PTEG lookup */ qemu_log_mask(CPU_LOG_MMU, "0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx " hash=" TARGET_FMT_plx "\n", - env->htab_base, env->htab_mask, vsid, ptem, hash); + ppc_hash64_hpt_base(cpu), ppc_hash64_hpt_mask(cpu), + vsid, ptem, hash); ptex = ppc_hash64_pteg_search(cpu, hash, sps, ptem, pte, pshift); if (ptex == -1) { @@ -614,8 +609,8 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu, qemu_log_mask(CPU_LOG_MMU, "1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx - " hash=" TARGET_FMT_plx "\n", env->htab_base, - env->htab_mask, vsid, ptem, ~hash); + " hash=" TARGET_FMT_plx "\n", ppc_hash64_hpt_base(cpu), + ppc_hash64_hpt_mask(cpu), vsid, ptem, ~hash); ptex = ppc_hash64_pteg_search(cpu, ~hash, sps, ptem, pte, pshift); } @@ -933,9 +928,9 @@ void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex, stq_p(env->external_htab + offset, pte0); stq_p(env->external_htab + offset + HASH_PTE_SIZE_64 / 2, pte1); } else { - stq_phys(CPU(cpu)->as, env->htab_base + offset, pte0); - stq_phys(CPU(cpu)->as, - env->htab_base + offset + HASH_PTE_SIZE_64 / 2, pte1); + hwaddr base = ppc_hash64_hpt_base(cpu); + stq_phys(CPU(cpu)->as, base + offset, pte0); + stq_phys(CPU(cpu)->as, base + offset + HASH_PTE_SIZE_64 / 2, pte1); } } diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h index edd687bcf8..5914a08db7 100644 --- a/target/ppc/mmu-hash64.h +++ b/target/ppc/mmu-hash64.h @@ -56,6 +56,9 @@ void ppc_hash64_update_rmls(CPUPPCState *env); * Hash page table definitions */ +#define SDR_64_HTABORG 0xFFFFFFFFFFFC0000ULL +#define SDR_64_HTABSIZE 0x000000000000001FULL + #define HPTES_PER_GROUP 8 #define HASH_PTE_SIZE_64 16 #define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP) @@ -91,6 +94,16 @@ void ppc_hash64_update_rmls(CPUPPCState *env); #define HPTE64_V_1TB_SEG 0x4000000000000000ULL #define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL +static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu) +{ + return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG; +} + +static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu) +{ + return (1ULL << ((cpu->env.spr[SPR_SDR1] & SDR_64_HTABSIZE) + 18 - 7)) - 1; +} + void ppc_hash64_set_sdr1(PowerPCCPU *cpu, target_ulong value, Error **errp); void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift, diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index eb2d482ef7..1381635d20 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -466,6 +466,7 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr, int rw, int type) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); hwaddr hash; target_ulong vsid; int ds, pr, target_page_bits; @@ -503,7 +504,7 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx " hash " TARGET_FMT_plx "\n", - env->htab_base, env->htab_mask, hash); + ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash); ctx->hash[0] = hash; ctx->hash[1] = ~hash; @@ -518,9 +519,11 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, uint32_t a0, a1, a2, a3; qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx - "\n", env->htab_base, env->htab_mask + 0x80); - for (curaddr = env->htab_base; - curaddr < (env->htab_base + env->htab_mask + 0x80); + "\n", ppc_hash32_hpt_base(cpu), + ppc_hash32_hpt_mask(env) + 0x80); + for (curaddr = ppc_hash32_hpt_base(cpu); + curaddr < (ppc_hash32_hpt_base(cpu) + + ppc_hash32_hpt_mask(cpu) + 0x80); curaddr += 16) { a0 = ldl_phys(cs->as, curaddr); a1 = ldl_phys(cs->as, curaddr + 4); @@ -1205,12 +1208,13 @@ static void mmu6xx_dump_BATs(FILE *f, fprintf_function cpu_fprintf, static void mmu6xx_dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); ppc6xx_tlb_t *tlb; target_ulong sr; int type, way, entry, i; - cpu_fprintf(f, "HTAB base = 0x%"HWADDR_PRIx"\n", env->htab_base); - cpu_fprintf(f, "HTAB mask = 0x%"HWADDR_PRIx"\n", env->htab_mask); + cpu_fprintf(f, "HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu)); + cpu_fprintf(f, "HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu)); cpu_fprintf(f, "\nSegment registers:\n"); for (i = 0; i < 32; i++) { @@ -1592,9 +1596,9 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem; tlb_miss: env->error_code |= ctx.key << 19; - env->spr[SPR_HASH1] = env->htab_base + + env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) + get_pteg_offset32(cpu, ctx.hash[0]); - env->spr[SPR_HASH2] = env->htab_base + + env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) + get_pteg_offset32(cpu, ctx.hash[1]); break; case POWERPC_MMU_SOFT_74xx: @@ -1999,7 +2003,6 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value) { qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value); assert(!env->external_htab); - env->spr[SPR_SDR1] = value; #if defined(TARGET_PPC64) if (env->mmu_model & POWERPC_MMU_64) { PowerPCCPU *cpu = ppc_env_get_cpu(env); @@ -2009,14 +2012,12 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value) if (local_err) { error_report_err(local_err); error_free(local_err); + return; } - } else -#endif /* defined(TARGET_PPC64) */ - { - /* FIXME: Should check for valid HTABMASK values */ - env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF; - env->htab_base = value & SDR_32_HTABORG; } +#endif /* defined(TARGET_PPC64) */ + /* FIXME: Should check for valid HTABMASK values in 32-bit case */ + env->spr[SPR_SDR1] = value; } /* Segment registers load and store */ |