If asid is changed in function helper_csrwr_asid(), qemu TLB is flushed, however loongArch TLB is still valid. So loongArch TLB need be invalidated in function invalidate_tlb() with different asid and bit effective need be cleared.
Signed-off-by: Bibo Mao <[email protected]> Reviewed-by: Song Gao <[email protected]> --- target/loongarch/tcg/tlb_helper.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index 8cfce48a29..f8fada5b9a 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -117,13 +117,7 @@ static void invalidate_tlb_entry(CPULoongArchState *env, int index) uint8_t tlb_v0 = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, V); uint8_t tlb_v1 = FIELD_EX64(tlb->tlb_entry1, TLBENTRY, V); uint64_t tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN); - uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); - if (!tlb_e) { - return; - } - - tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS); pagesize = MAKE_64BIT_MASK(tlb_ps, 1); mask = MAKE_64BIT_MASK(0, tlb_ps + 1); @@ -145,11 +139,19 @@ static void invalidate_tlb(CPULoongArchState *env, int index) { LoongArchTLB *tlb; uint16_t csr_asid, tlb_asid, tlb_g; + uint8_t tlb_e; csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); tlb = &env->tlb[index]; + tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); + if (!tlb_e) { + return; + } + + tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID); tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G); + /* QEMU TLB is flushed when asid is changed */ if (tlb_g == 0 && tlb_asid != csr_asid) { return; } -- 2.43.5
