diff options
author | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2023-10-23 17:07:53 +0100 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2023-11-07 03:39:11 -0500 |
commit | c9460561edbd8b2d4adbf1f7c5cb4ad4d210de4c (patch) | |
tree | 350146e485148047c5aea72232fe0043e1db6947 /hw/cxl/cxl-device-utils.c | |
parent | cac36a8faffc62ba6b07d8e9dfdc9fbf15c7d1bf (diff) |
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/cxl-device-utils.c')
-rw-r--r-- | hw/cxl/cxl-device-utils.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/hw/cxl/cxl-device-utils.c b/hw/cxl/cxl-device-utils.c index 327949a805..eb86634250 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); } } |