Add trace events for HDM decoder programming in the CXL Type-3 device
model. These paths control address-decode behaviour and are among the
most frequently debugged during CXL topology bring-up.
Three trace points are added:
cxl_hdm_decoder_write - guest write to a decoder CTRL register,
with the raw value and commit flag
cxl_hdm_decoder_commit - actual commit with decoded base, size,
interleave ways (IW) and granularity (IG)
cxl_hdm_decoder_uncommit - decoder uncommit with index
Base and size are extracted using the same split-register pattern
(ldl_le_p + 0xf0000000 mask) used by cxl_hdm_find_target() in
cxl-host.c, producing architecturally-meaningful addresses. IW and
IG are extracted from CTRL via FIELD_EX32.
Signed-off-by: Junjie Cao <[email protected]>
---
hw/mem/cxl_type3.c | 19 ++++++++++++++++++-
hw/mem/trace-events | 5 +++++
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 4739239da3..c3f7483b70 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -30,6 +30,7 @@
#include "system/numa.h"
#include "hw/cxl/cxl.h"
#include "hw/pci/msix.h"
+#include "trace.h"
/* type3 device private */
enum CXL_T3_MSIX_VECTOR {
@@ -419,13 +420,24 @@ static void hdm_decoder_commit(CXLType3Dev *ct3d, int
which)
int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
ComponentRegisters *cregs = &ct3d->cxl_cstate.crb;
uint32_t *cache_mem = cregs->cache_mem_registers;
- uint32_t ctrl;
+ uint32_t ctrl, low, high;
+ uint64_t base, size;
ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * hdm_inc);
/* TODO: Sanity checks that the decoder is possible */
ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
+ low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + which * hdm_inc);
+ high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + which * hdm_inc);
+ base = (low & 0xf0000000) | ((uint64_t)high << 32);
+ low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + which * hdm_inc);
+ high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + which * hdm_inc);
+ size = (low & 0xf0000000) | ((uint64_t)high << 32);
+ trace_cxl_hdm_decoder_commit(which, base, size,
+ FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW),
+ FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG));
+
stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * hdm_inc, ctrl);
}
@@ -436,6 +448,8 @@ static void hdm_decoder_uncommit(CXLType3Dev *ct3d, int
which)
uint32_t *cache_mem = cregs->cache_mem_registers;
uint32_t ctrl;
+ trace_cxl_hdm_decoder_uncommit(which);
+
ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * hdm_inc);
ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
@@ -623,6 +637,9 @@ static void ct3d_reg_write(void *opaque, hwaddr offset,
uint64_t value,
}
stl_le_p((uint8_t *)cache_mem + offset, value);
+ if (which_hdm >= 0) {
+ trace_cxl_hdm_decoder_write(which_hdm, value, should_commit);
+ }
if (should_commit) {
hdm_decoder_commit(ct3d, which_hdm);
} else if (should_uncommit) {
diff --git a/hw/mem/trace-events b/hw/mem/trace-events
index 8b6b02b5bf..07c7315148 100644
--- a/hw/mem/trace-events
+++ b/hw/mem/trace-events
@@ -6,3 +6,8 @@ mhp_pc_dimm_assigned_slot(int slot) "%d"
memory_device_pre_plug(const char *id, uint64_t addr) "id=%s addr=0x%"PRIx64
memory_device_plug(const char *id, uint64_t addr) "id=%s addr=0x%"PRIx64
memory_device_unplug(const char *id, uint64_t addr) "id=%s addr=0x%"PRIx64
+
+# cxl_type3.c
+cxl_hdm_decoder_write(int which, uint32_t value, bool commit) "decoder=%d
ctrl=0x%08x commit=%d"
+cxl_hdm_decoder_commit(int which, uint64_t base, uint64_t size, int iw, int
ig) "decoder=%d base=0x%"PRIx64" size=0x%"PRIx64" iw=%d ig=%d"
+cxl_hdm_decoder_uncommit(int which) "decoder=%d"
--
2.43.0