summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAntonio Nino Diaz <antonio.ninodiaz@arm.com>2018-11-08 10:58:26 +0000
committerAntonio Nino Diaz <antonio.ninodiaz@arm.com>2018-12-11 15:04:14 +0000
commite46924ea53f8c2c300b1ab1cf9e0c5676511ae67 (patch)
tree5ee86e7eeedf7c5e8d95695a9e21dbb826a52e51 /lib
parentfdd08233fb104176d3480cdcb23aacb2ec6e2b83 (diff)
SPM: Introduce SPRT C client library
Change-Id: I2f110b4d06d2821d8bdf818ab7523a5c0a6b9ab9 Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/sprt/aarch64/sprt_client_helpers.S41
-rw-r--r--lib/sprt/sprt_client.c80
-rw-r--r--lib/sprt/sprt_client.mk12
-rw-r--r--lib/sprt/sprt_client_private.h35
-rw-r--r--lib/sprt/sprt_queue.c104
-rw-r--r--lib/sprt/sprt_queue.h47
6 files changed, 319 insertions, 0 deletions
diff --git a/lib/sprt/aarch64/sprt_client_helpers.S b/lib/sprt/aarch64/sprt_client_helpers.S
new file mode 100644
index 0000000..4606854
--- /dev/null
+++ b/lib/sprt/aarch64/sprt_client_helpers.S
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+ .globl sprt_client_svc
+
+func sprt_client_svc
+ /*
+ * Save the address of the svc_args structure on the stack.
+ *
+ * Although x0 contains an 8-byte value, we are allocating 16 bytes
+ * on the stack to respect the 16-byte stack-alignment.
+ */
+ str x0, [sp, #-16]!
+
+ /* Load the SVC arguments values into the appropriate registers. */
+ ldp x6, x7, [x0, #48]
+ ldp x4, x5, [x0, #32]
+ ldp x2, x3, [x0, #16]
+ ldp x0, x1, [x0, #0]
+
+ svc #0
+
+ /*
+ * Pop the svc_args structure address from the stack into a caller-saved
+ * register.
+ */
+ ldr x9, [sp], #16
+
+ /*
+ * The return values are stored in x0-x3, put them in the svc_args
+ * return structure.
+ */
+ stp x0, x1, [x9, #0]
+ stp x2, x3, [x9, #16]
+ ret
+endfunc sprt_client_svc
diff --git a/lib/sprt/sprt_client.c b/lib/sprt/sprt_client.c
new file mode 100644
index 0000000..41f5307
--- /dev/null
+++ b/lib/sprt/sprt_client.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <sprt_svc.h>
+#include <stddef.h>
+
+#include "sprt_client.h"
+#include "sprt_client_private.h"
+#include "sprt_common.h"
+#include "sprt_queue.h"
+
+uint32_t sprt_version(void)
+{
+ struct svc_args args;
+
+ args.arg0 = SPRT_VERSION;
+
+ return sprt_client_svc(&args);
+}
+
+void sprt_wait_for_messages(void)
+{
+ struct svc_args args;
+
+ args.arg0 = SPRT_YIELD_AARCH64;
+
+ sprt_client_svc(&args);
+}
+
+/*
+ * Variable that points to the memory buffer that contains the queues used by
+ * this Secure Partition.
+ */
+static void *queue_messages;
+
+void sprt_initialize_queues(void *buffer_base)
+{
+ queue_messages = buffer_base;
+}
+
+int sprt_get_next_message(struct sprt_queue_entry_message *message,
+ int queue_num)
+{
+ struct sprt_queue *q = queue_messages;
+
+ while (queue_num-- > 0) {
+ uintptr_t next_addr = (uintptr_t)q + sizeof(struct sprt_queue) +
+ q->entry_num * q->entry_size;
+ q = (struct sprt_queue *) next_addr;
+ }
+
+ return sprt_queue_pop(q, message);
+}
+
+void sprt_message_end(struct sprt_queue_entry_message *message,
+ u_register_t arg0, u_register_t arg1, u_register_t arg2,
+ u_register_t arg3)
+{
+ struct svc_args args;
+
+ if (message->type == SPRT_MSG_TYPE_SERVICE_REQUEST) {
+ args.arg0 = SPRT_PUT_RESPONSE_AARCH64;
+ args.arg1 = message->token;
+ }
+
+ args.arg2 = arg0;
+ args.arg3 = arg1;
+ args.arg4 = arg2;
+ args.arg5 = arg3;
+ args.arg6 = ((uint32_t)message->service_handle << 16U)
+ | message->client_id;
+ args.arg7 = message->session_id;
+
+ sprt_client_svc(&args);
+}
diff --git a/lib/sprt/sprt_client.mk b/lib/sprt/sprt_client.mk
new file mode 100644
index 0000000..8d22430
--- /dev/null
+++ b/lib/sprt/sprt_client.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+SPRT_LIB_SOURCES := $(addprefix lib/sprt/, \
+ ${ARCH}/sprt_client_helpers.S \
+ sprt_client.c \
+ sprt_queue.c)
+
+SPRT_LIB_INCLUDES := -Iinclude/lib/sprt/
diff --git a/lib/sprt/sprt_client_private.h b/lib/sprt/sprt_client_private.h
new file mode 100644
index 0000000..57d8dc5
--- /dev/null
+++ b/lib/sprt/sprt_client_private.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPRT_CLIENT_PRIVATE_H
+#define SPRT_CLIENT_PRIVATE_H
+
+#include <stdint.h>
+
+struct svc_args {
+ u_register_t arg0;
+ u_register_t arg1;
+ u_register_t arg2;
+ u_register_t arg3;
+ u_register_t arg4;
+ u_register_t arg5;
+ u_register_t arg6;
+ u_register_t arg7;
+};
+
+/*
+ * Invoke an SVC call.
+ *
+ * The arguments to pass through the SVC call must be stored in the svc_args
+ * structure. The return values of the SVC call will be stored in the same
+ * structure (overriding the input arguments).
+ *
+ * Returns the first return value. It is equivalent to args.arg0 but is also
+ * provided as the return value for convenience.
+ */
+u_register_t sprt_client_svc(struct svc_args *args);
+
+#endif /* SPRT_CLIENT_PRIVATE_H */
diff --git a/lib/sprt/sprt_queue.c b/lib/sprt/sprt_queue.c
new file mode 100644
index 0000000..2bd4139
--- /dev/null
+++ b/lib/sprt/sprt_queue.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "sprt_queue.h"
+
+void sprt_queue_init(void *queue_base, uint32_t entry_num, uint32_t entry_size)
+{
+ assert(queue_base != NULL);
+ assert(entry_size > 0U);
+ assert(entry_num > 0U);
+
+ struct sprt_queue *queue = (struct sprt_queue *)queue_base;
+
+ queue->entry_num = entry_num;
+ queue->entry_size = entry_size;
+ queue->idx_write = 0U;
+ queue->idx_read = 0U;
+
+ memset(queue->data, 0, entry_num * entry_size);
+}
+
+int sprt_queue_is_empty(void *queue_base)
+{
+ assert(queue_base != NULL);
+
+ struct sprt_queue *queue = (struct sprt_queue *)queue_base;
+
+ return (queue->idx_write == queue->idx_read);
+}
+
+int sprt_queue_is_full(void *queue_base)
+{
+ assert(queue_base != NULL);
+
+ struct sprt_queue *queue = (struct sprt_queue *)queue_base;
+
+ uint32_t idx_next_write = (queue->idx_write + 1) % queue->entry_num;
+
+ return (idx_next_write == queue->idx_read);
+}
+
+int sprt_queue_push(void *queue_base, const void *entry)
+{
+ assert(entry != NULL);
+ assert(queue_base != NULL);
+
+ if (sprt_queue_is_full(queue_base) != 0) {
+ return -ENOMEM;
+ }
+
+ struct sprt_queue *queue = (struct sprt_queue *)queue_base;
+
+ uint8_t *dst_entry = &queue->data[queue->entry_size * queue->idx_write];
+
+ memcpy(dst_entry, entry, queue->entry_size);
+
+ /*
+ * Make sure that the message data is visible before increasing the
+ * counter of available messages.
+ */
+ __asm__ volatile("dmb st" ::: "memory");
+
+ queue->idx_write = (queue->idx_write + 1) % queue->entry_num;
+
+ __asm__ volatile("dmb st" ::: "memory");
+
+ return 0;
+}
+
+int sprt_queue_pop(void *queue_base, void *entry)
+{
+ assert(entry != NULL);
+ assert(queue_base != NULL);
+
+ if (sprt_queue_is_empty(queue_base) != 0) {
+ return -ENOENT;
+ }
+
+ struct sprt_queue *queue = (struct sprt_queue *)queue_base;
+
+ uint8_t *src_entry = &queue->data[queue->entry_size * queue->idx_read];
+
+ memcpy(entry, src_entry, queue->entry_size);
+
+ /*
+ * Make sure that the message data is visible before increasing the
+ * counter of read messages.
+ */
+ __asm__ volatile("dmb st" ::: "memory");
+
+ queue->idx_read = (queue->idx_read + 1) % queue->entry_num;
+
+ __asm__ volatile("dmb st" ::: "memory");
+
+ return 0;
+}
diff --git a/lib/sprt/sprt_queue.h b/lib/sprt/sprt_queue.h
new file mode 100644
index 0000000..4ea1bc2
--- /dev/null
+++ b/lib/sprt/sprt_queue.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPRT_QUEUE_H
+#define SPRT_QUEUE_H
+
+#include <stdint.h>
+
+/* Struct that defines a queue. Not to be used directly. */
+struct __attribute__((__packed__)) sprt_queue {
+ uint32_t entry_num; /* Number of entries */
+ uint32_t entry_size; /* Size of an entry */
+ uint32_t idx_write; /* Index of first empty entry */
+ uint32_t idx_read; /* Index of first entry to read */
+ uint8_t data[0]; /* Start of data */
+};
+
+#define SPRT_QUEUE_HEADER_SIZE (sizeof(struct sprt_queue))
+
+/*
+ * Initializes a memory region to be used as a queue of the given number of
+ * entries with the specified size.
+ */
+void sprt_queue_init(void *queue_base, uint32_t entry_num, uint32_t entry_size);
+
+/* Returns 1 if the queue is empty, 0 otherwise */
+int sprt_queue_is_empty(void *queue_base);
+
+/* Returns 1 if the queue is full, 0 otherwise */
+int sprt_queue_is_full(void *queue_base);
+
+/*
+ * Pushes a new entry intro the queue. Returns 0 on success, -ENOMEM if the
+ * queue is full.
+ */
+int sprt_queue_push(void *queue_base, const void *entry);
+
+/*
+ * Pops an entry from the queue. Returns 0 on success, -ENOENT if the queue is
+ * empty.
+ */
+int sprt_queue_pop(void *queue_base, void *entry);
+
+#endif /* SPRT_QUEUE_H */