diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index cf8ba2e5e3..716ffe08b2 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1137,6 +1137,8 @@ int pp_check(int key, int pp, int nx); int check_prot(int prot, int rw, int access_type); int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p, int ret, int rw); hwaddr get_pteg_offset(CPUPPCState *env, hwaddr hash, int pte_size); +int get_bat(CPUPPCState *env, mmu_ctx_t *ctx, + target_ulong virtual, int rw, int type); #endif /* !defined(CONFIG_USER_ONLY) */ void ppc_store_msr (CPUPPCState *env, target_ulong value); diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c index 4bae72a17a..3998d635f2 100644 --- a/target-ppc/mmu-hash32.c +++ b/target-ppc/mmu-hash32.c @@ -158,8 +158,8 @@ static int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h, return ret; } -int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx, - target_ulong eaddr, int rw, int type) +static int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx, + target_ulong eaddr, int rw, int type) { hwaddr hash; target_ulong vsid; @@ -302,3 +302,28 @@ int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx, return ret; } + +int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, + target_ulong eaddr, int rw, int access_type) +{ + bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0) + || (access_type != ACCESS_CODE && msr_dr == 0); + + if (real_mode) { + ctx->raddr = eaddr; + ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE; + return 0; + } else { + int ret = -1; + + /* Try to find a BAT */ + if (env->nb_BATs != 0) { + ret = get_bat(env, ctx, eaddr, rw, access_type); + } + if (ret < 0) { + /* We didn't match any BAT entry or don't have BATs */ + ret = get_segment32(env, ctx, eaddr, rw, access_type); + } + return ret; + } +} diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h index 6f9a0c2bf8..1318562107 100644 --- a/target-ppc/mmu-hash32.h +++ b/target-ppc/mmu-hash32.h @@ -4,8 +4,8 @@ #ifndef CONFIG_USER_ONLY int pte32_is_valid(target_ulong pte0); -int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx, - target_ulong eaddr, int rw, int type); +int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, + target_ulong eaddr, int rw, int access_type); #endif /* CONFIG_USER_ONLY */ diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 23eb4801cc..c7272982b8 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -350,8 +350,8 @@ static int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h, return ret; } -int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx, - target_ulong eaddr, int rw, int type) +static int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx, + target_ulong eaddr, int rw, int type) { hwaddr hash; target_ulong vsid; @@ -435,3 +435,18 @@ int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx, return ret; } + +int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, + target_ulong eaddr, int rw, int access_type) +{ + bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0) + || (access_type != ACCESS_CODE && 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); + } +} diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h index 690c1d829f..d8eb8ded8a 100644 --- a/target-ppc/mmu-hash64.h +++ b/target-ppc/mmu-hash64.h @@ -6,8 +6,8 @@ #ifdef TARGET_PPC64 void dump_slb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env); int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs); -int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx, - target_ulong eaddr, int rw, int type); +int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, + target_ulong eaddr, int rw, int access_type); #endif #endif /* CONFIG_USER_ONLY */ diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c index 5b82731133..ce39f494c5 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -426,8 +426,8 @@ static inline void bat_601_size_prot(CPUPPCState *env, target_ulong *blp, *protp = prot; } -static inline int get_bat(CPUPPCState *env, mmu_ctx_t *ctx, - target_ulong virtual, int rw, int type) +int get_bat(CPUPPCState *env, mmu_ctx_t *ctx, + target_ulong virtual, int rw, int type) { target_ulong *BATlt, *BATut, *BATu, *BATl; target_ulong BEPIl, BEPIu, bl; @@ -1256,8 +1256,6 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, ctx->prot = PAGE_READ | PAGE_EXEC; ret = 0; switch (env->mmu_model) { - case POWERPC_MMU_32B: - case POWERPC_MMU_601: case POWERPC_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_74xx: case POWERPC_MMU_SOFT_4xx: @@ -1265,15 +1263,7 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, case POWERPC_MMU_BOOKE: ctx->prot |= PAGE_WRITE; break; -#if defined(TARGET_PPC64) - case POWERPC_MMU_64B: - case POWERPC_MMU_2_06: - case POWERPC_MMU_2_06d: - /* Real address are 60 bits long */ - ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL; - ctx->prot |= PAGE_WRITE; - break; -#endif + case POWERPC_MMU_SOFT_4xx_Z: if (unlikely(msr_pe != 0)) { /* 403 family add some particular protections, @@ -1298,15 +1288,10 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, } } break; - case POWERPC_MMU_MPC8xx: - /* XXX: TODO */ - cpu_abort(env, "MPC8xx MMU model is not implemented\n"); - break; - case POWERPC_MMU_BOOKE206: - cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n"); - break; + default: - cpu_abort(env, "Unknown or invalid MMU model\n"); + /* Caller's checks mean we should never get here for other models */ + abort(); return -1; } @@ -1327,18 +1312,7 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, switch (env->mmu_model) { case POWERPC_MMU_32B: case POWERPC_MMU_601: - if (real_mode) { - ret = check_physical(env, ctx, eaddr, rw); - } else { - /* Try to find a BAT */ - if (env->nb_BATs != 0) { - ret = get_bat(env, ctx, eaddr, rw, access_type); - } - 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 = ppc_hash32_get_physical_address(env, ctx, eaddr, rw, access_type); break; case POWERPC_MMU_SOFT_6xx: @@ -1361,11 +1335,7 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, case POWERPC_MMU_64B: case POWERPC_MMU_2_06: case POWERPC_MMU_2_06d: - if (real_mode) { - ret = check_physical(env, ctx, eaddr, rw); - } else { - ret = get_segment64(env, ctx, eaddr, rw, access_type); - } + ret = ppc_hash64_get_physical_address(env, ctx, eaddr, rw, access_type); break; #endif