[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 14/48] target-ppc: Disentangle BAT code for 32-bit has
From: |
David Gibson |
Subject: |
[Qemu-ppc] [PATCH 14/48] target-ppc: Disentangle BAT code for 32-bit hash MMUs |
Date: |
Tue, 12 Mar 2013 21:31:16 +1100 |
The functions for looking up BATs (Block Address Translation - essentially
a level 0 TLB) are shared between the classic 32-bit hash MMUs and the
6xx style software loaded TLB implementations.
This patch splits out a copy for the 32-bit hash MMUs, to facilitate
cleaning it up. The remaining version is left, but cleaned up slightly
to no longer deal with PowerPC 601 peculiarities (601 has a hash MMU).
Signed-off-by: David Gibson <address@hidden>
---
target-ppc/cpu.h | 2 -
target-ppc/mmu-hash32.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++-
target-ppc/mmu_helper.c | 38 ++-----------
3 files changed, 142 insertions(+), 38 deletions(-)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 54e1dbc..74b6e0e 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1134,8 +1134,6 @@ void ppc_hw_interrupt (CPUPPCState *env);
#if !defined(CONFIG_USER_ONLY)
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
-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 0ccaf7c..f94b65d 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -25,6 +25,7 @@
#include "mmu-hash32.h"
//#define DEBUG_MMU
+//#define DEBUG_BAT
#ifdef DEBUG_MMU
# define LOG_MMU(...) qemu_log(__VA_ARGS__)
@@ -34,6 +35,12 @@
# define LOG_MMU_STATE(...) do { } while (0)
#endif
+#ifdef DEBUG_BATS
+# define LOG_BATS(...) qemu_log(__VA_ARGS__)
+#else
+# define LOG_BATS(...) do { } while (0)
+#endif
+
#define PTE_PTEM_MASK 0x7FFFFFBF
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
@@ -102,6 +109,136 @@ static int ppc_hash32_check_prot(int prot, int rw, int
access_type)
return ret;
}
+/* Perform BAT hit & translation */
+static void hash32_bat_size_prot(CPUPPCState *env, target_ulong *blp,
+ int *validp, int *protp, target_ulong *BATu,
+ target_ulong *BATl)
+{
+ target_ulong bl;
+ int pp, valid, prot;
+
+ bl = (*BATu & 0x00001FFC) << 15;
+ valid = 0;
+ prot = 0;
+ if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
+ ((msr_pr != 0) && (*BATu & 0x00000001))) {
+ valid = 1;
+ pp = *BATl & 0x00000003;
+ if (pp != 0) {
+ prot = PAGE_READ | PAGE_EXEC;
+ if (pp == 0x2) {
+ prot |= PAGE_WRITE;
+ }
+ }
+ }
+ *blp = bl;
+ *validp = valid;
+ *protp = prot;
+}
+
+static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
+ int *validp, int *protp,
+ target_ulong *BATu, target_ulong *BATl)
+{
+ target_ulong bl;
+ int key, pp, valid, prot;
+
+ bl = (*BATl & 0x0000003F) << 17;
+ LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
+ (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
+ prot = 0;
+ valid = (*BATl >> 6) & 1;
+ if (valid) {
+ pp = *BATu & 0x00000003;
+ if (msr_pr == 0) {
+ key = (*BATu >> 3) & 1;
+ } else {
+ key = (*BATu >> 2) & 1;
+ }
+ prot = ppc_hash32_pp_check(key, pp, 0);
+ }
+ *blp = bl;
+ *validp = valid;
+ *protp = prot;
+}
+
+static int ppc_hash32_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;
+ int i, valid, prot;
+ int ret = -1;
+
+ LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
+ type == ACCESS_CODE ? 'I' : 'D', virtual);
+ switch (type) {
+ case ACCESS_CODE:
+ BATlt = env->IBAT[1];
+ BATut = env->IBAT[0];
+ break;
+ default:
+ BATlt = env->DBAT[1];
+ BATut = env->DBAT[0];
+ break;
+ }
+ for (i = 0; i < env->nb_BATs; i++) {
+ BATu = &BATut[i];
+ BATl = &BATlt[i];
+ BEPIu = *BATu & 0xF0000000;
+ BEPIl = *BATu & 0x0FFE0000;
+ if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
+ hash32_bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
+ } else {
+ hash32_bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
+ }
+ LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
+ " BATl " TARGET_FMT_lx "\n", __func__,
+ type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
+ if ((virtual & 0xF0000000) == BEPIu &&
+ ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
+ /* BAT matches */
+ if (valid != 0) {
+ /* Get physical address */
+ ctx->raddr = (*BATl & 0xF0000000) |
+ ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
+ (virtual & 0x0001F000);
+ /* Compute access rights */
+ ctx->prot = prot;
+ ret = ppc_hash32_check_prot(ctx->prot, rw, type);
+ if (ret == 0) {
+ LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
+ i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
+ ctx->prot & PAGE_WRITE ? 'W' : '-');
+ }
+ break;
+ }
+ }
+ }
+ if (ret < 0) {
+#if defined(DEBUG_BATS)
+ if (qemu_log_enabled()) {
+ LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
+ for (i = 0; i < 4; i++) {
+ BATu = &BATut[i];
+ BATl = &BATlt[i];
+ BEPIu = *BATu & 0xF0000000;
+ BEPIl = *BATu & 0x0FFE0000;
+ bl = (*BATu & 0x00001FFC) << 15;
+ LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
+ " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
+ TARGET_FMT_lx " " TARGET_FMT_lx "\n",
+ __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
+ *BATu, *BATl, BEPIu, BEPIl, bl);
+ }
+ }
+#endif
+ }
+ /* No hit */
+ return ret;
+}
+
+
static inline int pte_is_valid_hash32(target_ulong pte0)
{
return pte0 & 0x80000000 ? 1 : 0;
@@ -398,7 +535,6 @@ static int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
return ret;
}
-
static int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
target_ulong eaddr, int rw,
int access_type)
@@ -415,7 +551,7 @@ static int ppc_hash32_get_physical_address(CPUPPCState
*env, mmu_ctx_t *ctx,
/* Try to find a BAT */
if (env->nb_BATs != 0) {
- ret = get_bat(env, ctx, eaddr, rw, access_type);
+ ret = ppc_hash32_get_bat(env, ctx, eaddr, rw, access_type);
}
if (ret < 0) {
/* We didn't match any BAT entry or don't have BATs */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 50ec0ac..9471d59 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -397,34 +397,8 @@ static inline void bat_size_prot(CPUPPCState *env,
target_ulong *blp,
*protp = prot;
}
-static inline void bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
- int *validp, int *protp,
- target_ulong *BATu, target_ulong *BATl)
-{
- target_ulong bl;
- int key, pp, valid, prot;
-
- bl = (*BATl & 0x0000003F) << 17;
- LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
- (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
- prot = 0;
- valid = (*BATl >> 6) & 1;
- if (valid) {
- pp = *BATu & 0x00000003;
- if (msr_pr == 0) {
- key = (*BATu >> 3) & 1;
- } else {
- key = (*BATu >> 2) & 1;
- }
- prot = pp_check(key, pp, 0);
- }
- *blp = bl;
- *validp = valid;
- *protp = prot;
-}
-
-int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
- target_ulong virtual, int rw, int type)
+static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
+ target_ulong virtual, int rw, int type)
{
target_ulong *BATlt, *BATut, *BATu, *BATl;
target_ulong BEPIl, BEPIu, bl;
@@ -448,11 +422,7 @@ int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
BATl = &BATlt[i];
BEPIu = *BATu & 0xF0000000;
BEPIl = *BATu & 0x0FFE0000;
- if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
- bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
- } else {
- bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
- }
+ bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
" BATl " TARGET_FMT_lx "\n", __func__,
type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
@@ -1309,7 +1279,7 @@ static int get_physical_address(CPUPPCState *env,
mmu_ctx_t *ctx,
} else {
/* Try to find a BAT */
if (env->nb_BATs != 0) {
- ret = get_bat(env, ctx, eaddr, rw, access_type);
+ ret = get_bat_6xx_tlb(env, ctx, eaddr, rw, access_type);
}
if (ret < 0) {
/* We didn't match any BAT entry or don't have BATs */
--
1.7.10.4
- [Qemu-ppc] [PATCH 44/48] mmu-hash*: Merge translate and fault handling functions, (continued)
- [Qemu-ppc] [PATCH 44/48] mmu-hash*: Merge translate and fault handling functions, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 48/48] target-ppc: Use QOM method dispatch for MMU fault handling, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 15/48] target-ppc: mmu_ctx_t should not be a global type, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 17/48] mmu-hash*: Add hash pte load/store helpers, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 03/48] target-ppc: Remove address check for logging, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 39/48] mmu-hash64: Factor SLB N bit into permissions bits, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 08/48] target-ppc: Rework get_physical_address(), David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 30/48] mmu-hash*: Fold pte_check*() logic into caller, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 38/48] mmu-hash*: Clean up permission checking, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 14/48] target-ppc: Disentangle BAT code for 32-bit hash MMUs,
David Gibson <=
- [Qemu-ppc] [PATCH 35/48] mmu-hash32: Don't look up page tables on BAT permission error, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 24/48] mmu-hash*: Cleanup segment-level NX check, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 07/48] target-ppc: Disentangle get_segment(), David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 32/48] mmu-hash32: Split BAT size logic from permissions logic, David Gibson, 2013/03/12
- [Qemu-ppc] [PATCH 11/48] target-ppc: Disentangle hash mmu versions of cpu_get_phys_page_debug(), David Gibson, 2013/03/12
- Re: [Qemu-ppc] [0/48] target-ppc: MMU implementation cleanup for hash MMUs, Alexander Graf, 2013/03/21