[PATCH v3 14/17] target/loongarch: Use mmu idx bitmap method when flush tlb

Bibo Mao posted 17 patches 3 months, 3 weeks ago
Maintainers: Song Gao <gaosong@loongson.cn>, Bibo Mao <maobibo@loongson.cn>, Jiaxun Yang <jiaxun.yang@flygoat.com>
There is a newer version of this series
[PATCH v3 14/17] target/loongarch: Use mmu idx bitmap method when flush tlb
Posted by Bibo Mao 3 months, 3 weeks ago
With API tlb_flush_range_by_mmuidx(), bitmap method of mmu idx should
be used rather than itself. And mmu idx comes from page table entry
information rather current running mode.

Also field KM in TLB misc records bitmap mask of TLB entry which
is access in kernel mode. If set, MMU_KERNEL_IDX should be added
to flush tlb.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 target/loongarch/tcg/tlb_helper.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
index 61cc19610e..d18b382e56 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -110,12 +110,12 @@ static void invalidate_tlb_entry(CPULoongArchState *env, int index)
     target_ulong addr, mask, pagesize;
     uint8_t tlb_ps;
     LoongArchTLB *tlb = &env->tlb[index];
-
-    int mmu_idx = cpu_mmu_index(env_cpu(env), false);
+    int mmu_idx;
     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);
+    uint16_t tlb_g, tlb_km;
 
     if (!tlb_e) {
         return;
@@ -125,13 +125,28 @@ static void invalidate_tlb_entry(CPULoongArchState *env, int index)
     pagesize = MAKE_64BIT_MASK(tlb_ps, 1);
     mask = MAKE_64BIT_MASK(0, tlb_ps + 1);
     addr = __vaddr((tlb_vppn << R_TLB_MISC_VPPN_SHIFT) & ~mask);
+    tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
+    tlb_km = FIELD_EX64(tlb->tlb_misc, TLB_MISC, KM);
+    if (tlb_g) {
+        mmu_idx = BIT(MMU_KERNEL_IDX);
+    } else {
+        mmu_idx = BIT(MMU_USER_IDX);
+    }
 
     if (tlb_v0) {
+        /* Even page is accessed in kernel mode */
+        if (tlb_km & 0x1) {
+            mmu_idx |= BIT(MMU_KERNEL_IDX);
+        }
         tlb_flush_range_by_mmuidx(env_cpu(env), addr, pagesize,
                                   mmu_idx, TARGET_LONG_BITS);
     }
 
     if (tlb_v1) {
+        /* Odd page is accessed in kernel mode */
+        if (tlb_km & 0x2) {
+            mmu_idx |= BIT(MMU_KERNEL_IDX);
+        }
         tlb_flush_range_by_mmuidx(env_cpu(env), addr + pagesize, pagesize,
                                   mmu_idx, TARGET_LONG_BITS);
     }
-- 
2.39.3