[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 54/77] ppc: Fix 64K pages support in full emulation
From: |
Benjamin Herrenschmidt |
Subject: |
[Qemu-ppc] [PATCH 54/77] ppc: Fix 64K pages support in full emulation |
Date: |
Wed, 11 Nov 2015 11:28:07 +1100 |
We were always advertising only 4K & 16M. Additionally the code wasn't
properly matching the page size with the PTE content, which meant we
could potentially hit an incorrect PTE if the guest used multiple sizes.
Finally, honor the CPU capabilities when decoding the size from the SLB
so we don't try to use 64K pages on 970.
This still doesn't add support for MPSS (Multiple Page Sizes per Segment)
Signed-off-by: Benjamin Herrenschmidt <address@hidden>
---
hw/ppc/spapr_hcall.c | 10 +++------
target-ppc/cpu.h | 7 ++++--
target-ppc/mmu-hash64.c | 54 +++++++++++++++++++++++++++++++++++----------
target-ppc/translate_init.c | 22 +++++++++++++++---
4 files changed, 69 insertions(+), 24 deletions(-)
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 7e2cb4b..ba1bcaf 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -56,7 +56,6 @@ static target_ulong compute_tlbie_rb(target_ulong v,
target_ulong r,
va_low &= 0x7ff;
if (v & HPTE64_V_LARGE) {
rb |= 1; /* L field */
-#if 0 /* Disable that P7 specific bit for now */
if (r & 0xff000) {
/* non-16MB large page, must be 64k */
/* (masks depend on page size) */
@@ -64,7 +63,6 @@ static target_ulong compute_tlbie_rb(target_ulong v,
target_ulong r,
rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
rb |= (va_low & 0xfe); /* AVAL field */
}
-#endif
} else {
/* 4kB page */
rb |= (va_low & 0x7ff) << 12; /* remaining 11b of AVA */
@@ -98,14 +96,12 @@ static target_ulong h_enter(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
target_ulong index;
uint64_t token;
- /* only handle 4k and 16M pages for now */
+ /* Handle non-4K pages */
if (pteh & HPTE64_V_LARGE) {
-#if 0 /* We don't support 64k pages yet */
if ((ptel & 0xf000) == 0x1000) {
/* 64k page */
- } else
-#endif
- if ((ptel & 0xff000) == 0) {
+ page_shift = 16;
+ } else if ((ptel & 0xff000) == 0) {
/* 16M page */
page_shift = 24;
/* lowest AVA bit must be 0 for 16M pages */
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index ca6c961..3fc3e1d 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -115,16 +115,19 @@ enum powerpc_mmu_t {
#define POWERPC_MMU_64 0x00010000
#define POWERPC_MMU_1TSEG 0x00020000
#define POWERPC_MMU_AMR 0x00040000
+#define POWERPC_MMU_64K 0x00080000
/* 64 bits PowerPC MMU */
POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
/* Architecture 2.03 and later (has LPCR) */
POWERPC_MMU_2_03 = POWERPC_MMU_64 | 0x00000002,
/* Architecture 2.06 variant */
POWERPC_MMU_2_06 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
- | POWERPC_MMU_AMR | 0x00000003,
+ | POWERPC_MMU_AMR | POWERPC_MMU_64K
+ | 0x00000003,
/* Architecture 2.07 variant */
POWERPC_MMU_2_07 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
- | POWERPC_MMU_AMR | 0x00000004,
+ | POWERPC_MMU_AMR | POWERPC_MMU_64K
+ | 0x00000004,
#endif /* defined(TARGET_PPC64) */
};
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 328998f..9071fe9 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -348,9 +348,31 @@ void ppc_hash64_stop_access(uint64_t token)
}
}
+/* Returns the effective page shift or 0. MPSS isn't supported yet so
+ * this will always be the slb_pshift or 0
+ */
+static uint32_t ppc_hash64_pte_size_decode(uint64_t pte1, uint32_t slb_pshift)
+{
+ switch(slb_pshift) {
+ case 12:
+ return 12;
+ case 16:
+ if ((pte1 & 0xf000) == 0x1000) {
+ return 16;
+ }
+ return 0;
+ case 24:
+ if ((pte1 & 0xff000) == 0) {
+ return 24;
+ }
+ return 0;
+ }
+ return 0;
+}
+
static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr hash,
- bool secondary, target_ulong ptem,
- ppc_hash_pte64_t *pte)
+ uint32_t slb_pshift, bool secondary,
+ target_ulong ptem, ppc_hash_pte64_t *pte)
{
int i;
uint64_t token;
@@ -369,6 +391,13 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env,
hwaddr hash,
if ((pte0 & HPTE64_V_VALID)
&& (secondary == !!(pte0 & HPTE64_V_SECONDARY))
&& HPTE64_V_COMPARE(pte0, ptem)) {
+ uint32_t pshift = ppc_hash64_pte_size_decode(pte1, slb_pshift);
+ if (pshift == 0) {
+ continue;
+ }
+ /* We don't do anything with pshift yet as qemu TLB only deals
+ * with 4K pages anyway
+ */
pte->pte0 = pte0;
pte->pte1 = pte1;
ppc_hash64_stop_access(token);
@@ -382,7 +411,7 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env,
hwaddr hash,
return -1;
}
-static uint64_t ppc_hash64_page_shift(ppc_slb_t *slb)
+static uint64_t ppc_hash64_page_shift(CPUPPCState *env, ppc_slb_t *slb)
{
uint64_t epnshift;
@@ -392,7 +421,8 @@ static uint64_t ppc_hash64_page_shift(ppc_slb_t *slb)
* encoded in the PTE */
if ((slb->vsid & SLB_VSID_LLP_MASK) == SLB_VSID_4K) {
epnshift = TARGET_PAGE_BITS;
- } else if ((slb->vsid & SLB_VSID_LLP_MASK) == SLB_VSID_64K) {
+ } else if ((slb->vsid & SLB_VSID_LLP_MASK) == SLB_VSID_64K &&
+ (env->mmu_model & POWERPC_MMU_64K)) {
epnshift = TARGET_PAGE_BITS_64K;
} else {
epnshift = TARGET_PAGE_BITS_16M;
@@ -408,7 +438,7 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
hwaddr hash;
uint64_t vsid, epnshift, epnmask, epn, ptem;
- epnshift = ppc_hash64_page_shift(slb);
+ epnshift = ppc_hash64_page_shift(env, slb);
epnmask = ~((1ULL << epnshift) - 1);
if (slb->vsid & SLB_VSID_B) {
@@ -436,7 +466,7 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
" vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
" hash=" TARGET_FMT_plx "\n",
env->htab_base, env->htab_mask, vsid, ptem, hash);
- pte_offset = ppc_hash64_pteg_search(env, hash, 0, ptem, pte);
+ pte_offset = ppc_hash64_pteg_search(env, hash, epnshift, 0, ptem, pte);
if (pte_offset == -1) {
/* Secondary PTEG lookup */
@@ -446,14 +476,14 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
" hash=" TARGET_FMT_plx "\n", env->htab_base,
env->htab_mask, vsid, ptem, ~hash);
- pte_offset = ppc_hash64_pteg_search(env, ~hash, 1, ptem, pte);
+ pte_offset = ppc_hash64_pteg_search(env, ~hash, epnshift, 1, ptem,
pte);
}
return pte_offset;
}
-static hwaddr ppc_hash64_pte_raddr(ppc_slb_t *slb, ppc_hash_pte64_t pte,
- target_ulong eaddr)
+static hwaddr ppc_hash64_pte_raddr(CPUPPCState *env, ppc_slb_t *slb,
+ ppc_hash_pte64_t pte, target_ulong eaddr)
{
hwaddr mask;
int target_page_bits;
@@ -461,7 +491,7 @@ static hwaddr ppc_hash64_pte_raddr(ppc_slb_t *slb,
ppc_hash_pte64_t pte,
/*
* We support 4K, 64K and 16M now
*/
- target_page_bits = ppc_hash64_page_shift(slb);
+ target_page_bits = ppc_hash64_page_shift(env, slb);
mask = (1ULL << target_page_bits) - 1;
return (rpn & ~mask) | (eaddr & mask);
}
@@ -699,7 +729,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu,
target_ulong eaddr,
/* 7. Determine the real address from the PTE */
- raddr = ppc_hash64_pte_raddr(&slb, pte, eaddr);
+ raddr = ppc_hash64_pte_raddr(env, &slb, pte, eaddr);
tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
prot, mmu_idx, TARGET_PAGE_SIZE);
@@ -752,7 +782,7 @@ hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env,
target_ulong addr)
return -1;
}
- return ppc_hash64_pte_raddr(&slb, pte, addr) & TARGET_PAGE_MASK;
+ return ppc_hash64_pte_raddr(env, &slb, pte, addr) & TARGET_PAGE_MASK;
}
void ppc_hash64_store_hpte(CPUPPCState *env,
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 504564d..b623206 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9998,8 +9998,8 @@ static void ppc_cpu_initfn(Object *obj)
if (pcc->sps) {
env->sps = *pcc->sps;
} else if (env->mmu_model & POWERPC_MMU_64) {
- /* Use default sets of page sizes */
- static const struct ppc_segment_page_sizes defsps = {
+ /* Use default sets of page sizes. We don't support MPSS */
+ static const struct ppc_segment_page_sizes defsps_4k = {
.sps = {
{ .page_shift = 12, /* 4K */
.slb_enc = 0,
@@ -10011,7 +10011,23 @@ static void ppc_cpu_initfn(Object *obj)
},
},
};
- env->sps = defsps;
+ static const struct ppc_segment_page_sizes defsps_64k = {
+ .sps = {
+ { .page_shift = 12, /* 4K */
+ .slb_enc = 0,
+ .enc = { { .page_shift = 12, .pte_enc = 0 } }
+ },
+ { .page_shift = 16, /* 64K */
+ .slb_enc = 0x110,
+ .enc = { { .page_shift = 16, .pte_enc = 1 } }
+ },
+ { .page_shift = 24, /* 16M */
+ .slb_enc = 0x100,
+ .enc = { { .page_shift = 24, .pte_enc = 0 } }
+ },
+ },
+ };
+ env->sps = (env->mmu_model & POWERPC_MMU_64K) ? defsps_64k : defsps_4k;
}
#endif /* defined(TARGET_PPC64) */
--
2.5.0
- [Qemu-ppc] [PATCH 50/77] ppc: Update LPCR definitions, (continued)
- [Qemu-ppc] [PATCH 50/77] ppc: Update LPCR definitions, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 49/77] ppc/pnv: Create a default PCI layout, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 51/77] ppc: Use a helper to filter writes to LPCR, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 53/77] ppc: Add proper real mode translation support, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 52/77] ppc: Cosmetic, align some comments, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 63/77] ppc: Initialize AMOR in PAPR mode, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 57/77] ppc: Enforce setting MSR:EE, IR and DR when MSR:PR is set, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 61/77] ppc: SPURR & PURR are HV writeable and privileged, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 55/77] ppc/pnv+spapr: Add "ibm, pa-features" property to the device-tree, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 56/77] ppc: Fix conditions for delivering external interrupts to a guest, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 54/77] ppc: Fix 64K pages support in full emulation,
Benjamin Herrenschmidt <=
- [Qemu-ppc] [PATCH 58/77] ppc: Initial HDEC support, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 59/77] ppc: Add placeholder SPRs for DPDES and DHDES on P8, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 62/77] ppc: Add dummy SPR_IC for POWER8, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 60/77] ppc: LPCR is a HV resource, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 64/77] ppc: Fix writing to AMR/UAMOR, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 65/77] ppc: Add POWER8 IAMR register, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 67/77] ppc: Add dummy write to VTB, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 66/77] ppc: Add a few more P8 PMU SPRs, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 68/77] ppc: Add dummy POWER8 MPPR register, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs, Benjamin Herrenschmidt, 2015/11/10