diff mbox series

[2/5] target/loongarch: Add do_lddir/ldpte()

Message ID 20240729013939.1807982-3-gaosong@loongson.cn
State New
Headers show
Series LoongArch/tcg: Add hardware page table walker support | expand

Commit Message

gaosong July 29, 2024, 1:39 a.m. UTC
do_lddir is used for accessing directory entries during page table
walking, do_ldpte is used for page table entry accesses during page
table walking.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/tcg/tlb_helper.c | 53 ++++++++++++++++++++-----------
 1 file changed, 34 insertions(+), 19 deletions(-)
diff mbox series

Patch

diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
index 97f38fc391..3c3452b316 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -507,11 +507,11 @@  bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     cpu_loop_exit_restore(cs, retaddr);
 }
 
-target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
-                          target_ulong level, uint32_t mem_idx)
+static target_ulong do_lddir(CPULoongArchState *env, target_ulong base,
+                             target_ulong badvaddr, target_ulong level)
 {
     CPUState *cs = env_cpu(env);
-    target_ulong badvaddr, index, phys, ret;
+    target_ulong index, phys, ret;
     int shift;
     uint64_t dir_base, dir_width;
 
@@ -535,7 +535,6 @@  target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
         }
     }
 
-    badvaddr = env->CSR_TLBRBADV;
     base = base & TARGET_PHYS_MASK;
 
     /* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
@@ -549,11 +548,18 @@  target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
     return ret;
 }
 
-void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
-                  uint32_t mem_idx)
+target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
+                          target_ulong level, uint32_t mem_idx)
+{
+    return do_lddir(env, base, env->CSR_TLBRBADV, level);
+}
+
+static void do_ldpte(CPULoongArchState *env, target_ulong base,
+                     target_ulong badvaddr, target_ulong *ptval0,
+                     target_ulong *ptval1, target_ulong *ps)
 {
     CPUState *cs = env_cpu(env);
-    target_ulong phys, tmp0, ptindex, ptoffset0, ptoffset1, ps, badv;
+    target_ulong  ptindex, ptoffset0, ptoffset1, phys0, phys1;
     int shift;
     uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
     uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
@@ -584,34 +590,43 @@  void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
             base = FIELD_DP64(base, TLBENTRY, G, 1);
         }
 
-        ps = dir_base + dir_width - 1;
+        *ps = dir_base + dir_width - 1;
         /*
          * Huge pages are evenly split into parity pages
          * when loaded into the tlb,
          * so the tlb page size needs to be divided by 2.
          */
-        tmp0 = base;
-        if (odd) {
-            tmp0 += MAKE_64BIT_MASK(ps, 1);
-        }
+        *ptval0 = base;
+        *ptval1 = base + MAKE_64BIT_MASK(*ps, 1);
     } else {
         /* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
         shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
         shift = (shift + 1) * 3;
-        badv = env->CSR_TLBRBADV;
 
-        ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
-        ptindex = ptindex & ~0x1;   /* clear bit 0 */
+        ptindex = (badvaddr >> ptbase) & ((1 << ptwidth) - 1);
+        ptindex = ptindex & ~0x1;  /* clear bit 0 */
         ptoffset0 = ptindex << shift;
         ptoffset1 = (ptindex + 1) << shift;
 
-        phys = base | (odd ? ptoffset1 : ptoffset0);
-        tmp0 = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
-        ps = ptbase;
+        phys0 = base | ptoffset0;
+        phys1 = base | ptoffset1;
+        *ptval0 = ldq_phys(cs->as, phys0) & TARGET_PHYS_MASK;
+        *ptval1 = ldq_phys(cs->as, phys1) & TARGET_PHYS_MASK;
+        *ps = ptbase;
     }
 
+    return;
+}
+
+void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
+                  uint32_t mem_idx)
+{
+    target_ulong tmp0, tmp1, ps;
+
+    do_ldpte(env, base, env->CSR_TLBRBADV, &tmp0, &tmp1, &ps);
+
     if (odd) {
-        env->CSR_TLBRELO1 = tmp0;
+        env->CSR_TLBRELO1 = tmp1;
     } else {
         env->CSR_TLBRELO0 = tmp0;
     }