aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2011-05-20 13:34:59 +1000
committerAlexander Graf <agraf@suse.de>2011-05-20 17:56:03 +0200
commitdecb471488dd9e7e7ab9957f120cb501c4489f63 (patch)
tree74a956708c8f54b05473d1406b459972b6c1ac16
parent1235a9cf179df04cd0dc30fce0089161d18f3168 (diff)
Fix a bug in mtsr/mtsrin emulation on ppc64
Early ppc64 CPUs include a hack to partially simulate the ppc32 segment registers, by translating writes to them into writes to the SLB. This is not used by any current Linux kernel, but it is used by the openbios used in the qemu mac99 model. Commit 81762d6dd0d430d87024f2c83e9c4dcc4329fb7d, cleaning up the SLB handling introduced a bug in this code, breaking the openbios currently in qemu. Specifically, there was an off by one error bitshuffling the register format used by mtsr into the format needed for the SLB load, causing the flag bits to end up in the wrong place. This caused the storage keys to be wrong under openbios, meaning that the translation code incorrectly thought a legitimate access was a permission violation. This patch fixes the bug, at the same time it fixes some build bug in the MMU debugging code (only exposed when DEBUG_MMU is enabled). Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--target-ppc/helper.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 4238be6133..4700632931 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -606,7 +606,7 @@ static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
r = pte64_check(ctx, pte0, pte1, h, rw, type);
LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
- pteg_base + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
+ pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
(int)((pte0 >> 1) & 1), ctx->ptem);
} else
#endif
@@ -621,7 +621,7 @@ static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
r = pte32_check(ctx, pte0, pte1, h, rw, type);
LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
- pteg_base + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
+ pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
(int)((pte0 >> 6) & 1), ctx->ptem);
}
switch (r) {
@@ -918,8 +918,7 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
if (eaddr != 0xEFFFFFFF)
LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
" vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
- " hash=" TARGET_FMT_plx " pg_addr="
- TARGET_FMT_plx "\n", env->htab_base,
+ " hash=" TARGET_FMT_plx "\n", env->htab_base,
env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
ret2 = find_pte(env, ctx, 1, rw, type,
target_page_bits);
@@ -2140,7 +2139,7 @@ void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
/* VSID = VSID */
rs |= (value & 0xfffffff) << 12;
/* flags = flags */
- rs |= ((value >> 27) & 0xf) << 9;
+ rs |= ((value >> 27) & 0xf) << 8;
ppc_store_slb(env, rb, rs);
} else