diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 9c7ea5bc35..2315d07fb1 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -87,8 +87,9 @@ enum {
         #define GET_LSA       0x2
         #define SET_LSA       0x3
     SANITIZE    = 0x44,
-        #define OVERWRITE     0x0
-        #define SECURE_ERASE  0x1
+        #define OVERWRITE        0x0
+        #define SECURE_ERASE     0x1
+        #define MEDIA_OPERATIONS 0x2
     PERSISTENT_MEM = 0x45,
         #define GET_SECURITY_STATE     0x0
     MEDIA_AND_POISON = 0x43,
@@ -1721,6 +1722,127 @@ static CXLRetCode cmd_sanitize_overwrite(const struct cxl_cmd *cmd,
     return CXL_MBOX_BG_STARTED;
 }
 
+enum {
+    MEDIA_OP_GENERAL  = 0x0,
+    MEDIA_OP_SANITIZE = 0x1,
+    MEDIA_OP_CLASS_MAX,
+} MEDIA_OPERATION_CLASS;
+
+enum {
+    MEDIA_OP_SUB_DISCOVERY = 0x0,
+    MEDIA_OP_SUB_SANITIZE = 0x0,
+    MEDIA_OP_SUB_ZERO     = 0x1,
+    MEDIA_OP_SUB_CLASS_MAX
+} MEDIA_OPERATION_SUB_CLASS;
+
+struct media_op_supported_list_entry {
+    uint8_t media_op_class;
+    uint8_t media_op_subclass;
+};
+
+struct media_op_discovery_out_pl {
+    uint64_t dpa_range_granularity;
+    uint16_t total_supported_operations;
+    uint16_t num_of_supported_operations;
+    struct media_op_supported_list_entry entry[0];
+};
+
+#define MAX_SUPPORTED_OPS 3
+struct media_op_supported_list_entry media_op_matrix[MAX_SUPPORTED_OPS] = {
+                                                            {0, 0},
+                                                            {1, 0},
+                                                            {1, 1} };
+
+static CXLRetCode cmd_media_operations(const struct cxl_cmd *cmd,
+                                         uint8_t *payload_in,
+                                         size_t len_in,
+                                         uint8_t *payload_out,
+                                         size_t *len_out,
+                                         CXLCCI *cci)
+{
+    struct {
+    uint8_t media_operation_class;
+    uint8_t media_operation_subclass;
+    uint8_t rsvd[2];
+    uint32_t dpa_range_count;
+    union {
+        struct {
+            uint64_t starting_dpa;
+            uint64_t length;
+        } dpa_range_list[0];
+        struct {
+            uint16_t start_index;
+            uint16_t num_supported_ops;
+        } discovery_osa;
+    };
+    } QEMU_PACKED *media_op_in_pl = (void *)payload_in;
+
+    uint8_t media_op_cl = media_op_in_pl->media_operation_class;
+    uint8_t media_op_subclass = media_op_in_pl->media_operation_subclass;
+    uint32_t dpa_range_count = media_op_in_pl->dpa_range_count;
+
+    if (len_in < sizeof(*media_op_in_pl)) {
+        return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
+    }
+
+    switch (media_op_cl) {
+    case MEDIA_OP_GENERAL:
+        switch (media_op_subclass) {
+        case MEDIA_OP_SUB_DISCOVERY:
+            int count = 0;
+            struct media_op_discovery_out_pl *media_out_pl =
+                (void *)payload_out;
+            int num_ops = media_op_in_pl->discovery_osa.num_supported_ops;
+            int start_index = media_op_in_pl->discovery_osa.start_index;
+
+            /* As per spec CXL 3.1 8.2.9.9.5.3 dpa_range_count */
+            /* should be zero for discovery sub class command */
+            if (dpa_range_count) {
+                return CXL_MBOX_INVALID_INPUT;
+            }
+
+            if ((start_index >= MEDIA_OP_CLASS_MAX) ||
+                (num_ops > MAX_SUPPORTED_OPS)) {
+                return CXL_MBOX_INVALID_INPUT;
+            }
+
+            media_out_pl->dpa_range_granularity = CXL_CAPACITY_MULTIPLIER;
+            media_out_pl->total_supported_operations = MAX_SUPPORTED_OPS;
+            if (num_ops > 0) {
+                for (int i = start_index; i < MAX_SUPPORTED_OPS; i++) {
+                    media_out_pl->entry[count].media_op_class =
+                            media_op_matrix[i].media_op_class;
+                    media_out_pl->entry[count].media_op_subclass =
+                            media_op_matrix[i].media_op_subclass;
+                    count++;
+                    if (count == num_ops) {
+                        goto disc_out;
+                    }
+                }
+            }
+disc_out:
+            media_out_pl->num_of_supported_operations = count;
+            *len_out = sizeof(struct media_op_discovery_out_pl) +
+            (sizeof(struct media_op_supported_list_entry) * count);
+            break;
+        default:
+            return CXL_MBOX_UNSUPPORTED;
+        }
+        break;
+    case MEDIA_OP_SANITIZE:
+        switch (media_op_subclass) {
+
+        default:
+            return CXL_MBOX_UNSUPPORTED;
+        }
+        break;
+    default:
+        return CXL_MBOX_UNSUPPORTED;
+    }
+
+    return CXL_MBOX_SUCCESS;
+}
+
 static CXLRetCode cmd_get_security_state(const struct cxl_cmd *cmd,
                                          uint8_t *payload_in,
                                          size_t len_in,
@@ -2864,6 +2986,10 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
          CXL_MBOX_SECURITY_STATE_CHANGE |
          CXL_MBOX_BACKGROUND_OPERATION |
          CXL_MBOX_BACKGROUND_OPERATION_ABORT)},
+    [SANITIZE][MEDIA_OPERATIONS] = { "MEDIA_OPERATIONS", cmd_media_operations,
+        ~0,
+        (CXL_MBOX_IMMEDIATE_DATA_CHANGE |
+         CXL_MBOX_BACKGROUND_OPERATION)},
     [PERSISTENT_MEM][GET_SECURITY_STATE] = { "GET_SECURITY_STATE",
         cmd_get_security_state, 0, 0 },
     [MEDIA_AND_POISON][GET_POISON_LIST] = { "MEDIA_AND_POISON_GET_POISON_LIST",
