aboutsummaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2012-01-25 16:27:26 +0100
committerAlexander Graf <agraf@suse.de>2012-02-02 02:47:46 +0100
commit3f162d119ef52fda714ebb498fcb4f4b7c354d38 (patch)
tree9d5a31eb5e617b8255fbd7a8d9f67169f61df6e3 /target-ppc
parent6d3db821c18fdc9727108b5b4bbb38cb7ab5c0e6 (diff)
PPC: booke206: Check for TLB overrun
Our internal helpers to fetch TLB entries were not able to tell us that an entry doesn't even exist. Pass an error out if we hit such a case to not accidently pass beyond the TLB array. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/cpu.h4
-rw-r--r--target-ppc/helper.c3
-rw-r--r--target-ppc/op_helper.c22
-rw-r--r--target-ppc/translate.c1
4 files changed, 29 insertions, 1 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 1026254605..668ddf34cb 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2112,6 +2112,10 @@ static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
ea &= (1 << (tlb_bits - ways_bits)) - 1;
r = (ea << ways_bits) | way;
+ if (r >= booke206_tlb_size(env, tlbn)) {
+ return NULL;
+ }
+
/* bump up to tlbn index */
for (i = 0; i < tlbn; i++) {
r += booke206_tlb_size(env, i);
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 2ce2d9238f..672494c593 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -1448,6 +1448,9 @@ static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
for (j = 0; j < ways; j++) {
tlb = booke206_get_tlbm(env, i, address, j);
+ if (!tlb) {
+ continue;
+ }
ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
rw, access_type);
if (ret != -1) {
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 1f1fa09368..be4e539c2d 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -4260,6 +4260,12 @@ void helper_booke206_tlbwe(void)
tlb = booke206_cur_tlb(env);
+ if (!tlb) {
+ helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
+ POWERPC_EXCP_INVAL |
+ POWERPC_EXCP_INVAL_INVAL);
+ }
+
/* check that we support the targeted size */
size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
size_ps = booke206_tlbnps(env, tlbn);
@@ -4311,7 +4317,11 @@ void helper_booke206_tlbre(void)
ppcmas_tlb_t *tlb = NULL;
tlb = booke206_cur_tlb(env);
- booke206_tlb_to_mas(env, tlb);
+ if (!tlb) {
+ env->spr[SPR_BOOKE_MAS1] = 0;
+ } else {
+ booke206_tlb_to_mas(env, tlb);
+ }
}
void helper_booke206_tlbsx(target_ulong address)
@@ -4330,6 +4340,10 @@ void helper_booke206_tlbsx(target_ulong address)
for (j = 0; j < ways; j++) {
tlb = booke206_get_tlbm(env, i, address, j);
+ if (!tlb) {
+ continue;
+ }
+
if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
continue;
}
@@ -4373,6 +4387,9 @@ static inline void booke206_invalidate_ea_tlb(CPUState *env, int tlbn,
for (i = 0; i < ways; i++) {
ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
+ if (!tlb) {
+ continue;
+ }
mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
!(tlb->mas1 & MAS1_IPROT)) {
@@ -4453,6 +4470,9 @@ void helper_booke206_tlbilx3(target_ulong address)
for (j = 0; j < ways; j++) {
tlb = booke206_get_tlbm(env, i, address, j);
+ if (!tlb) {
+ continue;
+ }
if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
(tlb->mas1 & MAS1_IPROT) ||
((tlb->mas1 & MAS1_IND) != ind) ||
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index d8ef7196b4..58a4853a0d 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -6088,6 +6088,7 @@ static void gen_tlbwe_booke206(DisasContext *ctx)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
}
+ gen_update_nip(ctx, ctx->nip - 4);
gen_helper_booke206_tlbwe();
#endif
}