[Qemu-devel] [PATCH 4/6] ppc/hash32: Rework R and C bit updates

Cédric Le Goater posted 6 patches 6 years, 10 months ago
[Qemu-devel] [PATCH 4/6] ppc/hash32: Rework R and C bit updates
Posted by Cédric Le Goater 6 years, 10 months ago
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


Re: [Qemu-devel] [PATCH 4/6] ppc/hash32: Rework R and C bit updates
Posted by David Gibson 6 years, 10 months ago
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