[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 11/26] Support 1T segments on ppc
From: |
David Gibson |
Subject: |
[Qemu-devel] [PATCH 11/26] Support 1T segments on ppc |
Date: |
Wed, 16 Mar 2011 15:56:48 +1100 |
Traditionally, the "segments" used for the two-stage translation used on
powerpc MMUs were 256MB in size. This was the only option on all hash
page table based 32-bit powerpc cpus, and on the earlier 64-bit hash page
table based cpus. However, newer 64-bit cpus also permit 1TB segments
This patch adds support for 1TB segment translation to the qemu code.
Signed-off-by: David Gibson <address@hidden>
---
target-ppc/cpu.h | 7 ++++++
target-ppc/helper.c | 54 +++++++++++++++++++++++++++++++++++---------------
2 files changed, 45 insertions(+), 16 deletions(-)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 71f8d72..9abf4a9 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -114,6 +114,7 @@ enum powerpc_mmu_t {
POWERPC_MMU_601 = 0x0000000A,
#if defined(TARGET_PPC64)
#define POWERPC_MMU_64 0x00010000
+#define POWERPC_MMU_1TSEG 0x00020000
/* 64 bits PowerPC MMU */
POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
/* 620 variant (no segment exceptions) */
@@ -382,9 +383,11 @@ struct ppc_slb_t {
/* 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
@@ -398,6 +401,10 @@ struct ppc_slb_t {
#define SEGMENT_SHIFT_256M 28
#define SEGMENT_MASK_256M ~((1ULL << SEGMENT_SHIFT_256M) - 1)
+#define SEGMENT_SHIFT_1T 40
+#define SEGMENT_MASK_1T ~((1ULL << SEGMENT_SHIFT_1T) - 1)
+
+
/*****************************************************************************/
/* Machine state register bits definition */
#define MSR_SF 63 /* Sixty-four-bit mode hflags */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 111675d..3e3b5da 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -671,19 +671,26 @@ static inline int find_pte(CPUState *env, mmu_ctx_t *ctx,
int h, int rw,
#if defined(TARGET_PPC64)
static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
{
- uint64_t esid;
+ uint64_t esid_256M, esid_1T;
int n;
LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
- esid = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
+ esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
+ esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
for (n = 0; n < env->slb_nr; n++) {
ppc_slb_t *slb = &env->slb[n];
LOG_SLB("%s: slot %d %016" PRIx64 " %016"
PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
- if (slb->esid == esid) {
+ /* We check for 1T matches on all MMUs here - if the MMU
+ * doesn't have 1T segment support, we will have prevented 1T
+ * entries from being inserted in the slbmte code. */
+ if ( ((slb->esid == esid_256M) &&
+ ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
+ || ((slb->esid == esid_1T) &&
+ ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T)) ) {
return slb;
}
}
@@ -736,16 +743,19 @@ void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t
T0)
int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
{
int slot = rb & 0xfff;
- uint64_t esid = rb & ~0xfff;
ppc_slb_t *slb = &env->slb[slot];
-
- if (slot >= env->slb_nr) {
- return -1;
- }
-
- slb->esid = esid;
+
+ if (rb & (0x1000 - env->slb_nr))
+ return -1; /* Reserved bits set or slot too high */
+ if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T))
+ return -1; /* Bad segment size */
+ if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG))
+ return -1; /* 1T segment on MMU that doesn't support it */
+
+ /* Mask out the slot number as we store the entry */
+ slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
slb->vsid = rs;
-
+
LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
" %016" PRIx64 "\n", __func__, slot, rb, rs,
slb->esid, slb->vsid);
@@ -795,6 +805,7 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
if (env->mmu_model & POWERPC_MMU_64) {
ppc_slb_t *slb;
target_ulong pageaddr;
+ int segment_bits;
LOG_MMU("Check SLBs\n");
slb = slb_lookup(env, eaddr);
@@ -802,7 +813,14 @@ static inline int get_segment(CPUState *env, mmu_ctx_t
*ctx,
return -5;
}
- vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
+ 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)
@@ -810,11 +828,15 @@ static inline int get_segment(CPUState *env, mmu_ctx_t
*ctx,
ds = 0;
ctx->nx = !!(slb->vsid & SLB_VSID_N);
- pageaddr = eaddr & ((1ULL << 28) - (1ULL << target_page_bits));
- /* XXX: this is false for 1 TB segments */
- hash = vsid ^ (pageaddr >> target_page_bits);
+ 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) & 0x0F80);
+ ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
+ ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
} else
#endif /* defined(TARGET_PPC64) */
{
--
1.7.1
- Re: [Qemu-devel] [PATCH 03/26] Add a hook to allow hypercalls to be emulated on PowerPC, (continued)
- [Qemu-devel] [PATCH 01/26] Clean up PowerPC SLB handling code, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 02/26] Allow qemu_devtree_setprop() to take arbitrary values, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 04/26] Implement PowerPC slbmfee and slbmfev instructions, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 05/26] Implement missing parts of the logic for the POWER PURR, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 07/26] Clean up slb_lookup() function, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 08/26] Parse SDR1 on mtspr instead of at translate time, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 09/26] Use "hash" more consistently in ppc mmu code, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 10/26] Better factor the ppc hash translation path, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 06/26] Correct ppc popcntb logic, implement popcntw and popcntd, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 11/26] Support 1T segments on ppc,
David Gibson <=
- [Qemu-devel] [PATCH 12/26] Add POWER7 support for ppc, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 15/26] Virtual hash page table handling on pSeries machine, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 14/26] Implement the bus structure for PAPR virtual IO, David Gibson, 2011/03/16
- [Qemu-devel] [PATCH 13/26] Start implementing pSeries logical partition machine, David Gibson, 2011/03/16