static uint64_t dev_reg_read(void *opaque, hwaddr offset, unsigned size)
{
- return 0;
+ CXLDeviceState *cxl_dstate = opaque;
+
+ switch (size) {
+ case 1:
+ return cxl_dstate->dev_reg_state[offset];
+ case 2:
+ return cxl_dstate->dev_reg_state16[offset / size];
+ case 4:
+ return cxl_dstate->dev_reg_state32[offset / size];
+ case 8:
+ return cxl_dstate->dev_reg_state64[offset / size];
+ default:
+ g_assert_not_reached();
+ }
}
static uint64_t mailbox_reg_read(void *opaque, hwaddr offset, unsigned size)
&cxl_dstate->memory_device);
}
-static void device_reg_init_common(CXLDeviceState *cxl_dstate) { }
+void cxl_event_set_status(CXLDeviceState *cxl_dstate, CXLEventLogType log_type,
+ bool available)
+{
+ if (available) {
+ cxl_dstate->event_status |= (1 << log_type);
+ } else {
+ cxl_dstate->event_status &= ~(1 << log_type);
+ }
+
+ ARRAY_FIELD_DP64(cxl_dstate->dev_reg_state64, CXL_DEV_EVENT_STATUS,
+ EVENT_STATUS, cxl_dstate->event_status);
+}
+
+static void device_reg_init_common(CXLDeviceState *cxl_dstate)
+{
+ CXLEventLogType log;
+
+ for (log = 0; log < CXL_EVENT_TYPE_MAX; log++) {
+ cxl_event_set_status(cxl_dstate, log, false);
+ }
+}
static void mailbox_reg_init_common(CXLDeviceState *cxl_dstate)
{
ARRAY_FIELD_DP64(cap_hdrs, CXL_DEV_CAP_ARRAY, CAP_VERSION, 1);
ARRAY_FIELD_DP64(cap_hdrs, CXL_DEV_CAP_ARRAY, CAP_COUNT, cap_count);
- cxl_device_cap_init(cxl_dstate, DEVICE_STATUS, 1);
+ cxl_device_cap_init(cxl_dstate, DEVICE_STATUS, 1, 2);
device_reg_init_common(cxl_dstate);
- cxl_device_cap_init(cxl_dstate, MAILBOX, 2);
+ cxl_device_cap_init(cxl_dstate, MAILBOX, 2, 1);
mailbox_reg_init_common(cxl_dstate);
- cxl_device_cap_init(cxl_dstate, MEMORY_DEVICE, 0x4000);
+ cxl_device_cap_init(cxl_dstate, MEMORY_DEVICE, 0x4000, 1);
memdev_reg_init_common(cxl_dstate);
cxl_initialize_mailbox(cxl_dstate);
#include "hw/cxl/cxl_component.h"
#include "hw/pci/pci_device.h"
#include "hw/register.h"
+#include "hw/cxl/cxl_events.h"
/*
* The following is how a CXL device's Memory Device registers are laid out.
MemoryRegion device_registers;
/* mmio for device capabilities array - 8.2.8.2 */
- MemoryRegion device;
+ struct {
+ MemoryRegion device;
+ union {
+ uint8_t dev_reg_state[CXL_DEVICE_STATUS_REGISTERS_LENGTH];
+ uint16_t dev_reg_state16[CXL_DEVICE_STATUS_REGISTERS_LENGTH / 2];
+ uint32_t dev_reg_state32[CXL_DEVICE_STATUS_REGISTERS_LENGTH / 4];
+ uint64_t dev_reg_state64[CXL_DEVICE_STATUS_REGISTERS_LENGTH / 8];
+ };
+ uint64_t event_status;
+ };
MemoryRegion memory_device;
struct {
MemoryRegion caps;
FIELD(CXL_DEV_CAP_ARRAY, CAP_VERSION, 16, 8)
FIELD(CXL_DEV_CAP_ARRAY, CAP_COUNT, 32, 16)
+void cxl_event_set_status(CXLDeviceState *cxl_dstate, CXLEventLogType log_type,
+ bool available);
+
/*
* Helper macro to initialize capability headers for CXL devices.
*
void cxl_initialize_mailbox(CXLDeviceState *cxl_dstate);
void cxl_process_mailbox(CXLDeviceState *cxl_dstate);
-#define cxl_device_cap_init(dstate, reg, cap_id) \
+#define cxl_device_cap_init(dstate, reg, cap_id, ver) \
do { \
uint32_t *cap_hdrs = dstate->caps_reg_state32; \
int which = R_CXL_DEV_##reg##_CAP_HDR0; \
FIELD_DP32(cap_hdrs[which], CXL_DEV_##reg##_CAP_HDR0, \
CAP_ID, cap_id); \
cap_hdrs[which] = FIELD_DP32( \
- cap_hdrs[which], CXL_DEV_##reg##_CAP_HDR0, CAP_VERSION, 1); \
+ cap_hdrs[which], CXL_DEV_##reg##_CAP_HDR0, CAP_VERSION, ver); \
cap_hdrs[which + 1] = \
FIELD_DP32(cap_hdrs[which + 1], CXL_DEV_##reg##_CAP_HDR1, \
CAP_OFFSET, CXL_##reg##_REGISTERS_OFFSET); \
CAP_LENGTH, CXL_##reg##_REGISTERS_LENGTH); \
} while (0)
+/* CXL 3.0 8.2.8.3.1 Event Status Register */
+REG64(CXL_DEV_EVENT_STATUS, 0)
+ FIELD(CXL_DEV_EVENT_STATUS, EVENT_STATUS, 0, 32)
+
/* CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register */
REG32(CXL_DEV_MAILBOX_CAP, 0)
FIELD(CXL_DEV_MAILBOX_CAP, PAYLOAD_SIZE, 0, 5)
--- /dev/null
+/*
+ * QEMU CXL Events
+ *
+ * Copyright (c) 2022 Intel
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_EVENTS_H
+#define CXL_EVENTS_H
+
+/*
+ * CXL rev 3.0 section 8.2.9.2.2; Table 8-49
+ *
+ * Define these as the bit position for the event status register for ease of
+ * setting the status.
+ */
+typedef enum CXLEventLogType {
+ CXL_EVENT_TYPE_INFO = 0,
+ CXL_EVENT_TYPE_WARN = 1,
+ CXL_EVENT_TYPE_FAIL = 2,
+ CXL_EVENT_TYPE_FATAL = 3,
+ CXL_EVENT_TYPE_DYNAMIC_CAP = 4,
+ CXL_EVENT_TYPE_MAX
+} CXLEventLogType;
+
+#endif /* CXL_EVENTS_H */