Qemu TCG provides some tlb flushing API, tlb can be flushed with specified mmu idx and virtual address. Here fine-grained tlb flush method is used.
Signed-off-by: Bibo Mao <maob...@loongson.cn> --- target/loongarch/tcg/tlb_helper.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index 47eb3ee318..0842b067b1 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -385,7 +385,8 @@ void helper_tlbclr(CPULoongArchState *env) } } - tlb_flush(env_cpu(env)); + /* Flush all user tlb entries */ + tlb_flush_by_mmuidx(env_cpu(env), BIT(MMU_USER_IDX)); } void helper_tlbflush(CPULoongArchState *env) @@ -447,7 +448,9 @@ void helper_invtlb_all_asid(CPULoongArchState *env, target_ulong info) tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); } } - tlb_flush(env_cpu(env)); + + /* Flush all user tlb entries */ + tlb_flush_by_mmuidx(env_cpu(env), BIT(MMU_USER_IDX)); } void helper_invtlb_page_asid(CPULoongArchState *env, target_ulong info, @@ -475,15 +478,19 @@ void helper_invtlb_page_asid(CPULoongArchState *env, target_ulong info, if (!tlb_g && (tlb_asid == asid) && (vpn == (tlb_vppn >> compare_shift))) { tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); + tlb_flush_range_by_mmuidx(env_cpu(env), vpn << (tlb_ps + 1), + BIT_ULL(tlb_ps + 1), + BIT(MMU_USER_IDX), TARGET_LONG_BITS); + break; } } - tlb_flush(env_cpu(env)); } void helper_invtlb_page_asid_or_g(CPULoongArchState *env, target_ulong info, target_ulong addr) { uint16_t asid = info & 0x3ff; + int mmu_idx; for (int i = 0; i < LOONGARCH_TLB_MAX; i++) { LoongArchTLB *tlb = &env->tlb[i]; @@ -505,9 +512,13 @@ void helper_invtlb_page_asid_or_g(CPULoongArchState *env, if ((tlb_g || (tlb_asid == asid)) && (vpn == (tlb_vppn >> compare_shift))) { tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); + mmu_idx = BIT(FIELD_EX64(tlb->tlb_entry0, TLBENTRY, PLV)); + tlb_flush_range_by_mmuidx(env_cpu(env), vpn << (tlb_ps + 1), + BIT_ULL(tlb_ps + 1), + mmu_idx, TARGET_LONG_BITS); + break; } } - tlb_flush(env_cpu(env)); } bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, -- 2.39.3