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);
|
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
|
#ifndef MMU_BOOOK3S_V3_H
|
||||||
#define MMU_BOOOK3S_V3_H
|
#define MMU_BOOOK3S_V3_H
|
||||||
|
|
||||||
|
#include "mmu-hash64.h"
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#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);
|
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
|
* The LPCR:HR bit is a shortcut that avoids having to
|
||||||
* dig out the partition table in the fast path. This is
|
* 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 ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
|
||||||
int mmu_idx);
|
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 /* TARGET_PPC64 */
|
||||||
|
|
||||||
#endif /* CONFIG_USER_ONLY */
|
#endif /* CONFIG_USER_ONLY */
|
||||||
|
|
|
@ -417,7 +417,7 @@ const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu,
|
||||||
hwaddr ptex, int n)
|
hwaddr ptex, int n)
|
||||||
{
|
{
|
||||||
hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
|
hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
|
||||||
hwaddr base = ppc_hash64_hpt_base(cpu);
|
hwaddr base;
|
||||||
hwaddr plen = n * HASH_PTE_SIZE_64;
|
hwaddr plen = n * HASH_PTE_SIZE_64;
|
||||||
const ppc_hash_pte64_t *hptes;
|
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);
|
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
|
||||||
return vhc->map_hptes(cpu->vhyp, ptex, n);
|
return vhc->map_hptes(cpu->vhyp, ptex, n);
|
||||||
}
|
}
|
||||||
|
base = ppc_hash64_hpt_base(cpu);
|
||||||
|
|
||||||
if (!base) {
|
if (!base) {
|
||||||
return NULL;
|
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,
|
void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
|
||||||
uint64_t pte0, uint64_t pte1)
|
uint64_t pte0, uint64_t pte1)
|
||||||
{
|
{
|
||||||
hwaddr base = ppc_hash64_hpt_base(cpu);
|
hwaddr base;
|
||||||
hwaddr offset = ptex * HASH_PTE_SIZE_64;
|
hwaddr offset = ptex * HASH_PTE_SIZE_64;
|
||||||
|
|
||||||
if (cpu->vhyp) {
|
if (cpu->vhyp) {
|
||||||
|
@ -950,6 +951,7 @@ void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
|
||||||
vhc->store_hpte(cpu->vhyp, ptex, pte0, pte1);
|
vhc->store_hpte(cpu->vhyp, ptex, pte0, pte1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
base = ppc_hash64_hpt_base(cpu);
|
||||||
|
|
||||||
stq_phys(CPU(cpu)->as, base + offset, pte0);
|
stq_phys(CPU(cpu)->as, base + offset, pte0);
|
||||||
stq_phys(CPU(cpu)->as, base + offset + HASH_PTE_SIZE_64 / 2, pte1);
|
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_HTABORG 0x0FFFFFFFFFFC0000ULL
|
||||||
#define SDR_64_HTABSIZE 0x000000000000001FULL
|
#define SDR_64_HTABSIZE 0x000000000000001FULL
|
||||||
|
|
||||||
|
#define PATE0_HTABORG 0x0FFFFFFFFFFC0000ULL
|
||||||
#define HPTES_PER_GROUP 8
|
#define HPTES_PER_GROUP 8
|
||||||
#define HASH_PTE_SIZE_64 16
|
#define HASH_PTE_SIZE_64 16
|
||||||
#define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)
|
#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_SHIFT 58
|
||||||
#define HPTE64_R_3_0_SSIZE_MASK (3ULL << HPTE64_R_3_0_SSIZE_SHIFT)
|
#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 {
|
struct ppc_hash_pte64 {
|
||||||
uint64_t pte0, pte1;
|
uint64_t pte0, pte1;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue