On 2026/10/9 上午11:05, SignKirigami wrote:
Add op 0x9, 0xa-0xf to instruction invtlb to support vm level 1.

Signed-off-by: SignKirigami <[email protected]>
Signed-off-by: Hengyu Yu <[email protected]>
---
  .../tcg/insn_trans/trans_privileged.c.inc     | 34 +++++++++++++
  target/loongarch/tcg/tlb_helper.c             | 51 ++++++++++++++++---
  2 files changed, 77 insertions(+), 8 deletions(-)

diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc 
b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
index 493ed7f24b..00e8f61e42 100644
--- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
@@ -328,6 +328,10 @@ static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
          return false;
      }
+ if (!avail_LVZ(ctx) && a->imm > 0x6) {
+        return false;
+    }
+
      switch (a->imm) {
      case 0x0:
      case 0x1:
@@ -352,6 +356,36 @@ static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
          gen_helper_invtlb_page_asid_or_g(tcg_env, rj, rk,
                                           tcg_constant_i32(0));
          break;
+    case 0x9:
+    case 0x10:
+    case 0x11:
+    case 0x12:
+    case 0x13:
+    case 0x14:
+    case 0x15:
+    case 0x16:
+        //TODO: refine 0x9-0x16
+        gen_helper_invtlb_all(tcg_env, rj, tcg_constant_i32(0),
+                              tcg_constant_i32(0));
+        break;
+    case 0xa:
+        gen_helper_invtlb_all_g(tcg_env, rj, tcg_constant_i32(1),
+                                tcg_constant_i32(1));
+        break;
+    case 0xb:
+        gen_helper_invtlb_all_g(tcg_env, rj, tcg_constant_i32(0),
+                                tcg_constant_i32(1));
+        break;
+    case 0xc:
+        gen_helper_invtlb_all_asid(tcg_env, rj, tcg_constant_i32(1));
+        break;
+    case 0xd:
+        gen_helper_invtlb_page_asid(tcg_env, rj, rk, tcg_constant_i32(1));
+        break;
+    case 0xe:
+        gen_helper_invtlb_page_asid_or_g(tcg_env, rj, rk,
+                                         tcg_constant_i32(1));
+        break;
      default:
          return false;
      }
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index 60c7193283..c02b7c2472 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -599,9 +599,18 @@ void helper_tlbflush(CPULoongArchState *env, uint32_t 
vm_level)
  void helper_invtlb_all(CPULoongArchState *env, target_ulong info, uint32_t op,
                         uint32_t to_guest)
  {
+    uint16_t gid = to_guest ? (info & 0xff) : get_tgid(env);
+
+    if (to_guest && env_vm_level(env) == VM_LEVEL1) {
+        do_raise_exception(env, EXCCODE_IPE, GETPC());
+    }
+
+    to_guest |= env_vm_level(env) == VM_LEVEL1;
+
      for (int i = 0; i < LOONGARCH_TLB_MAX; i++) {
-        env->tlb[i].tlb_misc = FIELD_DP64(env->tlb[i].tlb_misc,
-                                          TLB_MISC, E, 0);
+        LoongArchTLB *tlb = &env->tlb[i];
+        if ((op == 0 && to_guest == 0) || tlb_entry_matches_gid(tlb, gid))
+            tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0);
      }
      tlb_flush(env_cpu(env));
  }
if gtlb instruction is removed, I think helper_invtlb_xxx APIs can be simplified and remove parameter to_guest.

Regards
Bibo Mao
@@ -609,11 +618,19 @@ void helper_invtlb_all(CPULoongArchState *env, 
target_ulong info, uint32_t op,
  void helper_invtlb_all_g(CPULoongArchState *env, target_ulong info, uint32_t 
g,
                           uint32_t to_guest)
  {
+    uint16_t gid = to_guest ? (info & 0xff) : get_tgid(env);
+
+    if (to_guest && env_vm_level(env) == VM_LEVEL1) {
+        do_raise_exception(env, EXCCODE_IPE, GETPC());
+    }
+
+    to_guest |= env_vm_level(env) == VM_LEVEL1;
+
      for (int i = 0; i < LOONGARCH_TLB_MAX; i++) {
          LoongArchTLB *tlb = &env->tlb[i];
          uint8_t tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
- if (tlb_g == g) {
+        if (tlb_g == g && tlb_entry_matches_gid(tlb, gid)) {
              tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0);
          }
      }
@@ -624,13 +641,19 @@ void helper_invtlb_all_asid(CPULoongArchState *env, 
target_ulong info,
                              uint32_t to_guest)
  {
      uint16_t asid = info & R_CSR_ASID_ASID_MASK;
+    uint16_t gid = to_guest ? ((info >> 16) & 0xff) : get_tgid(env);
+
+    if (to_guest) {
+        do_raise_exception(env, EXCCODE_IPE, GETPC());
+    }
+    to_guest |= env_vm_level(env);
for (int i = 0; i < LOONGARCH_TLB_MAX; i++) {
          LoongArchTLB *tlb = &env->tlb[i];
          uint8_t tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
          uint16_t tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
- if (!tlb_g && (tlb_asid == asid)) {
+        if (!tlb_g && tlb_asid == asid && tlb_entry_matches_gid(tlb, gid)) {
              tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0);
          }
      }
@@ -640,12 +663,19 @@ void helper_invtlb_all_asid(CPULoongArchState *env, 
target_ulong info,
  void helper_invtlb_page_asid(CPULoongArchState *env, target_ulong info,
                               target_ulong addr, uint32_t to_guest)
  {
-    int asid = info & 0x3ff;
+
+    uint16_t asid = info & R_CSR_ASID_ASID_MASK;
+    uint16_t gid = to_guest ? ((info >> 16) & 0xff) : get_tgid(env);
      const LoongArchTLB *tlb;
      tlb_match func;
+ if (to_guest && env_vm_level(env)) {
+        do_raise_exception(env, EXCCODE_IPE, GETPC());
+    }
+    to_guest |= env_vm_level(env);
+
      func = tlb_match_asid;
-    tlb = loongarch_tlb_search_cb(env, addr, asid, func, to_guest, 0);
+    tlb = loongarch_tlb_search_cb(env, addr, asid, func, to_guest, gid);
      if (tlb) {
          invalidate_tlb(env, tlb - env->tlb, to_guest);
      }
@@ -654,13 +684,18 @@ void helper_invtlb_page_asid(CPULoongArchState *env, 
target_ulong info,
  void helper_invtlb_page_asid_or_g(CPULoongArchState *env, target_ulong info,
                                    target_ulong addr, uint32_t to_guest)
  {
-    int asid = info & 0x3ff;
+    uint16_t asid = info & R_CSR_ASID_ASID_MASK;
+    uint16_t gid = to_guest ? ((info >> 16) & 0xff) : get_tgid(env);
      const LoongArchTLB *tlb;
      tlb_match func;
func = tlb_match_any;
+    if (to_guest) {
+        do_raise_exception(env, EXCCODE_IPE, GETPC());
+    }
+    to_guest |= env_vm_level(env);
      tlb = loongarch_tlb_search_cb(env, addr, asid, func,
-                                  to_guest, 0);
+                                  to_guest, gid);
      if (tlb) {
          invalidate_tlb(env, tlb - env->tlb, to_guest);
      }



Reply via email to