diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2019-04-11 10:00:01 +0200 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2019-04-26 11:37:57 +1000 |
commit | a2dd4e83e76ba9c0d432145059dd9e2b2a096e2b (patch) | |
tree | 97554cc89ba0383a59e949cde23cddfefb409027 /hw/ppc/spapr.c | |
parent | 993aaf0c0003f7af1bf62c1c2d5cc3c0fe687f5b (diff) |
ppc/hash64: Rework R and C bit updates
With MT-TCG, we are now running translation in a racy way, thus
we need to mimic hardware when it comes to updating the R and
C bits, by doing byte stores.
The current "store_hpte" abstraction is ill suited for this, we
replace it with two separate callbacks for setting R and C.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <20190411080004.8690-4-clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/ppc/spapr.c')
-rw-r--r-- | hw/ppc/spapr.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index b81e237635..c56939a43b 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1520,10 +1520,10 @@ static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, /* Nothing to do for qemu managed HPT */ } -static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex, - uint64_t pte0, uint64_t pte1) +void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, + uint64_t pte0, uint64_t pte1) { - SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); + SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp); hwaddr offset = ptex * HASH_PTE_SIZE_64; if (!spapr->htab) { @@ -1551,6 +1551,38 @@ static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex, } } +static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, + uint64_t pte1) +{ + hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15; + SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); + + if (!spapr->htab) { + /* There should always be a hash table when this is called */ + error_report("spapr_hpte_set_c called with no hash table !"); + return; + } + + /* The HW performs a non-atomic byte update */ + stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80); +} + +static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex, + uint64_t pte1) +{ + hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14; + SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); + + if (!spapr->htab) { + /* There should always be a hash table when this is called */ + error_report("spapr_hpte_set_r called with no hash table !"); + return; + } + + /* The HW performs a non-atomic byte update */ + stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01); +} + int spapr_hpt_shift_for_ramsize(uint64_t ramsize) { int shift; @@ -4291,7 +4323,8 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) vhc->hpt_mask = spapr_hpt_mask; vhc->map_hptes = spapr_map_hptes; vhc->unmap_hptes = spapr_unmap_hptes; - vhc->store_hpte = spapr_store_hpte; + vhc->hpte_set_c = spapr_hpte_set_c; + vhc->hpte_set_r = spapr_hpte_set_r; vhc->get_pate = spapr_get_pate; vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; xic->ics_get = spapr_ics_get; |