Send updiscon packets based on the constraints already discussed in the previous patch:
- We do not implement any form of call/return prediction in the encoder, and TCG will always retire a single insn per cycle, e.g. irreport will always be equal to updiscon; - irdepth is not implemented since we'll always return a package where irreport == updiscon. Note that we're sending an updiscon packet if the 'updiscon_pending' flag is set when we're about the send a resync or a trap packet. The TCG helper in this case is just setting the trace encoder flags instead of actually triggering a RAM sink SMEM write. Signed-off-by: Daniel Henrique Barboza <[email protected]> --- hw/riscv/trace-encoder.c | 37 +++++++++++++++++++ hw/riscv/trace-encoder.h | 3 ++ target/riscv/helper.h | 1 + .../tcg/insn_trans/trans_privileged.c.inc | 11 ++++++ target/riscv/tcg/insn_trans/trans_rvi.c.inc | 2 + target/riscv/tcg/trace_helper.c | 14 +++++++ target/riscv/tcg/translate.c | 7 ++++ 7 files changed, 75 insertions(+) diff --git a/hw/riscv/trace-encoder.c b/hw/riscv/trace-encoder.c index b2e2707e0c..b9121d93a7 100644 --- a/hw/riscv/trace-encoder.c +++ b/hw/riscv/trace-encoder.c @@ -403,6 +403,22 @@ static void trencoder_send_sync_msg(Object *trencoder_obj, uint64_t pc) trencoder_send_message_smem(trencoder, msg, msg_size); } +static void trencoder_send_updiscon(TraceEncoder *trencoder, uint64_t pc) +{ + g_autofree uint8_t *format2_msg = g_malloc0(TRACE_MSG_MAX_SIZE); + uint8_t addr_msb = extract64(pc, 31, 1); + bool notify = addr_msb; + bool updiscon = !notify; + uint8_t msg_size; + + msg_size = rv_etrace_gen_encoded_format2_msg(format2_msg, pc, + notify, + updiscon); + trencoder_send_message_smem(trencoder, format2_msg, msg_size); + + trencoder->updiscon_pending = false; +} + void trencoder_set_first_trace_insn(Object *trencoder_obj, uint64_t pc) { TraceEncoder *trencoder = TRACE_ENCODER(trencoder_obj); @@ -410,6 +426,10 @@ void trencoder_set_first_trace_insn(Object *trencoder_obj, uint64_t pc) g_autofree uint8_t *msg = g_malloc0(TRACE_MSG_MAX_SIZE); uint8_t msg_size; + if (trencoder->updiscon_pending) { + trencoder_send_updiscon(trencoder, pc); + } + trencoder->first_pc = pc; trace_trencoder_first_trace_insn(pc); msg_size = rv_etrace_gen_encoded_sync_msg(msg, pc, priv); @@ -427,6 +447,10 @@ void trencoder_trace_trap_insn(Object *trencoder_obj, g_autofree uint8_t *msg = g_malloc0(TRACE_MSG_MAX_SIZE); uint8_t msg_size; + if (trencoder->updiscon_pending) { + trencoder_send_updiscon(trencoder, pc); + } + msg_size = rv_etrace_gen_encoded_trap_msg(msg, pc, priv, ecause, is_interrupt, tval); @@ -436,9 +460,22 @@ void trencoder_trace_trap_insn(Object *trencoder_obj, void trencoder_trace_ppccd(Object *trencoder_obj, uint64_t pc) { + TraceEncoder *trencoder = TRACE_ENCODER(trencoder_obj); + + if (trencoder->updiscon_pending) { + trencoder_send_updiscon(trencoder, pc); + } + trencoder_send_sync_msg(trencoder_obj, pc); } +void trencoder_report_updiscon(Object *trencoder_obj) +{ + TraceEncoder *trencoder = TRACE_ENCODER(trencoder_obj); + + trencoder->updiscon_pending = true; +} + static const Property trencoder_props[] = { /* * We need a link to the associated CPU to diff --git a/hw/riscv/trace-encoder.h b/hw/riscv/trace-encoder.h index 64e19c5752..9116fe4f56 100644 --- a/hw/riscv/trace-encoder.h +++ b/hw/riscv/trace-encoder.h @@ -36,6 +36,8 @@ struct TraceEncoder { uint32_t regs[TRACE_R_MAX]; RegisterInfo regs_info[TRACE_R_MAX]; + bool updiscon_pending; + bool enabled; bool trace_running; bool trace_next_insn; @@ -51,5 +53,6 @@ void trencoder_trace_trap_insn(Object *trencoder_obj, bool is_interrupt, uint64_t tval); void trencoder_trace_ppccd(Object *trencoder_obj, uint64_t pc); +void trencoder_report_updiscon(Object *trencoder_obj); #endif diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 0832159adc..68348e5473 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -132,6 +132,7 @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl) /* Trace helpers (should be put inside ifdef) */ DEF_HELPER_2(trace_insn, void, env, i64) +DEF_HELPER_1(trace_updiscon, void, env) #ifndef CONFIG_USER_ONLY DEF_HELPER_1(sret, tl, env) diff --git a/target/riscv/tcg/insn_trans/trans_privileged.c.inc b/target/riscv/tcg/insn_trans/trans_privileged.c.inc index e22df6fbe7..531eb40595 100644 --- a/target/riscv/tcg/insn_trans/trans_privileged.c.inc +++ b/target/riscv/tcg/insn_trans/trans_privileged.c.inc @@ -26,6 +26,8 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a) { + gen_trace_updiscon(ctx); + /* always generates U-level ECALL, fixed in do_interrupt handler */ generate_exception(ctx, RISCV_EXCP_U_ECALL); return true; @@ -40,6 +42,8 @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a) uint32_t ebreak = 0; uint32_t post = 0; + gen_trace_updiscon(ctx); + /* * The RISC-V semihosting spec specifies the following * three-instruction sequence to flag a semihosting call: @@ -101,6 +105,8 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a) { #ifndef CONFIG_USER_ONLY if (has_ext(ctx, RVS)) { + gen_trace_updiscon(ctx); + decode_save_opc(ctx, 0); translator_io_start(&ctx->base); gen_update_pc(ctx, 0); @@ -119,6 +125,8 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a) static bool trans_mret(DisasContext *ctx, arg_mret *a) { #ifndef CONFIG_USER_ONLY + gen_trace_updiscon(ctx); + decode_save_opc(ctx, 0); translator_io_start(&ctx->base); gen_update_pc(ctx, 0); @@ -153,6 +161,9 @@ static bool trans_mnret(DisasContext *ctx, arg_mnret *a) { #ifndef CONFIG_USER_ONLY REQUIRE_SMRNMI(ctx); + + gen_trace_updiscon(ctx); + decode_save_opc(ctx, 0); gen_helper_mnret(cpu_pc, tcg_env); tcg_gen_exit_tb(NULL, 0); /* no chaining */ diff --git a/target/riscv/tcg/insn_trans/trans_rvi.c.inc b/target/riscv/tcg/insn_trans/trans_rvi.c.inc index cc1b5dbbad..2de67c1a88 100644 --- a/target/riscv/tcg/insn_trans/trans_rvi.c.inc +++ b/target/riscv/tcg/insn_trans/trans_rvi.c.inc @@ -183,6 +183,8 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a) } } + gen_trace_updiscon(ctx); + lookup_and_goto_ptr(ctx); if (misaligned) { diff --git a/target/riscv/tcg/trace_helper.c b/target/riscv/tcg/trace_helper.c index 5a6d725f56..a4c5720a65 100644 --- a/target/riscv/tcg/trace_helper.c +++ b/target/riscv/tcg/trace_helper.c @@ -28,9 +28,23 @@ void helper_trace_insn(CPURISCVState *env, uint64_t pc) te->trace_next_insn = false; } } + +void helper_trace_updiscon(CPURISCVState *env) +{ + RISCVCPU *cpu = env_archcpu(env); + TraceEncoder *te = TRACE_ENCODER(cpu->trencoder); + + te->updiscon_pending = true; + te->trace_next_insn = true; +} #else /* #ifndef CONFIG_USER_ONLY */ void helper_trace_insn(CPURISCVState *env, uint64_t pc) { return; } + +void helper_trace_updiscon(CPURISCVState *env) +{ + return; +} #endif /* #ifndef CONFIG_USER_ONLY*/ diff --git a/target/riscv/tcg/translate.c b/target/riscv/tcg/translate.c index fb82a6b2fa..7f6dc6e9e3 100644 --- a/target/riscv/tcg/translate.c +++ b/target/riscv/tcg/translate.c @@ -627,6 +627,13 @@ static void gen_ctr_jal(DisasContext *ctx, int rd, target_ulong imm) } #endif +static void gen_trace_updiscon(DisasContext *ctx) +{ + if (ctx->cpu_trace_running) { + gen_helper_trace_updiscon(tcg_env); + } +} + static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) { TCGv succ_pc = dest_gpr(ctx, rd); -- 2.43.0
