diff options
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/mmu-hash32.c | 98 | ||||
-rw-r--r-- | target-ppc/mmu-hash64.c | 55 |
2 files changed, 66 insertions, 87 deletions
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c index a7c2e356e8..ad5ef44c28 100644 --- a/target-ppc/mmu-hash32.c +++ b/target-ppc/mmu-hash32.c @@ -91,17 +91,17 @@ static int ppc_hash32_pp_check(int key, int pp, int nx) return access; } -static int ppc_hash32_check_prot(int prot, int rw, int access_type) +static int ppc_hash32_check_prot(int prot, int rwx) { int ret; - if (access_type == ACCESS_CODE) { + if (rwx == 2) { if (prot & PAGE_EXEC) { ret = 0; } else { ret = -2; } - } else if (rw) { + } else if (rwx) { if (prot & PAGE_WRITE) { ret = 0; } else { @@ -172,7 +172,7 @@ static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp, } static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, - target_ulong virtual, int rw, int type) + target_ulong virtual, int rwx) { target_ulong *BATlt, *BATut, *BATu, *BATl; target_ulong BEPIl, BEPIu, bl; @@ -180,16 +180,13 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int ret = -1; LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__, - type == ACCESS_CODE ? 'I' : 'D', virtual); - switch (type) { - case ACCESS_CODE: + rwx == 2 ? 'I' : 'D', virtual); + if (rwx == 2) { BATlt = env->IBAT[1]; BATut = env->IBAT[0]; - break; - default: + } else { BATlt = env->DBAT[1]; BATut = env->DBAT[0]; - break; } for (i = 0; i < env->nb_BATs; i++) { BATu = &BATut[i]; @@ -214,7 +211,7 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, (virtual & 0x0001F000); /* Compute access rights */ ctx->prot = prot; - ret = ppc_hash32_check_prot(ctx->prot, rw, type); + ret = ppc_hash32_check_prot(ctx->prot, rwx); if (ret == 0) { LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n", i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-', @@ -248,7 +245,7 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, } static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0, - target_ulong pte1, int h, int rw, int type) + target_ulong pte1, int h, int rwx) { target_ulong mmask; int access, ret, pp; @@ -272,7 +269,7 @@ static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0, /* Keep the matching PTE informations */ ctx->raddr = pte1; ctx->prot = access; - ret = ppc_hash32_check_prot(ctx->prot, rw, type); + ret = ppc_hash32_check_prot(ctx->prot, rwx); if (ret == 0) { /* Access granted */ LOG_MMU("PTE access granted !\n"); @@ -287,7 +284,7 @@ static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0, } static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong *pte1p, - int ret, int rw) + int ret, int rwx) { int store = 0; @@ -298,7 +295,7 @@ static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong store = 1; } if (!(*pte1p & HPTE32_R_C)) { - if (rw == 1 && ret == 0) { + if (rwx == 1 && ret == 0) { /* Update changed flag */ *pte1p |= HPTE32_R_C; store = 1; @@ -318,7 +315,7 @@ hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash) /* PTE table lookup */ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h, - int rw, int type, int target_page_bits) + int rwx, int target_page_bits) { hwaddr pteg_off; target_ulong pte0, pte1; @@ -330,7 +327,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h, for (i = 0; i < HPTES_PER_GROUP; i++) { pte0 = ppc_hash32_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_32); pte1 = ppc_hash32_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_32); - r = pte_check_hash32(ctx, pte0, pte1, h, rw, type); + r = pte_check_hash32(ctx, pte0, pte1, h, rwx); LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " " TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n", pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h, @@ -365,7 +362,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h, ctx->raddr, ctx->prot, ret); /* Update page flags */ pte1 = ctx->raddr; - if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rw) == 1) { + if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rwx) == 1) { ppc_hash32_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_32, pte1); } @@ -381,7 +378,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h, } static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, - target_ulong eaddr, int rw, int type) + target_ulong eaddr, int rwx) { hwaddr hash; target_ulong vsid; @@ -401,9 +398,9 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, target_page_bits = TARGET_PAGE_BITS; LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx - " ir=%d dr=%d pr=%d %d t=%d\n", + " ir=%d dr=%d pr=%d %d\n", eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir, - (int)msr_dr, pr != 0 ? 1 : 0, rw, type); + (int)msr_dr, pr != 0 ? 1 : 0, rwx); pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits; hash = vsid ^ pgidx; ctx->ptem = (vsid << 7) | (pgidx >> 10); @@ -413,7 +410,7 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, ret = -1; if (!ds) { /* Check if instruction fetch is allowed, if needed */ - if (type != ACCESS_CODE || ctx->nx == 0) { + 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", @@ -429,15 +426,14 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, env->htab_base, env->htab_mask, vsid, ctx->ptem, ctx->hash[0]); /* Primary table lookup */ - ret = find_pte32(env, ctx, 0, rw, type, target_page_bits); + ret = find_pte32(env, ctx, 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, 1, rw, type, - target_page_bits); + ret2 = find_pte32(env, ctx, 1, rwx, target_page_bits); if (ret2 != -1) { ret = ret2; } @@ -486,13 +482,15 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, return 0; } - switch (type) { + if (rwx == 2) { + /* No code fetch is allowed in direct-store areas */ + return -4; + } + + switch (env->access_type) { case ACCESS_INT: /* Integer load/store : only access allowed */ break; - case ACCESS_CODE: - /* No code fetch is allowed in direct-store areas */ - return -4; case ACCESS_FLOAT: /* Floating point load/store */ return -4; @@ -514,7 +512,7 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, "address translation\n"); return -4; } - if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) { + if ((rwx == 1 || ctx->key != 1) && (rwx == 0 || ctx->key != 0)) { ctx->raddr = eaddr; ret = 2; } else { @@ -526,11 +524,10 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, } static int ppc_hash32_get_physical_address(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, - target_ulong eaddr, int rw, - int access_type) + target_ulong eaddr, int rwx) { - bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0) - || (access_type != ACCESS_CODE && msr_dr == 0); + bool real_mode = (rwx == 2 && msr_ir == 0) + || (rwx != 2 && msr_dr == 0); if (real_mode) { ctx->raddr = eaddr; @@ -541,11 +538,11 @@ static int ppc_hash32_get_physical_address(CPUPPCState *env, struct mmu_ctx_hash /* Try to find a BAT */ if (env->nb_BATs != 0) { - ret = ppc_hash32_get_bat(env, ctx, eaddr, rw, access_type); + ret = ppc_hash32_get_bat(env, ctx, eaddr, rwx); } if (ret < 0) { /* We didn't match any BAT entry or don't have BATs */ - ret = get_segment32(env, ctx, eaddr, rw, access_type); + ret = get_segment32(env, ctx, eaddr, rwx); } return ret; } @@ -555,7 +552,9 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr) { struct mmu_ctx_hash32 ctx; - if (unlikely(ppc_hash32_get_physical_address(env, &ctx, addr, 0, ACCESS_INT) + /* FIXME: Will not behave sanely for direct store segments, but + * they're almost never used */ + if (unlikely(ppc_hash32_get_physical_address(env, &ctx, addr, 0) != 0)) { return -1; } @@ -563,22 +562,13 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr) return ctx.raddr & TARGET_PAGE_MASK; } -int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, +int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx, int mmu_idx) { struct mmu_ctx_hash32 ctx; - int access_type; int ret = 0; - if (rw == 2) { - /* code access */ - rw = 0; - access_type = ACCESS_CODE; - } else { - /* data access */ - access_type = env->access_type; - } - ret = ppc_hash32_get_physical_address(env, &ctx, address, rw, access_type); + ret = ppc_hash32_get_physical_address(env, &ctx, address, rwx); if (ret == 0) { tlb_set_page(env, address & TARGET_PAGE_MASK, ctx.raddr & TARGET_PAGE_MASK, ctx.prot, @@ -586,7 +576,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, ret = 0; } else if (ret < 0) { LOG_MMU_STATE(env); - if (access_type == ACCESS_CODE) { + if (rwx == 2) { switch (ret) { case -1: /* No matches in page tables or TLB */ @@ -617,7 +607,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; - if (rw == 1) { + if (rwx == 1) { env->spr[SPR_DSISR] = 0x42000000; } else { env->spr[SPR_DSISR] = 0x40000000; @@ -628,7 +618,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; - if (rw == 1) { + if (rwx == 1) { env->spr[SPR_DSISR] = 0x0A000000; } else { env->spr[SPR_DSISR] = 0x08000000; @@ -636,7 +626,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, break; case -4: /* Direct store exception */ - switch (access_type) { + switch (env->access_type) { case ACCESS_FLOAT: /* Floating point load/store */ env->exception_index = POWERPC_EXCP_ALIGN; @@ -648,7 +638,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; - if (rw == 1) { + if (rwx == 1) { env->spr[SPR_DSISR] = 0x06000000; } else { env->spr[SPR_DSISR] = 0x04000000; @@ -659,7 +649,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; - if (rw == 1) { + if (rwx == 1) { env->spr[SPR_DSISR] = 0x06100000; } else { env->spr[SPR_DSISR] = 0x04100000; diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 30c25dd24b..654ef06308 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -276,17 +276,17 @@ static int ppc_hash64_pp_check(int key, int pp, int nx) return access; } -static int ppc_hash64_check_prot(int prot, int rw, int access_type) +static int ppc_hash64_check_prot(int prot, int rwx) { int ret; - if (access_type == ACCESS_CODE) { + if (rwx == 2) { if (prot & PAGE_EXEC) { ret = 0; } else { ret = -2; } - } else if (rw) { + } else if (rwx == 1) { if (prot & PAGE_WRITE) { ret = 0; } else { @@ -304,7 +304,7 @@ static int ppc_hash64_check_prot(int prot, int rw, int access_type) } static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0, - target_ulong pte1, int h, int rw, int type) + target_ulong pte1, int h, int rwx) { target_ulong mmask; int access, ret, pp; @@ -330,7 +330,7 @@ static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0, /* Keep the matching PTE informations */ ctx->raddr = pte1; ctx->prot = access; - ret = ppc_hash64_check_prot(ctx->prot, rw, type); + ret = ppc_hash64_check_prot(ctx->prot, rwx); if (ret == 0) { /* Access granted */ LOG_MMU("PTE access granted !\n"); @@ -372,7 +372,7 @@ static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx, /* PTE table lookup */ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h, - int rw, int type, int target_page_bits) + int rwx, int target_page_bits) { hwaddr pteg_off; target_ulong pte0, pte1; @@ -385,7 +385,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h, pte0 = ppc_hash64_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_64); pte1 = ppc_hash64_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_64); - r = pte64_check(ctx, pte0, pte1, h, rw, type); + r = pte64_check(ctx, pte0, pte1, h, rwx); LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " " TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n", pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h, @@ -420,7 +420,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h, ctx->raddr, ctx->prot, ret); /* Update page flags */ pte1 = ctx->raddr; - if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rw) == 1) { + if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rwx) == 1) { ppc_hash64_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_64, pte1); } } @@ -435,7 +435,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h, } static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, - target_ulong eaddr, int rw, int type) + target_ulong eaddr, int rwx) { hwaddr hash; target_ulong vsid; @@ -484,7 +484,7 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, ret = -1; /* Check if instruction fetch is allowed, if needed */ - if (type != ACCESS_CODE || ctx->nx == 0) { + 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", @@ -500,14 +500,14 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, env->htab_base, env->htab_mask, vsid, ctx->ptem, ctx->hash[0]); /* Primary table lookup */ - ret = find_pte64(env, ctx, 0, rw, type, target_page_bits); + ret = find_pte64(env, ctx, 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, 1, rw, type, target_page_bits); + ret2 = find_pte64(env, ctx, 1, rwx, target_page_bits); if (ret2 != -1) { ret = ret2; } @@ -522,18 +522,17 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, static int ppc_hash64_get_physical_address(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, - target_ulong eaddr, int rw, - int access_type) + target_ulong eaddr, int rwx) { - bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0) - || (access_type != ACCESS_CODE && msr_dr == 0); + bool real_mode = (rwx == 2 && msr_ir == 0) + || (rwx != 2 && msr_dr == 0); if (real_mode) { ctx->raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL; ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE; return 0; } else { - return get_segment64(env, ctx, eaddr, rw, access_type); + return get_segment64(env, ctx, eaddr, rwx); } } @@ -541,30 +540,20 @@ hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr) { struct mmu_ctx_hash64 ctx; - if (unlikely(ppc_hash64_get_physical_address(env, &ctx, addr, 0, ACCESS_INT) - != 0)) { + if (unlikely(ppc_hash64_get_physical_address(env, &ctx, addr, 0) != 0)) { return -1; } return ctx.raddr & TARGET_PAGE_MASK; } -int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, +int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx, int mmu_idx) { struct mmu_ctx_hash64 ctx; - int access_type; int ret = 0; - if (rw == 2) { - /* code access */ - rw = 0; - access_type = ACCESS_CODE; - } else { - /* data access */ - access_type = env->access_type; - } - ret = ppc_hash64_get_physical_address(env, &ctx, address, rw, access_type); + ret = ppc_hash64_get_physical_address(env, &ctx, address, rwx); if (ret == 0) { tlb_set_page(env, address & TARGET_PAGE_MASK, ctx.raddr & TARGET_PAGE_MASK, ctx.prot, @@ -572,7 +561,7 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, ret = 0; } else if (ret < 0) { LOG_MMU_STATE(env); - if (access_type == ACCESS_CODE) { + if (rwx == 2) { switch (ret) { case -1: env->exception_index = POWERPC_EXCP_ISI; @@ -601,7 +590,7 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; - if (rw == 1) { + if (rwx == 1) { env->spr[SPR_DSISR] = 0x42000000; } else { env->spr[SPR_DSISR] = 0x40000000; @@ -612,7 +601,7 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, env->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = address; - if (rw == 1) { + if (rwx == 1) { env->spr[SPR_DSISR] = 0x0A000000; } else { env->spr[SPR_DSISR] = 0x08000000; |