The ppccd (privilege change) trace packets consists of sync packets like we
already sent during trace start and resyncs.
The privilege change is being fetched via riscv_cpu_set_mode().
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
hw/riscv/trace-encoder.c | 18 ++++++++++++++++++
hw/riscv/trace-encoder.h | 1 +
target/riscv/cpu_helper.c | 13 ++++++++++++-
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/hw/riscv/trace-encoder.c b/hw/riscv/trace-encoder.c
index 0750bd22b5..9a4530bbea 100644
--- a/hw/riscv/trace-encoder.c
+++ b/hw/riscv/trace-encoder.c
@@ -389,6 +389,19 @@ static void trencoder_send_message_smem(TraceEncoder *trencoder,
trencoder_update_ramsink_writep(trencoder, dest, wrapped);
}
+static void trencoder_send_sync_msg(Object *trencoder_obj, uint64_t pc)
+{
+ TraceEncoder *trencoder = TRACE_ENCODER(trencoder_obj);
+ TracePrivLevel priv = trencoder_get_curr_priv_level(trencoder);
+ g_autofree uint8_t *msg = g_malloc0(TRACE_MSG_MAX_SIZE);
+ uint8_t msg_size;
+
+ trencoder->first_pc = pc;
+ msg_size = rv_etrace_gen_encoded_sync_msg(msg, pc, priv);
+
+ trencoder_send_message_smem(trencoder, msg, msg_size);
+}
+
void trencoder_set_first_trace_insn(Object *trencoder_obj, uint64_t pc)
{
TraceEncoder *trencoder = TRACE_ENCODER(trencoder_obj);
@@ -420,6 +433,11 @@ void trencoder_trace_trap_insn(Object *trencoder_obj,
trencoder_send_message_smem(trencoder, msg, msg_size);
}
+void trencoder_trace_ppccd(Object *trencoder_obj, uint64_t pc)
+{
+ trencoder_send_sync_msg(trencoder_obj, pc);
+}
+
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 4898026f2b..2bf07c01f6 100644
--- a/hw/riscv/trace-encoder.h
+++ b/hw/riscv/trace-encoder.h
@@ -50,5 +50,6 @@ void trencoder_trace_trap_insn(Object *trencoder_obj,
uint64_t pc, uint32_t ecause,
bool is_interrupt,
uint64_t tval);
+void trencoder_trace_ppccd(Object *trencoder_obj, uint64_t pc);
#endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index f2990cf7c4..665aad6dea 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1034,6 +1034,8 @@ void riscv_ctr_add_entry(CPURISCVState *env, target_long src, target_long dst,
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en)
{
+ CPUState *cs = env_cpu(env);
+
g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
if (newpriv != env->priv || env->virt_enabled != virt_en) {
@@ -1041,6 +1043,15 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en)
riscv_itrigger_update_priv(env);
}
+ if (newpriv != env->priv) {
+ RISCVCPU *cpu = RISCV_CPU(cs);
+
+ if (cpu->trencoder &&
+ TRACE_ENCODER(cpu->trencoder)->trace_running) {
+ trencoder_trace_ppccd(cpu->trencoder, env->pc);
+ }
+ }
+
riscv_pmu_update_fixed_ctrs(env, newpriv, virt_en);
}
@@ -1061,7 +1072,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en)
if (riscv_has_ext(env, RVH)) {
/* Flush the TLB on all virt mode changes. */
if (env->virt_enabled != virt_en) {
- tlb_flush(env_cpu(env));
+ tlb_flush(cs);
}
env->virt_enabled = virt_en;
--
2.51.1