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:
parent
79825f4d58
commit
3367c62f52
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user