From 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:13:47 +0200 Subject: Adding upstream version 2.8.0+dfsg. Signed-off-by: Daniel Baumann --- drivers/arm/rss/rss_comms.c | 170 +++++++++++++++++++++ drivers/arm/rss/rss_comms.mk | 22 +++ drivers/arm/rss/rss_comms_protocol.c | 75 +++++++++ drivers/arm/rss/rss_comms_protocol.h | 67 ++++++++ drivers/arm/rss/rss_comms_protocol_embed.c | 91 +++++++++++ drivers/arm/rss/rss_comms_protocol_embed.h | 47 ++++++ .../arm/rss/rss_comms_protocol_pointer_access.c | 74 +++++++++ .../arm/rss/rss_comms_protocol_pointer_access.h | 42 +++++ 8 files changed, 588 insertions(+) create mode 100644 drivers/arm/rss/rss_comms.c create mode 100644 drivers/arm/rss/rss_comms.mk create mode 100644 drivers/arm/rss/rss_comms_protocol.c create mode 100644 drivers/arm/rss/rss_comms_protocol.h create mode 100644 drivers/arm/rss/rss_comms_protocol_embed.c create mode 100644 drivers/arm/rss/rss_comms_protocol_embed.h create mode 100644 drivers/arm/rss/rss_comms_protocol_pointer_access.c create mode 100644 drivers/arm/rss/rss_comms_protocol_pointer_access.h (limited to 'drivers/arm/rss') diff --git a/drivers/arm/rss/rss_comms.c b/drivers/arm/rss/rss_comms.c new file mode 100644 index 0000000..5e224e1 --- /dev/null +++ b/drivers/arm/rss/rss_comms.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +/* Union as message space and reply space are never used at the same time, and this saves space as + * we can overlap them. + */ +union __packed __attribute__((aligned(4))) rss_comms_io_buffer_t { + struct serialized_rss_comms_msg_t msg; + struct serialized_rss_comms_reply_t reply; +}; + +static uint8_t select_protocol_version(const psa_invec *in_vec, size_t in_len, + const psa_outvec *out_vec, size_t out_len) +{ + size_t comms_mhu_msg_size; + size_t comms_embed_msg_min_size; + size_t comms_embed_reply_min_size; + size_t in_size_total = 0; + size_t out_size_total = 0; + size_t i; + + for (i = 0U; i < in_len; ++i) { + in_size_total += in_vec[i].len; + } + for (i = 0U; i < out_len; ++i) { + out_size_total += out_vec[i].len; + } + + comms_mhu_msg_size = mhu_get_max_message_size(); + + comms_embed_msg_min_size = sizeof(struct serialized_rss_comms_header_t) + + sizeof(struct rss_embed_msg_t) - + PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE; + + comms_embed_reply_min_size = sizeof(struct serialized_rss_comms_header_t) + + sizeof(struct rss_embed_reply_t) - + PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE; + + /* Use embed if we can pack into one message and reply, else use + * pointer_access. The underlying MHU transport protocol uses a + * single uint32_t to track the length, so the amount of data that + * can be in a message is 4 bytes less than mhu_get_max_message_size + * reports. + * + * TODO tune this with real performance numbers, it's possible a + * pointer_access message is less performant than multiple embed + * messages due to ATU configuration costs to allow access to the + * pointers. + */ + if ((comms_embed_msg_min_size + in_size_total > comms_mhu_msg_size - sizeof(uint32_t)) + || (comms_embed_reply_min_size + out_size_total > comms_mhu_msg_size) - sizeof(uint32_t)) { + return RSS_COMMS_PROTOCOL_POINTER_ACCESS; + } else { + return RSS_COMMS_PROTOCOL_EMBED; + } +} + +psa_status_t psa_call(psa_handle_t handle, int32_t type, const psa_invec *in_vec, size_t in_len, + psa_outvec *out_vec, size_t out_len) +{ + /* Declared statically to avoid using huge amounts of stack space. Maybe revisit if + * functions not being reentrant becomes a problem. + */ + static union rss_comms_io_buffer_t io_buf; + enum mhu_error_t err; + psa_status_t status; + static uint8_t seq_num = 1U; + size_t msg_size; + size_t reply_size = sizeof(io_buf.reply); + psa_status_t return_val; + size_t idx; + + if (type > INT16_MAX || type < INT16_MIN || in_len > PSA_MAX_IOVEC + || out_len > PSA_MAX_IOVEC) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + io_buf.msg.header.seq_num = seq_num, + /* No need to distinguish callers (currently concurrent calls are not supported). */ + io_buf.msg.header.client_id = 1U, + io_buf.msg.header.protocol_ver = select_protocol_version(in_vec, in_len, out_vec, out_len); + + status = rss_protocol_serialize_msg(handle, type, in_vec, in_len, out_vec, + out_len, &io_buf.msg, &msg_size); + if (status != PSA_SUCCESS) { + return status; + } + + VERBOSE("[RSS-COMMS] Sending message\n"); + VERBOSE("protocol_ver=%u\n", io_buf.msg.header.protocol_ver); + VERBOSE("seq_num=%u\n", io_buf.msg.header.seq_num); + VERBOSE("client_id=%u\n", io_buf.msg.header.client_id); + for (idx = 0; idx < in_len; idx++) { + VERBOSE("in_vec[%lu].len=%lu\n", idx, in_vec[idx].len); + VERBOSE("in_vec[%lu].buf=%p\n", idx, (void *)in_vec[idx].base); + } + + err = mhu_send_data((uint8_t *)&io_buf.msg, msg_size); + if (err != MHU_ERR_NONE) { + return PSA_ERROR_COMMUNICATION_FAILURE; + } + +#if DEBUG + /* + * Poisoning the message buffer (with a known pattern). + * Helps in detecting hypothetical RSS communication bugs. + */ + memset(&io_buf.msg, 0xA5, msg_size); +#endif + + err = mhu_receive_data((uint8_t *)&io_buf.reply, &reply_size); + if (err != MHU_ERR_NONE) { + return PSA_ERROR_COMMUNICATION_FAILURE; + } + + VERBOSE("[RSS-COMMS] Received reply\n"); + VERBOSE("protocol_ver=%u\n", io_buf.reply.header.protocol_ver); + VERBOSE("seq_num=%u\n", io_buf.reply.header.seq_num); + VERBOSE("client_id=%u\n", io_buf.reply.header.client_id); + + status = rss_protocol_deserialize_reply(out_vec, out_len, &return_val, + &io_buf.reply, reply_size); + if (status != PSA_SUCCESS) { + return status; + } + + VERBOSE("return_val=%d\n", return_val); + for (idx = 0U; idx < out_len; idx++) { + VERBOSE("out_vec[%lu].len=%lu\n", idx, out_vec[idx].len); + VERBOSE("out_vec[%lu].buf=%p\n", idx, (void *)out_vec[idx].base); + } + + /* Clear the MHU message buffer to remove assets from memory */ + memset(&io_buf, 0x0, sizeof(io_buf)); + + seq_num++; + + return return_val; +} + +int rss_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base) +{ + enum mhu_error_t err; + + err = mhu_init_sender(mhu_sender_base); + if (err != MHU_ERR_NONE) { + ERROR("[RSS-COMMS] Host to RSS MHU driver initialization failed: %d\n", err); + return -1; + } + + err = mhu_init_receiver(mhu_receiver_base); + if (err != MHU_ERR_NONE) { + ERROR("[RSS-COMMS] RSS to Host MHU driver initialization failed: %d\n", err); + return -1; + } + + return 0; +} diff --git a/drivers/arm/rss/rss_comms.mk b/drivers/arm/rss/rss_comms.mk new file mode 100644 index 0000000..c1c994b --- /dev/null +++ b/drivers/arm/rss/rss_comms.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +$(warning "RSS driver is an experimental feature") + +RSS_COMMS_SOURCES := $(addprefix drivers/arm/rss/, \ + rss_comms.c \ + rss_comms_protocol.c \ + rss_comms_protocol_embed.c \ + rss_comms_protocol_pointer_access.c \ + ) + +RSS_COMMS_SOURCES += $(addprefix drivers/arm/mhu/, \ + mhu_v2_x.c \ + mhu_wrapper_v2_x.c \ + ) + +PLAT_INCLUDES += -Idrivers/arm/rss \ + -Idrivers/arm/mhu diff --git a/drivers/arm/rss/rss_comms_protocol.c b/drivers/arm/rss/rss_comms_protocol.c new file mode 100644 index 0000000..a1b1b58 --- /dev/null +++ b/drivers/arm/rss/rss_comms_protocol.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include + +#include +#include "rss_comms_protocol.h" + +psa_status_t rss_protocol_serialize_msg(psa_handle_t handle, + int16_t type, + const psa_invec *in_vec, + uint8_t in_len, + const psa_outvec *out_vec, + uint8_t out_len, + struct serialized_rss_comms_msg_t *msg, + size_t *msg_len) +{ + psa_status_t status; + + assert(msg != NULL); + assert(msg_len != NULL); + assert(in_vec != NULL); + + switch (msg->header.protocol_ver) { + case RSS_COMMS_PROTOCOL_EMBED: + status = rss_protocol_embed_serialize_msg(handle, type, in_vec, in_len, out_vec, + out_len, &msg->msg.embed, msg_len); + if (status != PSA_SUCCESS) { + return status; + } + break; + case RSS_COMMS_PROTOCOL_POINTER_ACCESS: + status = rss_protocol_pointer_access_serialize_msg(handle, type, in_vec, in_len, + out_vec, out_len, + &msg->msg.pointer_access, + msg_len); + if (status != PSA_SUCCESS) { + return status; + } + break; + default: + return PSA_ERROR_NOT_SUPPORTED; + } + + *msg_len += sizeof(struct serialized_rss_comms_header_t); + + return PSA_SUCCESS; +} + +psa_status_t rss_protocol_deserialize_reply(psa_outvec *out_vec, + uint8_t out_len, + psa_status_t *return_val, + const struct serialized_rss_comms_reply_t *reply, + size_t reply_size) +{ + assert(reply != NULL); + assert(return_val != NULL); + + switch (reply->header.protocol_ver) { + case RSS_COMMS_PROTOCOL_EMBED: + return rss_protocol_embed_deserialize_reply(out_vec, out_len, return_val, + &reply->reply.embed, reply_size); + case RSS_COMMS_PROTOCOL_POINTER_ACCESS: + return rss_protocol_pointer_access_deserialize_reply(out_vec, out_len, return_val, + &reply->reply.pointer_access, + reply_size); + default: + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_SUCCESS; +} diff --git a/drivers/arm/rss/rss_comms_protocol.h b/drivers/arm/rss/rss_comms_protocol.h new file mode 100644 index 0000000..9a38057 --- /dev/null +++ b/drivers/arm/rss/rss_comms_protocol.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __RSS_COMMS_PROTOCOL_H__ +#define __RSS_COMMS_PROTOCOL_H__ + +#include +#include + +#include +#include "rss_comms_protocol_embed.h" +#include "rss_comms_protocol_pointer_access.h" + +enum rss_comms_protocol_version_t { + RSS_COMMS_PROTOCOL_EMBED = 0, + RSS_COMMS_PROTOCOL_POINTER_ACCESS = 1, +}; + +struct __packed serialized_rss_comms_header_t { + uint8_t protocol_ver; + uint8_t seq_num; + uint16_t client_id; +}; + +/* MHU message passed from Host to RSS to deliver a PSA client call */ +struct __packed serialized_rss_comms_msg_t { + struct serialized_rss_comms_header_t header; + union __packed { + struct rss_embed_msg_t embed; + struct rss_pointer_access_msg_t pointer_access; + } msg; +}; + +/* MHU reply message to hold the PSA client reply result returned by RSS */ +struct __packed serialized_rss_comms_reply_t { + struct serialized_rss_comms_header_t header; + union __packed { + struct rss_embed_reply_t embed; + struct rss_pointer_access_reply_t pointer_access; + } reply; +}; + +/* in_len and out_len are uint8_ts, therefore if there are more than 255 iovecs + * an error may occur. + */ +CASSERT(PSA_MAX_IOVEC <= UINT8_MAX, assert_rss_comms_max_iovec_too_large); + +psa_status_t rss_protocol_serialize_msg(psa_handle_t handle, + int16_t type, + const psa_invec *in_vec, + uint8_t in_len, + const psa_outvec *out_vec, + uint8_t out_len, + struct serialized_rss_comms_msg_t *msg, + size_t *msg_len); + +psa_status_t rss_protocol_deserialize_reply(psa_outvec *out_vec, + uint8_t out_len, + psa_status_t *return_val, + const struct serialized_rss_comms_reply_t *reply, + size_t reply_size); + +#endif /* __RSS_COMMS_PROTOCOL_H__ */ diff --git a/drivers/arm/rss/rss_comms_protocol_embed.c b/drivers/arm/rss/rss_comms_protocol_embed.c new file mode 100644 index 0000000..801b7cc --- /dev/null +++ b/drivers/arm/rss/rss_comms_protocol_embed.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include +#include "rss_comms_protocol_embed.h" + +#define TYPE_OFFSET (16U) +#define TYPE_MASK (0xFFFFUL << TYPE_OFFSET) +#define IN_LEN_OFFSET (8U) +#define IN_LEN_MASK (0xFFUL << IN_LEN_OFFSET) +#define OUT_LEN_OFFSET (0U) +#define OUT_LEN_MASK (0xFFUL << OUT_LEN_OFFSET) + +#define PARAM_PACK(type, in_len, out_len) \ + (((((uint32_t)type) << TYPE_OFFSET) & TYPE_MASK) | \ + ((((uint32_t)in_len) << IN_LEN_OFFSET) & IN_LEN_MASK) | \ + ((((uint32_t)out_len) << OUT_LEN_OFFSET) & OUT_LEN_MASK)) + +psa_status_t rss_protocol_embed_serialize_msg(psa_handle_t handle, + int16_t type, + const psa_invec *in_vec, + uint8_t in_len, + const psa_outvec *out_vec, + uint8_t out_len, + struct rss_embed_msg_t *msg, + size_t *msg_len) +{ + uint32_t payload_size = 0; + uint32_t i; + + assert(msg != NULL); + assert(msg_len != NULL); + assert(in_vec != NULL); + + msg->ctrl_param = PARAM_PACK(type, in_len, out_len); + msg->handle = handle; + + /* Fill msg iovec lengths */ + for (i = 0U; i < in_len; ++i) { + msg->io_size[i] = in_vec[i].len; + } + for (i = 0U; i < out_len; ++i) { + msg->io_size[in_len + i] = out_vec[i].len; + } + + for (i = 0U; i < in_len; ++i) { + if (in_vec[i].len > sizeof(msg->trailer) - payload_size) { + return PSA_ERROR_INVALID_ARGUMENT; + } + memcpy(msg->trailer + payload_size, in_vec[i].base, in_vec[i].len); + payload_size += in_vec[i].len; + } + + /* Output the actual size of the message, to optimize sending */ + *msg_len = sizeof(*msg) - sizeof(msg->trailer) + payload_size; + + return PSA_SUCCESS; +} + +psa_status_t rss_protocol_embed_deserialize_reply(psa_outvec *out_vec, + uint8_t out_len, + psa_status_t *return_val, + const struct rss_embed_reply_t *reply, + size_t reply_size) +{ + uint32_t payload_offset = 0; + uint32_t i; + + assert(reply != NULL); + assert(return_val != NULL); + + for (i = 0U; i < out_len; ++i) { + if (sizeof(reply) - sizeof(reply->trailer) + payload_offset > reply_size) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memcpy(out_vec[i].base, reply->trailer + payload_offset, out_vec[i].len); + payload_offset += out_vec[i].len; + } + + *return_val = reply->return_val; + + return PSA_SUCCESS; +} diff --git a/drivers/arm/rss/rss_comms_protocol_embed.h b/drivers/arm/rss/rss_comms_protocol_embed.h new file mode 100644 index 0000000..c81c795 --- /dev/null +++ b/drivers/arm/rss/rss_comms_protocol_embed.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __RSS_COMMS_PROTOCOL_EMBED_H__ +#define __RSS_COMMS_PROTOCOL_EMBED_H__ + +#include + +#include + +#include + + + +struct __packed rss_embed_msg_t { + psa_handle_t handle; + uint32_t ctrl_param; /* type, in_len, out_len */ + uint16_t io_size[PSA_MAX_IOVEC]; + uint8_t trailer[PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE]; +}; + +struct __packed rss_embed_reply_t { + int32_t return_val; + uint16_t out_size[PSA_MAX_IOVEC]; + uint8_t trailer[PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE]; +}; + +psa_status_t rss_protocol_embed_serialize_msg(psa_handle_t handle, + int16_t type, + const psa_invec *in_vec, + uint8_t in_len, + const psa_outvec *out_vec, + uint8_t out_len, + struct rss_embed_msg_t *msg, + size_t *msg_len); + +psa_status_t rss_protocol_embed_deserialize_reply(psa_outvec *out_vec, + uint8_t out_len, + psa_status_t *return_val, + const struct rss_embed_reply_t *reply, + size_t reply_size); + +#endif /* __RSS_COMMS_PROTOCOL_EMBED_H__ */ diff --git a/drivers/arm/rss/rss_comms_protocol_pointer_access.c b/drivers/arm/rss/rss_comms_protocol_pointer_access.c new file mode 100644 index 0000000..5007b9d --- /dev/null +++ b/drivers/arm/rss/rss_comms_protocol_pointer_access.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include + +#include "rss_comms_protocol_pointer_access.h" + +#define TYPE_OFFSET (16U) +#define TYPE_MASK (0xFFFFUL << TYPE_OFFSET) +#define IN_LEN_OFFSET (8U) +#define IN_LEN_MASK (0xFFUL << IN_LEN_OFFSET) +#define OUT_LEN_OFFSET (0U) +#define OUT_LEN_MASK (0xFFUL << OUT_LEN_OFFSET) + +#define PARAM_PACK(type, in_len, out_len) \ + (((((uint32_t)type) << TYPE_OFFSET) & TYPE_MASK) | \ + ((((uint32_t)in_len) << IN_LEN_OFFSET) & IN_LEN_MASK) | \ + ((((uint32_t)out_len) << OUT_LEN_OFFSET) & OUT_LEN_MASK)) + +psa_status_t rss_protocol_pointer_access_serialize_msg(psa_handle_t handle, + int16_t type, + const psa_invec *in_vec, + uint8_t in_len, + const psa_outvec *out_vec, + uint8_t out_len, + struct rss_pointer_access_msg_t *msg, + size_t *msg_len) +{ + unsigned int i; + + assert(msg != NULL); + assert(msg_len != NULL); + assert(in_vec != NULL); + + msg->ctrl_param = PARAM_PACK(type, in_len, out_len); + msg->handle = handle; + + /* Fill msg iovec lengths */ + for (i = 0U; i < in_len; ++i) { + msg->io_sizes[i] = in_vec[i].len; + msg->host_ptrs[i] = (uint64_t)in_vec[i].base; + } + for (i = 0U; i < out_len; ++i) { + msg->io_sizes[in_len + i] = out_vec[i].len; + msg->host_ptrs[in_len + i] = (uint64_t)out_vec[i].base; + } + + *msg_len = sizeof(*msg); + + return PSA_SUCCESS; +} + +psa_status_t rss_protocol_pointer_access_deserialize_reply(psa_outvec *out_vec, + uint8_t out_len, + psa_status_t *return_val, + const struct rss_pointer_access_reply_t *reply, + size_t reply_size) +{ + unsigned int i; + + assert(reply != NULL); + assert(return_val != NULL); + + for (i = 0U; i < out_len; ++i) { + out_vec[i].len = reply->out_sizes[i]; + } + + *return_val = reply->return_val; + + return PSA_SUCCESS; +} diff --git a/drivers/arm/rss/rss_comms_protocol_pointer_access.h b/drivers/arm/rss/rss_comms_protocol_pointer_access.h new file mode 100644 index 0000000..a4d054b --- /dev/null +++ b/drivers/arm/rss/rss_comms_protocol_pointer_access.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __RSS_COMMS_PROTOCOL_POINTER_ACCESS_H__ +#define __RSS_COMMS_PROTOCOL_POINTER_ACCESS_H__ + +#include + +#include + +struct __packed rss_pointer_access_msg_t { + psa_handle_t handle; + uint32_t ctrl_param; + uint32_t io_sizes[PSA_MAX_IOVEC]; + uint64_t host_ptrs[PSA_MAX_IOVEC]; +}; + +struct __packed rss_pointer_access_reply_t { + int32_t return_val; + uint32_t out_sizes[PSA_MAX_IOVEC]; +}; + +psa_status_t rss_protocol_pointer_access_serialize_msg(psa_handle_t handle, + int16_t type, + const psa_invec *in_vec, + uint8_t in_len, + const psa_outvec *out_vec, + uint8_t out_len, + struct rss_pointer_access_msg_t *msg, + size_t *msg_len); + +psa_status_t rss_protocol_pointer_access_deserialize_reply(psa_outvec *out_vec, + uint8_t out_len, + psa_status_t *return_val, + const struct rss_pointer_access_reply_t *reply, + size_t reply_size); + +#endif /* __RSS_COMMS_PROTOCOL_POINTER_ACCESS_H__ */ -- cgit v1.2.3