mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 09:13:55 -06:00
target/riscv: Add itrigger support when icount is not enabled
When icount is not enabled, there is no API in QEMU that can get the guest instruction number. Translate the guest code in a way that each TB only has one instruction. After executing the instruction, decrease the count by 1 until it reaches 0 where the itrigger fires. Note that only when priviledge matches the itrigger configuration, the count will decrease. Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-Id: <20221013062946.7530-2-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
fb3f3730e4
commit
2c9d747121
9 changed files with 131 additions and 11 deletions
|
@ -112,6 +112,8 @@ typedef struct DisasContext {
|
|||
/* PointerMasking extension */
|
||||
bool pm_mask_enabled;
|
||||
bool pm_base_enabled;
|
||||
/* Use icount trigger for native debug */
|
||||
bool itrigger;
|
||||
/* TCG of the current insn_start */
|
||||
TCGOp *insn_start;
|
||||
} DisasContext;
|
||||
|
@ -257,15 +259,39 @@ static void gen_exception_inst_addr_mis(DisasContext *ctx)
|
|||
generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
|
||||
}
|
||||
|
||||
static void lookup_and_goto_ptr(DisasContext *ctx)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (ctx->itrigger) {
|
||||
gen_helper_itrigger_match(cpu_env);
|
||||
}
|
||||
#endif
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
}
|
||||
|
||||
static void exit_tb(DisasContext *ctx)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (ctx->itrigger) {
|
||||
gen_helper_itrigger_match(cpu_env);
|
||||
}
|
||||
#endif
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
{
|
||||
if (translator_use_goto_tb(&ctx->base, dest)) {
|
||||
/*
|
||||
* Under itrigger, instruction executes one by one like singlestep,
|
||||
* direct block chain benefits will be small.
|
||||
*/
|
||||
if (translator_use_goto_tb(&ctx->base, dest) && !ctx->itrigger) {
|
||||
tcg_gen_goto_tb(n);
|
||||
gen_set_pc_imm(ctx, dest);
|
||||
tcg_gen_exit_tb(ctx->base.tb, n);
|
||||
} else {
|
||||
gen_set_pc_imm(ctx, dest);
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
lookup_and_goto_ptr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1142,6 +1168,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
|||
memset(ctx->ftemp, 0, sizeof(ctx->ftemp));
|
||||
ctx->pm_mask_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_MASK_ENABLED);
|
||||
ctx->pm_base_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_BASE_ENABLED);
|
||||
ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
|
||||
ctx->zero = tcg_constant_tl(0);
|
||||
}
|
||||
|
||||
|
@ -1181,7 +1208,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
|||
|
||||
/* Only the first insn within a TB is allowed to cross a page boundary. */
|
||||
if (ctx->base.is_jmp == DISAS_NEXT) {
|
||||
if (!is_same_page(&ctx->base, ctx->base.pc_next)) {
|
||||
if (ctx->itrigger || !is_same_page(&ctx->base, ctx->base.pc_next)) {
|
||||
ctx->base.is_jmp = DISAS_TOO_MANY;
|
||||
} else {
|
||||
unsigned page_ofs = ctx->base.pc_next & ~TARGET_PAGE_MASK;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue