/* * 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 #include "qemu/uuid.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; /* * Common Event Record Format * CXL rev 3.0 section 8.2.9.2.1; Table 8-42 */ #define CXL_EVENT_REC_HDR_RES_LEN 0xf typedef struct CXLEventRecordHdr { QemuUUID id; uint8_t length; uint8_t flags[3]; uint16_t handle; uint16_t related_handle; uint64_t timestamp; uint8_t maint_op_class; uint8_t reserved[CXL_EVENT_REC_HDR_RES_LEN]; } QEMU_PACKED CXLEventRecordHdr; #define CXL_EVENT_RECORD_DATA_LENGTH 0x50 typedef struct CXLEventRecordRaw { CXLEventRecordHdr hdr; uint8_t data[CXL_EVENT_RECORD_DATA_LENGTH]; } QEMU_PACKED CXLEventRecordRaw; #define CXL_EVENT_RECORD_SIZE (sizeof(CXLEventRecordRaw)) /* * Get Event Records output payload * CXL rev 3.0 section 8.2.9.2.2; Table 8-50 */ #define CXL_GET_EVENT_FLAG_OVERFLOW BIT(0) #define CXL_GET_EVENT_FLAG_MORE_RECORDS BIT(1) typedef struct CXLGetEventPayload { uint8_t flags; uint8_t reserved1; uint16_t overflow_err_count; uint64_t first_overflow_timestamp; uint64_t last_overflow_timestamp; uint16_t record_count; uint8_t reserved2[0xa]; CXLEventRecordRaw records[]; } QEMU_PACKED CXLGetEventPayload; #define CXL_EVENT_PAYLOAD_HDR_SIZE (sizeof(CXLGetEventPayload)) /* * Clear Event Records input payload * CXL rev 3.0 section 8.2.9.2.3; Table 8-51 */ typedef struct CXLClearEventPayload { uint8_t event_log; /* CXLEventLogType */ uint8_t clear_flags; uint8_t nr_recs; uint8_t reserved[3]; uint16_t handle[]; } CXLClearEventPayload; /** * Event Interrupt Policy * * CXL rev 3.0 section 8.2.9.2.4; Table 8-52 */ typedef enum CXLEventIntMode { CXL_INT_NONE = 0x00, CXL_INT_MSI_MSIX = 0x01, CXL_INT_FW = 0x02, CXL_INT_RES = 0x03, } CXLEventIntMode; #define CXL_EVENT_INT_MODE_MASK 0x3 #define CXL_EVENT_INT_SETTING(vector) ((((uint8_t)vector & 0xf) << 4) | CXL_INT_MSI_MSIX) typedef struct CXLEventInterruptPolicy { uint8_t info_settings; uint8_t warn_settings; uint8_t failure_settings; uint8_t fatal_settings; uint8_t dyn_cap_settings; } QEMU_PACKED CXLEventInterruptPolicy; /* DCD is optional but other fields are not */ #define CXL_EVENT_INT_SETTING_MIN_LEN 4 /* * General Media Event Record * CXL rev 3.0 Section 8.2.9.2.1.1; Table 8-43 */ #define CXL_EVENT_GEN_MED_COMP_ID_SIZE 0x10 #define CXL_EVENT_GEN_MED_RES_SIZE 0x2e typedef struct CXLEventGenMedia { CXLEventRecordHdr hdr; uint64_t phys_addr; uint8_t descriptor; uint8_t type; uint8_t transaction_type; uint16_t validity_flags; uint8_t channel; uint8_t rank; uint8_t device[3]; uint8_t component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE]; uint8_t reserved[CXL_EVENT_GEN_MED_RES_SIZE]; } QEMU_PACKED CXLEventGenMedia; /* * DRAM Event Record * CXL Rev 3.0 Section 8.2.9.2.1.2: Table 8-44 * All fields little endian. */ typedef struct CXLEventDram { CXLEventRecordHdr hdr; uint64_t phys_addr; uint8_t descriptor; uint8_t type; uint8_t transaction_type; uint16_t validity_flags; uint8_t channel; uint8_t rank; uint8_t nibble_mask[3]; uint8_t bank_group; uint8_t bank; uint8_t row[3]; uint16_t column; uint64_t correction_mask[4]; uint8_t reserved[0x17]; } QEMU_PACKED CXLEventDram; /* * Memory Module Event Record * CXL Rev 3.0 Section 8.2.9.2.1.3: Table 8-45 * All fields little endian. */ typedef struct CXLEventMemoryModule { CXLEventRecordHdr hdr; uint8_t type; uint8_t health_status; uint8_t media_status; uint8_t additional_status; uint8_t life_used; int16_t temperature; uint32_t dirty_shutdown_count; uint32_t corrected_volatile_error_count; uint32_t corrected_persistent_error_count; uint8_t reserved[0x3d]; } QEMU_PACKED CXLEventMemoryModule; #endif /* CXL_EVENTS_H */