hw/cxl/events: Add event status register

The device status register block was defined.  However, there were no
individual registers nor any data wired up.

Define the event status register [CXL 3.0; 8.2.8.3.1] as part of the
device status register block.  Wire up the register and initialize the
event status for each log.

To support CXL 3.0 the version of the device status register block needs
to be 2.  Change the macro to allow for setting the version.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Fan Ni <fan.ni@samsung.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20230530133603.16934-2-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Ira Weiny 2023-05-30 14:35:57 +01:00 committed by Michael S. Tsirkin
parent 6bda41a69b
commit d7b84ddc3b
3 changed files with 86 additions and 8 deletions

View File

@ -41,7 +41,20 @@ static uint64_t caps_reg_read(void *opaque, hwaddr offset, unsigned size)
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)
@ -236,7 +249,27 @@ void cxl_device_register_block_init(Object *obj, CXLDeviceState *cxl_dstate)
&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)
{
@ -258,13 +291,13 @@ void cxl_device_register_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);

View File

@ -13,6 +13,7 @@
#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.
@ -86,7 +87,16 @@ typedef struct cxl_device_state {
MemoryRegion device_registers;
/* mmio for device capabilities array - 8.2.8.2 */
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;
@ -141,6 +151,9 @@ REG64(CXL_DEV_CAP_ARRAY, 0) /* Documented as 128 bit register but 64 byte access
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.
*
@ -175,7 +188,7 @@ CXL_DEVICE_CAPABILITY_HEADER_REGISTER(MEMORY_DEVICE,
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; \
@ -183,7 +196,7 @@ void cxl_process_mailbox(CXLDeviceState *cxl_dstate);
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); \
@ -192,6 +205,10 @@ void cxl_process_mailbox(CXLDeviceState *cxl_dstate);
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)

View File

@ -0,0 +1,28 @@
/*
* 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 */