Skip to content

Commit

Permalink
ipc: add cache flushing and invalidation for IPC data
Browse files Browse the repository at this point in the history
This patch addresses an issue with incorrect IPC responses due to the
lack of cache flushing and invalidation on secondary cores.

The following changes have been made:

1. Added cache writeback for IPC message data in `ipc_msg_send` when the
   current core is not the primary core.
2. Added cache invalidation for IPC message data in
   `ipc_prepare_to_send` before writing to the mailbox.

These changes ensure that the IPC data is correctly synchronized between
cores.

Signed-off-by: Tomasz Leman <[email protected]>
  • Loading branch information
tmleman authored and lgirdwood committed Nov 5, 2024
1 parent c019576 commit 79ca991
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/include/sof/ipc/msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct ipc_msg {
uint32_t extension; /* extension specific to platform */
uint32_t tx_size; /* payload size in bytes */
void *tx_data; /* pointer to payload data */
bool is_shared; /* the message is shared cross-core */
struct list_item list;
};

Expand Down
9 changes: 9 additions & 0 deletions src/ipc/ipc-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,15 @@ void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority)
msg->tx_data != data) {
ret = memcpy_s(msg->tx_data, msg->tx_size, data, msg->tx_size);
assert(!ret);
if (!cpu_is_primary(cpu_get_id())) {
/* Write back data to memory to maintain coherence between cores.
* The response was prepared on a secondary core but will be sent
* to the host from the primary core.
*/
dcache_writeback_region((__sparse_force void __sparse_cache *)msg->tx_data,
msg->tx_size);
msg->is_shared = true;
}
}

/*
Expand Down
19 changes: 16 additions & 3 deletions src/ipc/ipc4/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ struct ipc4_msg_data {
static struct ipc4_msg_data msg_data;

/* fw sends a fw ipc message to send the status of the last host ipc message */
static struct ipc_msg msg_reply = {0, 0, 0, 0, LIST_INIT(msg_reply.list)};
static struct ipc_msg msg_reply = {0, 0, 0, 0, false, LIST_INIT(msg_reply.list)};

static struct ipc_msg msg_notify = {0, 0, 0, 0, LIST_INIT(msg_notify.list)};
static struct ipc_msg msg_notify = {0, 0, 0, 0, false, LIST_INIT(msg_notify.list)};

#if CONFIG_LIBRARY
static inline struct ipc4_message_request *ipc4_get_message_request(void)
Expand Down Expand Up @@ -1494,14 +1494,25 @@ struct ipc_cmd_hdr *ipc_prepare_to_send(const struct ipc_msg *msg)
msg_data.msg_out.pri = msg->header;
msg_data.msg_out.ext = msg->extension;

if (msg->tx_size)
if (msg->tx_size) {
/* Invalidate cache to ensure we read the latest data from memory.
* The response was prepared on a secondary core but will be sent
* to the host from the primary core.
*/
if (msg->is_shared) {
dcache_invalidate_region((__sparse_force void __sparse_cache *)msg->tx_data,
msg->tx_size);
}

mailbox_dspbox_write(0, (uint32_t *)msg->tx_data, msg->tx_size);
}

/* free memory for get config function */
if (msg == &msg_reply && msg_reply.tx_size > 0) {
rfree(msg_reply.tx_data);
msg_reply.tx_data = NULL;
msg_reply.tx_size = 0;
msg_reply.is_shared = false;
}

return &msg_data.msg_out;
Expand Down Expand Up @@ -1535,6 +1546,7 @@ void ipc_send_panic_notification(void)
{
msg_notify.header = SOF_IPC4_NOTIF_HEADER(SOF_IPC4_EXCEPTION_CAUGHT);
msg_notify.extension = cpu_get_id();
msg_notify.is_shared = !cpu_is_primary(cpu_get_id());
msg_notify.tx_size = 0;
msg_notify.tx_data = NULL;
list_init(&msg_notify.list);
Expand Down Expand Up @@ -1567,6 +1579,7 @@ void ipc_send_buffer_status_notify(void)
msg_notify.header = SOF_IPC4_NOTIF_HEADER(SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS);
msg_notify.extension = 0;
msg_notify.tx_size = 0;
msg_notify.is_shared = false;

tr_dbg(&ipc_tr, "tx-notify\t: %#x|%#x", msg_notify.header, msg_notify.extension);

Expand Down
1 change: 1 addition & 0 deletions src/library_manager/lib_notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ struct ipc_msg *lib_notif_msg_init(uint32_t header, uint32_t size)
/* Update header and size, since message handle can be reused */
msg->header = header;
msg->tx_size = size;
msg->is_shared = !cpu_is_primary(cpu_get_id());
return msg;
}

Expand Down

0 comments on commit 79ca991

Please sign in to comment.