qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 2/3] target/ppc: add hash MMU support on POWE


From: David Gibson
Subject: Re: [Qemu-devel] [PATCH v2 2/3] target/ppc: add hash MMU support on POWER9 for PowerNV only
Date: Mon, 19 Feb 2018 11:33:26 +1100
User-agent: Mutt/1.9.2 (2017-12-15)

On Fri, Feb 16, 2018 at 09:45:03AM +0100, Cédric Le Goater wrote:
> The HPTE bits definitions are slightly modified in ISA v3.0. Let's add
> some helpers to hide the differences in the hash MMU code.
> 
> On a POWER9 processor, the Partition Table is composed of a pair of
> doublewords per partition. The first doubleword indicates whether the
> partition uses HPT or Radix Trees translation and contains the address
> of the host's translation table structure and size.
> 
> The first doubleword of the PTCR holds the Hash Page Table base
> address for the host when the hash MMU is in use. Also add an helper
> to retrieve the HPT base address depending on the MMU revision.
> 
> Signed-off-by: Cédric Le Goater <address@hidden>
> ---
> 
>  Changes since v1:
> 
>  - introduced ppc64_v3_get_patbe0()
>  
>  hw/ppc/spapr_hcall.c       |  5 +++--
>  target/ppc/mmu-book3s-v3.h |  5 +++++
>  target/ppc/mmu-hash64.c    | 48 
> +++++++++++++++++++++++++++++++++++++---------
>  target/ppc/mmu-hash64.h    | 34 ++++++++++++++++++++++++++++++--
>  4 files changed, 79 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index 198656048063..738bf7cf5ed1 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -94,7 +94,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, 
> sPAPRMachineState *spapr,
>          return H_PARAMETER;
>      }
>  
> -    raddr = (ptel & HPTE64_R_RPN) & ~((1ULL << apshift) - 1);
> +    raddr = (ptel & ppc_hash64_hpte_r_rpn(cpu)) & ~((1ULL << apshift) - 1);
>  
>      if (is_ram_address(spapr, raddr)) {
>          /* Regular RAM - should have WIMG=0010 */
> @@ -586,7 +586,8 @@ static int rehash_hpte(PowerPCCPU *cpu,
>  
>      base_pg_shift = ppc_hash64_hpte_page_shift_noslb(cpu, pte0, pte1);
>      assert(base_pg_shift); /* H_ENTER shouldn't allow a bad encoding */
> -    avpn = HPTE64_V_AVPN_VAL(pte0) & ~(((1ULL << base_pg_shift) - 1) >> 23);
> +    avpn = ppc_hash64_hpte_v_avpn_val(cpu, pte0) &
> +        ~(((1ULL << base_pg_shift) - 1) >> 23);
>  
>      if (pte0 & HPTE64_V_SECONDARY) {
>          pteg = ~pteg;
> diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h
> index fdf80987d7b2..a7ab580c3140 100644
> --- a/target/ppc/mmu-book3s-v3.h
> +++ b/target/ppc/mmu-book3s-v3.h
> @@ -54,6 +54,11 @@ static inline bool ppc64_radix_guest(PowerPCCPU *cpu)
>  int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
>                                int mmu_idx);
>  
> +static inline hwaddr ppc64_v3_get_patbe0(PowerPCCPU *cpu)
> +{
> +    return ldq_phys(CPU(cpu)->as, cpu->env.spr[SPR_PTCR] & PTCR_PATB);
> +}
> +
>  #endif /* TARGET_PPC64 */
>  
>  #endif /* CONFIG_USER_ONLY */
> diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
> index c9b72b742956..acaeaf82d59c 100644
> --- a/target/ppc/mmu-hash64.c
> +++ b/target/ppc/mmu-hash64.c
> @@ -289,6 +289,22 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, 
> target_ulong rb)
>      return rt;
>  }
>  
> +hwaddr ppc_hash64_hpt_reg(PowerPCCPU *cpu)
> +{
> +    CPUPPCState *env = &cpu->env;
> +
> +    if (env->mmu_model & POWERPC_MMU_V3) {
> +        if (msr_hv) {
> +            return ppc64_v3_get_patbe0(cpu);

This is the only caller, I think you might as well just open-code the
load here.

> +        } else {
> +            error_report("HPT Support Unimplemented");
> +            exit(1);
> +        }
> +    } else {
> +        return cpu->env.spr[SPR_SDR1];
> +    }
> +}
> +
>  /* Check No-Execute or Guarded Storage */
>  static inline int ppc_hash64_pte_noexec_guard(PowerPCCPU *cpu,
>                                                ppc_hash_pte64_t pte)
> @@ -451,8 +467,9 @@ void ppc_hash64_unmap_hptes(PowerPCCPU *cpu, const 
> ppc_hash_pte64_t *hptes,
>                          false, n * HASH_PTE_SIZE_64);
>  }
>  
> -static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps,
> -    uint64_t pte0, uint64_t pte1)
> +static unsigned hpte_page_shift(PowerPCCPU *cpu,
> +                                const struct ppc_one_seg_page_size *sps,
> +                                uint64_t pte0, uint64_t pte1)
>  {
>      int i;
>  
> @@ -478,7 +495,7 @@ static unsigned hpte_page_shift(const struct 
> ppc_one_seg_page_size *sps,
>              continue;
>          }
>  
> -        mask = ((1ULL << ps->page_shift) - 1) & HPTE64_R_RPN;
> +        mask = ((1ULL << ps->page_shift) - 1) & ppc_hash64_hpte_r_rpn(cpu);
>  
>          if ((pte1 & mask) == ((uint64_t)ps->pte_enc << HPTE64_R_RPN_SHIFT)) {
>              return ps->page_shift;
> @@ -488,6 +505,18 @@ static unsigned hpte_page_shift(const struct 
> ppc_one_seg_page_size *sps,
>      return 0; /* Bad page size encoding */
>  }
>  
> +static bool ppc_hash64_hpte_v_compare(PowerPCCPU *cpu, target_ulong pte0,
> +                                      target_ulong ptem)
> +{
> +    CPUPPCState *env = &cpu->env;
> +
> +    if (env->mmu_model & POWERPC_MMU_V3) {
> +        return HPTE64_V_COMPARE_3_0(pte0, ptem);
> +    } else {
> +        return HPTE64_V_COMPARE(pte0, ptem);
> +    }
> +}
> +
>  static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash,
>                                       const struct ppc_one_seg_page_size *sps,
>                                       target_ulong ptem,
> @@ -508,8 +537,8 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, 
> hwaddr hash,
>          pte1 = ppc_hash64_hpte1(cpu, pteg, i);
>  
>          /* This compares V, B, H (secondary) and the AVPN */
> -        if (HPTE64_V_COMPARE(pte0, ptem)) {
> -            *pshift = hpte_page_shift(sps, pte0, pte1);
> +        if (ppc_hash64_hpte_v_compare(cpu, pte0, ptem)) {
> +            *pshift = hpte_page_shift(cpu, sps, pte0, pte1);
>              /*
>               * If there is no match, ignore the PTE, it could simply
>               * be for a different segment size encoding and the
> @@ -569,7 +598,8 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
>          epn = (eaddr & ~SEGMENT_MASK_256M) & epnmask;
>          hash = vsid ^ (epn >> sps->page_shift);
>      }
> -    ptem = (slb->vsid & SLB_VSID_PTEM) | ((epn >> 16) & HPTE64_V_AVPN);
> +    ptem = (slb->vsid & SLB_VSID_PTEM) | ((epn >> 16) &
> +                                          ppc_hash64_hpte_v_avpn(cpu));
>      ptem |= HPTE64_V_VALID;
>  
>      /* Page address translation */
> @@ -624,7 +654,7 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
>              break;
>          }
>  
> -        shift = hpte_page_shift(sps, pte0, pte1);
> +        shift = hpte_page_shift(cpu, sps, pte0, pte1);
>          if (shift) {
>              return shift;
>          }
> @@ -860,7 +890,7 @@ skip_slb_search:
>  
>      /* 7. Determine the real address from the PTE */
>  
> -    raddr = deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, eaddr);
> +    raddr = deposit64(pte.pte1 & ppc_hash64_hpte_r_rpn(cpu), 0, apshift, 
> eaddr);
>  
>      tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
>                   prot, mmu_idx, 1ULL << apshift);
> @@ -910,7 +940,7 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, 
> target_ulong addr)
>          return -1;
>      }
>  
> -    return deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, addr)
> +    return deposit64(pte.pte1 & ppc_hash64_hpte_r_rpn(cpu), 0, apshift, addr)
>          & TARGET_PAGE_MASK;
>  }
>  
> diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
> index d297b97d3773..7796b4ff5f11 100644
> --- a/target/ppc/mmu-hash64.h
> +++ b/target/ppc/mmu-hash64.h
> @@ -69,8 +69,12 @@ void ppc_hash64_update_rmls(CPUPPCState *env);
>  #define HPTE64_V_SSIZE_SHIFT    62
>  #define HPTE64_V_AVPN_SHIFT     7
>  #define HPTE64_V_AVPN           0x3fffffffffffff80ULL
> +#define HPTE64_V_AVPN_3_0       0x000fffffffffff80ULL
>  #define HPTE64_V_AVPN_VAL(x)    (((x) & HPTE64_V_AVPN) >> 
> HPTE64_V_AVPN_SHIFT)
> +#define HPTE64_V_AVPN_VAL_3_0(x)                        \
> +    (((x) & HPTE64_V_AVPN_3_0) >> HPTE64_V_AVPN_SHIFT)
>  #define HPTE64_V_COMPARE(x, y)  (!(((x) ^ (y)) & 0xffffffffffffff83ULL))
> +#define HPTE64_V_COMPARE_3_0(x, y)  (!(((x) ^ (y)) & 0x3fffffffffffff83ULL))
>  #define HPTE64_V_BOLTED         0x0000000000000010ULL
>  #define HPTE64_V_LARGE          0x0000000000000004ULL
>  #define HPTE64_V_SECONDARY      0x0000000000000002ULL
> @@ -81,6 +85,7 @@ void ppc_hash64_update_rmls(CPUPPCState *env);
>  #define HPTE64_R_KEY_HI         0x3000000000000000ULL
>  #define HPTE64_R_RPN_SHIFT      12
>  #define HPTE64_R_RPN            0x0ffffffffffff000ULL
> +#define HPTE64_R_RPN_3_0        0x01fffffffffff000ULL
>  #define HPTE64_R_FLAGS          0x00000000000003ffULL
>  #define HPTE64_R_PP             0x0000000000000003ULL
>  #define HPTE64_R_N              0x0000000000000004ULL
> @@ -98,9 +103,34 @@ void ppc_hash64_update_rmls(CPUPPCState *env);
>  #define HPTE64_V_1TB_SEG        0x4000000000000000ULL
>  #define HPTE64_V_VRMA_MASK      0x4001ffffff000000ULL
>  
> +static inline target_ulong ppc_hash64_hpte_r_rpn(PowerPCCPU *cpu)
> +{
> +    CPUPPCState *env = &cpu->env;
> +
> +    return env->mmu_model & POWERPC_MMU_V3 ? HPTE64_R_RPN_3_0 : HPTE64_R_RPN;
> +}
> +
> +static inline target_ulong ppc_hash64_hpte_v_avpn(PowerPCCPU *cpu)
> +{
> +    CPUPPCState *env = &cpu->env;
> +
> +    return env->mmu_model & POWERPC_MMU_V3 ? HPTE64_V_AVPN_3_0 : 
> HPTE64_V_AVPN;
> +}
> +
> +static inline target_ulong ppc_hash64_hpte_v_avpn_val(PowerPCCPU *cpu,
> +                                                      target_ulong pte0)
> +{
> +    CPUPPCState *env = &cpu->env;
> +
> +    return env->mmu_model & POWERPC_MMU_V3 ?
> +        HPTE64_V_AVPN_VAL_3_0(pte0) : HPTE64_V_AVPN_VAL(pte0);
> +}
> +
> +hwaddr ppc_hash64_hpt_reg(PowerPCCPU *cpu);
> +
>  static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
>  {
> -    return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG;
> +    return ppc_hash64_hpt_reg(cpu) & SDR_64_HTABORG;
>  }
>  
>  static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
> @@ -110,7 +140,7 @@ static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
>              PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
>          return vhc->hpt_mask(cpu->vhyp);
>      }
> -    return (1ULL << ((cpu->env.spr[SPR_SDR1] & SDR_64_HTABSIZE) + 18 - 7)) - 
> 1;
> +    return (1ULL << ((ppc_hash64_hpt_reg(cpu) & SDR_64_HTABSIZE) + 18 - 7)) 
> - 1;
>  }
>  
>  struct ppc_hash_pte64 {

-- 
David Gibson                    | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
                                | _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]