aboutsummaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/cpu.h21
-rw-r--r--target-ppc/helper.c26
-rw-r--r--target-ppc/machine.c16
-rw-r--r--target-ppc/op_helper.c12
-rw-r--r--target-ppc/translate_init.c27
5 files changed, 67 insertions, 35 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 758c5549af..46d86be4d7 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -368,10 +368,16 @@ typedef struct ppcmas_tlb_t {
} ppcmas_tlb_t;
union ppc_tlb_t {
- ppc6xx_tlb_t tlb6;
- ppcemb_tlb_t tlbe;
- ppcmas_tlb_t tlbm;
+ ppc6xx_tlb_t *tlb6;
+ ppcemb_tlb_t *tlbe;
+ ppcmas_tlb_t *tlbm;
};
+
+/* possible TLB variants */
+#define TLB_NONE 0
+#define TLB_6XX 1
+#define TLB_EMB 2
+#define TLB_MAS 3
#endif
#define SDR_32_HTABORG 0xFFFF0000UL
@@ -911,7 +917,8 @@ struct CPUPPCState {
int last_way; /* Last used way used to allocate TLB in a LRU way */
int id_tlbs; /* If 1, MMU has separated TLBs for instructions & data */
int nb_pids; /* Number of available PID registers */
- ppc_tlb_t *tlb; /* TLB is optional. Allocate them only if needed */
+ int tlb_type; /* Type of TLB we're dealing with */
+ ppc_tlb_t tlb; /* TLB is optional. Allocate them only if needed */
/* 403 dedicated access protection registers */
target_ulong pb[4];
#endif
@@ -1942,9 +1949,9 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
static inline int booke206_tlbm_id(CPUState *env, ppcmas_tlb_t *tlbm)
{
uintptr_t tlbml = (uintptr_t)tlbm;
- uintptr_t tlbl = (uintptr_t)env->tlb;
+ uintptr_t tlbl = (uintptr_t)env->tlb.tlbm;
- return (tlbml - tlbl) / sizeof(env->tlb[0]);
+ return (tlbml - tlbl) / sizeof(env->tlb.tlbm[0]);
}
static inline int booke206_tlb_size(CPUState *env, int tlbn)
@@ -2004,7 +2011,7 @@ static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
r += booke206_tlb_size(env, i);
}
- return &env->tlb[r].tlbm;
+ return &env->tlb.tlbm[r];
}
#endif
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 8cf9ee1182..38849768c5 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -323,7 +323,7 @@ static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
if (env->id_tlbs == 1)
max *= 2;
for (nr = 0; nr < max; nr++) {
- tlb = &env->tlb[nr].tlb6;
+ tlb = &env->tlb.tlb6[nr];
pte_invalidate(&tlb->pte0);
}
tlb_flush(env, 1);
@@ -340,7 +340,7 @@ static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
/* Invalidate ITLB + DTLB, all ways */
for (way = 0; way < env->nb_ways; way++) {
nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
- tlb = &env->tlb[nr].tlb6;
+ tlb = &env->tlb.tlb6[nr];
if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
env->nb_tlb, eaddr);
@@ -367,7 +367,7 @@ void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
int nr;
nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
- tlb = &env->tlb[nr].tlb6;
+ tlb = &env->tlb.tlb6[nr];
LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
" PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
/* Invalidate any pending reference in Qemu for this virtual address */
@@ -391,7 +391,7 @@ static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
for (way = 0; way < env->nb_ways; way++) {
nr = ppc6xx_tlb_getnum(env, eaddr, way,
access_type == ACCESS_CODE ? 1 : 0);
- tlb = &env->tlb[nr].tlb6;
+ tlb = &env->tlb.tlb6[nr];
/* This test "emulates" the PTE index match for hardware TLBs */
if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
@@ -434,7 +434,7 @@ static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
/* Update page flags */
- pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
+ pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, rw);
}
return ret;
@@ -1049,7 +1049,7 @@ int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
/* Default return value is no match */
ret = -1;
for (i = 0; i < env->nb_tlb; i++) {
- tlb = &env->tlb[i].tlbe;
+ tlb = &env->tlb.tlbe[i];
if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
ret = i;
break;
@@ -1066,7 +1066,7 @@ static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
int i;
for (i = 0; i < env->nb_tlb; i++) {
- tlb = &env->tlb[i].tlbe;
+ tlb = &env->tlb.tlbe[i];
tlb->prot &= ~PAGE_VALID;
}
tlb_flush(env, 1);
@@ -1082,7 +1082,7 @@ static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
int i;
for (i = 0; i < env->nb_tlb; i++) {
- tlb = &env->tlb[i].tlbe;
+ tlb = &env->tlb.tlbe[i];
if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
end = tlb->EPN + tlb->size;
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
@@ -1107,7 +1107,7 @@ static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
raddr = (target_phys_addr_t)-1ULL;
pr = msr_pr;
for (i = 0; i < env->nb_tlb; i++) {
- tlb = &env->tlb[i].tlbe;
+ tlb = &env->tlb.tlbe[i];
if (ppcemb_tlb_check(env, tlb, &raddr, address,
env->spr[SPR_40x_PID], 0, i) < 0)
continue;
@@ -1248,7 +1248,7 @@ static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
ret = -1;
raddr = (target_phys_addr_t)-1ULL;
for (i = 0; i < env->nb_tlb; i++) {
- tlb = &env->tlb[i].tlbe;
+ tlb = &env->tlb.tlbe[i];
ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
access_type, i);
if (!ret) {
@@ -1273,14 +1273,14 @@ void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
{
int tlb_size;
int i, j;
- ppc_tlb_t *tlb = env->tlb;
+ ppcmas_tlb_t *tlb = env->tlb.tlbm;
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
if (flags & (1 << i)) {
tlb_size = booke206_tlb_size(env, i);
for (j = 0; j < tlb_size; j++) {
- if (!check_iprot || !(tlb[j].tlbm.mas1 & MAS1_IPROT)) {
- tlb[j].tlbm.mas1 &= ~MAS1_VALID;
+ if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
+ tlb[j].mas1 &= ~MAS1_VALID;
}
}
}
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 0c1986e528..1c40d4358a 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -52,12 +52,12 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_sbe32s(f, &env->last_way);
qemu_put_sbe32s(f, &env->id_tlbs);
qemu_put_sbe32s(f, &env->nb_pids);
- if (env->tlb) {
+ if (env->tlb.tlb6) {
// XXX assumes 6xx
for (i = 0; i < env->nb_tlb; i++) {
- qemu_put_betls(f, &env->tlb[i].tlb6.pte0);
- qemu_put_betls(f, &env->tlb[i].tlb6.pte1);
- qemu_put_betls(f, &env->tlb[i].tlb6.EPN);
+ qemu_put_betls(f, &env->tlb.tlb6[i].pte0);
+ qemu_put_betls(f, &env->tlb.tlb6[i].pte1);
+ qemu_put_betls(f, &env->tlb.tlb6[i].EPN);
}
}
for (i = 0; i < 4; i++)
@@ -140,12 +140,12 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_sbe32s(f, &env->last_way);
qemu_get_sbe32s(f, &env->id_tlbs);
qemu_get_sbe32s(f, &env->nb_pids);
- if (env->tlb) {
+ if (env->tlb.tlb6) {
// XXX assumes 6xx
for (i = 0; i < env->nb_tlb; i++) {
- qemu_get_betls(f, &env->tlb[i].tlb6.pte0);
- qemu_get_betls(f, &env->tlb[i].tlb6.pte1);
- qemu_get_betls(f, &env->tlb[i].tlb6.EPN);
+ qemu_get_betls(f, &env->tlb.tlb6[i].pte0);
+ qemu_get_betls(f, &env->tlb.tlb6[i].pte1);
+ qemu_get_betls(f, &env->tlb.tlb6[i].EPN);
}
}
for (i = 0; i < 4; i++)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 135211dee6..82b6651925 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3959,7 +3959,7 @@ target_ulong helper_4xx_tlbre_hi (target_ulong entry)
int size;
entry &= PPC4XX_TLB_ENTRY_MASK;
- tlb = &env->tlb[entry].tlbe;
+ tlb = &env->tlb.tlbe[entry];
ret = tlb->EPN;
if (tlb->prot & PAGE_VALID) {
ret |= PPC4XX_TLBHI_V;
@@ -3979,7 +3979,7 @@ target_ulong helper_4xx_tlbre_lo (target_ulong entry)
target_ulong ret;
entry &= PPC4XX_TLB_ENTRY_MASK;
- tlb = &env->tlb[entry].tlbe;
+ tlb = &env->tlb.tlbe[entry];
ret = tlb->RPN;
if (tlb->prot & PAGE_EXEC) {
ret |= PPC4XX_TLBLO_EX;
@@ -3998,7 +3998,7 @@ void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
val);
entry &= PPC4XX_TLB_ENTRY_MASK;
- tlb = &env->tlb[entry].tlbe;
+ tlb = &env->tlb.tlbe[entry];
/* Invalidate previous TLB (if it's valid) */
if (tlb->prot & PAGE_VALID) {
end = tlb->EPN + tlb->size;
@@ -4056,7 +4056,7 @@ void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
val);
entry &= PPC4XX_TLB_ENTRY_MASK;
- tlb = &env->tlb[entry].tlbe;
+ tlb = &env->tlb.tlbe[entry];
tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
tlb->prot = PAGE_READ;
@@ -4091,7 +4091,7 @@ void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
__func__, word, (int)entry, value);
do_flush_tlbs = 0;
entry &= 0x3F;
- tlb = &env->tlb[entry].tlbe;
+ tlb = &env->tlb.tlbe[entry];
switch (word) {
default:
/* Just here to please gcc */
@@ -4150,7 +4150,7 @@ target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
int size;
entry &= 0x3F;
- tlb = &env->tlb[entry].tlbe;
+ tlb = &env->tlb.tlbe[entry];
switch (word) {
default:
/* Just here to please gcc */
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index fc50ae3cd2..f542b8e4f3 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -844,6 +844,7 @@ static void gen_6xx_7xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
env->nb_tlb = nb_tlbs;
env->nb_ways = nb_ways;
env->id_tlbs = 1;
+ env->tlb_type = TLB_6XX;
spr_register(env, SPR_DMISS, "DMISS",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
@@ -1337,6 +1338,7 @@ static void gen_74xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
env->nb_tlb = nb_tlbs;
env->nb_ways = nb_ways;
env->id_tlbs = 1;
+ env->tlb_type = TLB_6XX;
/* XXX : not implemented */
spr_register(env, SPR_PTEHI, "PTEHI",
SPR_NOACCESS, SPR_NOACCESS,
@@ -3282,6 +3284,7 @@ static void init_proc_401x2 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_4xx_softmmu(env);
env->dcache_line_size = 32;
@@ -3352,6 +3355,7 @@ static void init_proc_IOP480 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_4xx_softmmu(env);
env->dcache_line_size = 32;
@@ -3431,6 +3435,7 @@ static void init_proc_403GCX (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_4xx_softmmu(env);
env->dcache_line_size = 32;
@@ -3479,6 +3484,7 @@ static void init_proc_405 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_4xx_softmmu(env);
env->dcache_line_size = 32;
@@ -3561,6 +3567,7 @@ static void init_proc_440EP (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_BookE(env);
env->dcache_line_size = 32;
@@ -3624,6 +3631,7 @@ static void init_proc_440GP (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_BookE(env);
env->dcache_line_size = 32;
@@ -3687,6 +3695,7 @@ static void init_proc_440x4 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_BookE(env);
env->dcache_line_size = 32;
@@ -3767,6 +3776,7 @@ static void init_proc_440x5 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_BookE(env);
env->dcache_line_size = 32;
@@ -3854,6 +3864,7 @@ static void init_proc_460 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_BookE(env);
env->dcache_line_size = 32;
@@ -3944,6 +3955,7 @@ static void init_proc_460F (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_BookE(env);
env->dcache_line_size = 32;
@@ -4251,6 +4263,7 @@ static void init_proc_e200 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ env->tlb_type = TLB_EMB;
#endif
init_excp_e200(env);
env->dcache_line_size = 32;
@@ -4464,6 +4477,7 @@ static void init_proc_e500 (CPUPPCState *env, int version)
#if !defined(CONFIG_USER_ONLY)
env->nb_tlb = 0;
+ env->tlb_type = TLB_MAS;
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
env->nb_tlb += booke206_tlb_size(env, i);
}
@@ -9186,6 +9200,7 @@ static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def)
env->nb_BATs = 0;
env->nb_tlb = 0;
env->nb_ways = 0;
+ env->tlb_type = TLB_NONE;
#endif
/* Register SPR common to all PowerPC implementations */
gen_spr_generic(env);
@@ -9310,7 +9325,17 @@ static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def)
int nb_tlb = env->nb_tlb;
if (env->id_tlbs != 0)
nb_tlb *= 2;
- env->tlb = qemu_mallocz(nb_tlb * sizeof(ppc_tlb_t));
+ switch (env->tlb_type) {
+ case TLB_6XX:
+ env->tlb.tlb6 = qemu_mallocz(nb_tlb * sizeof(ppc6xx_tlb_t));
+ break;
+ case TLB_EMB:
+ env->tlb.tlbe = qemu_mallocz(nb_tlb * sizeof(ppcemb_tlb_t));
+ break;
+ case TLB_MAS:
+ env->tlb.tlbm = qemu_mallocz(nb_tlb * sizeof(ppcmas_tlb_t));
+ break;
+ }
/* Pre-compute some useful values */
env->tlb_per_way = env->nb_tlb / env->nb_ways;
}