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 81762d6dd0, 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>
This commit is contained in:
David Gibson 2011-05-20 13:34:59 +10:00 committed by Alexander Graf
parent 1235a9cf17
commit decb471488

View File

@ -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