Add trace events for CXL mailbox command processing: command entry,
handler completion, and all payload-length validation failures.

Three trace points are added:

  cxl_mailbox_cmd           - command entry with set, cmd, name, len_in
  cxl_mailbox_cmd_done      - handler return with ret code and len_out
  cxl_mailbox_payload_error - payload length mismatch (all 21 sites)

To make set/cmd accessible inside individual command handlers (which
do not receive them as parameters), add a current_opcode field to
CXLCCI that is set before handler dispatch.  This mirrors the existing
cci->bg.opcode pattern used for background operations.

The payload_error event covers not only the centralised entry check in
cxl_process_cci_message() but also every handler-internal return of
CXL_MBOX_INVALID_PAYLOAD_LENGTH, including variable-length command
validators in tunnelling, DCD, firmware update, set-feature, media
operations, and physical-port commands.

As a minor cleanup, add a CXLCCI *cci parameter to
media_operations_discovery() so it can access current_opcode.  This
aligns it with media_operations_sanitize() which already receives cci.

Signed-off-by: Junjie Cao <[email protected]>
---
 hw/cxl/cxl-mailbox-utils.c  | 71 +++++++++++++++++++++++++++++++++++--
 hw/cxl/trace-events         |  5 +++
 include/hw/cxl/cxl_device.h |  1 +
 3 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index d8ba7e8625..10af11dc1f 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -27,6 +27,7 @@
 #include "system/hostmem.h"
 #include "qemu/range.h"
 #include "qapi/qapi-types-cxl.h"
+#include "trace.h"
 
 #define CXL_CAPACITY_MULTIPLIER   (256 * MiB)
 #define CXL_DC_EVENT_LOG_SIZE 8
@@ -179,14 +180,23 @@ static CXLRetCode cmd_tunnel_management_cmd(const struct 
cxl_cmd *cmd,
     out = (void *)payload_out;
 
     if (len_in < sizeof(*in)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
     /* Enough room for minimum sized message - no payload */
     if (in->size < sizeof(in->ccimessage)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
     /* Length of input payload should be in->size + a wrapping tunnel header */
     if (in->size != len_in - offsetof(typeof(*out), ccimessage)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
     if (in->ccimessage.category != CXL_CCI_CAT_REQ) {
@@ -299,6 +309,9 @@ static CXLRetCode cmd_events_clear_records(const struct 
cxl_cmd *cmd,
 
     if (len_in < sizeof(*pl) ||
         len_in < sizeof(*pl) + sizeof(*pl->handle) * pl->nr_recs) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -361,6 +374,9 @@ static CXLRetCode cmd_events_set_interrupt_policy(const 
struct cxl_cmd *cmd,
     CXLEventLog *log;
 
     if (len_in < CXL_EVENT_INT_SETTING_MIN_LEN) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -604,6 +620,9 @@ static CXLRetCode cmd_get_physical_port_state(const struct 
cxl_cmd *cmd,
     out = (struct cxl_fmapi_get_phys_port_state_resp_pl *)payload_out;
 
     if (len_in < sizeof(*in)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
     /* Check if what was requested can fit */
@@ -782,6 +801,9 @@ static CXLRetCode cmd_physical_port_control(const struct 
cxl_cmd *cmd,
     } QEMU_PACKED *in = (void *)payload_in;
 
     if (len_in < sizeof(*in)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -961,6 +983,9 @@ static CXLRetCode cmd_firmware_update_transfer(const struct 
cxl_cmd *cmd,
     size_t offset, length;
 
     if (len < sizeof(*fw_transfer)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -1718,6 +1743,9 @@ static CXLRetCode cmd_features_set_feature(const struct 
cxl_cmd *cmd,
     uint16_t count;
 
     if (len_in < sizeof(*hdr)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -1748,6 +1776,9 @@ static CXLRetCode cmd_features_set_feature(const struct 
cxl_cmd *cmd,
     bytes_to_copy = len_in - sizeof(CXLSetFeatureInHeader);
 
     if (bytes_to_copy == 0) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -1762,6 +1793,9 @@ static CXLRetCode cmd_features_set_feature(const struct 
cxl_cmd *cmd,
 
         if ((uint32_t)hdr->offset + bytes_to_copy >
             sizeof(ct3d->patrol_scrub_wr_attrs)) {
+            trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                            cci->current_opcode & 0xff,
+                                            cmd->name, len_in);
             return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
         }
         memcpy((uint8_t *)&ct3d->patrol_scrub_wr_attrs + hdr->offset,
@@ -1789,6 +1823,9 @@ static CXLRetCode cmd_features_set_feature(const struct 
cxl_cmd *cmd,
 
         if ((uint32_t)hdr->offset + bytes_to_copy >
             sizeof(ct3d->ecs_wr_attrs)) {
+            trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                            cci->current_opcode & 0xff,
+                                            cmd->name, len_in);
             return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
         }
         memcpy((uint8_t *)&ct3d->ecs_wr_attrs + hdr->offset,
@@ -2294,6 +2331,9 @@ static CXLRetCode cmd_ccls_set_lsa(const struct cxl_cmd 
*cmd,
 
     *len_out = 0;
     if (len_in < hdr_len) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -2661,7 +2701,8 @@ static const struct media_op_supported_list_entry 
media_op_matrix[] = {
 static CXLRetCode media_operations_discovery(uint8_t *payload_in,
                                              size_t len_in,
                                              uint8_t *payload_out,
-                                             size_t *len_out)
+                                             size_t *len_out,
+                                             CXLCCI *cci)
 {
     struct {
         uint8_t media_operation_class;
@@ -2680,6 +2721,9 @@ static CXLRetCode media_operations_discovery(uint8_t 
*payload_in,
     int count = 0;
 
     if (len_in < sizeof(*media_op_in_disc_pl)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        "MEDIA_OPERATIONS", len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -2741,6 +2785,9 @@ static CXLRetCode media_operations_sanitize(CXLType3Dev 
*ct3d,
 
     dpa_range_list_size = dpa_range_count * sizeof(struct 
dpa_range_list_entry);
     if (len_in < (sizeof(*media_op_in_sanitize_pl) + dpa_range_list_size)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        "MEDIA_OPERATIONS", len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -2792,6 +2839,9 @@ static CXLRetCode cmd_media_operations(const struct 
cxl_cmd *cmd,
     uint8_t media_op_subclass = 0;
 
     if (len_in < sizeof(*media_op_in_common_pl)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -2805,7 +2855,7 @@ static CXLRetCode cmd_media_operations(const struct 
cxl_cmd *cmd,
         }
 
         return media_operations_discovery(payload_in, len_in, payload_out,
-                                             len_out);
+                                             len_out, cci);
     case MEDIA_OP_CLASS_SANITIZE:
         switch (media_op_subclass) {
         case MEDIA_OP_SAN_SUBC_SANITIZE:
@@ -3712,6 +3762,9 @@ static CXLRetCode cmd_dcd_add_dyn_cap_rsp(const struct 
cxl_cmd *cmd,
     CXLRetCode ret;
 
     if (len_in < sizeof(*in)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -3723,6 +3776,9 @@ static CXLRetCode cmd_dcd_add_dyn_cap_rsp(const struct 
cxl_cmd *cmd,
 
     if (len_in <
         sizeof(*in) + sizeof(*in->updated_entries) * in->num_entries_updated) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -3883,6 +3939,9 @@ static CXLRetCode cmd_dcd_release_dyn_cap(const struct 
cxl_cmd *cmd,
     CXLRetCode ret;
 
     if (len_in < sizeof(*in)) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -3892,6 +3951,9 @@ static CXLRetCode cmd_dcd_release_dyn_cap(const struct 
cxl_cmd *cmd,
 
     if (len_in <
         sizeof(*in) + sizeof(*in->updated_entries) * in->num_entries_updated) {
+        trace_cxl_mailbox_payload_error(cci->current_opcode >> 8,
+                                        cci->current_opcode & 0xff,
+                                        cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -4588,7 +4650,11 @@ int cxl_process_cci_message(CXLCCI *cci, uint8_t set, 
uint8_t cmd,
         return CXL_MBOX_UNSUPPORTED;
     }
 
+    cci->current_opcode = (set << 8) | cmd;
+    trace_cxl_mailbox_cmd(set, cmd, cxl_cmd->name, len_in);
+
     if (len_in != cxl_cmd->in && cxl_cmd->in != ~0) {
+        trace_cxl_mailbox_payload_error(set, cmd, cxl_cmd->name, len_in);
         return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
     }
 
@@ -4620,6 +4686,7 @@ int cxl_process_cci_message(CXLCCI *cci, uint8_t set, 
uint8_t cmd,
     }
 
     ret = (*h)(cxl_cmd, pl_in, len_in, pl_out, len_out, cci);
+    trace_cxl_mailbox_cmd_done(set, cmd, ret, *len_out);
     if ((cxl_cmd->effect & CXL_MBOX_BACKGROUND_OPERATION) &&
         ret == CXL_MBOX_BG_STARTED) {
         *bg_started = true;
diff --git a/hw/cxl/trace-events b/hw/cxl/trace-events
index 23bc9b19b9..609def2dec 100644
--- a/hw/cxl/trace-events
+++ b/hw/cxl/trace-events
@@ -1 +1,6 @@
 # See docs/devel/tracing.rst for syntax documentation.
+
+# cxl-mailbox-utils.c
+cxl_mailbox_cmd(uint8_t set, uint8_t cmd, const char *name, size_t len_in) 
"set=0x%02x cmd=0x%02x [%s] len_in=%zu"
+cxl_mailbox_cmd_done(uint8_t set, uint8_t cmd, int ret, size_t len_out) 
"set=0x%02x cmd=0x%02x ret=%d len_out=%zu"
+cxl_mailbox_payload_error(uint8_t set, uint8_t cmd, const char *name, size_t 
len_in) "set=0x%02x cmd=0x%02x [%s] len_in=%zu"
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 393f312217..3237d59ab2 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -207,6 +207,7 @@ typedef struct CXLCCI {
         time_t last_partxfer;
     } fw;
 
+    uint16_t current_opcode;
     size_t payload_max;
     /* Pointer to device hosting the CCI */
     DeviceState *d;
-- 
2.43.0


Reply via email to