Add generation, encoding and sending logic for N-Trace ProgTraceCorrelation message.
Signed-off-by: Konstantin Semichastnov <[email protected]> --- hw/riscv/rv-trace-messages.c | 40 ++++++++++++++++++++++++++++++++++++++++ hw/riscv/rv-trace-messages.h | 4 ++++ hw/riscv/trace-encoder.c | 28 ++++++++++++++++++++++++++++ hw/riscv/trace-encoder.h | 8 ++++++++ 4 files changed, 80 insertions(+) diff --git a/hw/riscv/rv-trace-messages.c b/hw/riscv/rv-trace-messages.c index 8a9a3c6955..708e48bbed 100644 --- a/hw/riscv/rv-trace-messages.c +++ b/hw/riscv/rv-trace-messages.c @@ -359,11 +359,14 @@ typedef enum { WIDTH_FADDR = 63, WIDTH_UADDR = 63, WIDTH_HIST = 32, + WIDTH_EVCODE = 4, + WIDTH_CDF = 2, WIDTH_RCODE = 4, } NTraceFieldWidth; typedef enum { TCODE_PROG_TRACE_SYNC = 0x9, + TCODE_PROG_TRACE_CORRELATION = 0x21, TCODE_RESOURCE_FULL = 0x1b, TCODE_INDIRECT_BRANCH_HIST = 0x1c, } NTraceTcodeFieldValues; @@ -373,6 +376,10 @@ typedef enum { SYNC_TRACE_ENABLED = 5, } NTraceSyncFieldValues; +typedef enum { + CDF_ICNT_AND_HIST_PRESENT = 1, +} NTraceCdfFieldValues; + typedef enum { RCODE_HIST_PRESENT = 1, } NTraceRcodeFieldValues; @@ -432,6 +439,20 @@ typedef struct NTraceFieldPayload { .value = (val), \ } +#define PAYLOAD_EVCODE(val) \ + { \ + .type = FIELD_FIXED, \ + .width = WIDTH_EVCODE, \ + .value = (val), \ + } + +#define PAYLOAD_CDF(val) \ + { \ + .type = FIELD_FIXED, \ + .width = WIDTH_CDF, \ + .value = (val), \ + } + #define PAYLOAD_RCODE(val) \ { \ .type = FIELD_FIXED, \ @@ -531,6 +552,25 @@ size_t rv_ntrace_gen_encoded_prog_trace_sync_msg(uint8_t *buf, uint64_t faddr) return rv_ntrace_gen_encoded_msg(buf, msg_fields); } +size_t rv_ntrace_gen_encoded_prog_trace_correlation_msg(uint8_t *buf, + uint32_t evcode, + uint32_t icnt, + uint32_t hist) +{ + const NTraceFieldPayload msg_fields[] = { + PAYLOAD_TCODE(TCODE_PROG_TRACE_CORRELATION), + /* SRC field is not supported for now */ + PAYLOAD_EVCODE(evcode), + PAYLOAD_CDF(CDF_ICNT_AND_HIST_PRESENT), + PAYLOAD_ICNT(icnt), + PAYLOAD_HIST(hist), + /* TSTAMP field is not supported for now */ + PAYLOAD_END(), + }; + + return rv_ntrace_gen_encoded_msg(buf, msg_fields); +} + size_t rv_ntrace_gen_encoded_resource_full_msg(uint8_t *buf, uint32_t hist) { const NTraceFieldPayload msg_fields[] = { diff --git a/hw/riscv/rv-trace-messages.h b/hw/riscv/rv-trace-messages.h index 7ed8737d14..a4d14de59a 100644 --- a/hw/riscv/rv-trace-messages.h +++ b/hw/riscv/rv-trace-messages.h @@ -38,6 +38,10 @@ size_t rv_etrace_gen_encoded_format1(uint8_t *buf, bool notify, bool updiscon); size_t rv_ntrace_gen_encoded_prog_trace_sync_msg(uint8_t *buf, uint64_t faddr); +size_t rv_ntrace_gen_encoded_prog_trace_correlation_msg(uint8_t *buf, + uint32_t evcode, + uint32_t icnt, + uint32_t hist); size_t rv_ntrace_gen_encoded_resource_full_msg(uint8_t *buf, uint32_t hist); size_t rv_ntrace_gen_indirect_branch_hist_msg(uint8_t *buf, uint8_t btype, uint32_t icnt, uint64_t uaddr, diff --git a/hw/riscv/trace-encoder.c b/hw/riscv/trace-encoder.c index 302458bfba..c36d205f50 100644 --- a/hw/riscv/trace-encoder.c +++ b/hw/riscv/trace-encoder.c @@ -259,6 +259,16 @@ static void trencoder_te_ctrl_postw(RegisterInfo *reg, uint64_t val) RISCVCPU *cpu = te->cpu; CPURISCVState *env = &cpu->env; + + if (te->ntrace && te->enabled) { + if (!trTeActive || !trTeEnable || !trTeInstTracing) { + uint32_t inst_len = get_inst_len_at(env->pc); + + trencoder_send_prog_trace_correlation(OBJECT(te), env->pc, inst_len, + CORRELATION_TRACE_DISABLED); + } + } + if (!trTeActive) { te->enabled = false; te->trace_running = false; @@ -658,6 +668,24 @@ static uint32_t rv_ntrace_get_and_reset_icnt(TraceEncoder *trencoder, return icnt; } +void trencoder_send_prog_trace_correlation(Object *trencoder_obj, uint64_t pc, + uint32_t inst_len, + TraceStopReason evcode) +{ + TraceEncoder *trencoder = TRACE_ENCODER(trencoder_obj); + g_autofree uint8_t *msg = g_malloc0(TRACE_MSG_MAX_SIZE); + uint32_t icnt = rv_ntrace_get_and_reset_icnt(trencoder, pc, inst_len); + uint32_t hist = rv_ntrace_encode_and_reset_branch_map(trencoder); + uint8_t msg_size; + + g_assert(trencoder->ntrace); + + msg_size = rv_ntrace_gen_encoded_prog_trace_correlation_msg(msg, evcode, + icnt, hist); + + trencoder_send_message_smem(trencoder, msg, msg_size); +} + void trencoder_trace_trap_insn(Object *trencoder_obj, uint64_t curr_pc, uint64_t target_pc, uint32_t ecause, bool is_interrupt, uint64_t tval) diff --git a/hw/riscv/trace-encoder.h b/hw/riscv/trace-encoder.h index d1ff813035..55d53c2582 100644 --- a/hw/riscv/trace-encoder.h +++ b/hw/riscv/trace-encoder.h @@ -63,12 +63,20 @@ typedef enum { BTYPE_INTERRUPT = 3, } TraceBranchType; +typedef enum { + CORRELATION_TRACE_DISABLED = 4, +} TraceStopReason; + #define TYPE_TRACE_ENCODER "trace-encoder" OBJECT_DECLARE_SIMPLE_TYPE(TraceEncoder, TRACE_ENCODER) void trencoder_set_first_trace_insn(Object *trencoder_obj, uint64_t pc); void trencoder_send_prog_trace_sync(Object *trencoder_obj, uint64_t pc); +void trencoder_send_prog_trace_correlation(Object *trencoder_obj, + uint64_t pc, + uint32_t inst_len, + TraceStopReason evcode); void trencoder_send_indirect_branch_hist(TraceEncoder *trencoder, uint64_t curr_pc, uint32_t curr_inst_len, -- 2.43.0
