diff --git a/src/include/sof/ipc/msg.h b/src/include/sof/ipc/msg.h index a24fa3711ad0..20dfaf6eb519 100644 --- a/src/include/sof/ipc/msg.h +++ b/src/include/sof/ipc/msg.h @@ -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; }; diff --git a/src/ipc/ipc-common.c b/src/ipc/ipc-common.c index bf94e0481ec0..7714a4650150 100644 --- a/src/ipc/ipc-common.c +++ b/src/ipc/ipc-common.c @@ -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; + } } /* diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index 3d7e82645a4f..6645d6fd08e5 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -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) @@ -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; @@ -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); @@ -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); diff --git a/src/library_manager/lib_notification.c b/src/library_manager/lib_notification.c index 29ca2de2a951..f76fc05942b1 100644 --- a/src/library_manager/lib_notification.c +++ b/src/library_manager/lib_notification.c @@ -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; }