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
