[PATCH 09/13] hw/riscv: add n-trace ProgTraceCorrelation rv-trace-message

Konstantin Semichastnov <[email protected]>
Newsgroups org.nongnu.qemu-riscv,org.nongnu.qemu-devel
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.