mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-25 14:25:44 +00:00
SPM: Introduce SPRT C host library
Change-Id: If57ec9cc0791f49d9ade83dff9d24ef9047963a8 Co-authored-by: Jean-Paul Etienne <jean-paul.etienne@arm.com> Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
This commit is contained in:
parent
56ae97924d
commit
07c13a30d2
7 changed files with 279 additions and 1 deletions
38
include/lib/sprt/sprt_common.h
Normal file
38
include/lib/sprt/sprt_common.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPRT_COMMON_H
|
||||||
|
#define SPRT_COMMON_H
|
||||||
|
|
||||||
|
#define SPRT_MAX_MSG_ARGS 6
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Message types supported.
|
||||||
|
*/
|
||||||
|
#define SPRT_MSG_TYPE_SERVICE_HANDLE_OPEN 1
|
||||||
|
#define SPRT_MSG_TYPE_SERVICE_HANDLE_CLOSE 2
|
||||||
|
/* TODO: Add other types of SPRT messages. */
|
||||||
|
#define SPRT_MSG_TYPE_SERVICE_TUN_REQUEST 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Struct that defines the layout of the fields corresponding to a request in
|
||||||
|
* shared memory.
|
||||||
|
*/
|
||||||
|
struct __attribute__((__packed__)) sprt_queue_entry_message {
|
||||||
|
uint32_t type; /* Type of message (result of an SPCI call). */
|
||||||
|
uint16_t client_id; /* SPCI client ID */
|
||||||
|
uint16_t service_handle;/* SPCI service handle */
|
||||||
|
uint32_t session_id; /* Optional SPCI session ID */
|
||||||
|
uint32_t token; /* SPCI request token */
|
||||||
|
uint64_t args[SPRT_MAX_MSG_ARGS];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SPRT_QUEUE_ENTRY_MSG_SIZE (sizeof(struct sprt_queue_entry_message))
|
||||||
|
|
||||||
|
#define SPRT_QUEUE_NUM_BLOCKING 0
|
||||||
|
#define SPRT_QUEUE_NUM_NON_BLOCKING 1
|
||||||
|
|
||||||
|
#endif /* SPRT_COMMON_H */
|
26
include/lib/sprt/sprt_host.h
Normal file
26
include/lib/sprt/sprt_host.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef SPRT_HOST_H
|
||||||
|
#define SPRT_HOST_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "sprt_common.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the specified buffer to be used by SPM.
|
||||||
|
*/
|
||||||
|
void sprt_initialize_queues(void *buffer_base, size_t buffer_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Push a message to the queue number `queue_num` in a buffer that has been
|
||||||
|
* initialized by `sprt_initialize_queues`.
|
||||||
|
*/
|
||||||
|
int sprt_push_message(void *buffer_base,
|
||||||
|
const struct sprt_queue_entry_message *message,
|
||||||
|
int queue_num);
|
||||||
|
|
||||||
|
#endif /* SPRT_HOST_H */
|
48
lib/sprt/sprt_host.c
Normal file
48
lib/sprt/sprt_host.c
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "sprt_common.h"
|
||||||
|
#include "sprt_queue.h"
|
||||||
|
|
||||||
|
void sprt_initialize_queues(void *buffer_base, size_t buffer_size)
|
||||||
|
{
|
||||||
|
/* Initialize queue for blocking messages */
|
||||||
|
|
||||||
|
void *blocking_base = buffer_base;
|
||||||
|
uint32_t blocking_num = 4U;
|
||||||
|
size_t blocking_size = SPRT_QUEUE_HEADER_SIZE +
|
||||||
|
SPRT_QUEUE_ENTRY_MSG_SIZE * blocking_num;
|
||||||
|
|
||||||
|
sprt_queue_init(blocking_base, blocking_num, SPRT_QUEUE_ENTRY_MSG_SIZE);
|
||||||
|
|
||||||
|
/* Initialize queue for non-blocking messages */
|
||||||
|
|
||||||
|
void *non_blocking_base = (void *)((uintptr_t)blocking_base + blocking_size);
|
||||||
|
size_t non_blocking_size = buffer_size - blocking_size;
|
||||||
|
uint32_t non_blocking_num = (non_blocking_size - SPRT_QUEUE_HEADER_SIZE) /
|
||||||
|
SPRT_QUEUE_ENTRY_MSG_SIZE;
|
||||||
|
|
||||||
|
sprt_queue_init(non_blocking_base, non_blocking_num, SPRT_QUEUE_ENTRY_MSG_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sprt_push_message(void *buffer_base,
|
||||||
|
const struct sprt_queue_entry_message *message,
|
||||||
|
int queue_num)
|
||||||
|
{
|
||||||
|
struct sprt_queue *q = buffer_base;
|
||||||
|
|
||||||
|
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_push(q, message);
|
||||||
|
}
|
11
lib/sprt/sprt_host.mk
Normal file
11
lib/sprt/sprt_host.mk
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
#
|
||||||
|
|
||||||
|
SPRT_LIB_SOURCES := $(addprefix lib/sprt/, \
|
||||||
|
sprt_host.c \
|
||||||
|
sprt_queue.c)
|
||||||
|
|
||||||
|
SPRT_LIB_INCLUDES := -Iinclude/lib/sprt/
|
104
lib/sprt/sprt_queue.c
Normal file
104
lib/sprt/sprt_queue.c
Normal file
|
@ -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;
|
||||||
|
}
|
47
lib/sprt/sprt_queue.h
Normal file
47
lib/sprt/sprt_queue.h
Normal file
|
@ -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 */
|
|
@ -11,6 +11,8 @@ ifneq (${ARCH},aarch64)
|
||||||
$(error "Error: SPM is only supported on aarch64.")
|
$(error "Error: SPM is only supported on aarch64.")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
include lib/sprt/sprt_host.mk
|
||||||
|
|
||||||
SPM_SOURCES := $(addprefix services/std_svc/spm/, \
|
SPM_SOURCES := $(addprefix services/std_svc/spm/, \
|
||||||
${ARCH}/spm_helpers.S \
|
${ARCH}/spm_helpers.S \
|
||||||
${ARCH}/spm_shim_exceptions.S \
|
${ARCH}/spm_shim_exceptions.S \
|
||||||
|
@ -18,8 +20,10 @@ SPM_SOURCES := $(addprefix services/std_svc/spm/, \
|
||||||
sp_xlat.c \
|
sp_xlat.c \
|
||||||
spci.c \
|
spci.c \
|
||||||
spm_main.c \
|
spm_main.c \
|
||||||
sprt.c)
|
sprt.c) \
|
||||||
|
${SPRT_LIB_SOURCES}
|
||||||
|
|
||||||
|
INCLUDES += ${SPRT_LIB_INCLUDES}
|
||||||
|
|
||||||
# Force SMC Calling Convention 2 when using SPM
|
# Force SMC Calling Convention 2 when using SPM
|
||||||
SMCCC_MAJOR_VERSION := 2
|
SMCCC_MAJOR_VERSION := 2
|
||||||
|
|
Loading…
Add table
Reference in a new issue