Raise GSPR when a guest accesses IOCSR, debug or idle resources, and
decode HVC for guest PLV0.

Use the common exception path so trapping instructions do not manufacture
destination values or require a helper named after the exception cause.

Signed-off-by: SignKirigami <[email protected]>
Signed-off-by: Hengyu Yu <[email protected]>
---
 target/loongarch/disas.c                      |  1 +
 target/loongarch/insns.decode                 |  1 +
 .../tcg/insn_trans/trans_privileged.c.inc     | 32 +++++++++++++++++++
 3 files changed, 34 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 54c35b8d03..82b0bf868f 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -712,6 +712,7 @@ INSN(gtlbsrch,     empty)
 INSN(gtlbrd,       empty)
 INSN(gtlbwr,       empty)
 INSN(gtlbfill,     empty)
+INSN(hvcl,         i)
 INSN(cacop,        cop_r_i)
 INSN(lddir,        rr_i)
 INSN(ldpte,        j_i)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index cbcc30c31f..b40fabe9d7 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -505,6 +505,7 @@ gtlbsrch         0000 01100100 10000 01010 00000 00001    
@empty
 gtlbrd           0000 01100100 10000 01011 00000 00001    @empty
 gtlbwr           0000 01100100 10000 01100 00000 00001    @empty
 gtlbfill         0000 01100100 10000 01101 00000 00001    @empty
+hvcl             0000 0000 0010 1011 1 ...............    @i15
 
 iocsrrd_b        0000 01100100 10000 00000 ..... .....    @rr
 iocsrrd_h        0000 01100100 10000 00001 ..... .....    @rr
diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc 
b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
index fb6318b438..2dedcadfbb 100644
--- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
@@ -48,6 +48,7 @@ GEN_FALSE_TRANS(gtlbsrch)
 GEN_FALSE_TRANS(gtlbrd)
 GEN_FALSE_TRANS(gtlbwr)
 GEN_FALSE_TRANS(gtlbfill)
+GEN_FALSE_TRANS(hvcl)
 
 #else
 
@@ -347,6 +348,10 @@ static bool gen_iocsrrd(DisasContext *ctx, arg_rr *a,
     if (check_plv(ctx)) {
         return false;
     }
+    if (ctx->guest_mode) {
+        generate_exception(ctx, EXCCODE_GSPR);
+        return true;
+    }
     func(dest, tcg_env, src1);
     return true;
 }
@@ -360,6 +365,10 @@ static bool gen_iocsrwr(DisasContext *ctx, arg_rr *a,
     if (check_plv(ctx)) {
         return false;
     }
+    if (ctx->guest_mode) {
+        generate_exception(ctx, EXCCODE_GSPR);
+        return true;
+    }
     func(tcg_env, addr, val);
     return true;
 }
@@ -624,6 +633,10 @@ static bool trans_dbcl(DisasContext *ctx, arg_dbcl *a)
     if (check_plv(ctx)) {
         return false;
     }
+    if (ctx->guest_mode) {
+        generate_exception(ctx, EXCCODE_GSPR);
+        return true;
+    }
     generate_exception(ctx, EXCCODE_DBP);
     return true;
 }
@@ -634,9 +647,28 @@ static bool trans_idle(DisasContext *ctx, arg_idle *a)
         return false;
     }
 
+    if (ctx->guest_mode) {
+        generate_exception(ctx, EXCCODE_GSPR);
+        return true;
+    }
+
     tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
     gen_helper_idle(tcg_env);
     ctx->base.is_jmp = DISAS_NORETURN;
     return true;
 }
+
+static bool trans_hvcl(DisasContext *ctx, arg_hvcl *a)
+{
+    if (!avail_LVZ(ctx) || !ctx->guest_mode) {
+        return false;
+    }
+    if (ctx->plv != MMU_PLV_KERNEL) {
+        generate_exception(ctx, EXCCODE_IPE);
+        return true;
+    }
+
+    generate_exception(ctx, EXCCODE_HVC);
+    return true;
+}
 #endif
-- 
2.55.0


Reply via email to