aboutsummaryrefslogtreecommitdiff
path: root/include/hw/cxl
diff options
context:
space:
mode:
Diffstat (limited to 'include/hw/cxl')
-rw-r--r--include/hw/cxl/cxl_device.h214
-rw-r--r--include/hw/cxl/cxl_events.h18
-rw-r--r--include/hw/cxl/cxl_mailbox.h19
3 files changed, 244 insertions, 7 deletions
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 279b276..ed6cd50 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -164,7 +164,7 @@ typedef struct CXLEventLog {
} CXLEventLog;
typedef struct CXLCCI {
- const struct cxl_cmd (*cxl_cmd_set)[256];
+ struct cxl_cmd cxl_cmd_set[256][256];
struct cel_log {
uint16_t opcode;
uint16_t effect;
@@ -176,16 +176,34 @@ typedef struct CXLCCI {
uint16_t opcode;
uint16_t complete_pct;
uint16_t ret_code; /* Current value of retcode */
+ bool aborted;
uint64_t starttime;
/* set by each bg cmd, cleared by the bg_timer when complete */
uint64_t runtime;
QEMUTimer *timer;
+ QemuMutex lock; /* serializes mbox abort vs timer cb */
} bg;
+
+ /* firmware update */
+ struct {
+ uint8_t active_slot;
+ uint8_t staged_slot;
+ bool slot[4];
+ uint8_t curr_action;
+ uint8_t curr_slot;
+ /* handle partial transfers */
+ bool transferring;
+ size_t prev_offset;
+ size_t prev_len;
+ time_t last_partxfer;
+ } fw;
+
size_t payload_max;
/* Pointer to device hosting the CCI */
DeviceState *d;
/* Pointer to the device hosting the protocol conversion */
DeviceState *intf;
+ bool initialized;
} CXLCCI;
typedef struct cxl_device_state {
@@ -234,7 +252,7 @@ typedef struct cxl_device_state {
} timestamp;
/* memory region size, HDM */
- uint64_t mem_size;
+ uint64_t static_mem_size;
uint64_t pmem_size;
uint64_t vmem_size;
@@ -249,8 +267,8 @@ void cxl_device_register_block_init(Object *obj, CXLDeviceState *dev,
typedef struct CXLType3Dev CXLType3Dev;
typedef struct CSWMBCCIDev CSWMBCCIDev;
/* Set up default values for the register block */
-void cxl_device_register_init_t3(CXLType3Dev *ct3d);
-void cxl_device_register_init_swcci(CSWMBCCIDev *sw);
+void cxl_device_register_init_t3(CXLType3Dev *ct3d, int msi_n);
+void cxl_device_register_init_swcci(CSWMBCCIDev *sw, int msi_n);
/*
* CXL r3.1 Section 8.2.8.1: CXL Device Capabilities Array Register
@@ -301,6 +319,9 @@ void cxl_initialize_mailbox_t3(CXLCCI *cci, DeviceState *d, size_t payload_max);
void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf,
DeviceState *d, size_t payload_max);
void cxl_init_cci(CXLCCI *cci, size_t payload_max);
+void cxl_destroy_cci(CXLCCI *cci);
+void cxl_add_cci_commands(CXLCCI *cci, const struct cxl_cmd (*cxl_cmd_set)[256],
+ size_t payload_max);
int cxl_process_cci_message(CXLCCI *cci, uint8_t set, uint8_t cmd,
size_t len_in, uint8_t *pl_in,
size_t *len_out, uint8_t *pl_out,
@@ -395,9 +416,14 @@ static inline void __toggle_media(CXLDeviceState *cxl_dstate, int val)
#define cxl_dev_enable_media(cxlds) \
do { __toggle_media((cxlds), 0x1); } while (0)
-static inline bool sanitize_running(CXLCCI *cci)
+static inline bool cxl_dev_media_disabled(CXLDeviceState *cxl_dstate)
+{
+ uint64_t dev_status_reg = cxl_dstate->mbox_reg_state64[R_CXL_MEM_DEV_STS];
+ return FIELD_EX64(dev_status_reg, CXL_MEM_DEV_STS, MEDIA_STATUS) == 0x3;
+}
+static inline bool scan_media_running(CXLCCI *cci)
{
- return !!cci->bg.runtime && cci->bg.opcode == 0x4400;
+ return !!cci->bg.runtime && cci->bg.opcode == 0x4304;
}
typedef struct CXLError {
@@ -420,6 +446,115 @@ typedef struct CXLPoison {
typedef QLIST_HEAD(, CXLPoison) CXLPoisonList;
#define CXL_POISON_LIST_LIMIT 256
+/* CXL memory device patrol scrub control attributes */
+typedef struct CXLMemPatrolScrubReadAttrs {
+ uint8_t scrub_cycle_cap;
+ uint16_t scrub_cycle;
+ uint8_t scrub_flags;
+} QEMU_PACKED CXLMemPatrolScrubReadAttrs;
+
+typedef struct CXLMemPatrolScrubWriteAttrs {
+ uint8_t scrub_cycle_hr;
+ uint8_t scrub_flags;
+} QEMU_PACKED CXLMemPatrolScrubWriteAttrs;
+
+#define CXL_MEMDEV_PS_GET_FEATURE_VERSION 0x01
+#define CXL_MEMDEV_PS_SET_FEATURE_VERSION 0x01
+#define CXL_MEMDEV_PS_SCRUB_CYCLE_CHANGE_CAP_DEFAULT BIT(0)
+#define CXL_MEMDEV_PS_SCRUB_REALTIME_REPORT_CAP_DEFAULT BIT(1)
+#define CXL_MEMDEV_PS_CUR_SCRUB_CYCLE_DEFAULT 12
+#define CXL_MEMDEV_PS_MIN_SCRUB_CYCLE_DEFAULT 1
+#define CXL_MEMDEV_PS_ENABLE_DEFAULT 0
+
+/* CXL memory device DDR5 ECS control attributes */
+#define CXL_ECS_GET_FEATURE_VERSION 0x01
+#define CXL_ECS_SET_FEATURE_VERSION 0x01
+#define CXL_ECS_LOG_ENTRY_TYPE_DEFAULT 0x01
+#define CXL_ECS_REALTIME_REPORT_CAP_DEFAULT 1
+#define CXL_ECS_THRESHOLD_COUNT_DEFAULT 3 /* 3: 256, 4: 1024, 5: 4096 */
+#define CXL_ECS_MODE_DEFAULT 0
+#define CXL_ECS_NUM_MEDIA_FRUS 3 /* Default */
+
+typedef struct CXLMemECSFRUReadAttrs {
+ uint8_t ecs_cap;
+ uint16_t ecs_config;
+ uint8_t ecs_flags;
+} QEMU_PACKED CXLMemECSFRUReadAttrs;
+
+typedef struct CXLMemECSReadAttrs {
+ uint8_t ecs_log_cap;
+ CXLMemECSFRUReadAttrs fru_attrs[CXL_ECS_NUM_MEDIA_FRUS];
+} QEMU_PACKED CXLMemECSReadAttrs;
+
+typedef struct CXLMemECSFRUWriteAttrs {
+ uint16_t ecs_config;
+} QEMU_PACKED CXLMemECSFRUWriteAttrs;
+
+typedef struct CXLMemECSWriteAttrs {
+ uint8_t ecs_log_cap;
+ CXLMemECSFRUWriteAttrs fru_attrs[CXL_ECS_NUM_MEDIA_FRUS];
+} QEMU_PACKED CXLMemECSWriteAttrs;
+
+#define DCD_MAX_NUM_REGION 8
+
+typedef struct CXLDCExtentRaw {
+ uint64_t start_dpa;
+ uint64_t len;
+ uint8_t tag[0x10];
+ uint16_t shared_seq;
+ uint8_t rsvd[0x6];
+} QEMU_PACKED CXLDCExtentRaw;
+
+typedef struct CXLDCExtent {
+ uint64_t start_dpa;
+ uint64_t len;
+ uint8_t tag[0x10];
+ uint16_t shared_seq;
+ uint8_t rsvd[0x6];
+
+ QTAILQ_ENTRY(CXLDCExtent) node;
+} CXLDCExtent;
+typedef QTAILQ_HEAD(, CXLDCExtent) CXLDCExtentList;
+
+typedef struct CXLDCExtentGroup {
+ CXLDCExtentList list;
+ QTAILQ_ENTRY(CXLDCExtentGroup) node;
+} CXLDCExtentGroup;
+typedef QTAILQ_HEAD(, CXLDCExtentGroup) CXLDCExtentGroupList;
+
+typedef struct CXLDCRegion {
+ uint64_t base; /* aligned to 256*MiB */
+ uint64_t decode_len; /* aligned to 256*MiB */
+ uint64_t len;
+ uint64_t block_size;
+ uint32_t dsmadhandle;
+ uint8_t flags;
+ unsigned long *blk_bitmap;
+} CXLDCRegion;
+
+typedef struct CXLSetFeatureInfo {
+ QemuUUID uuid;
+ uint8_t data_transfer_flag;
+ bool data_saved_across_reset;
+ uint16_t data_offset;
+ size_t data_size;
+} CXLSetFeatureInfo;
+
+struct CXLSanitizeInfo;
+
+typedef struct CXLAlertConfig {
+ uint8_t valid_alerts;
+ uint8_t enable_alerts;
+ uint8_t life_used_crit_alert_thresh;
+ uint8_t life_used_warn_thresh;
+ uint16_t over_temp_crit_alert_thresh;
+ uint16_t under_temp_crit_alert_thresh;
+ uint16_t over_temp_warn_thresh;
+ uint16_t under_temp_warn_thresh;
+ uint16_t cor_vmem_err_warn_thresh;
+ uint16_t cor_pmem_err_warn_thresh;
+} QEMU_PACKED CXLAlertConfig;
+
struct CXLType3Dev {
/* Private */
PCIDevice parent_obj;
@@ -441,6 +576,12 @@ struct CXLType3Dev {
CXLCCI vdm_fm_owned_ld_mctp_cci;
CXLCCI ld0_cci;
+ CXLAlertConfig alert_config;
+
+ /* PCIe link characteristics */
+ PCIExpLinkSpeed speed;
+ PCIExpLinkWidth width;
+
/* DOE */
DOECap doe_cdat;
@@ -452,6 +593,38 @@ struct CXLType3Dev {
unsigned int poison_list_cnt;
bool poison_list_overflowed;
uint64_t poison_list_overflow_ts;
+ /* Poison Injection - backup */
+ CXLPoisonList poison_list_bkp;
+ CXLPoisonList scan_media_results;
+ bool scan_media_hasrun;
+
+ CXLSetFeatureInfo set_feat_info;
+
+ /* Patrol scrub control attributes */
+ CXLMemPatrolScrubReadAttrs patrol_scrub_attrs;
+ CXLMemPatrolScrubWriteAttrs patrol_scrub_wr_attrs;
+ /* ECS control attributes */
+ CXLMemECSReadAttrs ecs_attrs;
+ CXLMemECSWriteAttrs ecs_wr_attrs;
+
+ struct dynamic_capacity {
+ HostMemoryBackend *host_dc;
+ AddressSpace host_dc_as;
+ /*
+ * total_capacity is equivalent to the dynamic capability
+ * memory region size.
+ */
+ uint64_t total_capacity; /* 256M aligned */
+ CXLDCExtentList extents;
+ CXLDCExtentGroupList extents_pending;
+ uint32_t total_extent_count;
+ uint32_t ext_list_gen_seq;
+
+ uint8_t num_regions; /* 0-8 regions */
+ CXLDCRegion regions[DCD_MAX_NUM_REGION];
+ } dc;
+
+ struct CXLSanitizeInfo *media_op_sanitize;
};
#define TYPE_CXL_TYPE3 "cxl-type3"
@@ -498,9 +671,36 @@ CXLRetCode cxl_event_get_records(CXLDeviceState *cxlds, CXLGetEventPayload *pl,
size_t *len);
CXLRetCode cxl_event_clear_records(CXLDeviceState *cxlds,
CXLClearEventPayload *pl);
+void cxl_discard_all_event_records(CXLDeviceState *cxlds);
void cxl_event_irq_assert(CXLType3Dev *ct3d);
void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d);
-
+void cxl_clear_poison_list_overflowed(CXLType3Dev *ct3d);
+
+CXLDCRegion *cxl_find_dc_region(CXLType3Dev *ct3d, uint64_t dpa, uint64_t len);
+
+void cxl_remove_extent_from_extent_list(CXLDCExtentList *list,
+ CXLDCExtent *extent);
+void cxl_insert_extent_to_extent_list(CXLDCExtentList *list, uint64_t dpa,
+ uint64_t len, uint8_t *tag,
+ uint16_t shared_seq);
+bool test_any_bits_set(const unsigned long *addr, unsigned long nr,
+ unsigned long size);
+bool cxl_extents_contains_dpa_range(CXLDCExtentList *list,
+ uint64_t dpa, uint64_t len);
+CXLDCExtentGroup *cxl_insert_extent_to_extent_group(CXLDCExtentGroup *group,
+ uint64_t dpa,
+ uint64_t len,
+ uint8_t *tag,
+ uint16_t shared_seq);
+void cxl_extent_group_list_insert_tail(CXLDCExtentGroupList *list,
+ CXLDCExtentGroup *group);
+void cxl_extent_group_list_delete_front(CXLDCExtentGroupList *list);
+void ct3_set_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
+ uint64_t len);
+void ct3_clear_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
+ uint64_t len);
+bool ct3_test_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
+ uint64_t len);
#endif
diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h
index 5170b8d..38cadaa 100644
--- a/include/hw/cxl/cxl_events.h
+++ b/include/hw/cxl/cxl_events.h
@@ -166,4 +166,22 @@ typedef struct CXLEventMemoryModule {
uint8_t reserved[0x3d];
} QEMU_PACKED CXLEventMemoryModule;
+/*
+ * CXL r3.1 section Table 8-50: Dynamic Capacity Event Record
+ * All fields little endian.
+ */
+typedef struct CXLEventDynamicCapacity {
+ CXLEventRecordHdr hdr;
+ uint8_t type;
+ uint8_t validity_flags;
+ uint16_t host_id;
+ uint8_t updated_region_id;
+ uint8_t flags;
+ uint8_t reserved2[2];
+ uint8_t dynamic_capacity_extent[0x28]; /* defined in cxl_device.h */
+ uint8_t reserved[0x18];
+ uint32_t extents_avail;
+ uint32_t tags_avail;
+} QEMU_PACKED CXLEventDynamicCapacity;
+
#endif /* CXL_EVENTS_H */
diff --git a/include/hw/cxl/cxl_mailbox.h b/include/hw/cxl/cxl_mailbox.h
new file mode 100644
index 0000000..9008402
--- /dev/null
+++ b/include/hw/cxl/cxl_mailbox.h
@@ -0,0 +1,19 @@
+/*
+ * QEMU CXL Mailbox
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_MAILBOX_H
+#define CXL_MAILBOX_H
+
+#define CXL_MBOX_IMMEDIATE_CONFIG_CHANGE (1 << 1)
+#define CXL_MBOX_IMMEDIATE_DATA_CHANGE (1 << 2)
+#define CXL_MBOX_IMMEDIATE_POLICY_CHANGE (1 << 3)
+#define CXL_MBOX_IMMEDIATE_LOG_CHANGE (1 << 4)
+#define CXL_MBOX_SECURITY_STATE_CHANGE (1 << 5)
+#define CXL_MBOX_BACKGROUND_OPERATION (1 << 6)
+#define CXL_MBOX_BACKGROUND_OPERATION_ABORT (1 << 7)
+
+#endif