diff options
-rw-r--r-- | hw/ppc/spapr_hcall.c | 38 | ||||
-rw-r--r-- | target-ppc/mmu-hash32.c | 18 | ||||
-rw-r--r-- | target-ppc/mmu-hash32.h | 28 | ||||
-rw-r--r-- | target-ppc/mmu-hash64.c | 17 | ||||
-rw-r--r-- | target-ppc/mmu-hash64.h | 40 |
5 files changed, 94 insertions, 47 deletions
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 7be743c..22cfb7e 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -52,7 +52,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong page_shift = 12; target_ulong raddr; target_ulong i; - uint8_t *hpte; + hwaddr hpte; /* only handle 4k and 16M pages for now */ if (pteh & HPTE64_V_LARGE) { @@ -97,26 +97,26 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr, } if (likely((flags & H_EXACT) == 0)) { pte_index &= ~7ULL; - hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64); + hpte = pte_index * HASH_PTE_SIZE_64; for (i = 0; ; ++i) { if (i == 8) { return H_PTEG_FULL; } - if ((ldq_p(hpte) & HPTE64_V_VALID) == 0) { + if ((ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) == 0) { break; } hpte += HASH_PTE_SIZE_64; } } else { i = 0; - hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64); - if (ldq_p(hpte) & HPTE64_V_VALID) { + hpte = pte_index * HASH_PTE_SIZE_64; + if (ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) { return H_PTEG_FULL; } } - stq_p(hpte + (HASH_PTE_SIZE_64/2), ptel); + ppc_hash64_store_hpte1(env, hpte, ptel); /* eieio(); FIXME: need some sort of barrier for smp? */ - stq_p(hpte, pteh); + ppc_hash64_store_hpte0(env, hpte, pteh); args[0] = pte_index + i; return H_SUCCESS; @@ -134,17 +134,17 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, target_ulong flags, target_ulong *vp, target_ulong *rp) { - uint8_t *hpte; + hwaddr hpte; target_ulong v, r, rb; if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) { return REMOVE_PARM; } - hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64); + hpte = ptex * HASH_PTE_SIZE_64; - v = ldq_p(hpte); - r = ldq_p(hpte + (HASH_PTE_SIZE_64/2)); + v = ppc_hash64_load_hpte0(env, hpte); + r = ppc_hash64_load_hpte1(env, hpte); if ((v & HPTE64_V_VALID) == 0 || ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) || @@ -153,7 +153,7 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, } *vp = v; *rp = r; - stq_p(hpte, 0); + ppc_hash64_store_hpte0(env, hpte, 0); rb = compute_tlbie_rb(v, r, ptex); ppc_tlb_invalidate_one(env, rb); return REMOVE_SUCCESS; @@ -260,17 +260,17 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong flags = args[0]; target_ulong pte_index = args[1]; target_ulong avpn = args[2]; - uint8_t *hpte; + hwaddr hpte; target_ulong v, r, rb; if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) { return H_PARAMETER; } - hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64); + hpte = pte_index * HASH_PTE_SIZE_64; - v = ldq_p(hpte); - r = ldq_p(hpte + (HASH_PTE_SIZE_64/2)); + v = ppc_hash64_load_hpte0(env, hpte); + r = ppc_hash64_load_hpte1(env, hpte); if ((v & HPTE64_V_VALID) == 0 || ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) { @@ -283,11 +283,11 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr, r |= (flags << 48) & HPTE64_R_KEY_HI; r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO); rb = compute_tlbie_rb(v, r, pte_index); - stq_p(hpte, v & ~HPTE64_V_VALID); + ppc_hash64_store_hpte0(env, hpte, v & ~HPTE64_V_VALID); ppc_tlb_invalidate_one(env, rb); - stq_p(hpte + (HASH_PTE_SIZE_64/2), r); + ppc_hash64_store_hpte1(env, hpte, r); /* Don't need a memory barrier, due to qemu's global lock */ - stq_p(hpte, v); + ppc_hash64_store_hpte0(env, hpte, v); return H_SUCCESS; } diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c index a1bbd50..a7c2e35 100644 --- a/target-ppc/mmu-hash32.c +++ b/target-ppc/mmu-hash32.c @@ -328,13 +328,8 @@ 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 < 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); - } else { - pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8)); - pte1 = ldl_phys(env->htab_base + pteg_off + (i * 8) + 4); - } + 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); LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " " TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n", @@ -371,13 +366,8 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h, /* Update page flags */ pte1 = ctx->raddr; if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rw) == 1) { - if (env->external_htab) { - stl_p(env->external_htab + pteg_off + (good * 8) + 4, - pte1); - } else { - stl_phys_notdirty(env->htab_base + pteg_off + - (good * 8) + 4, pte1); - } + ppc_hash32_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_32, + pte1); } } diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h index a09ccb3..2344184 100644 --- a/target-ppc/mmu-hash32.h +++ b/target-ppc/mmu-hash32.h @@ -69,6 +69,34 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, #define HPTE32_R_WIMG 0x00000078 #define HPTE32_R_PP 0x00000003 +static inline target_ulong ppc_hash32_load_hpte0(CPUPPCState *env, + hwaddr pte_offset) +{ + assert(!env->external_htab); /* Not supported on 32-bit for now */ + return ldl_phys(env->htab_base + pte_offset); +} + +static inline target_ulong ppc_hash32_load_hpte1(CPUPPCState *env, + hwaddr pte_offset) +{ + assert(!env->external_htab); /* Not supported on 32-bit for now */ + return ldl_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_32/2); +} + +static inline void ppc_hash32_store_hpte0(CPUPPCState *env, + hwaddr pte_offset, target_ulong pte0) +{ + assert(!env->external_htab); /* Not supported on 32-bit for now */ + stl_phys(env->htab_base + pte_offset, pte0); +} + +static inline void ppc_hash32_store_hpte1(CPUPPCState *env, + hwaddr pte_offset, target_ulong pte1) +{ + assert(!env->external_htab); /* Not supported on 32-bit for now */ + stl_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_32/2, pte1); +} + #endif /* CONFIG_USER_ONLY */ #endif /* __MMU_HASH32_H__ */ diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index f3223dd..30c25dd 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -382,13 +382,8 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h, ret = -1; /* No entry found */ 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); - } else { - pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16)); - pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8); - } + 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); LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " " @@ -426,13 +421,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h, /* Update page flags */ pte1 = ctx->raddr; if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rw) == 1) { - if (env->external_htab) { - stq_p(env->external_htab + pteg_off + (good * 16) + 8, - pte1); - } else { - stq_phys_notdirty(env->htab_base + pteg_off + - (good * 16) + 8, pte1); - } + ppc_hash64_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_64, pte1); } } diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h index 80b86d9..84576c0 100644 --- a/target-ppc/mmu-hash64.h +++ b/target-ppc/mmu-hash64.h @@ -73,6 +73,46 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, #define HPTE64_V_1TB_SEG 0x4000000000000000ULL #define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL +static inline target_ulong ppc_hash64_load_hpte0(CPUPPCState *env, + hwaddr pte_offset) +{ + if (env->external_htab) { + return ldq_p(env->external_htab + pte_offset); + } else { + return ldq_phys(env->htab_base + pte_offset); + } +} + +static inline target_ulong ppc_hash64_load_hpte1(CPUPPCState *env, + hwaddr pte_offset) +{ + if (env->external_htab) { + return ldq_p(env->external_htab + pte_offset + HASH_PTE_SIZE_64/2); + } else { + return ldq_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_64/2); + } +} + +static inline void ppc_hash64_store_hpte0(CPUPPCState *env, + hwaddr pte_offset, target_ulong pte0) +{ + if (env->external_htab) { + stq_p(env->external_htab + pte_offset, pte0); + } else { + stq_phys(env->htab_base + pte_offset, pte0); + } +} + +static inline void ppc_hash64_store_hpte1(CPUPPCState *env, + hwaddr pte_offset, target_ulong pte1) +{ + if (env->external_htab) { + stq_p(env->external_htab + pte_offset + HASH_PTE_SIZE_64/2, pte1); + } else { + stq_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_64/2, pte1); + } +} + #endif /* CONFIG_USER_ONLY */ #endif /* !defined (__MMU_HASH64_H__) */ |