aboutsummaryrefslogtreecommitdiff
path: root/hw/cxl
diff options
context:
space:
mode:
authorJonathan Cameron <Jonathan.Cameron@huawei.com>2023-10-23 17:07:53 +0100
committerMichael S. Tsirkin <mst@redhat.com>2023-11-07 03:39:11 -0500
commitc9460561edbd8b2d4adbf1f7c5cb4ad4d210de4c (patch)
tree350146e485148047c5aea72232fe0043e1db6947 /hw/cxl
parentcac36a8faffc62ba6b07d8e9dfdc9fbf15c7d1bf (diff)
downloadqemu-c9460561edbd8b2d4adbf1f7c5cb4ad4d210de4c.zip
qemu-c9460561edbd8b2d4adbf1f7c5cb4ad4d210de4c.tar.gz
qemu-c9460561edbd8b2d4adbf1f7c5cb4ad4d210de4c.tar.bz2
hw/cxl/mbox: Generalize the CCI command processing
By moving the parts of the mailbox command handling that are CCI type specific out to the caller, make the main handling code generic. Rename it to cxl_process_cci_message() to reflect this new generality. Change the type3 mailbox handling (reused shortly for the switch mailbox CCI) to take a snapshot of the mailbox input data rather than operating on it in place. This reduces the chance of bugs due to aliasing going forwars. Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Message-Id: <20231023160806.13206-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-device-utils.c44
-rw-r--r--hw/cxl/cxl-mailbox-utils.c51
2 files changed, 53 insertions, 42 deletions
diff --git a/hw/cxl/cxl-device-utils.c b/hw/cxl/cxl-device-utils.c
index 327949a..eb86634 100644
--- a/hw/cxl/cxl-device-utils.c
+++ b/hw/cxl/cxl-device-utils.c
@@ -157,7 +157,49 @@ static void mailbox_reg_write(void *opaque, hwaddr offset, uint64_t value,
if (ARRAY_FIELD_EX32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CTRL,
DOORBELL)) {
- cxl_process_mailbox(cci);
+ uint64_t command_reg =
+ cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_CMD];
+ uint8_t cmd_set = FIELD_EX64(command_reg, CXL_DEV_MAILBOX_CMD,
+ COMMAND_SET);
+ uint8_t cmd = FIELD_EX64(command_reg, CXL_DEV_MAILBOX_CMD, COMMAND);
+ size_t len_in = FIELD_EX64(command_reg, CXL_DEV_MAILBOX_CMD, LENGTH);
+ uint8_t *pl = cxl_dstate->mbox_reg_state + A_CXL_DEV_CMD_PAYLOAD;
+ /*
+ * Copy taken to avoid need for individual command handlers to care
+ * about aliasing.
+ */
+ g_autofree uint8_t *pl_in_copy = NULL;
+ size_t len_out = 0;
+ uint64_t status_reg;
+ bool bg_started = false;
+ int rc;
+
+ pl_in_copy = g_memdup2(pl, len_in);
+ if (len_in == 0 || pl_in_copy) {
+ /* Avoid stale data - including from earlier cmds */
+ memset(pl, 0, CXL_MAILBOX_MAX_PAYLOAD_SIZE);
+ rc = cxl_process_cci_message(cci, cmd_set, cmd, len_in, pl_in_copy,
+ &len_out, pl, &bg_started);
+ } else {
+ rc = CXL_MBOX_INTERNAL_ERROR;
+ }
+
+ /* Set bg and the return code */
+ status_reg = FIELD_DP64(0, CXL_DEV_MAILBOX_STS, BG_OP,
+ bg_started ? 1 : 0);
+ status_reg = FIELD_DP64(status_reg, CXL_DEV_MAILBOX_STS, ERRNO, rc);
+ /* Set the return length */
+ command_reg = FIELD_DP64(0, CXL_DEV_MAILBOX_CMD, COMMAND_SET, cmd_set);
+ command_reg = FIELD_DP64(command_reg, CXL_DEV_MAILBOX_CMD,
+ COMMAND, cmd);
+ command_reg = FIELD_DP64(command_reg, CXL_DEV_MAILBOX_CMD,
+ LENGTH, len_out);
+
+ cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_CMD] = command_reg;
+ cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_STS] = status_reg;
+ /* Tell the host we're done */
+ ARRAY_FIELD_DP32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CTRL,
+ DOORBELL, 0);
}
}
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 5484dfb..239acc6 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -754,58 +754,27 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
cmd_media_clear_poison, 72, 0 },
};
-void cxl_process_mailbox(CXLCCI *cci)
+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, bool *bg_started)
{
- uint16_t ret = CXL_MBOX_SUCCESS;
const struct cxl_cmd *cxl_cmd;
- uint64_t status_reg = 0;
opcode_handler h;
- CXLDeviceState *cxl_dstate = &CXL_TYPE3(cci->d)->cxl_dstate;
- uint64_t command_reg = cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_CMD];
-
- uint8_t set = FIELD_EX64(command_reg, CXL_DEV_MAILBOX_CMD, COMMAND_SET);
- uint8_t cmd = FIELD_EX64(command_reg, CXL_DEV_MAILBOX_CMD, COMMAND);
- uint16_t len_in = FIELD_EX64(command_reg, CXL_DEV_MAILBOX_CMD, LENGTH);
- uint8_t *pl = cxl_dstate->mbox_reg_state + A_CXL_DEV_CMD_PAYLOAD;
- /*
- * Copy taken to avoid need for individual command handlers to care
- * about aliasing.
- */
- g_autofree uint8_t *pl_in_copy = NULL;
- size_t len_out = 0;
- pl_in_copy = g_memdup2(pl, len_in);
- /* Avoid stale data - including from earlier commands */
- memset(pl, 0, CXL_MAILBOX_MAX_PAYLOAD_SIZE);
+ *len_out = 0;
cxl_cmd = &cci->cxl_cmd_set[set][cmd];
h = cxl_cmd->handler;
- if (h) {
- if (len_in == cxl_cmd->in || cxl_cmd->in == ~0) {
- ret = (*h)(cxl_cmd, pl, len_in, pl, &len_out, cci);
- assert(len_out <= cci->payload_max);
- } else {
- ret = CXL_MBOX_INVALID_PAYLOAD_LENGTH;
- }
- } else {
+ if (!h) {
qemu_log_mask(LOG_UNIMP, "Command %04xh not implemented\n",
set << 8 | cmd);
- ret = CXL_MBOX_UNSUPPORTED;
+ return CXL_MBOX_UNSUPPORTED;
}
- /* Set the return code */
- status_reg = FIELD_DP64(0, CXL_DEV_MAILBOX_STS, ERRNO, ret);
-
- /* Set the return length */
- command_reg = FIELD_DP64(command_reg, CXL_DEV_MAILBOX_CMD, COMMAND_SET, 0);
- command_reg = FIELD_DP64(command_reg, CXL_DEV_MAILBOX_CMD, COMMAND, 0);
- command_reg = FIELD_DP64(command_reg, CXL_DEV_MAILBOX_CMD, LENGTH, len_out);
-
- cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_CMD] = command_reg;
- cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_STS] = status_reg;
+ if (len_in != cxl_cmd->in && cxl_cmd->in != ~0) {
+ return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
+ }
- /* Tell the host we're done */
- ARRAY_FIELD_DP32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CTRL,
- DOORBELL, 0);
+ return (*h)(cxl_cmd, pl_in, len_in, pl_out, len_out, cci);
}
void cxl_init_cci(CXLCCI *cci, size_t payload_max)