[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 27/45] mmu-hash*: Make find_pte{32, 64} do more of the
From: |
David Gibson |
Subject: |
[Qemu-ppc] [PATCH 27/45] mmu-hash*: Make find_pte{32, 64} do more of the job of finding ptes |
Date: |
Wed, 6 Mar 2013 14:44:15 +1100 |
find_pte{32,64}() are not particularly well named. They only "find" a PTE
within a given PTE group, and they also do permissions checking and other
things.
This patch makes it somewhat close to matching the name, by folding the
search of both primary and secondary hash bucket into it, along with the
various address bit shuffling to determine the right hash buckets.
In the 32-bit case we also remove the code for splitting large pages into
4k pieces for the qemu tlb, since no 32-bit hash MMUs support multiple page
sizes.
Signed-off-by: David Gibson <address@hidden>
---
target-ppc/mmu-hash32.c | 116 ++++++++++++++------------------------------
target-ppc/mmu-hash64.c | 123 ++++++++++++++++++++++-------------------------
2 files changed, 92 insertions(+), 147 deletions(-)
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 7c13a49..b7a26a2 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -44,8 +44,6 @@
struct mmu_ctx_hash32 {
hwaddr raddr; /* Real address */
int prot; /* Protection bits */
- hwaddr hash[2]; /* Pagetable hash values */
- target_ulong ptem; /* Virtual segment ID | API */
int key; /* Access key */
int nx; /* Non-execute area */
};
@@ -377,15 +375,44 @@ static hwaddr ppc_hash32_pteg_search(CPUPPCState *env,
hwaddr pteg_off,
}
static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
- target_ulong eaddr, int h, int rwx, int target_page_bits)
+ target_ulong sr, target_ulong eaddr, int rwx)
{
hwaddr pteg_off, pte_offset;
ppc_hash_pte32_t pte;
+ hwaddr hash;
+ uint32_t vsid, pgidx, ptem;
int ret;
ret = -1; /* No entry found */
- pteg_off = get_pteg_offset32(env, ctx->hash[h]);
- pte_offset = ppc_hash32_pteg_search(env, pteg_off, h, ctx->ptem, &pte);
+ vsid = sr & SR32_VSID;
+ ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) ||
+ ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0;
+ pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
+ hash = vsid ^ pgidx;
+ ptem = (vsid << 7) | (pgidx >> 10);
+
+ /* Page address translation */
+ LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
+ " hash " TARGET_FMT_plx "\n",
+ env->htab_base, env->htab_mask, hash);
+
+ /* Primary PTEG lookup */
+ LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+ " vsid=%" PRIx32 " ptem=%" PRIx32
+ " hash=" TARGET_FMT_plx "\n",
+ env->htab_base, env->htab_mask, vsid, ptem, hash);
+ pteg_off = get_pteg_offset32(env, hash);
+ pte_offset = ppc_hash32_pteg_search(env, pteg_off, 0, ptem, &pte);
+ if (pte_offset == -1) {
+ /* Secondary PTEG lookup */
+ LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+ " vsid=%" PRIx32 " api=%" PRIx32
+ " hash=" TARGET_FMT_plx "\n", env->htab_base,
+ env->htab_mask, vsid, ptem, ~hash);
+ pteg_off = get_pteg_offset32(env, ~hash);
+ pte_offset = ppc_hash32_pteg_search(env, pteg_off, 1, ptem, &pte);
+ }
+
if (pte_offset != -1) {
ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx);
LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
@@ -396,23 +423,14 @@ static int find_pte32(CPUPPCState *env, struct
mmu_ctx_hash32 *ctx,
}
}
- /* We have a TLB that saves 4K pages, so let's
- * split a huge page to 4k chunks */
- if (target_page_bits != TARGET_PAGE_BITS) {
- ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))
- & TARGET_PAGE_MASK;
- }
return ret;
}
static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
target_ulong eaddr, int rwx)
{
- hwaddr hash;
- target_ulong vsid;
- int pr, target_page_bits;
- int ret, ret2;
- target_ulong sr, pgidx;
+ int ret;
+ target_ulong sr;
/* 1. Handle real mode accesses */
if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
@@ -444,71 +462,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct
mmu_ctx_hash32 *ctx,
if ((rwx == 2) && ctx->nx) {
return -3;
}
-
- pr = msr_pr;
- ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
- ((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
-
- 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
- " ir=%d dr=%d pr=%d %d\n",
- eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
- (int)msr_dr, pr != 0 ? 1 : 0, rwx);
- pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
- hash = vsid ^ pgidx;
- ctx->ptem = (vsid << 7) | (pgidx >> 10);
-
- LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n",
- ctx->key, ctx->nx, vsid);
- ret = -1;
-
- /* Page address translation */
- LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
- " hash " TARGET_FMT_plx "\n",
- env->htab_base, env->htab_mask, hash);
- ctx->hash[0] = hash;
- ctx->hash[1] = ~hash;
-
- LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
- " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
- " hash=" TARGET_FMT_plx "\n",
- env->htab_base, env->htab_mask, vsid, ctx->ptem,
- ctx->hash[0]);
- /* Primary table lookup */
- ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
- if (ret == -1) {
- /* Secondary table lookup */
- LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
- " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
- " hash=" TARGET_FMT_plx "\n", env->htab_base,
- env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
- ret2 = find_pte32(env, ctx, eaddr, 1, rwx, target_page_bits);
- if (ret2 != -1) {
- ret = ret2;
- }
- }
-#if defined(DUMP_PAGE_TABLES)
- if (qemu_log_enabled()) {
- hwaddr curaddr;
- uint32_t a0, a1, a2, a3;
-
- qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
- "\n", sdr, mask + 0x80);
- for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
- curaddr += 16) {
- a0 = ldl_phys(curaddr);
- a1 = ldl_phys(curaddr + 4);
- a2 = ldl_phys(curaddr + 8);
- a3 = ldl_phys(curaddr + 12);
- if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
- qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
- curaddr, a0, a1, a2, a3);
- }
- }
- }
-#endif
+ ret = find_pte32(env, ctx, sr, eaddr, rwx);
return ret;
}
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 66b2d24..36e2c84 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -43,8 +43,6 @@
struct mmu_ctx_hash64 {
hwaddr raddr; /* Real address */
int prot; /* Protection bits */
- hwaddr hash[2]; /* Pagetable hash values */
- target_ulong ptem; /* Virtual segment ID | API */
int key; /* Access key */
};
@@ -377,15 +375,67 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env,
hwaddr pteg_off,
}
static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
- target_ulong eaddr, int h, int rwx, int target_page_bits)
+ ppc_slb_t *slb, target_ulong eaddr, int rwx)
{
hwaddr pteg_off, pte_offset;
ppc_hash_pte64_t pte;
+ uint64_t vsid, pageaddr, ptem;
+ hwaddr hash;
+ int segment_bits, target_page_bits;
int ret;
ret = -1; /* No entry found */
- pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;
- pte_offset = ppc_hash64_pteg_search(env, pteg_off, h, ctx->ptem, &pte);
+
+ if (slb->vsid & SLB_VSID_B) {
+ vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
+ segment_bits = 40;
+ } else {
+ vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
+ segment_bits = 28;
+ }
+
+ target_page_bits = (slb->vsid & SLB_VSID_L)
+ ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
+ ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
+ : (slb->vsid & SLB_VSID_KS));
+
+ pageaddr = eaddr & ((1ULL << segment_bits)
+ - (1ULL << target_page_bits));
+ if (slb->vsid & SLB_VSID_B) {
+ hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
+ } else {
+ hash = vsid ^ (pageaddr >> target_page_bits);
+ }
+ /* Only 5 bits of the page index are used in the AVPN */
+ ptem = (slb->vsid & SLB_VSID_PTEM) |
+ ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
+
+ ret = -1;
+
+ /* Page address translation */
+ LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
+ " hash " TARGET_FMT_plx "\n",
+ env->htab_base, env->htab_mask, hash);
+
+
+ /* Primary PTEG lookup */
+ LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+ " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
+ " hash=" TARGET_FMT_plx "\n",
+ env->htab_base, env->htab_mask, vsid, ptem, hash);
+ pteg_off = (hash * HASH_PTEG_SIZE_64) & env->htab_mask;
+ pte_offset = ppc_hash64_pteg_search(env, pteg_off, 0, ptem, &pte);
+ if (pte_offset == -1) {
+ /* Secondary PTEG lookup */
+ LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+ " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+ " hash=" TARGET_FMT_plx "\n", env->htab_base,
+ env->htab_mask, vsid, ptem, ~hash);
+
+ pteg_off = (~hash * HASH_PTEG_SIZE_64) & env->htab_mask;
+ pte_offset = ppc_hash64_pteg_search(env, pteg_off, 1, ptem, &pte);
+ }
+
if (pte_offset != -1) {
ret = pte64_check(ctx, pte.pte0, pte.pte1, rwx);
LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
@@ -408,13 +458,8 @@ static int find_pte64(CPUPPCState *env, struct
mmu_ctx_hash64 *ctx,
static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
target_ulong eaddr, int rwx)
{
- hwaddr hash;
- target_ulong vsid;
- int pr, target_page_bits;
- int ret, ret2;
+ int ret;
ppc_slb_t *slb;
- target_ulong pageaddr;
- int segment_bits;
/* 1. Handle real mode accesses */
if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
@@ -437,61 +482,7 @@ static int ppc_hash64_translate(CPUPPCState *env, struct
mmu_ctx_hash64 *ctx,
return -3;
}
- pr = msr_pr;
-
- if (slb->vsid & SLB_VSID_B) {
- vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
- segment_bits = 40;
- } else {
- vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
- segment_bits = 28;
- }
-
- target_page_bits = (slb->vsid & SLB_VSID_L)
- ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
- ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
- : (slb->vsid & SLB_VSID_KS));
-
- pageaddr = eaddr & ((1ULL << segment_bits)
- - (1ULL << target_page_bits));
- if (slb->vsid & SLB_VSID_B) {
- hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
- } else {
- hash = vsid ^ (pageaddr >> target_page_bits);
- }
- /* Only 5 bits of the page index are used in the AVPN */
- ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
- ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
-
- LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n",
- ctx->key, !!(slb->vsid & SLB_VSID_N), vsid);
- ret = -1;
-
- /* Page address translation */
- LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
- " hash " TARGET_FMT_plx "\n",
- env->htab_base, env->htab_mask, hash);
- ctx->hash[0] = hash;
- ctx->hash[1] = ~hash;
-
- LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
- " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
- " hash=" TARGET_FMT_plx "\n",
- env->htab_base, env->htab_mask, vsid, ctx->ptem,
- ctx->hash[0]);
- /* Primary table lookup */
- ret = find_pte64(env, ctx, eaddr, 0, rwx, target_page_bits);
- if (ret == -1) {
- /* Secondary table lookup */
- LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
- " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
- " hash=" TARGET_FMT_plx "\n", env->htab_base,
- env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
- ret2 = find_pte64(env, ctx, eaddr, 1, rwx, target_page_bits);
- if (ret2 != -1) {
- ret = ret2;
- }
- }
+ ret = find_pte64(env, ctx, slb, eaddr, rwx);
return ret;
}
--
1.7.10.4
- [Qemu-ppc] [PATCH 09/45] target-ppc: Disentangle get_physical_address() paths, (continued)
- [Qemu-ppc] [PATCH 09/45] target-ppc: Disentangle get_physical_address() paths, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 45/45] mmu-hash64: Implement Virtual Page Class Key Protection, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 11/45] target-ppc: Disentangle hash mmu versions of cpu_get_phys_page_debug(), David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 38/45] mmu-hash*: Clean up permission checking, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 04/45] target-ppc: Move SLB handling into a mmu-hash64.c, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 02/45] target-ppc: Trivial cleanups in mmu_helper.c, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 01/45] target-ppc: Remove vestigial PowerPC 620 support, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 40/45] mmu-hash*: Clean up PTE flags update, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 32/45] mmu-hash32: Split BAT size logic from permissions logic, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 42/45] mmu-hash*: Correctly mask RPN from hash PTE, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 27/45] mmu-hash*: Make find_pte{32, 64} do more of the job of finding ptes,
David Gibson <=
- [Qemu-ppc] [PATCH 28/45] mmu-hash*: Remove permission checking from find_pte{32, 64}(), David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 23/45] mmu-hash32: Split direct store segment handling into a helper, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 10/45] target-ppc: Disentangle hash mmu paths for cpu_ppc_handle_mmu_fault, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 19/45] mmu-hash64: Remove nx from mmu_ctx_hash64, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 06/45] target-ppc: Disentangle find_pte(), David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 34/45] mmu-hash32: Cleanup BAT lookup, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 29/45] mmu-hash64: Clean up ppc_hash64_htab_lookup(), David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 30/45] mmu-hash*: Fold pte_check*() logic into caller, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 18/45] mmu-hash*: Reduce use of access_type, David Gibson, 2013/03/05
- [Qemu-ppc] [PATCH 25/45] mmu-hash*: Don't keep looking for PTEs after we find a match, David Gibson, 2013/03/05