blob: a905b8831d60422670f8a1c7a40fa91fc166499b [file] [log] [blame]
Tamas Ban53ac24f2022-01-18 16:32:18 +01001/*
2 * Copyright (c) 2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdint.h>
8#include <string.h>
9
10#include <common/debug.h>
11#include <drivers/arm/mhu.h>
12#include <drivers/arm/rss_comms.h>
Tamas Ban53ac24f2022-01-18 16:32:18 +010013#include <psa/client.h>
Raef Coles734aaac2022-06-15 14:37:22 +010014#include <rss_comms_protocol.h>
Tamas Ban53ac24f2022-01-18 16:32:18 +010015
Raef Coles734aaac2022-06-15 14:37:22 +010016/* Union as message space and reply space are never used at the same time, and this saves space as
17 * we can overlap them.
Tamas Ban53ac24f2022-01-18 16:32:18 +010018 */
Raef Coles734aaac2022-06-15 14:37:22 +010019union __packed __attribute__((aligned(4))) rss_comms_io_buffer_t {
20 struct serialized_rss_comms_msg_t msg;
21 struct serialized_rss_comms_reply_t reply;
22};
Tamas Ban53ac24f2022-01-18 16:32:18 +010023
Raef Coles734aaac2022-06-15 14:37:22 +010024static uint8_t select_protocol_version(const psa_invec *in_vec, size_t in_len,
25 const psa_outvec *out_vec, size_t out_len)
Tamas Ban53ac24f2022-01-18 16:32:18 +010026{
Raef Coles734aaac2022-06-15 14:37:22 +010027 size_t comms_mhu_msg_size;
28 size_t comms_embed_msg_min_size;
29 size_t comms_embed_reply_min_size;
30 size_t in_size_total = 0;
31 size_t out_size_total = 0;
32 size_t i;
Tamas Ban53ac24f2022-01-18 16:32:18 +010033
34 for (i = 0U; i < in_len; ++i) {
Raef Coles734aaac2022-06-15 14:37:22 +010035 in_size_total += in_vec[i].len;
Tamas Ban53ac24f2022-01-18 16:32:18 +010036 }
Tamas Ban53ac24f2022-01-18 16:32:18 +010037 for (i = 0U; i < out_len; ++i) {
Raef Coles734aaac2022-06-15 14:37:22 +010038 out_size_total += out_vec[i].len;
Tamas Ban53ac24f2022-01-18 16:32:18 +010039 }
Tamas Ban53ac24f2022-01-18 16:32:18 +010040
Raef Coles734aaac2022-06-15 14:37:22 +010041 comms_mhu_msg_size = mhu_get_max_message_size();
Tamas Ban53ac24f2022-01-18 16:32:18 +010042
Raef Coles734aaac2022-06-15 14:37:22 +010043 comms_embed_msg_min_size = sizeof(struct serialized_rss_comms_header_t) +
44 sizeof(struct rss_embed_msg_t) -
Tamas Ban9cc87142022-10-05 11:56:04 +020045 PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE;
Tamas Ban53ac24f2022-01-18 16:32:18 +010046
Raef Coles734aaac2022-06-15 14:37:22 +010047 comms_embed_reply_min_size = sizeof(struct serialized_rss_comms_header_t) +
48 sizeof(struct rss_embed_reply_t) -
Tamas Ban9cc87142022-10-05 11:56:04 +020049 PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE;
Tamas Ban53ac24f2022-01-18 16:32:18 +010050
Raef Coles734aaac2022-06-15 14:37:22 +010051 /* Use embed if we can pack into one message and reply, else use
52 * pointer_access. The underlying MHU transport protocol uses a
53 * single uint32_t to track the length, so the amount of data that
54 * can be in a message is 4 bytes less than mhu_get_max_message_size
55 * reports.
56 *
57 * TODO tune this with real performance numbers, it's possible a
58 * pointer_access message is less performant than multiple embed
59 * messages due to ATU configuration costs to allow access to the
60 * pointers.
61 */
Vijayenthiran Subramaniama9434152023-12-06 14:27:09 +053062 if ((comms_embed_msg_min_size + in_size_total >
63 comms_mhu_msg_size - sizeof(uint32_t)) ||
64 (comms_embed_reply_min_size + out_size_total >
65 comms_mhu_msg_size - sizeof(uint32_t))) {
Raef Coles734aaac2022-06-15 14:37:22 +010066 return RSS_COMMS_PROTOCOL_POINTER_ACCESS;
67 } else {
68 return RSS_COMMS_PROTOCOL_EMBED;
69 }
Tamas Ban53ac24f2022-01-18 16:32:18 +010070}
71
Raef Coles734aaac2022-06-15 14:37:22 +010072psa_status_t psa_call(psa_handle_t handle, int32_t type, const psa_invec *in_vec, size_t in_len,
Tamas Ban53ac24f2022-01-18 16:32:18 +010073 psa_outvec *out_vec, size_t out_len)
74{
Tamas Band1bbcbe2022-10-03 15:34:02 +020075 /* Declared statically to avoid using huge amounts of stack space. Maybe revisit if
76 * functions not being reentrant becomes a problem.
77 */
78 static union rss_comms_io_buffer_t io_buf;
Tamas Ban53ac24f2022-01-18 16:32:18 +010079 enum mhu_error_t err;
Raef Coles734aaac2022-06-15 14:37:22 +010080 psa_status_t status;
81 static uint8_t seq_num = 1U;
82 size_t msg_size;
83 size_t reply_size = sizeof(io_buf.reply);
84 psa_status_t return_val;
85 size_t idx;
Tamas Ban53ac24f2022-01-18 16:32:18 +010086
Raef Coles734aaac2022-06-15 14:37:22 +010087 if (type > INT16_MAX || type < INT16_MIN || in_len > PSA_MAX_IOVEC
88 || out_len > PSA_MAX_IOVEC) {
89 return PSA_ERROR_INVALID_ARGUMENT;
Tamas Ban53ac24f2022-01-18 16:32:18 +010090 }
Raef Coles734aaac2022-06-15 14:37:22 +010091
92 io_buf.msg.header.seq_num = seq_num,
93 /* No need to distinguish callers (currently concurrent calls are not supported). */
94 io_buf.msg.header.client_id = 1U,
95 io_buf.msg.header.protocol_ver = select_protocol_version(in_vec, in_len, out_vec, out_len);
96
97 status = rss_protocol_serialize_msg(handle, type, in_vec, in_len, out_vec,
98 out_len, &io_buf.msg, &msg_size);
99 if (status != PSA_SUCCESS) {
100 return status;
Tamas Ban53ac24f2022-01-18 16:32:18 +0100101 }
102
Raef Coles734aaac2022-06-15 14:37:22 +0100103 VERBOSE("[RSS-COMMS] Sending message\n");
104 VERBOSE("protocol_ver=%u\n", io_buf.msg.header.protocol_ver);
105 VERBOSE("seq_num=%u\n", io_buf.msg.header.seq_num);
106 VERBOSE("client_id=%u\n", io_buf.msg.header.client_id);
107 for (idx = 0; idx < in_len; idx++) {
108 VERBOSE("in_vec[%lu].len=%lu\n", idx, in_vec[idx].len);
109 VERBOSE("in_vec[%lu].buf=%p\n", idx, (void *)in_vec[idx].base);
Tamas Ban53ac24f2022-01-18 16:32:18 +0100110 }
111
Raef Coles734aaac2022-06-15 14:37:22 +0100112 err = mhu_send_data((uint8_t *)&io_buf.msg, msg_size);
Tamas Ban53ac24f2022-01-18 16:32:18 +0100113 if (err != MHU_ERR_NONE) {
114 return PSA_ERROR_COMMUNICATION_FAILURE;
115 }
116
Tamas Ban53ac24f2022-01-18 16:32:18 +0100117#if DEBUG
118 /*
119 * Poisoning the message buffer (with a known pattern).
120 * Helps in detecting hypothetical RSS communication bugs.
121 */
Raef Coles734aaac2022-06-15 14:37:22 +0100122 memset(&io_buf.msg, 0xA5, msg_size);
Tamas Ban53ac24f2022-01-18 16:32:18 +0100123#endif
Raef Coles734aaac2022-06-15 14:37:22 +0100124
125 err = mhu_receive_data((uint8_t *)&io_buf.reply, &reply_size);
Tamas Ban53ac24f2022-01-18 16:32:18 +0100126 if (err != MHU_ERR_NONE) {
127 return PSA_ERROR_COMMUNICATION_FAILURE;
128 }
129
Raef Coles734aaac2022-06-15 14:37:22 +0100130 VERBOSE("[RSS-COMMS] Received reply\n");
131 VERBOSE("protocol_ver=%u\n", io_buf.reply.header.protocol_ver);
132 VERBOSE("seq_num=%u\n", io_buf.reply.header.seq_num);
133 VERBOSE("client_id=%u\n", io_buf.reply.header.client_id);
Tamas Ban53ac24f2022-01-18 16:32:18 +0100134
Raef Coles734aaac2022-06-15 14:37:22 +0100135 status = rss_protocol_deserialize_reply(out_vec, out_len, &return_val,
136 &io_buf.reply, reply_size);
137 if (status != PSA_SUCCESS) {
138 return status;
139 }
Tamas Ban53ac24f2022-01-18 16:32:18 +0100140
Raef Coles734aaac2022-06-15 14:37:22 +0100141 VERBOSE("return_val=%d\n", return_val);
142 for (idx = 0U; idx < out_len; idx++) {
143 VERBOSE("out_vec[%lu].len=%lu\n", idx, out_vec[idx].len);
144 VERBOSE("out_vec[%lu].buf=%p\n", idx, (void *)out_vec[idx].base);
145 }
146
Tamas Bana7dcfda2022-09-16 13:42:29 +0200147 /* Clear the MHU message buffer to remove assets from memory */
148 memset(&io_buf, 0x0, sizeof(io_buf));
149
Raef Coles734aaac2022-06-15 14:37:22 +0100150 seq_num++;
Tamas Ban53ac24f2022-01-18 16:32:18 +0100151
Raef Coles734aaac2022-06-15 14:37:22 +0100152 return return_val;
Tamas Ban53ac24f2022-01-18 16:32:18 +0100153}
154
155int rss_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base)
156{
157 enum mhu_error_t err;
158
159 err = mhu_init_sender(mhu_sender_base);
160 if (err != MHU_ERR_NONE) {
David Vincze7a93f9e2022-12-01 15:10:34 +0100161 if (err == MHU_ERR_ALREADY_INIT) {
162 INFO("[RSS-COMMS] Host to RSS MHU driver already initialized\n");
163 } else {
164 ERROR("[RSS-COMMS] Host to RSS MHU driver initialization failed: %d\n", err);
165 return -1;
166 }
Tamas Ban53ac24f2022-01-18 16:32:18 +0100167 }
168
169 err = mhu_init_receiver(mhu_receiver_base);
170 if (err != MHU_ERR_NONE) {
David Vincze7a93f9e2022-12-01 15:10:34 +0100171 if (err == MHU_ERR_ALREADY_INIT) {
172 INFO("[RSS-COMMS] RSS to Host MHU driver already initialized\n");
173 } else {
174 ERROR("[RSS-COMMS] RSS to Host MHU driver initialization failed: %d\n", err);
175 return -1;
176 }
Tamas Ban53ac24f2022-01-18 16:32:18 +0100177 }
178
179 return 0;
180}