[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Re: [PATCH 12/15] Support 1T segments on ppc
From: |
Alexander Graf |
Subject: |
[Qemu-devel] Re: [PATCH 12/15] Support 1T segments on ppc |
Date: |
Sat, 12 Feb 2011 16:57:39 +0100 |
On 12.02.2011, at 15:54, David Gibson wrote:
> 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 | 58 ++++++++++++++++++++++++++++++++++++---------------
> 2 files changed, 48 insertions(+), 17 deletions(-)
>
> diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> index 3df6758..53b788f 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 6a1127f..158da09 100644
> --- a/target-ppc/helper.c
> +++ b/target-ppc/helper.c
> @@ -669,19 +669,25 @@ 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 match_256M, match_1T;
> int n;
>
> LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
>
> - esid = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
> + match_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V |
> + (SLB_VSID_B_256M >> SLB_VSID_SSIZE_SHIFT);
> + match_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V |
> + (SLB_VSID_B_1T >> SLB_VSID_SSIZE_SHIFT);
>
> 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 == match_256M) || (slb->esid == match_1T)) {
> return slb;
> }
> }
> @@ -734,16 +740,21 @@ 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))
Braces...
> + return -1; /* Reserved bits set or slot too high */
> + if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T))
here too
> + return -1; /* Bad segment size */
> + if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG))
and here
> + return -1; /* 1T segment on MMU that doesn't support it */
> +
> + /* We stuff a copy of the B field into slb->esid to simplify
> + * lookup later */
> + slb->esid = (rb & (SLB_ESID_ESID | SLB_ESID_V)) |
> + (rs >> SLB_VSID_SSIZE_SHIFT);
Wouldn't it be easier to add another field?
> 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);
> @@ -760,7 +771,8 @@ int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb,
> target_ulong *rt)
> return -1;
> }
>
> - *rt = slb->esid;
> + /* Mask out the extra copy of the B field inserted in store_slb */
> + *rt = slb->esid & ~0x3;
> return 0;
> }
>
> @@ -793,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);
> @@ -800,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)
> @@ -808,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)
Braces
> + hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
> + else
here too
Alex
- [Qemu-devel] Re: [PATCH 11/15] Better factor the ppc hash translation path, (continued)
[Qemu-devel] [PATCH 05/15] Implement PowerPC slbmfee and slbmfev instructions, David Gibson, 2011/02/12
[Qemu-devel] [PATCH 12/15] Support 1T segments on ppc, David Gibson, 2011/02/12
- [Qemu-devel] Re: [PATCH 12/15] Support 1T segments on ppc,
Alexander Graf <=
[Qemu-devel] [PATCH 13/15] Add POWER7 support for ppc, David Gibson, 2011/02/12
[Qemu-devel] [PATCH 14/15] Start implementing pSeries logical partition machine, David Gibson, 2011/02/12