From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
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.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
target/ppc/mmu-hash32.c | 45 ++++++++++++++++++++++++++++-------------
1 file changed, 31 insertions(+), 14 deletions(-)
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 3f4dee835e2d..55cf156a0b49 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -345,6 +345,24 @@ static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off,
return -1;
}
+static void ppc_hash32_set_r(PowerPCCPU *cpu, hwaddr pte_offset, uint32_t pte1)
+{
+ target_ulong base = ppc_hash32_hpt_base(cpu);
+ hwaddr offset = pte_offset + 6;
+
+ /* The HW performs a non-atomic byte update */
+ stb_phys(CPU(cpu)->as, base + offset, ((pte1 >> 8) & 0xff) | 0x01);
+}
+
+static void ppc_hash32_set_c(PowerPCCPU *cpu, hwaddr pte_offset, uint64_t pte1)
+{
+ target_ulong base = ppc_hash32_hpt_base(cpu);
+ hwaddr offset = pte_offset + 7;
+
+ /* The HW performs a non-atomic byte update */
+ stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80);
+}
+
static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
target_ulong sr, target_ulong eaddr,
ppc_hash_pte32_t *pte)
@@ -403,7 +421,6 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
hwaddr pte_offset;
ppc_hash_pte32_t pte;
int prot;
- uint32_t new_pte1;
const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
hwaddr raddr;
@@ -519,20 +536,20 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
/* 8. Update PTE referenced and changed bits if necessary */
- new_pte1 = pte.pte1 | HPTE32_R_R; /* set referenced bit */
- if (rwx == 1) {
- new_pte1 |= HPTE32_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 (new_pte1 != pte.pte1) {
- ppc_hash32_store_hpte1(cpu, pte_offset, new_pte1);
+ if (!(pte.pte1 & HPTE32_R_R)) {
+ ppc_hash32_set_r(cpu, pte_offset, pte.pte1);
}
+ if (!(pte.pte1 & HPTE32_R_C)) {
+ if (rwx == 1) {
+ ppc_hash32_set_c(cpu, pte_offset, 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;
+ }
+ }
/* 9. Determine the real address from the PTE */
--
2.20.1
On Thu, Apr 11, 2019 at 10:00:02AM +0200, Cédric Le Goater wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>
> 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.
>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
Applied, thanks.
> ---
> target/ppc/mmu-hash32.c | 45 ++++++++++++++++++++++++++++-------------
> 1 file changed, 31 insertions(+), 14 deletions(-)
>
> diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
> index 3f4dee835e2d..55cf156a0b49 100644
> --- a/target/ppc/mmu-hash32.c
> +++ b/target/ppc/mmu-hash32.c
> @@ -345,6 +345,24 @@ static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off,
> return -1;
> }
>
> +static void ppc_hash32_set_r(PowerPCCPU *cpu, hwaddr pte_offset, uint32_t pte1)
> +{
> + target_ulong base = ppc_hash32_hpt_base(cpu);
> + hwaddr offset = pte_offset + 6;
> +
> + /* The HW performs a non-atomic byte update */
> + stb_phys(CPU(cpu)->as, base + offset, ((pte1 >> 8) & 0xff) | 0x01);
> +}
> +
> +static void ppc_hash32_set_c(PowerPCCPU *cpu, hwaddr pte_offset, uint64_t pte1)
> +{
> + target_ulong base = ppc_hash32_hpt_base(cpu);
> + hwaddr offset = pte_offset + 7;
> +
> + /* The HW performs a non-atomic byte update */
> + stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80);
> +}
> +
> static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
> target_ulong sr, target_ulong eaddr,
> ppc_hash_pte32_t *pte)
> @@ -403,7 +421,6 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
> hwaddr pte_offset;
> ppc_hash_pte32_t pte;
> int prot;
> - uint32_t new_pte1;
> const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
> hwaddr raddr;
>
> @@ -519,20 +536,20 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
>
> /* 8. Update PTE referenced and changed bits if necessary */
>
> - new_pte1 = pte.pte1 | HPTE32_R_R; /* set referenced bit */
> - if (rwx == 1) {
> - new_pte1 |= HPTE32_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 (new_pte1 != pte.pte1) {
> - ppc_hash32_store_hpte1(cpu, pte_offset, new_pte1);
> + if (!(pte.pte1 & HPTE32_R_R)) {
> + ppc_hash32_set_r(cpu, pte_offset, pte.pte1);
> }
> + if (!(pte.pte1 & HPTE32_R_C)) {
> + if (rwx == 1) {
> + ppc_hash32_set_c(cpu, pte_offset, 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;
> + }
> + }
>
> /* 9. Determine the real address from the PTE */
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
© 2016 - 2026 Red Hat, Inc.