aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/ppc/cpu.h11
-rw-r--r--target/ppc/machine.c1
-rw-r--r--target/ppc/mmu-hash32.c14
-rw-r--r--target/ppc/mmu-hash32.h26
-rw-r--r--target/ppc/mmu-hash64.c35
-rw-r--r--target/ppc/mmu-hash64.h13
-rw-r--r--target/ppc/mmu_helper.c31
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 */