aboutsummaryrefslogtreecommitdiff
path: root/hw/cxl
diff options
context:
space:
mode:
authorIra Weiny <ira.weiny@intel.com>2023-05-30 14:36:00 +0100
committerMichael S. Tsirkin <mst@redhat.com>2023-06-22 18:55:14 -0400
commit6676bb973ba53d60886b06213ec98fbd736d66a1 (patch)
tree28911071ca8f35c75b76f7743687b4039bd886ad /hw/cxl
parent22d7e3be0714f39bae43bd0c05f6e6d149a47b13 (diff)
downloadqemu-6676bb973ba53d60886b06213ec98fbd736d66a1.zip
qemu-6676bb973ba53d60886b06213ec98fbd736d66a1.tar.gz
qemu-6676bb973ba53d60886b06213ec98fbd736d66a1.tar.bz2
hw/cxl/events: Add event interrupt support
Replace the stubbed out CXL Get/Set Event interrupt policy mailbox commands. Enable those commands to control interrupts for each of the event log types. Skip the standard input mailbox length on the Set command due to DCD being optional. Perform the checks separately. Signed-off-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Fan Ni <fan.ni@samsung.com> Reviewed-by: Davidlohr Bueso <dave@stgolabs.net> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Message-Id: <20230530133603.16934-5-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/cxl')
-rw-r--r--hw/cxl/cxl-events.c33
-rw-r--r--hw/cxl/cxl-mailbox-utils.c106
2 files changed, 117 insertions, 22 deletions
diff --git a/hw/cxl/cxl-events.c b/hw/cxl/cxl-events.c
index 5da1b76..d161d57 100644
--- a/hw/cxl/cxl-events.c
+++ b/hw/cxl/cxl-events.c
@@ -13,6 +13,8 @@
#include "qemu/bswap.h"
#include "qemu/typedefs.h"
#include "qemu/error-report.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
#include "hw/cxl/cxl.h"
#include "hw/cxl/cxl_events.h"
@@ -26,7 +28,7 @@ static void reset_overflow(CXLEventLog *log)
log->last_overflow_timestamp = 0;
}
-void cxl_event_init(CXLDeviceState *cxlds)
+void cxl_event_init(CXLDeviceState *cxlds, int start_msg_num)
{
CXLEventLog *log;
int i;
@@ -37,9 +39,16 @@ void cxl_event_init(CXLDeviceState *cxlds)
log->overflow_err_count = 0;
log->first_overflow_timestamp = 0;
log->last_overflow_timestamp = 0;
+ log->irq_enabled = false;
+ log->irq_vec = start_msg_num++;
qemu_mutex_init(&log->lock);
QSIMPLEQ_INIT(&log->events);
}
+
+ /* Override -- Dynamic Capacity uses the same vector as info */
+ cxlds->event_logs[CXL_EVENT_TYPE_DYNAMIC_CAP].irq_vec =
+ cxlds->event_logs[CXL_EVENT_TYPE_INFO].irq_vec;
+
}
static CXLEvent *cxl_event_get_head(CXLEventLog *log)
@@ -215,3 +224,25 @@ CXLRetCode cxl_event_clear_records(CXLDeviceState *cxlds, CXLClearEventPayload *
return CXL_MBOX_SUCCESS;
}
+
+void cxl_event_irq_assert(CXLType3Dev *ct3d)
+{
+ CXLDeviceState *cxlds = &ct3d->cxl_dstate;
+ PCIDevice *pdev = &ct3d->parent_obj;
+ int i;
+
+ for (i = 0; i < CXL_EVENT_TYPE_MAX; i++) {
+ CXLEventLog *log = &cxlds->event_logs[i];
+
+ if (!log->irq_enabled || cxl_event_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);
+ }
+ }
+}
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 3f46538..02f9b5a 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -80,25 +80,6 @@ struct cxl_cmd {
uint8_t *payload;
};
-#define DEFINE_MAILBOX_HANDLER_ZEROED(name, size) \
- uint16_t __zero##name = size; \
- static CXLRetCode cmd_##name(struct cxl_cmd *cmd, \
- CXLDeviceState *cxl_dstate, uint16_t *len) \
- { \
- *len = __zero##name; \
- memset(cmd->payload, 0, *len); \
- return CXL_MBOX_SUCCESS; \
- }
-#define DEFINE_MAILBOX_HANDLER_NOP(name) \
- static CXLRetCode cmd_##name(struct cxl_cmd *cmd, \
- CXLDeviceState *cxl_dstate, uint16_t *len) \
- { \
- return CXL_MBOX_SUCCESS; \
- }
-
-DEFINE_MAILBOX_HANDLER_ZEROED(events_get_interrupt_policy, 4);
-DEFINE_MAILBOX_HANDLER_NOP(events_set_interrupt_policy);
-
static CXLRetCode cmd_events_get_records(struct cxl_cmd *cmd,
CXLDeviceState *cxlds,
uint16_t *len)
@@ -136,6 +117,88 @@ static CXLRetCode cmd_events_clear_records(struct cxl_cmd *cmd,
return cxl_event_clear_records(cxlds, pl);
}
+static CXLRetCode cmd_events_get_interrupt_policy(struct cxl_cmd *cmd,
+ CXLDeviceState *cxlds,
+ uint16_t *len)
+{
+ CXLEventInterruptPolicy *policy;
+ CXLEventLog *log;
+
+ policy = (CXLEventInterruptPolicy *)cmd->payload;
+ memset(policy, 0, sizeof(*policy));
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_INFO];
+ if (log->irq_enabled) {
+ policy->info_settings = CXL_EVENT_INT_SETTING(log->irq_vec);
+ }
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_WARN];
+ if (log->irq_enabled) {
+ policy->warn_settings = CXL_EVENT_INT_SETTING(log->irq_vec);
+ }
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_FAIL];
+ if (log->irq_enabled) {
+ policy->failure_settings = CXL_EVENT_INT_SETTING(log->irq_vec);
+ }
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_FATAL];
+ if (log->irq_enabled) {
+ policy->fatal_settings = CXL_EVENT_INT_SETTING(log->irq_vec);
+ }
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_DYNAMIC_CAP];
+ if (log->irq_enabled) {
+ /* Dynamic Capacity borrows the same vector as info */
+ policy->dyn_cap_settings = CXL_INT_MSI_MSIX;
+ }
+
+ *len = sizeof(*policy);
+ return CXL_MBOX_SUCCESS;
+}
+
+static CXLRetCode cmd_events_set_interrupt_policy(struct cxl_cmd *cmd,
+ CXLDeviceState *cxlds,
+ uint16_t *len)
+{
+ CXLEventInterruptPolicy *policy;
+ CXLEventLog *log;
+
+ if (*len < CXL_EVENT_INT_SETTING_MIN_LEN) {
+ return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
+ }
+
+ policy = (CXLEventInterruptPolicy *)cmd->payload;
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_INFO];
+ log->irq_enabled = (policy->info_settings & CXL_EVENT_INT_MODE_MASK) ==
+ CXL_INT_MSI_MSIX;
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_WARN];
+ log->irq_enabled = (policy->warn_settings & CXL_EVENT_INT_MODE_MASK) ==
+ CXL_INT_MSI_MSIX;
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_FAIL];
+ log->irq_enabled = (policy->failure_settings & CXL_EVENT_INT_MODE_MASK) ==
+ CXL_INT_MSI_MSIX;
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_FATAL];
+ log->irq_enabled = (policy->fatal_settings & CXL_EVENT_INT_MODE_MASK) ==
+ CXL_INT_MSI_MSIX;
+
+ /* DCD is optional */
+ if (*len < sizeof(*policy)) {
+ return CXL_MBOX_SUCCESS;
+ }
+
+ log = &cxlds->event_logs[CXL_EVENT_TYPE_DYNAMIC_CAP];
+ log->irq_enabled = (policy->dyn_cap_settings & CXL_EVENT_INT_MODE_MASK) ==
+ CXL_INT_MSI_MSIX;
+
+ *len = sizeof(*policy);
+ return CXL_MBOX_SUCCESS;
+}
+
/* 8.2.9.2.1 */
static CXLRetCode cmd_firmware_update_get_info(struct cxl_cmd *cmd,
CXLDeviceState *cxl_dstate,
@@ -611,9 +674,10 @@ static struct cxl_cmd cxl_cmd_set[256][256] = {
[EVENTS][CLEAR_RECORDS] = { "EVENTS_CLEAR_RECORDS",
cmd_events_clear_records, ~0, IMMEDIATE_LOG_CHANGE },
[EVENTS][GET_INTERRUPT_POLICY] = { "EVENTS_GET_INTERRUPT_POLICY",
- cmd_events_get_interrupt_policy, 0, 0 },
+ cmd_events_get_interrupt_policy, 0, 0 },
[EVENTS][SET_INTERRUPT_POLICY] = { "EVENTS_SET_INTERRUPT_POLICY",
- cmd_events_set_interrupt_policy, 4, IMMEDIATE_CONFIG_CHANGE },
+ cmd_events_set_interrupt_policy,
+ ~0, IMMEDIATE_CONFIG_CHANGE },
[FIRMWARE_UPDATE][GET_INFO] = { "FIRMWARE_UPDATE_GET_INFO",
cmd_firmware_update_get_info, 0, 0 },
[TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },