diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2013-03-12 00:31:18 +0000 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2013-03-22 15:28:48 +0100 |
commit | d5aea6f367d25b630a952a5a0c8289add774a8e8 (patch) | |
tree | 7a8a8ed8ab64426cd81300f54440042c72c75955 /target-ppc | |
parent | 5dc68eb0e4e41462bf93cf5c67fe4045571fc7bf (diff) |
mmu-hash*: Add header file for definitions
Currently cpu.h contains a number of definitions relating to the 64-bit
hash MMU. Some are used in the MMU emulation code, but some are only used
in the spapr MMU management hcall implementations.
This patch moves these definitions (except for a few that are needed
more widely) into mmu-hash64.h header, shared between the MMU emulation
code and the spapr hcall code. The MMU emulation code is also updated to
actually use a number of those definitions in place of hard coded
constants.
Similarly, we add new analogous definitions to mmu-hash32.h and use those
in place of many hard-coded constants in mmu-hash32.c
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[agraf: fix 32-bit hosts]
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/cpu.h | 24 | ||||
-rw-r--r-- | target-ppc/kvm.c | 1 | ||||
-rw-r--r-- | target-ppc/mmu-hash32.c | 78 | ||||
-rw-r--r-- | target-ppc/mmu-hash32.h | 61 | ||||
-rw-r--r-- | target-ppc/mmu-hash64.c | 35 | ||||
-rw-r--r-- | target-ppc/mmu-hash64.h | 62 |
6 files changed, 171 insertions, 90 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index e5f46b3418..e96afa61ec 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -394,36 +394,12 @@ union ppc_tlb_t { #define SDR_64_HTABSIZE 0x000000000000001FULL #endif /* defined(TARGET_PPC64 */ -#define HASH_PTE_SIZE_32 8 -#define HASH_PTE_SIZE_64 16 - typedef struct ppc_slb_t ppc_slb_t; struct ppc_slb_t { uint64_t esid; uint64_t vsid; }; -/* Bits in the SLB ESID word */ -#define SLB_ESID_ESID 0xFFFFFFFFF0000000ULL -#define SLB_ESID_V 0x0000000008000000ULL /* valid */ - -/* Bits in the SLB VSID word */ -#define SLB_VSID_SHIFT 12 -#define SLB_VSID_SHIFT_1T 24 -#define SLB_VSID_SSIZE_SHIFT 62 -#define SLB_VSID_B 0xc000000000000000ULL -#define SLB_VSID_B_256M 0x0000000000000000ULL -#define SLB_VSID_B_1T 0x4000000000000000ULL -#define SLB_VSID_VSID 0x3FFFFFFFFFFFF000ULL -#define SLB_VSID_PTEM (SLB_VSID_B | SLB_VSID_VSID) -#define SLB_VSID_KS 0x0000000000000800ULL -#define SLB_VSID_KP 0x0000000000000400ULL -#define SLB_VSID_N 0x0000000000000200ULL /* no-execute */ -#define SLB_VSID_L 0x0000000000000100ULL -#define SLB_VSID_C 0x0000000000000080ULL /* class */ -#define SLB_VSID_LP 0x0000000000000030ULL -#define SLB_VSID_ATTR 0x0000000000000FFFULL - #define SEGMENT_SHIFT_256M 28 #define SEGMENT_MASK_256M (~((1ULL << SEGMENT_SHIFT_256M) - 1)) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 9870d60884..597066f5a0 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -32,6 +32,7 @@ #include "sysemu/device_tree.h" #include "hw/sysbus.h" #include "hw/spapr.h" +#include "mmu-hash64.h" #include "hw/sysbus.h" #include "hw/spapr.h" diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c index 5b48aa8486..a1bbd50398 100644 --- a/target-ppc/mmu-hash32.c +++ b/target-ppc/mmu-hash32.c @@ -51,7 +51,6 @@ struct mmu_ctx_hash32 { int nx; /* Non-execute area */ }; -#define PTE_PTEM_MASK 0x7FFFFFBF #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B) static int ppc_hash32_pp_check(int key, int pp, int nx) @@ -127,13 +126,13 @@ static void hash32_bat_size_prot(CPUPPCState *env, target_ulong *blp, target_ulong bl; int pp, valid, prot; - bl = (*BATu & 0x00001FFC) << 15; + bl = (*BATu & BATU32_BL) << 15; valid = 0; prot = 0; - if (((msr_pr == 0) && (*BATu & 0x00000002)) || - ((msr_pr != 0) && (*BATu & 0x00000001))) { + if (((msr_pr == 0) && (*BATu & BATU32_VS)) || + ((msr_pr != 0) && (*BATu & BATU32_VP))) { valid = 1; - pp = *BATl & 0x00000003; + pp = *BATl & BATL32_PP; if (pp != 0) { prot = PAGE_READ | PAGE_EXEC; if (pp == 0x2) { @@ -153,17 +152,17 @@ static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp, target_ulong bl; int key, pp, valid, prot; - bl = (*BATl & 0x0000003F) << 17; + bl = (*BATl & BATL32_601_BL) << 17; LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n", - (uint8_t)(*BATl & 0x0000003F), bl, ~bl); + (uint8_t)(*BATl & BATL32_601_BL), bl, ~bl); prot = 0; - valid = (*BATl >> 6) & 1; + valid = !!(*BATl & BATL32_601_V); if (valid) { - pp = *BATu & 0x00000003; + pp = *BATu & BATU32_601_PP; if (msr_pr == 0) { - key = (*BATu >> 3) & 1; + key = !!(*BATu & BATU32_601_KS); } else { - key = (*BATu >> 2) & 1; + key = !!(*BATu & BATU32_601_KP); } prot = ppc_hash32_pp_check(key, pp, 0); } @@ -195,8 +194,8 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, for (i = 0; i < env->nb_BATs; i++) { BATu = &BATut[i]; BATl = &BATlt[i]; - BEPIu = *BATu & 0xF0000000; - BEPIl = *BATu & 0x0FFE0000; + BEPIu = *BATu & BATU32_BEPIU; + BEPIl = *BATu & BATU32_BEPIL; if (unlikely(env->mmu_model == POWERPC_MMU_601)) { hash32_bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl); } else { @@ -205,13 +204,13 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, 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) { + if ((virtual & BATU32_BEPIU) == BEPIu && + ((virtual & BATU32_BEPIL) & ~bl) == BEPIl) { /* BAT matches */ if (valid != 0) { /* Get physical address */ - ctx->raddr = (*BATl & 0xF0000000) | - ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) | + ctx->raddr = (*BATl & BATL32_BRPNU) | + ((virtual & BATU32_BEPIL & bl) | (*BATl & BATL32_BRPNL)) | (virtual & 0x0001F000); /* Compute access rights */ ctx->prot = prot; @@ -232,8 +231,8 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, for (i = 0; i < 4; i++) { BATu = &BATut[i]; BATl = &BATlt[i]; - BEPIu = *BATu & 0xF0000000; - BEPIl = *BATu & 0x0FFE0000; + BEPIu = *BATu & BATU32_BEPIU; + BEPIl = *BATu & BATU32_BEPIL; 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 " " @@ -248,28 +247,19 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, return ret; } - -static inline int pte_is_valid_hash32(target_ulong pte0) -{ - return pte0 & 0x80000000 ? 1 : 0; -} - static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0, target_ulong pte1, int h, int rw, int type) { - target_ulong ptem, mmask; - int access, ret, pteh, ptev, pp; + target_ulong mmask; + int access, ret, pp; ret = -1; /* Check validity and table match */ - ptev = pte_is_valid_hash32(pte0); - pteh = (pte0 >> 6) & 1; - if (ptev && h == pteh) { + if ((pte0 & HPTE32_V_VALID) && (h == !!(pte0 & HPTE32_V_SECONDARY))) { /* Check vsid & api */ - ptem = pte0 & PTE_PTEM_MASK; mmask = PTE_CHECK_MASK; - pp = pte1 & 0x00000003; - if (ptem == ctx->ptem) { + pp = pte1 & HPTE32_R_PP; + if (HPTE32_V_COMPARE(pte0, ctx->ptem)) { if (ctx->raddr != (hwaddr)-1ULL) { /* all matches should have equal RPN, WIMG & PP */ if ((ctx->raddr & mmask) != (pte1 & mmask)) { @@ -302,15 +292,15 @@ static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong int store = 0; /* Update page flags */ - if (!(*pte1p & 0x00000100)) { + if (!(*pte1p & HPTE32_R_R)) { /* Update accessed flag */ - *pte1p |= 0x00000100; + *pte1p |= HPTE32_R_R; store = 1; } - if (!(*pte1p & 0x00000080)) { + if (!(*pte1p & HPTE32_R_C)) { if (rw == 1 && ret == 0) { /* Update changed flag */ - *pte1p |= 0x00000080; + *pte1p |= HPTE32_R_C; store = 1; } else { /* Force page fault for first write access */ @@ -323,7 +313,7 @@ static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash) { - return (hash * HASH_PTE_SIZE_32 * 8) & env->htab_mask; + return (hash * HASH_PTEG_SIZE_32) & env->htab_mask; } /* PTE table lookup */ @@ -337,7 +327,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h, ret = -1; /* No entry found */ pteg_off = get_pteg_offset32(env, ctx->hash[h]); - for (i = 0; i < 8; i++) { + for (i = 0; i < HPTES_PER_GROUP; i++) { if (env->external_htab) { pte0 = ldl_p(env->external_htab + pteg_off + (i * 8)); pte1 = ldl_p(env->external_htab + pteg_off + (i * 8) + 4); @@ -413,11 +403,11 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, ctx->eaddr = eaddr; sr = env->sr[eaddr >> 28]; - ctx->key = (((sr & 0x20000000) && (pr != 0)) || - ((sr & 0x40000000) && (pr == 0))) ? 1 : 0; - ds = sr & 0x80000000 ? 1 : 0; - ctx->nx = sr & 0x10000000 ? 1 : 0; - vsid = sr & 0x00FFFFFF; + ctx->key = (((sr & SR32_KP) && (pr != 0)) || + ((sr & SR32_KS) && (pr == 0))) ? 1 : 0; + ds = !!(sr & SR32_T); + 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=" TARGET_FMT_lx " lr=" TARGET_FMT_lx diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h index 3435aa5513..a09ccb3d38 100644 --- a/target-ppc/mmu-hash32.h +++ b/target-ppc/mmu-hash32.h @@ -8,6 +8,67 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr); int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, int mmu_idx); +/* + * Segment register definitions + */ + +#define SR32_T 0x80000000 +#define SR32_KS 0x40000000 +#define SR32_KP 0x20000000 +#define SR32_NX 0x10000000 +#define SR32_VSID 0x00ffffff + +/* + * Block Address Translation (BAT) definitions + */ + +#define BATU32_BEPIU 0xf0000000 +#define BATU32_BEPIL 0x0ffe0000 +#define BATU32_BEPI 0xfffe0000 +#define BATU32_BL 0x00001ffc +#define BATU32_VS 0x00000002 +#define BATU32_VP 0x00000001 + + +#define BATL32_BRPNU 0xf0000000 +#define BATL32_BRPNL 0x0ffe0000 +#define BATL32_BRPN 0xfffe0000 +#define BATL32_WIMG 0x00000078 +#define BATL32_PP 0x00000003 + +/* PowerPC 601 has slightly different BAT registers */ + +#define BATU32_601_KS 0x00000008 +#define BATU32_601_KP 0x00000004 +#define BATU32_601_PP 0x00000003 + +#define BATL32_601_V 0x00000040 +#define BATL32_601_BL 0x0000003f + +/* + * Hash page table definitions + */ + +#define HPTES_PER_GROUP 8 +#define HASH_PTE_SIZE_32 8 +#define HASH_PTEG_SIZE_32 (HASH_PTE_SIZE_32 * HPTES_PER_GROUP) + +#define HPTE32_V_VALID 0x80000000 +#define HPTE32_V_VSID 0x7fffff80 +#define HPTE32_V_SECONDARY 0x00000040 +#define HPTE32_V_API 0x0000003f +#define HPTE32_V_COMPARE(x, y) (!(((x) ^ (y)) & 0x7fffffbf)) + +#define HPTE32_R_RPN 0xfffff000 +#define HPTE32_R_R 0x00000100 +#define HPTE32_R_C 0x00000080 +#define HPTE32_R_W 0x00000040 +#define HPTE32_R_I 0x00000020 +#define HPTE32_R_M 0x00000010 +#define HPTE32_R_G 0x00000008 +#define HPTE32_R_WIMG 0x00000078 +#define HPTE32_R_PP 0x00000003 + #endif /* CONFIG_USER_ONLY */ #endif /* __MMU_HASH32_H__ */ diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 3008be8ee9..f3223dd383 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -233,7 +233,6 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb) * 64-bit hash table MMU handling */ -#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F) static int ppc_hash64_pp_check(int key, int pp, int nx) @@ -304,29 +303,21 @@ static int ppc_hash64_check_prot(int prot, int rw, int access_type) return ret; } -static inline int pte64_is_valid(target_ulong pte0) -{ - return pte0 & 0x0000000000000001ULL ? 1 : 0; -} - static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0, target_ulong pte1, int h, int rw, int type) { - target_ulong ptem, mmask; - int access, ret, pteh, ptev, pp; + target_ulong mmask; + int access, ret, pp; ret = -1; /* Check validity and table match */ - ptev = pte64_is_valid(pte0); - pteh = (pte0 >> 1) & 1; - if (ptev && h == pteh) { + if ((pte0 & HPTE64_V_VALID) && (h == !!(pte0 & HPTE64_V_SECONDARY))) { /* Check vsid & api */ - ptem = pte0 & PTE64_PTEM_MASK; mmask = PTE64_CHECK_MASK; - pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004); - ctx->nx = (pte1 >> 2) & 1; /* No execute bit */ - ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit */ - if (ptem == ctx->ptem) { + pp = (pte1 & HPTE64_R_PP) | ((pte1 & HPTE64_R_PP0) >> 61); + /* No execute if either noexec or guarded bits set */ + ctx->nx = (pte1 & HPTE64_R_N) || (pte1 & HPTE64_R_G); + if (HPTE64_V_COMPARE(pte0, ctx->ptem)) { if (ctx->raddr != (hwaddr)-1ULL) { /* all matches should have equal RPN, WIMG & PP */ if ((ctx->raddr & mmask) != (pte1 & mmask)) { @@ -360,15 +351,15 @@ static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx, int store = 0; /* Update page flags */ - if (!(*pte1p & 0x00000100)) { + if (!(*pte1p & HPTE64_R_R)) { /* Update accessed flag */ - *pte1p |= 0x00000100; + *pte1p |= HPTE64_R_R; store = 1; } - if (!(*pte1p & 0x00000080)) { + if (!(*pte1p & HPTE64_R_C)) { if (rw == 1 && ret == 0) { /* Update changed flag */ - *pte1p |= 0x00000080; + *pte1p |= HPTE64_R_C; store = 1; } else { /* Force page fault for first write access */ @@ -389,8 +380,8 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h, int ret, r; ret = -1; /* No entry found */ - pteg_off = (ctx->hash[h] * HASH_PTE_SIZE_64 * 8) & env->htab_mask; - for (i = 0; i < 8; i++) { + pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask; + for (i = 0; i < HPTES_PER_GROUP; i++) { if (env->external_htab) { pte0 = ldq_p(env->external_htab + pteg_off + (i * 16)); pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8); diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h index 665d3b0247..80b86d91ae 100644 --- a/target-ppc/mmu-hash64.h +++ b/target-ppc/mmu-hash64.h @@ -11,6 +11,68 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, int mmu_idx); #endif +/* + * SLB definitions + */ + +/* Bits in the SLB ESID word */ +#define SLB_ESID_ESID 0xFFFFFFFFF0000000ULL +#define SLB_ESID_V 0x0000000008000000ULL /* valid */ + +/* Bits in the SLB VSID word */ +#define SLB_VSID_SHIFT 12 +#define SLB_VSID_SHIFT_1T 24 +#define SLB_VSID_SSIZE_SHIFT 62 +#define SLB_VSID_B 0xc000000000000000ULL +#define SLB_VSID_B_256M 0x0000000000000000ULL +#define SLB_VSID_B_1T 0x4000000000000000ULL +#define SLB_VSID_VSID 0x3FFFFFFFFFFFF000ULL +#define SLB_VSID_PTEM (SLB_VSID_B | SLB_VSID_VSID) +#define SLB_VSID_KS 0x0000000000000800ULL +#define SLB_VSID_KP 0x0000000000000400ULL +#define SLB_VSID_N 0x0000000000000200ULL /* no-execute */ +#define SLB_VSID_L 0x0000000000000100ULL +#define SLB_VSID_C 0x0000000000000080ULL /* class */ +#define SLB_VSID_LP 0x0000000000000030ULL +#define SLB_VSID_ATTR 0x0000000000000FFFULL + +/* + * Hash page table definitions + */ + +#define HPTES_PER_GROUP 8 +#define HASH_PTE_SIZE_64 16 +#define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP) + +#define HPTE64_V_SSIZE_SHIFT 62 +#define HPTE64_V_AVPN_SHIFT 7 +#define HPTE64_V_AVPN 0x3fffffffffffff80ULL +#define HPTE64_V_AVPN_VAL(x) (((x) & HPTE64_V_AVPN) >> HPTE64_V_AVPN_SHIFT) +#define HPTE64_V_COMPARE(x, y) (!(((x) ^ (y)) & 0xffffffffffffff80ULL)) +#define HPTE64_V_LARGE 0x0000000000000004ULL +#define HPTE64_V_SECONDARY 0x0000000000000002ULL +#define HPTE64_V_VALID 0x0000000000000001ULL + +#define HPTE64_R_PP0 0x8000000000000000ULL +#define HPTE64_R_TS 0x4000000000000000ULL +#define HPTE64_R_KEY_HI 0x3000000000000000ULL +#define HPTE64_R_RPN_SHIFT 12 +#define HPTE64_R_RPN 0x0ffffffffffff000ULL +#define HPTE64_R_FLAGS 0x00000000000003ffULL +#define HPTE64_R_PP 0x0000000000000003ULL +#define HPTE64_R_N 0x0000000000000004ULL +#define HPTE64_R_G 0x0000000000000008ULL +#define HPTE64_R_M 0x0000000000000010ULL +#define HPTE64_R_I 0x0000000000000020ULL +#define HPTE64_R_W 0x0000000000000040ULL +#define HPTE64_R_WIMG 0x0000000000000078ULL +#define HPTE64_R_C 0x0000000000000080ULL +#define HPTE64_R_R 0x0000000000000100ULL +#define HPTE64_R_KEY_LO 0x0000000000000e00ULL + +#define HPTE64_V_1TB_SEG 0x4000000000000000ULL +#define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL + #endif /* CONFIG_USER_ONLY */ #endif /* !defined (__MMU_HASH64_H__) */ |