Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 1 | /* |
David Vincze | 85ff4d2 | 2023-09-08 08:00:01 +0200 | [diff] [blame] | 2 | * Copyright (c) 2022-2024, Arm Limited. All rights reserved. |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 13 | #include <psa/client.h> |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 14 | #include <rss_comms_protocol.h> |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 15 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 16 | /* 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 18 | */ |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 19 | union __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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 23 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 24 | static 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 26 | { |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 27 | 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 33 | |
| 34 | for (i = 0U; i < in_len; ++i) { |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 35 | in_size_total += in_vec[i].len; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 36 | } |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 37 | for (i = 0U; i < out_len; ++i) { |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 38 | out_size_total += out_vec[i].len; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 39 | } |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 40 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 41 | comms_mhu_msg_size = mhu_get_max_message_size(); |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 42 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 43 | comms_embed_msg_min_size = sizeof(struct serialized_rss_comms_header_t) + |
| 44 | sizeof(struct rss_embed_msg_t) - |
Tamas Ban | 9cc8714 | 2022-10-05 11:56:04 +0200 | [diff] [blame] | 45 | PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 46 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 47 | comms_embed_reply_min_size = sizeof(struct serialized_rss_comms_header_t) + |
| 48 | sizeof(struct rss_embed_reply_t) - |
Tamas Ban | 9cc8714 | 2022-10-05 11:56:04 +0200 | [diff] [blame] | 49 | PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 50 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 51 | /* 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 Subramaniam | a943415 | 2023-12-06 14:27:09 +0530 | [diff] [blame] | 62 | 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 Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 66 | return RSS_COMMS_PROTOCOL_POINTER_ACCESS; |
| 67 | } else { |
| 68 | return RSS_COMMS_PROTOCOL_EMBED; |
| 69 | } |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 70 | } |
| 71 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 72 | psa_status_t psa_call(psa_handle_t handle, int32_t type, const psa_invec *in_vec, size_t in_len, |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 73 | psa_outvec *out_vec, size_t out_len) |
| 74 | { |
Tamas Ban | d1bbcbe | 2022-10-03 15:34:02 +0200 | [diff] [blame] | 75 | /* 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 79 | enum mhu_error_t err; |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 80 | 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 86 | |
David Vincze | 85ff4d2 | 2023-09-08 08:00:01 +0200 | [diff] [blame] | 87 | if (type > PSA_CALL_TYPE_MAX || type < PSA_CALL_TYPE_MIN || |
| 88 | in_len > PSA_MAX_IOVEC || out_len > PSA_MAX_IOVEC) { |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 89 | return PSA_ERROR_INVALID_ARGUMENT; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 90 | } |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 91 | |
| 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 101 | } |
| 102 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 103 | 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 110 | } |
| 111 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 112 | err = mhu_send_data((uint8_t *)&io_buf.msg, msg_size); |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 113 | if (err != MHU_ERR_NONE) { |
| 114 | return PSA_ERROR_COMMUNICATION_FAILURE; |
| 115 | } |
| 116 | |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 117 | #if DEBUG |
| 118 | /* |
| 119 | * Poisoning the message buffer (with a known pattern). |
| 120 | * Helps in detecting hypothetical RSS communication bugs. |
| 121 | */ |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 122 | memset(&io_buf.msg, 0xA5, msg_size); |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 123 | #endif |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 124 | |
| 125 | err = mhu_receive_data((uint8_t *)&io_buf.reply, &reply_size); |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 126 | if (err != MHU_ERR_NONE) { |
| 127 | return PSA_ERROR_COMMUNICATION_FAILURE; |
| 128 | } |
| 129 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 130 | 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 134 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 135 | 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 140 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 141 | 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 Ban | a7dcfda | 2022-09-16 13:42:29 +0200 | [diff] [blame] | 147 | /* Clear the MHU message buffer to remove assets from memory */ |
| 148 | memset(&io_buf, 0x0, sizeof(io_buf)); |
| 149 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 150 | seq_num++; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 151 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 152 | return return_val; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | int 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 Vincze | 7a93f9e | 2022-12-01 15:10:34 +0100 | [diff] [blame] | 161 | 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | err = mhu_init_receiver(mhu_receiver_base); |
| 170 | if (err != MHU_ERR_NONE) { |
David Vincze | 7a93f9e | 2022-12-01 15:10:34 +0100 | [diff] [blame] | 171 | 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 Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | return 0; |
| 180 | } |