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 <[email protected]> --- 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
