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
