target/ppc: Support for POWER9 native hash

(Might need more patch splitting)

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <20190215170029.15641-12-clg@kaod.org>
[dwg: Hack to fix compile with some earlier include tweaks of mine]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Benjamin Herrenschmidt 2019-02-15 18:00:28 +01:00 committed by David Gibson
parent 79825f4d58
commit 3367c62f52
4 changed files with 70 additions and 20 deletions

View file

@ -41,3 +41,21 @@ hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr)
return ppc_hash64_get_phys_page_debug(cpu, eaddr);
}
}
bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, ppc_v3_pate_t *entry)
{
uint64_t patb = cpu->env.spr[SPR_PTCR] & PTCR_PATB;
uint64_t pats = cpu->env.spr[SPR_PTCR] & PTCR_PATS;
/* Calculate number of entries */
pats = 1ull << (pats + 12 - 4);
if (pats <= lpid) {
return false;
}
/* Grab entry */
patb += 16 * lpid;
entry->dw0 = ldq_phys(CPU(cpu)->as, patb);
entry->dw1 = ldq_phys(CPU(cpu)->as, patb + 8);
return true;
}

View file

@ -20,6 +20,8 @@
#ifndef MMU_BOOOK3S_V3_H
#define MMU_BOOOK3S_V3_H
#include "mmu-hash64.h"
#ifndef CONFIG_USER_ONLY
/*
@ -52,6 +54,9 @@ static inline bool ppc64_use_proc_tbl(PowerPCCPU *cpu)
return !!(cpu->env.spr[SPR_LPCR] & LPCR_UPRT);
}
bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid,
ppc_v3_pate_t *entry);
/*
* The LPCR:HR bit is a shortcut that avoids having to
* dig out the partition table in the fast path. This is
@ -67,6 +72,48 @@ hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr);
int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
int mmu_idx);
static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
{
uint64_t base;
if (cpu->vhyp) {
return 0;
}
if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
ppc_v3_pate_t pate;
if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
return 0;
}
base = pate.dw0;
} else {
base = cpu->env.spr[SPR_SDR1];
}
return base & SDR_64_HTABORG;
}
static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
{
uint64_t base;
if (cpu->vhyp) {
PPCVirtualHypervisorClass *vhc =
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
return vhc->hpt_mask(cpu->vhyp);
}
if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
ppc_v3_pate_t pate;
if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
return 0;
}
base = pate.dw0;
} else {
base = cpu->env.spr[SPR_SDR1];
}
return (1ULL << ((base & SDR_64_HTABSIZE) + 18 - 7)) - 1;
}
#endif /* TARGET_PPC64 */
#endif /* CONFIG_USER_ONLY */

View file

@ -417,7 +417,7 @@ const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu,
hwaddr ptex, int n)
{
hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
hwaddr base = ppc_hash64_hpt_base(cpu);
hwaddr base;
hwaddr plen = n * HASH_PTE_SIZE_64;
const ppc_hash_pte64_t *hptes;
@ -426,6 +426,7 @@ const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu,
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
return vhc->map_hptes(cpu->vhyp, ptex, n);
}
base = ppc_hash64_hpt_base(cpu);
if (!base) {
return NULL;
@ -941,7 +942,7 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr)
void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
uint64_t pte0, uint64_t pte1)
{
hwaddr base = ppc_hash64_hpt_base(cpu);
hwaddr base;
hwaddr offset = ptex * HASH_PTE_SIZE_64;
if (cpu->vhyp) {
@ -950,6 +951,7 @@ void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
vhc->store_hpte(cpu->vhyp, ptex, pte0, pte1);
return;
}
base = ppc_hash64_hpt_base(cpu);
stq_phys(CPU(cpu)->as, base + offset, pte0);
stq_phys(CPU(cpu)->as, base + offset + HASH_PTE_SIZE_64 / 2, pte1);

View file

@ -63,6 +63,7 @@ void ppc_hash64_filter_pagesizes(PowerPCCPU *cpu,
#define SDR_64_HTABORG 0x0FFFFFFFFFFC0000ULL
#define SDR_64_HTABSIZE 0x000000000000001FULL
#define PATE0_HTABORG 0x0FFFFFFFFFFC0000ULL
#define HPTES_PER_GROUP 8
#define HASH_PTE_SIZE_64 16
#define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)
@ -107,24 +108,6 @@ void ppc_hash64_filter_pagesizes(PowerPCCPU *cpu,
#define HPTE64_R_3_0_SSIZE_SHIFT 58
#define HPTE64_R_3_0_SSIZE_MASK (3ULL << HPTE64_R_3_0_SSIZE_SHIFT)
static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
{
if (cpu->vhyp) {
return 0;
}
return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG;
}
static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
{
if (cpu->vhyp) {
PPCVirtualHypervisorClass *vhc =
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;
}
struct ppc_hash_pte64 {
uint64_t pte0, pte1;
};