@@ -1266,6 +1266,20 @@ SRST
Inject PCIe AER error
ERST
+ {
+ .name = "cxl_event_inject",
+ .args_type = "id:s",
+ .params = "id <error_status>",
+ .help = "inject cxl events and interrupt\n\t\t\t"
+ "<id> = qdev device id\n\t\t\t",
+ .cmd = hmp_cxl_event_inject,
+ },
+
+SRST
+``cxl_event_inject``
+ Inject CXL Events
+ERST
+
{
.name = "netdev_add",
.args_type = "netdev:O",
@@ -10,8 +10,14 @@
#include <stdint.h>
#include "qemu/osdep.h"
+#include "sysemu/sysemu.h"
+#include "monitor/monitor.h"
#include "qemu/bswap.h"
#include "qemu/typedefs.h"
+#include "qapi/qmp/qdict.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
#include "hw/cxl/cxl.h"
#include "hw/cxl/cxl_events.h"
@@ -68,6 +74,11 @@ uint16_t log_overflow(struct cxl_event_log *log)
return cnt;
}
+static void reset_log(struct cxl_event_log *log)
+{
+ log->cur_event = 0;
+}
+
#define CXL_EVENT_RECORD_FLAG_PERMANENT BIT(2)
#define CXL_EVENT_RECORD_FLAG_MAINT_NEEDED BIT(3)
#define CXL_EVENT_RECORD_FLAG_PERF_DEGRADED BIT(4)
@@ -246,3 +257,74 @@ void cxl_mock_add_event_logs(CXLDeviceState *cxlds)
event_store_add_event(cxlds, CXL_EVENT_TYPE_FATAL,
(struct cxl_event_record_raw *)&dram);
}
+
+static void cxl_reset_all_logs(CXLDeviceState *cxlds)
+{
+ int i;
+
+ for (i = 0; i < CXL_EVENT_TYPE_MAX; i++) {
+ struct cxl_event_log *log = find_event_log(cxlds, i);
+
+ if (!log) {
+ continue;
+ }
+
+ reset_log(log);
+ }
+}
+
+static void cxl_event_irq_assert(PCIDevice *pdev)
+{
+ CXLType3Dev *ct3d = container_of(pdev, struct CXLType3Dev, parent_obj);
+ CXLDeviceState *cxlds = &ct3d->cxl_dstate;
+ int i;
+
+ for (i = 0; i < CXL_EVENT_TYPE_MAX; i++) {
+ struct cxl_event_log *log;
+
+ log = find_event_log(cxlds, i);
+ if (!log || !log->irq_enabled || log_empty(log)) {
+ continue;
+ }
+
+ /* Notifies interrupt, legacy IRQ is not supported */
+ if (msix_enabled(pdev)) {
+ msix_notify(pdev, log->irq_vec);
+ } else if (msi_enabled(pdev)) {
+ msi_notify(pdev, log->irq_vec);
+ }
+ }
+}
+
+static int do_cxl_event_inject(Monitor *mon, const QDict *qdict)
+{
+ const char *id = qdict_get_str(qdict, "id");
+ CXLType3Dev *ct3d;
+ PCIDevice *pdev;
+ int ret;
+
+ ret = pci_qdev_find_device(id, &pdev);
+ if (ret < 0) {
+ monitor_printf(mon,
+ "id or cxl device path is invalid or device not "
+ "found. %s\n", id);
+ return ret;
+ }
+
+ ct3d = container_of(pdev, struct CXLType3Dev, parent_obj);
+ cxl_reset_all_logs(&ct3d->cxl_dstate);
+
+ cxl_event_irq_assert(pdev);
+ return 0;
+}
+
+void hmp_cxl_event_inject(Monitor *mon, const QDict *qdict)
+{
+ const char *id = qdict_get_str(qdict, "id");
+
+ if (do_cxl_event_inject(mon, qdict) < 0) {
+ return;
+ }
+
+ monitor_printf(mon, "OK id: %s\n", id);
+}
@@ -12,4 +12,9 @@ void cxl_fmws_link_targets(CXLState *stat, Error **errp) {};
void cxl_machine_init(Object *obj, CXLState *state) {};
void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState *state, Error **errp) {};
+void hmp_cxl_event_inject(Monitor *mon, const QDict *qdict)
+{
+ monitor_printf(mon, "CXL devices not supported\n");
+}
+
const MemoryRegionOps cfmws_ops;
@@ -459,7 +459,7 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp)
ComponentRegisters *regs = &cxl_cstate->crb;
MemoryRegion *mr = ®s->component_registers;
uint8_t *pci_conf = pci_dev->config;
- unsigned short msix_num = 3;
+ unsigned short msix_num = 7;
int i;
if (!cxl_setup_memory(ct3d, errp)) {
@@ -502,6 +502,11 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp)
msix_vector_use(pci_dev, i);
}
+ ct3d->cxl_dstate.event_vector[CXL_EVENT_TYPE_INFO] = 6;
+ ct3d->cxl_dstate.event_vector[CXL_EVENT_TYPE_WARN] = 5;
+ ct3d->cxl_dstate.event_vector[CXL_EVENT_TYPE_FAIL] = 4;
+ ct3d->cxl_dstate.event_vector[CXL_EVENT_TYPE_FATAL] = 3;
+
/* DOE Initailization */
if (ct3d->spdm_port) {
pcie_doe_init(pci_dev, &ct3d->doe_spdm, 0x160, doe_spdm_prot, true, 2);
@@ -84,6 +84,8 @@
#define CXL_TEST_EVENT_CNT_MAX 15
struct cxl_event_log {
+ bool irq_enabled;
+ int irq_vec;
int cur_event;
int nr_events;
struct cxl_event_record_raw *events[CXL_TEST_EVENT_CNT_MAX];
@@ -129,6 +131,7 @@ typedef struct cxl_device_state {
/* memory region for persistent memory, HDM */
uint64_t pmem_size;
+ uint16_t event_vector[CXL_EVENT_TYPE_MAX];
struct cxl_event_log event_logs[CXL_EVENT_TYPE_MAX];
} CXLDeviceState;
@@ -64,6 +64,9 @@ extern unsigned int nb_prom_envs;
/* pcie aer error injection */
void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict);
+/* CXL */
+void hmp_cxl_event_inject(Monitor *mon, const QDict *qdict);
+
/* serial ports */
/* Return the Chardev for serial port i, or NULL if none */