helper_lddir and helper_ldpte used TARGET_PHYS_MASK (bits 0-47) when
extracting the base address from a directory entry.  This retained flag
bits (V, D, PLV, MAT, etc.) at positions 0-11, which were then OR'd
with the next-level index, producing a wrong physical address whenever
the directory entry carried non-zero flags.

Fix both helpers to extract only the PPN field (bits 12-47) before
computing the address of the next-level page table entry.

Signed-off-by: numpy1314 <[email protected]>
---
 target/loongarch/tcg/tlb_helper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index 776626072d..d75e20baf0 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -887,7 +887,10 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
     }
 
     badvaddr = sys->CSR_TLBRBADV;
-    base = base & palen_mask;
+    /* Extract only the PPN field (bits 12-47) from the directory entry.
+     * Flag bits (V, D, PLV, MAT, etc.) at positions 0-11 must not
+     * participate in the next-level address calculation. */
+    base = (target_ulong)FIELD_EX64(base, TLBENTRY_64, PPN) << 
TARGET_PAGE_BITS;
     get_dir_base_width(env, &dir_base, &dir_width, level,
                        env_vm_level(env) == LOONGARCH_VM_LEVEL_GUEST);
     index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
@@ -912,11 +915,9 @@ void helper_ldpte(CPULoongArchState *env, target_ulong 
base, target_ulong odd,
     uint64_t badv;
     uint64_t ptbase = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, PTBASE);
     uint64_t ptwidth = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, PTWIDTH);
-    uint64_t palen_mask = loongarch_palen_mask(env);
     uint64_t dir_base, dir_width;
     uint8_t  ps;
 
-
     /*
      * The parameter "base" has only two types,
      * one is the page table base address,
@@ -959,9 +960,8 @@ void helper_ldpte(CPULoongArchState *env, target_ulong 
base, target_ulong odd,
         }
     } else {
         badv = sys->CSR_TLBRBADV;
-
-        base = base & palen_mask;
-
+        /* Strip flag bits (0-11) from base before address calculation. */
+        base = (target_ulong)FIELD_EX64(base, TLBENTRY_64, PPN) << 
TARGET_PAGE_BITS;
         ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
         ptindex = ptindex & ~0x1;   /* clear bit 0 */
         ptoffset0 = ptindex << 3;
-- 
2.55.0


Reply via email to