mmu-hash*: Cleanup segment-level NX check
On the ppc hash mmus, no-execute can be set at the segment level (on more recent 64-bit hash mmus it can also be set at the page level). This patch separates out this check to make it clearer what is going on, and avoiding excessive indentation of the remaining translation code. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
723ed73ada
commit
bb218042c8
@ -466,10 +466,16 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
|
||||
&ctx->raddr, &ctx->prot);
|
||||
}
|
||||
|
||||
/* 5. Check for segment level no-execute violation */
|
||||
ctx->nx = !!(sr & SR32_NX);
|
||||
if ((rwx == 2) && ctx->nx) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
pr = msr_pr;
|
||||
ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
|
||||
((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
|
||||
ctx->nx = !!(sr & SR32_NX);
|
||||
|
||||
vsid = sr & SR32_VSID;
|
||||
target_page_bits = TARGET_PAGE_BITS;
|
||||
LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
|
||||
@ -485,59 +491,53 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
|
||||
ctx->key, ctx->nx, vsid);
|
||||
ret = -1;
|
||||
|
||||
/* Check if instruction fetch is allowed, if needed */
|
||||
if (rwx != 2 || ctx->nx == 0) {
|
||||
/* Page address translation */
|
||||
LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
|
||||
" hash " TARGET_FMT_plx "\n",
|
||||
env->htab_base, env->htab_mask, hash);
|
||||
ctx->hash[0] = hash;
|
||||
ctx->hash[1] = ~hash;
|
||||
/* Page address translation */
|
||||
LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
|
||||
" hash " TARGET_FMT_plx "\n",
|
||||
env->htab_base, env->htab_mask, hash);
|
||||
ctx->hash[0] = hash;
|
||||
ctx->hash[1] = ~hash;
|
||||
|
||||
/* Initialize real address with an invalid value */
|
||||
ctx->raddr = (hwaddr)-1ULL;
|
||||
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, ctx->ptem,
|
||||
ctx->hash[0]);
|
||||
/* Primary table lookup */
|
||||
ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
|
||||
if (ret < 0) {
|
||||
/* Secondary table lookup */
|
||||
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, ctx->ptem, ctx->hash[1]);
|
||||
ret2 = find_pte32(env, ctx, eaddr, 1, rwx, target_page_bits);
|
||||
if (ret2 != -1) {
|
||||
ret = ret2;
|
||||
}
|
||||
/* Initialize real address with an invalid value */
|
||||
ctx->raddr = (hwaddr)-1ULL;
|
||||
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, ctx->ptem,
|
||||
ctx->hash[0]);
|
||||
/* Primary table lookup */
|
||||
ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
|
||||
if (ret < 0) {
|
||||
/* Secondary table lookup */
|
||||
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, ctx->ptem, ctx->hash[1]);
|
||||
ret2 = find_pte32(env, ctx, eaddr, 1, rwx, target_page_bits);
|
||||
if (ret2 != -1) {
|
||||
ret = ret2;
|
||||
}
|
||||
#if defined(DUMP_PAGE_TABLES)
|
||||
if (qemu_log_enabled()) {
|
||||
hwaddr curaddr;
|
||||
uint32_t a0, a1, a2, a3;
|
||||
|
||||
qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
|
||||
"\n", sdr, mask + 0x80);
|
||||
for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
|
||||
curaddr += 16) {
|
||||
a0 = ldl_phys(curaddr);
|
||||
a1 = ldl_phys(curaddr + 4);
|
||||
a2 = ldl_phys(curaddr + 8);
|
||||
a3 = ldl_phys(curaddr + 12);
|
||||
if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
|
||||
qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
|
||||
curaddr, a0, a1, a2, a3);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
LOG_MMU("No access allowed\n");
|
||||
ret = -3;
|
||||
}
|
||||
#if defined(DUMP_PAGE_TABLES)
|
||||
if (qemu_log_enabled()) {
|
||||
hwaddr curaddr;
|
||||
uint32_t a0, a1, a2, a3;
|
||||
|
||||
qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
|
||||
"\n", sdr, mask + 0x80);
|
||||
for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
|
||||
curaddr += 16) {
|
||||
a0 = ldl_phys(curaddr);
|
||||
a1 = ldl_phys(curaddr + 4);
|
||||
a2 = ldl_phys(curaddr + 8);
|
||||
a3 = ldl_phys(curaddr + 12);
|
||||
if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
|
||||
qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
|
||||
curaddr, a0, a1, a2, a3);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -454,14 +454,20 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr = msr_pr;
|
||||
|
||||
LOG_MMU("Check SLBs\n");
|
||||
/* 2. Translation is on, so look up the SLB */
|
||||
slb = slb_lookup(env, eaddr);
|
||||
|
||||
if (!slb) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* 3. Check for segment level no-execute violation */
|
||||
if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
pr = msr_pr;
|
||||
|
||||
if (slb->vsid & SLB_VSID_B) {
|
||||
vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
|
||||
segment_bits = 40;
|
||||
@ -490,38 +496,32 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
|
||||
ctx->key, !!(slb->vsid & SLB_VSID_N), vsid);
|
||||
ret = -1;
|
||||
|
||||
/* Check if instruction fetch is allowed, if needed */
|
||||
if (rwx != 2 || !(slb->vsid & SLB_VSID_N)) {
|
||||
/* Page address translation */
|
||||
LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
|
||||
" hash " TARGET_FMT_plx "\n",
|
||||
env->htab_base, env->htab_mask, hash);
|
||||
ctx->hash[0] = hash;
|
||||
ctx->hash[1] = ~hash;
|
||||
/* Page address translation */
|
||||
LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
|
||||
" hash " TARGET_FMT_plx "\n",
|
||||
env->htab_base, env->htab_mask, hash);
|
||||
ctx->hash[0] = hash;
|
||||
ctx->hash[1] = ~hash;
|
||||
|
||||
/* Initialize real address with an invalid value */
|
||||
ctx->raddr = (hwaddr)-1ULL;
|
||||
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, ctx->ptem,
|
||||
ctx->hash[0]);
|
||||
/* Primary table lookup */
|
||||
ret = find_pte64(env, ctx, eaddr, 0, rwx, target_page_bits);
|
||||
if (ret < 0) {
|
||||
/* Secondary table lookup */
|
||||
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, ctx->ptem, ctx->hash[1]);
|
||||
ret2 = find_pte64(env, ctx, eaddr, 1, rwx, target_page_bits);
|
||||
if (ret2 != -1) {
|
||||
ret = ret2;
|
||||
}
|
||||
/* Initialize real address with an invalid value */
|
||||
ctx->raddr = (hwaddr)-1ULL;
|
||||
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, ctx->ptem,
|
||||
ctx->hash[0]);
|
||||
/* Primary table lookup */
|
||||
ret = find_pte64(env, ctx, eaddr, 0, rwx, target_page_bits);
|
||||
if (ret < 0) {
|
||||
/* Secondary table lookup */
|
||||
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, ctx->ptem, ctx->hash[1]);
|
||||
ret2 = find_pte64(env, ctx, eaddr, 1, rwx, target_page_bits);
|
||||
if (ret2 != -1) {
|
||||
ret = ret2;
|
||||
}
|
||||
} else {
|
||||
LOG_MMU("No access allowed\n");
|
||||
ret = -3;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user