|
@@ -47,6 +47,9 @@ enum {
|
|
|
TIMESTAMP = 0x03,
|
|
|
#define GET 0x0
|
|
|
#define SET 0x1
|
|
|
+ LOGS = 0x04,
|
|
|
+ #define GET_SUPPORTED 0x0
|
|
|
+ #define GET_LOG 0x1
|
|
|
};
|
|
|
|
|
|
/* 8.2.8.4.5.1 Command Return Codes */
|
|
@@ -147,6 +150,70 @@ static ret_code cmd_timestamp_set(struct cxl_cmd *cmd,
|
|
|
|
|
|
static QemuUUID cel_uuid;
|
|
|
|
|
|
+/* 8.2.9.4.1 */
|
|
|
+static ret_code cmd_logs_get_supported(struct cxl_cmd *cmd,
|
|
|
+ CXLDeviceState *cxl_dstate,
|
|
|
+ uint16_t *len)
|
|
|
+{
|
|
|
+ struct {
|
|
|
+ uint16_t entries;
|
|
|
+ uint8_t rsvd[6];
|
|
|
+ struct {
|
|
|
+ QemuUUID uuid;
|
|
|
+ uint32_t size;
|
|
|
+ } log_entries[1];
|
|
|
+ } QEMU_PACKED *supported_logs = (void *)cmd->payload;
|
|
|
+ QEMU_BUILD_BUG_ON(sizeof(*supported_logs) != 0x1c);
|
|
|
+
|
|
|
+ supported_logs->entries = 1;
|
|
|
+ supported_logs->log_entries[0].uuid = cel_uuid;
|
|
|
+ supported_logs->log_entries[0].size = 4 * cxl_dstate->cel_size;
|
|
|
+
|
|
|
+ *len = sizeof(*supported_logs);
|
|
|
+ return CXL_MBOX_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/* 8.2.9.4.2 */
|
|
|
+static ret_code cmd_logs_get_log(struct cxl_cmd *cmd,
|
|
|
+ CXLDeviceState *cxl_dstate,
|
|
|
+ uint16_t *len)
|
|
|
+{
|
|
|
+ struct {
|
|
|
+ QemuUUID uuid;
|
|
|
+ uint32_t offset;
|
|
|
+ uint32_t length;
|
|
|
+ } QEMU_PACKED QEMU_ALIGNED(16) *get_log = (void *)cmd->payload;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 8.2.9.4.2
|
|
|
+ * The device shall return Invalid Parameter if the Offset or Length
|
|
|
+ * fields attempt to access beyond the size of the log as reported by Get
|
|
|
+ * Supported Logs.
|
|
|
+ *
|
|
|
+ * XXX: Spec is wrong, "Invalid Parameter" isn't a thing.
|
|
|
+ * XXX: Spec doesn't address incorrect UUID incorrectness.
|
|
|
+ *
|
|
|
+ * The CEL buffer is large enough to fit all commands in the emulation, so
|
|
|
+ * the only possible failure would be if the mailbox itself isn't big
|
|
|
+ * enough.
|
|
|
+ */
|
|
|
+ if (get_log->offset + get_log->length > cxl_dstate->payload_size) {
|
|
|
+ return CXL_MBOX_INVALID_INPUT;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!qemu_uuid_is_equal(&get_log->uuid, &cel_uuid)) {
|
|
|
+ return CXL_MBOX_UNSUPPORTED;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Store off everything to local variables so we can wipe out the payload */
|
|
|
+ *len = get_log->length;
|
|
|
+
|
|
|
+ memmove(cmd->payload, cxl_dstate->cel_log + get_log->offset,
|
|
|
+ get_log->length);
|
|
|
+
|
|
|
+ return CXL_MBOX_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
#define IMMEDIATE_CONFIG_CHANGE (1 << 1)
|
|
|
#define IMMEDIATE_POLICY_CHANGE (1 << 3)
|
|
|
#define IMMEDIATE_LOG_CHANGE (1 << 4)
|
|
@@ -162,6 +229,8 @@ static struct cxl_cmd cxl_cmd_set[256][256] = {
|
|
|
cmd_events_set_interrupt_policy, 4, IMMEDIATE_CONFIG_CHANGE },
|
|
|
[TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },
|
|
|
[TIMESTAMP][SET] = { "TIMESTAMP_SET", cmd_timestamp_set, 8, IMMEDIATE_POLICY_CHANGE },
|
|
|
+ [LOGS][GET_SUPPORTED] = { "LOGS_GET_SUPPORTED", cmd_logs_get_supported, 0, 0 },
|
|
|
+ [LOGS][GET_LOG] = { "LOGS_GET_LOG", cmd_logs_get_log, 0x18, 0 },
|
|
|
};
|
|
|
|
|
|
void cxl_process_mailbox(CXLDeviceState *cxl_dstate)
|