diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2013-03-12 00:31:11 +0000 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2013-03-22 15:28:47 +0100 |
commit | 629bd516fda67c95ba1c7d1393bacb9e68ea0712 (patch) | |
tree | 19da881c94afcf1b53a5d65fde2d2770280f0271 /target-ppc | |
parent | 44bc910794eff956ceba0030f0751a26bed748b5 (diff) | |
download | qemu-629bd516fda67c95ba1c7d1393bacb9e68ea0712.zip qemu-629bd516fda67c95ba1c7d1393bacb9e68ea0712.tar.gz qemu-629bd516fda67c95ba1c7d1393bacb9e68ea0712.tar.bz2 |
target-ppc: Disentangle get_physical_address() paths
Depending on the MSR state, for 64-bit hash MMUs, get_physical_address
can either call check_physical (which has further tests for mmu type)
or get_segment64. Similarly for 32-bit hash MMUs we can either call
check_physucal or get_bat() and get_segment32().
This patch splits off the whole get_physical_addresss() path for hash
MMUs into 32-bit and 64-bit versions, handling real mode correctly for
such MMUs without going to check_physical and rechecking the mmu type.
Correspondingly, the hash MMU specific paths in check_physical() are
removed.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/cpu.h | 2 | ||||
-rw-r--r-- | target-ppc/mmu-hash32.c | 29 | ||||
-rw-r--r-- | target-ppc/mmu-hash32.h | 4 | ||||
-rw-r--r-- | target-ppc/mmu-hash64.c | 19 | ||||
-rw-r--r-- | target-ppc/mmu-hash64.h | 4 | ||||
-rw-r--r-- | target-ppc/mmu_helper.c | 46 |
6 files changed, 58 insertions, 46 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index cf8ba2e..716ffe0 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 4bae72a..3998d63 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 6f9a0c2..1318562 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 23eb480..c727298 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 690c1d8..d8eb8de 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 5b82731..ce39f49 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 |