Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 1 | /* |
| 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 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) - |
| 45 | 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) - |
| 49 | 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 | */ |
| 62 | if ((comms_embed_msg_min_size + in_size_total > comms_mhu_msg_size - sizeof(uint32_t)) |
| 63 | || (comms_embed_reply_min_size + out_size_total > comms_mhu_msg_size) - sizeof(uint32_t)) { |
| 64 | return RSS_COMMS_PROTOCOL_POINTER_ACCESS; |
| 65 | } else { |
| 66 | return RSS_COMMS_PROTOCOL_EMBED; |
| 67 | } |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 68 | } |
| 69 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 70 | 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] | 71 | psa_outvec *out_vec, size_t out_len) |
| 72 | { |
| 73 | enum mhu_error_t err; |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 74 | psa_status_t status; |
| 75 | static uint8_t seq_num = 1U; |
| 76 | size_t msg_size; |
| 77 | size_t reply_size = sizeof(io_buf.reply); |
| 78 | psa_status_t return_val; |
| 79 | size_t idx; |
| 80 | /* Declared statically to avoid using huge amounts of stack space. Maybe revisit if |
| 81 | * functions not being reentrant becomes a problem. |
| 82 | */ |
| 83 | static union rss_comms_io_buffer_t io_buf; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 84 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 85 | if (type > INT16_MAX || type < INT16_MIN || in_len > PSA_MAX_IOVEC |
| 86 | || out_len > PSA_MAX_IOVEC) { |
| 87 | return PSA_ERROR_INVALID_ARGUMENT; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 88 | } |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 89 | |
| 90 | io_buf.msg.header.seq_num = seq_num, |
| 91 | /* No need to distinguish callers (currently concurrent calls are not supported). */ |
| 92 | io_buf.msg.header.client_id = 1U, |
| 93 | io_buf.msg.header.protocol_ver = select_protocol_version(in_vec, in_len, out_vec, out_len); |
| 94 | |
| 95 | status = rss_protocol_serialize_msg(handle, type, in_vec, in_len, out_vec, |
| 96 | out_len, &io_buf.msg, &msg_size); |
| 97 | if (status != PSA_SUCCESS) { |
| 98 | return status; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 99 | } |
| 100 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 101 | VERBOSE("[RSS-COMMS] Sending message\n"); |
| 102 | VERBOSE("protocol_ver=%u\n", io_buf.msg.header.protocol_ver); |
| 103 | VERBOSE("seq_num=%u\n", io_buf.msg.header.seq_num); |
| 104 | VERBOSE("client_id=%u\n", io_buf.msg.header.client_id); |
| 105 | for (idx = 0; idx < in_len; idx++) { |
| 106 | VERBOSE("in_vec[%lu].len=%lu\n", idx, in_vec[idx].len); |
| 107 | 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] | 108 | } |
| 109 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 110 | err = mhu_send_data((uint8_t *)&io_buf.msg, msg_size); |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 111 | if (err != MHU_ERR_NONE) { |
| 112 | return PSA_ERROR_COMMUNICATION_FAILURE; |
| 113 | } |
| 114 | |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 115 | #if DEBUG |
| 116 | /* |
| 117 | * Poisoning the message buffer (with a known pattern). |
| 118 | * Helps in detecting hypothetical RSS communication bugs. |
| 119 | */ |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 120 | memset(&io_buf.msg, 0xA5, msg_size); |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 121 | #endif |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 122 | |
| 123 | err = mhu_receive_data((uint8_t *)&io_buf.reply, &reply_size); |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 124 | if (err != MHU_ERR_NONE) { |
| 125 | return PSA_ERROR_COMMUNICATION_FAILURE; |
| 126 | } |
| 127 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 128 | VERBOSE("[RSS-COMMS] Received reply\n"); |
| 129 | VERBOSE("protocol_ver=%u\n", io_buf.reply.header.protocol_ver); |
| 130 | VERBOSE("seq_num=%u\n", io_buf.reply.header.seq_num); |
| 131 | VERBOSE("client_id=%u\n", io_buf.reply.header.client_id); |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 132 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 133 | status = rss_protocol_deserialize_reply(out_vec, out_len, &return_val, |
| 134 | &io_buf.reply, reply_size); |
| 135 | if (status != PSA_SUCCESS) { |
| 136 | return status; |
| 137 | } |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 138 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 139 | VERBOSE("return_val=%d\n", return_val); |
| 140 | for (idx = 0U; idx < out_len; idx++) { |
| 141 | VERBOSE("out_vec[%lu].len=%lu\n", idx, out_vec[idx].len); |
| 142 | VERBOSE("out_vec[%lu].buf=%p\n", idx, (void *)out_vec[idx].base); |
| 143 | } |
| 144 | |
| 145 | seq_num++; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 146 | |
Raef Coles | 734aaac | 2022-06-15 14:37:22 +0100 | [diff] [blame] | 147 | return return_val; |
Tamas Ban | 53ac24f | 2022-01-18 16:32:18 +0100 | [diff] [blame] | 148 | } |
| 149 | |
| 150 | int rss_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base) |
| 151 | { |
| 152 | enum mhu_error_t err; |
| 153 | |
| 154 | err = mhu_init_sender(mhu_sender_base); |
| 155 | if (err != MHU_ERR_NONE) { |
| 156 | ERROR("[RSS-COMMS] Host to RSS MHU driver initialization failed: %d\n", err); |
| 157 | return -1; |
| 158 | } |
| 159 | |
| 160 | err = mhu_init_receiver(mhu_receiver_base); |
| 161 | if (err != MHU_ERR_NONE) { |
| 162 | ERROR("[RSS-COMMS] RSS to Host MHU driver initialization failed: %d\n", err); |
| 163 | return -1; |
| 164 | } |
| 165 | |
| 166 | return 0; |
| 167 | } |