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 <dbarboza@ventanamicro.com>
---
hw/riscv/trace-encoder.c | 37 +++++++++++++++++++
hw/riscv/trace-encoder.h | 3 ++
target/riscv/helper.h | 1 +
.../riscv/insn_trans/trans_privileged.c.inc | 11 ++++++
target/riscv/insn_trans/trans_rvi.c.inc | 2 +
target/riscv/trace_helper.c | 14 +++++++
target/riscv/translate.c | 9 +++++
7 files changed, 77 insertions(+)
diff --git a/hw/riscv/trace-encoder.c b/hw/riscv/trace-encoder.c
index 9a4530bbea..5572483d26 100644
--- a/hw/riscv/trace-encoder.c
+++ b/hw/riscv/trace-encoder.c
@@ -402,6 +402,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);
@@ -409,6 +425,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);
@@ -426,6 +446,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);
@@ -435,9 +459,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 2bf07c01f6..0c44092ccb 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 e80320ad16..f27ff319e9 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -131,6 +131,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/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
index 8a62b4cfcd..28089539d5 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -26,6 +26,8 @@
static bool trans_ecall(DisasContext *ctx, arg_ecall *a)
{
+ gen_trace_updiscon();
+
/* 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();
+
/*
* The RISC-V semihosting spec specifies the following
* three-instruction sequence to flag a semihosting call:
@@ -95,6 +99,8 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
{
#ifndef CONFIG_USER_ONLY
if (has_ext(ctx, RVS)) {
+ gen_trace_updiscon();
+
decode_save_opc(ctx, 0);
translator_io_start(&ctx->base);
gen_update_pc(ctx, 0);
@@ -113,6 +119,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();
+
decode_save_opc(ctx, 0);
translator_io_start(&ctx->base);
gen_update_pc(ctx, 0);
@@ -129,6 +137,9 @@ static bool trans_mnret(DisasContext *ctx, arg_mnret *a)
{
#ifndef CONFIG_USER_ONLY
REQUIRE_SMRNMI(ctx);
+
+ gen_trace_updiscon();
+
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/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc
index 54b9b4f241..ac00cbc802 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -183,6 +183,8 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
}
}
+ gen_trace_updiscon();
+
lookup_and_goto_ptr(ctx);
if (misaligned) {
diff --git a/target/riscv/trace_helper.c b/target/riscv/trace_helper.c
index ed84e6f79a..4b2b645f04 100644
--- a/target/riscv/trace_helper.c
+++ b/target/riscv/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/translate.c b/target/riscv/translate.c
index ff288051e3..26c7678cb9 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -617,6 +617,15 @@ static void gen_ctr_jal(DisasContext *ctx, int rd, target_ulong imm)
}
#endif
+static void gen_trace_updiscon(void)
+{
+ TCGLabel *skip = gen_new_label();
+
+ tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_trace_running, 0, skip);
+ gen_helper_trace_updiscon(tcg_env);
+ gen_set_label(skip);
+}
+
static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
{
TCGv succ_pc = dest_gpr(ctx, rd);
--
2.51.1