Raise GSPR when a guest accesses IOCSR, debug, idle and cpucfg resources, and decode HVC for guest PLV0.
Signed-off-by: SignKirigami <[email protected]> Signed-off-by: Hengyu Yu <[email protected]> --- target/loongarch/disas.c | 1 + target/loongarch/insns.decode | 1 + target/loongarch/tcg/helper.h | 2 +- .../tcg/insn_trans/trans_extra.c.inc | 5 +++ .../tcg/insn_trans/trans_privileged.c.inc | 32 +++++++++++++++++++ target/loongarch/tcg/op_helper.c | 3 ++ 6 files changed, 43 insertions(+), 1 deletion(-) diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c index 6425dea17c..7d47fc0151 100644 --- a/target/loongarch/disas.c +++ b/target/loongarch/disas.c @@ -706,6 +706,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/helper.h b/target/loongarch/tcg/helper.h index 84eaee208c..be1573af9d 100644 --- a/target/loongarch/tcg/helper.h +++ b/target/loongarch/tcg/helper.h @@ -10,7 +10,7 @@ DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl) DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl) DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl) -DEF_HELPER_FLAGS_2(cpucfg, TCG_CALL_NO_RWG_SE, tl, env, tl) +DEF_HELPER_FLAGS_2(cpucfg, TCG_CALL_NO_WG_SE, tl, env, tl) /* Floating-point helper */ DEF_HELPER_FLAGS_3(fadd_s, TCG_CALL_NO_WG, i64, env, i64, i64) diff --git a/target/loongarch/tcg/insn_trans/trans_extra.c.inc b/target/loongarch/tcg/insn_trans/trans_extra.c.inc index 655dce329e..275755a1f0 100644 --- a/target/loongarch/tcg/insn_trans/trans_extra.c.inc +++ b/target/loongarch/tcg/insn_trans/trans_extra.c.inc @@ -82,6 +82,11 @@ static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a) { + if (is_guest_mmu_idx(ctx->mem_idx)) { + generate_exception(ctx, EXCCODE_GSPR); + return true; + } + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc index ae481aa83f..bd50e91422 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 @@ -301,6 +302,10 @@ static bool gen_iocsrrd(DisasContext *ctx, arg_rr *a, if (check_plv(ctx)) { return false; } + if (is_guest_mmu_idx(ctx->mem_idx)) { + generate_exception(ctx, EXCCODE_GSPR); + return true; + } func(dest, tcg_env, src1); return true; } @@ -314,6 +319,10 @@ static bool gen_iocsrwr(DisasContext *ctx, arg_rr *a, if (check_plv(ctx)) { return false; } + if (is_guest_mmu_idx(ctx->mem_idx)) { + generate_exception(ctx, EXCCODE_GSPR); + return true; + } func(tcg_env, addr, val); return true; } @@ -584,6 +593,10 @@ static bool trans_dbcl(DisasContext *ctx, arg_dbcl *a) if (check_plv(ctx)) { return false; } + if (is_guest_mmu_idx(ctx->mem_idx)) { + generate_exception(ctx, EXCCODE_GSPR); + return true; + } generate_exception(ctx, EXCCODE_DBP); return true; } @@ -594,9 +607,28 @@ static bool trans_idle(DisasContext *ctx, arg_idle *a) return false; } + if (is_guest_mmu_idx(ctx->mem_idx)) { + 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) || !is_guest_mmu_idx(ctx->mem_idx)) { + return false; + } + + if (check_plv(ctx)) { + return false; + } + + generate_exception(ctx, EXCCODE_HVC); + return true; +} #endif diff --git a/target/loongarch/tcg/op_helper.c b/target/loongarch/tcg/op_helper.c index 3035dfa08d..e2fe4b212f 100644 --- a/target/loongarch/tcg/op_helper.c +++ b/target/loongarch/tcg/op_helper.c @@ -20,6 +20,9 @@ /* Exceptions helpers */ void helper_raise_exception(CPULoongArchState *env, uint32_t exception) { + if (exception == EXCCODE_GSPR || exception == EXCCODE_HVC) { + trigger_vm_exit(env); + } do_raise_exception(env, exception, GETPC()); } -- 2.55.0
