Commit 3367c62f authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by David Gibson
Browse files

target/ppc: Support for POWER9 native hash



(Might need more patch splitting)

Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarCé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: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent 79825f4d
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -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;
}
+47 −0
Original line number Diff line number Diff line
@@ -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 */
+4 −2
Original line number Diff line number Diff line
@@ -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);
+1 −18
Original line number Diff line number Diff line
@@ -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;
};