aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-ppc/cpu.h1
-rw-r--r--target-ppc/mmu-hash64.c37
-rw-r--r--target-ppc/mmu-hash64.h3
3 files changed, 30 insertions, 11 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index aae33a9237..b706b9fdf6 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -45,6 +45,7 @@
# define TARGET_VIRT_ADDR_SPACE_BITS 64
#endif
+#define TARGET_PAGE_BITS_64K 16
#define TARGET_PAGE_BITS_16M 24
#else /* defined (TARGET_PPC64) */
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index b0278c95e1..971751f7de 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -388,6 +388,24 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr hash,
return -1;
}
+static uint64_t ppc_hash64_page_shift(ppc_slb_t *slb)
+{
+ uint64_t epnshift;
+
+ /* Page size according to the SLB, which we use to generate the
+ * EPN for hash table lookup.. When we implement more recent MMU
+ * extensions this might be different from the actual page size
+ * 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) {
+ epnshift = TARGET_PAGE_BITS_64K;
+ } else {
+ epnshift = TARGET_PAGE_BITS_16M;
+ }
+ return epnshift;
+}
+
static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
ppc_slb_t *slb, target_ulong eaddr,
ppc_hash_pte64_t *pte)
@@ -396,12 +414,7 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
hwaddr hash;
uint64_t vsid, epnshift, epnmask, epn, ptem;
- /* Page size according to the SLB, which we use to generate the
- * EPN for hash table lookup.. When we implement more recent MMU
- * extensions this might be different from the actual page size
- * encoded in the PTE */
- epnshift = (slb->vsid & SLB_VSID_L)
- ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
+ epnshift = ppc_hash64_page_shift(slb);
epnmask = ~((1ULL << epnshift) - 1);
if (slb->vsid & SLB_VSID_B) {
@@ -448,12 +461,14 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
static hwaddr ppc_hash64_pte_raddr(ppc_slb_t *slb, ppc_hash_pte64_t pte,
target_ulong eaddr)
{
+ hwaddr mask;
+ int target_page_bits;
hwaddr rpn = pte.pte1 & HPTE64_R_RPN;
- /* FIXME: Add support for SLLP extended page sizes */
- int target_page_bits = (slb->vsid & SLB_VSID_L)
- ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
- hwaddr mask = (1ULL << target_page_bits) - 1;
-
+ /*
+ * We support 4K, 64K and 16M now
+ */
+ target_page_bits = ppc_hash64_page_shift(slb);
+ mask = (1ULL << target_page_bits) - 1;
return (rpn & ~mask) | (eaddr & mask);
}
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 49e385db90..291750f3e5 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -37,6 +37,9 @@ void ppc_hash64_store_hpte(CPUPPCState *env, target_ulong index,
#define SLB_VSID_C 0x0000000000000080ULL /* class */
#define SLB_VSID_LP 0x0000000000000030ULL
#define SLB_VSID_ATTR 0x0000000000000FFFULL
+#define SLB_VSID_LLP_MASK (SLB_VSID_L | SLB_VSID_LP)
+#define SLB_VSID_4K 0x0000000000000000ULL
+#define SLB_VSID_64K 0x0000000000000110ULL
/*
* Hash page table definitions