qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com,
	palmer@dabbelt.com, zhiwei_liu@linux.alibaba.com,
	fei2.wu@intel.com
Subject: [PATCH v6 20/25] target/riscv: Move leaf pte processing out of level loop
Date: Sat, 25 Mar 2023 03:54:24 -0700	[thread overview]
Message-ID: <20230325105429.1142530-21-richard.henderson@linaro.org> (raw)
In-Reply-To: <20230325105429.1142530-1-richard.henderson@linaro.org>

Move the code that never loops outside of the loop.
Unchain the if-return-else statements.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/cpu_helper.c | 234 +++++++++++++++++++++-----------------
 1 file changed, 127 insertions(+), 107 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 00f70a3dd5..ce12dcec1d 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -879,6 +879,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
     }
 
     int ptshift = (levels - 1) * ptidxbits;
+    target_ulong pte;
+    hwaddr pte_addr;
     int i;
 
 #if !TCG_OVERSIZED_GUEST
@@ -895,7 +897,6 @@ restart:
         }
 
         /* check that physical address of PTE is legal */
-        hwaddr pte_addr;
 
         if (two_stage && first_stage) {
             int vbase_prot;
@@ -927,7 +928,6 @@ restart:
             return TRANSLATE_PMP_FAIL;
         }
 
-        target_ulong pte;
         if (riscv_cpu_mxl(env) == MXL_RV32) {
             pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
         } else {
@@ -952,120 +952,140 @@ restart:
         if (!(pte & PTE_V)) {
             /* Invalid PTE */
             return TRANSLATE_FAIL;
-        } else if (!pbmte && (pte & PTE_PBMT)) {
+        }
+        if (pte & (PTE_R | PTE_W | PTE_X)) {
+            goto leaf;
+        }
+
+        /* Inner PTE, continue walking */
+        if (pte & (PTE_D | PTE_A | PTE_U | PTE_ATTR)) {
             return TRANSLATE_FAIL;
-        } else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
-            /* Inner PTE, continue walking */
-            if (pte & (PTE_D | PTE_A | PTE_U | PTE_ATTR)) {
-                return TRANSLATE_FAIL;
-            }
-            base = ppn << PGSHIFT;
-        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
-            /* Reserved leaf PTE flags: PTE_W */
-            return TRANSLATE_FAIL;
-        } else if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
-            /* Reserved leaf PTE flags: PTE_W + PTE_X */
-            return TRANSLATE_FAIL;
-        } else if ((pte & PTE_U) && ((mode != PRV_U) &&
-                   (!sum || access_type == MMU_INST_FETCH))) {
-            /* User PTE flags when not U mode and mstatus.SUM is not set,
-               or the access type is an instruction fetch */
-            return TRANSLATE_FAIL;
-        } else if (!(pte & PTE_U) && (mode != PRV_S)) {
-            /* Supervisor PTE flags when not S mode */
-            return TRANSLATE_FAIL;
-        } else if (ppn & ((1ULL << ptshift) - 1)) {
-            /* Misaligned PPN */
-            return TRANSLATE_FAIL;
-        } else if (access_type == MMU_DATA_LOAD && !((pte & PTE_R) ||
-                   ((pte & PTE_X) && mxr))) {
-            /* Read access check failed */
-            return TRANSLATE_FAIL;
-        } else if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
-            /* Write access check failed */
-            return TRANSLATE_FAIL;
-        } else if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
-            /* Fetch access check failed */
-            return TRANSLATE_FAIL;
-        } else {
-            /* if necessary, set accessed and dirty bits. */
-            target_ulong updated_pte = pte | PTE_A |
+        }
+        base = ppn << PGSHIFT;
+    }
+
+    /* No leaf pte at any translation level. */
+    return TRANSLATE_FAIL;
+
+ leaf:
+    if (ppn & ((1ULL << ptshift) - 1)) {
+        /* Misaligned PPN */
+        return TRANSLATE_FAIL;
+    }
+    if (!pbmte && (pte & PTE_PBMT)) {
+        /* Reserved without Svpbmt. */
+        return TRANSLATE_FAIL;
+    }
+    if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
+        /* Reserved leaf PTE flags: PTE_W */
+        return TRANSLATE_FAIL;
+    }
+    if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
+        /* Reserved leaf PTE flags: PTE_W + PTE_X */
+        return TRANSLATE_FAIL;
+    }
+    if ((pte & PTE_U) &&
+        ((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
+        /*
+         * User PTE flags when not U mode and mstatus.SUM is not set,
+         * or the access type is an instruction fetch.
+         */
+        return TRANSLATE_FAIL;
+    }
+    if (!(pte & PTE_U) && (mode != PRV_S)) {
+        /* Supervisor PTE flags when not S mode */
+        return TRANSLATE_FAIL;
+    }
+    if (access_type == MMU_DATA_LOAD &&
+        !((pte & PTE_R) || ((pte & PTE_X) && mxr))) {
+        /* Read access check failed */
+        return TRANSLATE_FAIL;
+    }
+    if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
+        /* Write access check failed */
+        return TRANSLATE_FAIL;
+    }
+    if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
+        /* Fetch access check failed */
+        return TRANSLATE_FAIL;
+    }
+
+    /* If necessary, set accessed and dirty bits. */
+    target_ulong updated_pte = pte | PTE_A |
                 (access_type == MMU_DATA_STORE ? PTE_D : 0);
 
-            /* Page table updates need to be atomic with MTTCG enabled */
-            if (updated_pte != pte) {
-                if (!hade) {
-                    return TRANSLATE_FAIL;
-                }
+    /* Page table updates need to be atomic with MTTCG enabled */
+    if (updated_pte != pte) {
+        if (!hade) {
+            return TRANSLATE_FAIL;
+        }
 
-                /*
-                 * - if accessed or dirty bits need updating, and the PTE is
-                 *   in RAM, then we do so atomically with a compare and swap.
-                 * - if the PTE is in IO space or ROM, then it can't be updated
-                 *   and we return TRANSLATE_FAIL.
-                 * - if the PTE changed by the time we went to update it, then
-                 *   it is no longer valid and we must re-walk the page table.
-                 */
-                MemoryRegion *mr;
-                hwaddr l = sizeof(target_ulong), addr1;
-                mr = address_space_translate(cs->as, pte_addr,
-                    &addr1, &l, false, MEMTXATTRS_UNSPECIFIED);
-                if (memory_region_is_ram(mr)) {
-                    target_ulong *pte_pa =
-                        qemu_map_ram_ptr(mr->ram_block, addr1);
+        /*
+         * - if accessed or dirty bits need updating, and the PTE is
+         *   in RAM, then we do so atomically with a compare and swap.
+         * - if the PTE is in IO space or ROM, then it can't be updated
+         *   and we return TRANSLATE_FAIL.
+         * - if the PTE changed by the time we went to update it, then
+         *   it is no longer valid and we must re-walk the page table.
+         */
+        MemoryRegion *mr;
+        hwaddr l = sizeof(target_ulong), addr1;
+        mr = address_space_translate(cs->as, pte_addr, &addr1, &l, false,
+                                     MEMTXATTRS_UNSPECIFIED);
+        if (memory_region_is_ram(mr)) {
+            target_ulong *pte_pa = qemu_map_ram_ptr(mr->ram_block, addr1);
 #if TCG_OVERSIZED_GUEST
-                    /* MTTCG is not enabled on oversized TCG guests so
-                     * page table updates do not need to be atomic */
-                    *pte_pa = pte = updated_pte;
+            /*
+             * MTTCG is not enabled on oversized TCG guests so
+             * page table updates do not need to be atomic.
+             */
+            *pte_pa = pte = updated_pte;
 #else
-                    target_ulong old_pte =
-                        qatomic_cmpxchg(pte_pa, pte, updated_pte);
-                    if (old_pte != pte) {
-                        goto restart;
-                    } else {
-                        pte = updated_pte;
-                    }
+            target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+            if (old_pte != pte) {
+                goto restart;
+            }
+            pte = updated_pte;
 #endif
-                } else {
-                    /* misconfigured PTE in ROM (AD bits are not preset) or
-                     * PTE is in IO space and can't be updated atomically */
-                    return TRANSLATE_FAIL;
-                }
-            }
-
-            /* for superpage mappings, make a fake leaf PTE for the TLB's
-               benefit. */
-            target_ulong vpn = addr >> PGSHIFT;
-
-            if (cpu->cfg.ext_svnapot && (pte & PTE_N)) {
-                napot_bits = ctzl(ppn) + 1;
-                if ((i != (levels - 1)) || (napot_bits != 4)) {
-                    return TRANSLATE_FAIL;
-                }
-            }
-
-            napot_mask = (1 << napot_bits) - 1;
-            *physical = (((ppn & ~napot_mask) | (vpn & napot_mask) |
-                          (vpn & (((target_ulong)1 << ptshift) - 1))
-                         ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
-
-            /* set permissions on the TLB entry */
-            if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
-                *prot |= PAGE_READ;
-            }
-            if ((pte & PTE_X)) {
-                *prot |= PAGE_EXEC;
-            }
-            /* add write permission on stores or if the page is already dirty,
-               so that we TLB miss on later writes to update the dirty bit */
-            if ((pte & PTE_W) &&
-                    (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
-                *prot |= PAGE_WRITE;
-            }
-            return TRANSLATE_SUCCESS;
+        } else {
+            /*
+             * Misconfigured PTE in ROM (AD bits are not preset) or
+             * PTE is in IO space and can't be updated atomically.
+             */
+            return TRANSLATE_FAIL;
         }
     }
-    return TRANSLATE_FAIL;
+
+    /* For superpage mappings, make a fake leaf PTE for the TLB's benefit. */
+    target_ulong vpn = addr >> PGSHIFT;
+
+    if (cpu->cfg.ext_svnapot && (pte & PTE_N)) {
+        napot_bits = ctzl(ppn) + 1;
+        if ((i != (levels - 1)) || (napot_bits != 4)) {
+            return TRANSLATE_FAIL;
+        }
+    }
+
+    napot_mask = (1 << napot_bits) - 1;
+    *physical = (((ppn & ~napot_mask) | (vpn & napot_mask) |
+                  (vpn & (((target_ulong)1 << ptshift) - 1))
+                 ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
+
+    /* set permissions on the TLB entry */
+    if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
+        *prot |= PAGE_READ;
+    }
+    if (pte & PTE_X) {
+        *prot |= PAGE_EXEC;
+    }
+    /*
+     * Add write permission on stores or if the page is already dirty,
+     * so that we TLB miss on later writes to update the dirty bit.
+     */
+    if ((pte & PTE_W) && (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
+        *prot |= PAGE_WRITE;
+    }
+    return TRANSLATE_SUCCESS;
 }
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
-- 
2.34.1



  parent reply	other threads:[~2023-03-25 16:02 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-25 10:54 [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
2023-03-25 10:54 ` [PATCH v6 01/25] target/riscv: Extract virt enabled state from tb flags Richard Henderson
2023-04-06  2:35   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 02/25] target/riscv: Add a general status enum for extensions Richard Henderson
2023-03-26 12:54   ` liweiwei
2023-04-11  2:05   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 03/25] target/riscv: Encode the FS and VS on a normal way for tb flags Richard Henderson
2023-04-11  1:59   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} from tb_flags Richard Henderson
2023-03-27  1:34   ` liweiwei
2023-03-27 16:22     ` Richard Henderson
2023-03-28  2:34   ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs,vs} " LIU Zhiwei
2023-04-11  2:02   ` [PATCH v6 04/25] target/riscv: Remove mstatus_hs_{fs, vs} " Alistair Francis
2023-03-25 10:54 ` [PATCH v6 05/25] target/riscv: Add a tb flags field for vstart Richard Henderson
2023-04-11  2:07   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 06/25] target/riscv: Separate priv from mmu_idx Richard Henderson
2023-03-28  2:39   ` LIU Zhiwei
2023-04-11  2:08   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 07/25] target/riscv: Reduce overhead of MSTATUS_SUM change Richard Henderson
2023-03-28  2:41   ` LIU Zhiwei
2023-04-11  2:11   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 08/25] accel/tcg: Add cpu_ld*_code_mmu Richard Henderson
2023-04-11  3:10   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 09/25] target/riscv: Use cpu_ld*_code_mmu for HLVX Richard Henderson
2023-04-11  3:12   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 10/25] target/riscv: Handle HLV, HSV via helpers Richard Henderson
2023-04-11  3:34   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 11/25] target/riscv: Rename MMU_HYP_ACCESS_BIT to MMU_2STAGE_BIT Richard Henderson
2023-04-11  3:36   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 12/25] target/riscv: Introduce mmuidx_sum Richard Henderson
2023-04-11  3:39   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 13/25] target/riscv: Introduce mmuidx_priv Richard Henderson
2023-03-27  2:07   ` LIU Zhiwei
2023-03-27 16:29     ` Richard Henderson
2023-03-28  1:33       ` LIU Zhiwei
2023-03-28  1:54         ` LIU Zhiwei
2023-03-28 14:27           ` Richard Henderson
2023-04-11  3:53   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 14/25] target/riscv: Introduce mmuidx_2stage Richard Henderson
2023-04-11  3:55   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 15/25] target/riscv: Move hstatus.spvp check to check_access_hlsv Richard Henderson
2023-04-11  3:56   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 16/25] target/riscv: Set MMU_2STAGE_BIT in riscv_cpu_mmu_index Richard Henderson
2023-04-11  4:02   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 17/25] target/riscv: Check SUM in the correct register Richard Henderson
2023-04-11  4:25   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 18/25] target/riscv: Hoist second stage mode change to callers Richard Henderson
2023-04-11  4:25   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 19/25] target/riscv: Hoist pbmte and hade out of the level loop Richard Henderson
2023-04-11  4:26   ` Alistair Francis
2023-03-25 10:54 ` Richard Henderson [this message]
2023-04-11  4:30   ` [PATCH v6 20/25] target/riscv: Move leaf pte processing out of " Alistair Francis
2023-03-25 10:54 ` [PATCH v6 21/25] target/riscv: Suppress pte update with is_debug Richard Henderson
2023-04-11  4:30   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 22/25] target/riscv: Don't modify SUM " Richard Henderson
2023-04-11  4:31   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 23/25] target/riscv: Merge checks for reserved pte flags Richard Henderson
2023-04-11  4:32   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 24/25] target/riscv: Reorg access check in get_physical_address Richard Henderson
2023-04-11  4:55   ` Alistair Francis
2023-03-25 10:54 ` [PATCH v6 25/25] target/riscv: Reorg sum " Richard Henderson
2023-04-11  5:36   ` Alistair Francis
2023-03-26  5:17 ` [PATCH v6 00/25] target/riscv: MSTATUS_SUM + cleanups Richard Henderson
2023-03-26 14:18 ` liweiwei
2023-03-27 16:43 ` Daniel Henrique Barboza
2023-03-28  1:22   ` Wu, Fei
2023-04-04  6:42 ` Wu, Fei
2023-04-04  7:11   ` LIU Zhiwei
2023-04-04  7:23     ` Wu, Fei
2023-04-11  5:38 ` Alistair Francis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230325105429.1142530-21-richard.henderson@linaro.org \
    --to=richard.henderson@linaro.org \
    --cc=alistair.francis@wdc.com \
    --cc=fei2.wu@intel.com \
    --cc=palmer@dabbelt.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=zhiwei_liu@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).