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 /target/ppc/mmu-hash64.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 'target/ppc/mmu-hash64.c')
-rw-r--r-- | target/ppc/mmu-hash64.c | 76 |
1 files changed, 45 insertions, 31 deletions
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index c74818b2e7..7899eb2918 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -725,6 +725,39 @@ static void ppc_hash64_set_dsi(CPUState *cs, uint64_t dar, uint64_t dsisr) } +static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1) +{ + hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16; + + if (cpu->vhyp) { + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->hpte_set_r(cpu->vhyp, ptex, pte1); + return; + } + base = ppc_hash64_hpt_base(cpu); + + + /* The HW performs a non-atomic byte update */ + stb_phys(CPU(cpu)->as, base + offset, ((pte1 >> 8) & 0xff) | 0x01); +} + +static void ppc_hash64_set_c(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1) +{ + hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 15; + + if (cpu->vhyp) { + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->hpte_set_c(cpu->vhyp, ptex, pte1); + return; + } + base = ppc_hash64_hpt_base(cpu); + + /* The HW performs a non-atomic byte update */ + stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80); +} + int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx) { @@ -735,7 +768,6 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, hwaddr ptex; ppc_hash_pte64_t pte; int exec_prot, pp_prot, amr_prot, prot; - uint64_t new_pte1; const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC}; hwaddr raddr; @@ -883,19 +915,19 @@ skip_slb_search: /* 6. Update PTE referenced and changed bits if necessary */ - new_pte1 = pte.pte1 | HPTE64_R_R; /* set referenced bit */ - if (rwx == 1) { - new_pte1 |= HPTE64_R_C; /* set changed (dirty) bit */ - } else { - /* - * Treat the page as read-only for now, so that a later write - * will pass through this function again to set the C bit - */ - prot &= ~PAGE_WRITE; + if (!(pte.pte1 & HPTE64_R_R)) { + ppc_hash64_set_r(cpu, ptex, pte.pte1); } - - if (new_pte1 != pte.pte1) { - ppc_hash64_store_hpte(cpu, ptex, pte.pte0, new_pte1); + if (!(pte.pte1 & HPTE64_R_C)) { + if (rwx == 1) { + ppc_hash64_set_c(cpu, ptex, pte.pte1); + } else { + /* + * Treat the page as read-only for now, so that a later write + * will pass through this function again to set the C bit + */ + prot &= ~PAGE_WRITE; + } } /* 7. Determine the real address from the PTE */ @@ -954,24 +986,6 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr) & TARGET_PAGE_MASK; } -void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex, - uint64_t pte0, uint64_t pte1) -{ - hwaddr base; - hwaddr offset = ptex * HASH_PTE_SIZE_64; - - if (cpu->vhyp) { - PPCVirtualHypervisorClass *vhc = - PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); - 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); -} - void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex, target_ulong pte0, target_ulong pte1) { |