mirror of https://github.com/ARMmbed/mbed-os.git
commit
e4dde3460f
|
@ -1,7 +1,7 @@
|
|||
567 Milosch Meriac
|
||||
470 Alessandro Angelino
|
||||
49 Jaeden Amero
|
||||
42 Niklas Hauser
|
||||
568 Milosch Meriac
|
||||
477 Alessandro Angelino
|
||||
72 Jaeden Amero
|
||||
53 Niklas Hauser
|
||||
3 Hugo Vincent
|
||||
3 JaredCJR
|
||||
3 Jim Huang
|
||||
|
|
|
@ -1 +1 @@
|
|||
v0.24.1
|
||||
v0.25.0
|
||||
|
|
|
@ -81,7 +81,7 @@ rsync:
|
|||
# Copying licenses
|
||||
cp $(UVISOR_DIR)/LICENSE* $(TARGET_SUPPORTED)
|
||||
|
||||
TARGET_M%: $(TARGET_SUPPORTED)/*/*/*_m%_*.a
|
||||
TARGET_M%: $(TARGET_SUPPORTED)/*/*/*_cortex_m%*.a
|
||||
@printf "#\n# Copying $@ files...\n"
|
||||
mkdir $(foreach file,$^,$(dir $(file))$@)
|
||||
$(foreach file,$^,mv $(file) $(dir $(file))$@/lib$(notdir $(file));)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include "api/inc/page_allocator_exports.h"
|
||||
#include "api/inc/rpc_exports.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -43,10 +44,15 @@ UVISOR_EXTERN const uint32_t __uvisor_mode;
|
|||
UVISOR_BOX_MAGIC, \
|
||||
UVISOR_BOX_VERSION, \
|
||||
0, \
|
||||
0, \
|
||||
sizeof(RtxBoxIndex), \
|
||||
{ \
|
||||
0, \
|
||||
0, \
|
||||
0, \
|
||||
sizeof(uvisor_rpc_outgoing_message_queue_t), \
|
||||
sizeof(uvisor_rpc_incoming_message_queue_t), \
|
||||
sizeof(uvisor_rpc_fn_group_queue_t), \
|
||||
}, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
acl_list, \
|
||||
acl_list_count \
|
||||
|
@ -74,7 +80,10 @@ UVISOR_EXTERN const uint32_t __uvisor_mode;
|
|||
(UVISOR_MIN_STACK(stack_size) + \
|
||||
(context_size) + \
|
||||
(__uvisor_box_heapsize) + \
|
||||
sizeof(RtxBoxIndex) \
|
||||
sizeof(RtxBoxIndex) + \
|
||||
sizeof(uvisor_rpc_outgoing_message_queue_t) + \
|
||||
sizeof(uvisor_rpc_incoming_message_queue_t) + \
|
||||
sizeof(uvisor_rpc_fn_group_queue_t) \
|
||||
) \
|
||||
* 8) \
|
||||
/ 6)]; \
|
||||
|
@ -83,9 +92,14 @@ UVISOR_EXTERN const uint32_t __uvisor_mode;
|
|||
UVISOR_BOX_MAGIC, \
|
||||
UVISOR_BOX_VERSION, \
|
||||
UVISOR_MIN_STACK(stack_size), \
|
||||
sizeof(RtxBoxIndex), \
|
||||
context_size, \
|
||||
__uvisor_box_heapsize, \
|
||||
sizeof(RtxBoxIndex), \
|
||||
{ \
|
||||
context_size, \
|
||||
sizeof(uvisor_rpc_outgoing_message_queue_t), \
|
||||
sizeof(uvisor_rpc_incoming_message_queue_t), \
|
||||
sizeof(uvisor_rpc_fn_group_queue_t), \
|
||||
}, \
|
||||
__uvisor_box_lib_config, \
|
||||
__uvisor_box_namespace, \
|
||||
acl_list, \
|
||||
|
@ -139,13 +153,6 @@ UVISOR_EXTERN const uint32_t __uvisor_mode;
|
|||
|
||||
#define uvisor_ctx (*__uvisor_ps)
|
||||
|
||||
/* Return the numeric box ID of the current box. */
|
||||
UVISOR_EXTERN int uvisor_box_id_self(void);
|
||||
|
||||
/* Return the numeric box ID of the box that is calling through the most recent
|
||||
* secure gateway. Return -1 if there is no secure gateway calling box. */
|
||||
UVISOR_EXTERN int uvisor_box_id_caller(void);
|
||||
|
||||
/* Copy the box namespace of the specified box ID to the memory provided by
|
||||
* box_namespace. The box_namespace's length must be at least
|
||||
* MAX_BOX_NAMESPACE_LENGTH bytes. Return how many bytes were copied into
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_BOX_ID_H__
|
||||
#define __UVISOR_API_BOX_ID_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
|
||||
/* Return the numeric box ID of the current box. */
|
||||
UVISOR_EXTERN int uvisor_box_id_self(void);
|
||||
|
||||
/* Return the numeric box ID of the box that is calling through the most recent
|
||||
* secure gateway. Return -1 if there is no secure gateway calling box. */
|
||||
UVISOR_EXTERN int uvisor_box_id_caller(void) UVISOR_DEPRECATED;
|
||||
|
||||
#endif /* __UVISOR_API_BOX_ID_H__ */
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_BOX_INIT_H__
|
||||
#define __UVISOR_API_BOX_INIT_H__
|
||||
|
||||
#include "api/inc/uvisor-lib.h"
|
||||
|
||||
UVISOR_EXTERN void __uvisor_lib_box_init(void * lib_config);
|
||||
|
||||
#endif
|
|
@ -18,6 +18,7 @@
|
|||
#define __UVISOR_API_NVIC_VIRTUAL_H__
|
||||
|
||||
#include "api/inc/interrupts.h"
|
||||
#include "api/inc/unvic_exports.h"
|
||||
|
||||
#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
|
||||
#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
|
||||
|
@ -29,5 +30,6 @@
|
|||
#define NVIC_GetActive __NVIC_GetActive
|
||||
#define NVIC_SetPriority vIRQ_SetPriority
|
||||
#define NVIC_GetPriority vIRQ_GetPriority
|
||||
#define NVIC_SystemReset() vIRQ_SystemReset(RESET_REASON_NO_REASON)
|
||||
|
||||
#endif /* __UVISOR_API_NVIC_VIRTUAL_H__ */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define __UVISOR_API_EXPORT_TABLE_EXPORTS_H__
|
||||
|
||||
#include "rt_OsEventObserver.h"
|
||||
#include "api/inc/pool_queue_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* If this magic doesn't match what you get in a TUvisorExportTable, then you
|
||||
|
@ -39,9 +40,21 @@ typedef struct {
|
|||
|
||||
OsEventObserver os_event_observer;
|
||||
|
||||
UvisorPoolTable pool;
|
||||
|
||||
/* This must be the last element of the table so that uvisor-input.S can
|
||||
* export the size statically. */
|
||||
uint32_t size;
|
||||
} TUvisorExportTable;
|
||||
|
||||
static inline TUvisorExportTable const * uvisor_export_table(void)
|
||||
{
|
||||
/* Defined in uvisor-input.S */
|
||||
extern uint32_t uvisor_config;
|
||||
extern uint32_t uvisor_export_table_size;
|
||||
|
||||
uintptr_t uvisor_config_addr = (uintptr_t) &uvisor_config;
|
||||
return (TUvisorExportTable *) (uvisor_config_addr - uvisor_export_table_size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
#define UVISOR_ERROR_INVALID_BOX_ID (-2)
|
||||
#define UVISOR_ERROR_BUFFER_TOO_SMALL (-3)
|
||||
#define UVISOR_ERROR_BOX_NAMESPACE_ANONYMOUS (-4)
|
||||
#define UVISOR_ERROR_BAD_MAGIC (-5)
|
||||
#define UVISOR_ERROR_BAD_VERSION (-6)
|
||||
#define UVISOR_ERROR_OUT_OF_STRUCTURES (-7)
|
||||
#define UVISOR_ERROR_INVALID_PARAMETERS (-8)
|
||||
#define UVISOR_ERROR_NOT_IMPLEMENTED (-9)
|
||||
|
||||
|
||||
#define UVISOR_ERROR_CLASS_MASK (0xFFFF0000UL)
|
||||
|
@ -29,6 +34,7 @@
|
|||
|
||||
typedef enum {
|
||||
USER_NOT_ALLOWED = 1,
|
||||
DEBUG_BOX_HALT,
|
||||
} THaltUserError;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#ifndef __UVISOR_API_INTERRUPTS_H__
|
||||
#define __UVISOR_API_INTERRUPTS_H__
|
||||
|
||||
#include "api/inc/unvic_exports.h"
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -60,4 +61,10 @@ UVISOR_EXTERN void vIRQ_DisableAll(void);
|
|||
* ::vIRQ_DisableAll for more information. */
|
||||
UVISOR_EXTERN void vIRQ_EnableAll(void);
|
||||
|
||||
/** Reset the device.
|
||||
* @warning Currently only the debug box can reset the device.
|
||||
* @param reason[in] Reason for rebooting. Currently not used.
|
||||
*/
|
||||
UVISOR_EXTERN void vIRQ_SystemReset(TResetReason reason);
|
||||
|
||||
#endif /* __UVISOR_API_INTERRUPTS_H__ */
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_LIB_HOOK_EXPORTS_H__
|
||||
#define __UVISOR_API_LIB_HOOK_EXPORTS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Predeclaration */
|
||||
typedef struct uvisor_semaphore UvisorSemaphore;
|
||||
|
||||
/*
|
||||
* uVisor library hooks
|
||||
*
|
||||
* All functions that uVisor needs to call that are implemented in uvisor-lib.
|
||||
* These functions will be run by unprivileged code only. */
|
||||
typedef struct {
|
||||
void (*box_init)(void * lib_config);
|
||||
int (*semaphore_init)(UvisorSemaphore * semaphore, int32_t count);
|
||||
int (*semaphore_pend)(UvisorSemaphore * semaphore, uint32_t timeout_ms);
|
||||
} UvisorLibHooks;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_MAGIC_EXPORTS_H__
|
||||
#define __UVISOR_API_MAGIC_EXPORTS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* udf imm16
|
||||
* UDF - ARMv7M ARM section A7.7.191
|
||||
* 111 1;0 111;1111; <imm4>; 1 01 0; <imm12> (Encoding T2)
|
||||
*/
|
||||
#define UDF_OPCODE(imm16) \
|
||||
((uint32_t) (0xA000F7F0UL | (((uint32_t) (imm16) & 0xFFFU) << 16U) | (((uint32_t) (imm16) & 0xF000UL) >> 12)))
|
||||
|
||||
/** Magics
|
||||
*
|
||||
* The following magics are used to verify various things within uVisor.The
|
||||
* magics are chosen to be one of the explicitly undefined Thumb-2
|
||||
* instructions.
|
||||
*/
|
||||
#if defined(__thumb__) && defined(__thumb2__)
|
||||
#define UVISOR_RPC_GATEWAY_MAGIC_ASYNC UDF_OPCODE(0x07C2)
|
||||
#define UVISOR_RPC_GATEWAY_MAGIC_SYNC UDF_OPCODE(0x07C3)
|
||||
#define UVISOR_POOL_MAGIC UDF_OPCODE(0x07C4)
|
||||
#define UVISOR_POOL_QUEUE_MAGIC UDF_OPCODE(0x07C5)
|
||||
#else
|
||||
#error "Unsupported instruction set. The ARM Thumb-2 instruction set must be supported."
|
||||
#endif /* __thumb__ && __thumb2__ */
|
||||
|
||||
|
||||
#endif /* __UVISOR_API_MAGIC_EXPORTS_H__ */
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef UVISOR_POOL_QUEUE_EXPORTS_H
|
||||
#define UVISOR_POOL_QUEUE_EXPORTS_H
|
||||
|
||||
#include "api/inc/magic_exports.h"
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include "api/inc/uvisor_semaphore_exports.h"
|
||||
#include "api/inc/uvisor_spinlock_exports.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define UVISOR_POOL_QUEUE_NON_BLOCKING (0)
|
||||
#define UVISOR_POOL_QUEUE_BLOCKING (1)
|
||||
|
||||
#define UVISOR_POOL_SLOT_INVALID ((uint8_t) 0xFFU)
|
||||
#define UVISOR_POOL_SLOT_IS_DEQUEUED ((uint8_t) 0xFEU)
|
||||
#define UVISOR_POOL_SLOT_IS_FREE ((uint8_t) 0xFDU)
|
||||
#define UVISOR_POOL_MAX_VALID ((uint8_t) 0xFCU)
|
||||
|
||||
typedef uint8_t uvisor_pool_slot_t;
|
||||
|
||||
typedef struct uvisor_pool_queue_entry {
|
||||
union {
|
||||
struct {
|
||||
/* The next slot in the queue */
|
||||
uvisor_pool_slot_t next;
|
||||
|
||||
/* The previous slot in the queue */
|
||||
uvisor_pool_slot_t prev;
|
||||
} queued;
|
||||
struct {
|
||||
/* If the slot is free, the next available slot in the free list */
|
||||
uvisor_pool_slot_t next;
|
||||
|
||||
/* If the slot is free or dequeued */
|
||||
uvisor_pool_slot_t state;
|
||||
} dequeued;
|
||||
};
|
||||
} uvisor_pool_queue_entry_t;
|
||||
|
||||
/* These are assumed to only be statically allocated, so the management array
|
||||
* in in-place. */
|
||||
typedef struct uvisor_pool {
|
||||
/* Magic that identifies this as a uvisor_pool type. */
|
||||
uint32_t magic;
|
||||
|
||||
/* The array holds slots of data. */
|
||||
void const * array;
|
||||
|
||||
/* The distance between elements in the array. */
|
||||
size_t stride;
|
||||
|
||||
/* The maximum number of elements that could be in the array. */
|
||||
uvisor_pool_slot_t num;
|
||||
|
||||
/* Whether or not the queue can block callers who want to allocate slots
|
||||
* from the pool. If non-zero, when no slots is available in the pool,
|
||||
* callers will be blocked up to their timeout amount of time before giving
|
||||
* up. */
|
||||
int blocking;
|
||||
|
||||
/* The number of items currently allocated from the pool. For testing and
|
||||
* debug purposes only. */
|
||||
uvisor_pool_slot_t num_allocated;
|
||||
|
||||
/* The first free slot. */
|
||||
uvisor_pool_slot_t first_free;
|
||||
|
||||
/* The semaphore is used to block allocations when the pool is full. */
|
||||
UvisorSemaphore semaphore;
|
||||
|
||||
/* The spinlock serializes updates to the management array. */
|
||||
UvisorSpinlock spinlock;
|
||||
|
||||
/* This must be at the end so we can allocate memory for pools by
|
||||
* allocating enough room for the size of the pool appended by an array of
|
||||
* entries. */
|
||||
uvisor_pool_queue_entry_t management_array[];
|
||||
} uvisor_pool_t;
|
||||
|
||||
typedef struct uvisor_pool_queue {
|
||||
/* Magic that identifies this as a uvisor_pool_queue type. */
|
||||
uint32_t magic;
|
||||
|
||||
/* The first allocated slot */
|
||||
uvisor_pool_slot_t head;
|
||||
|
||||
/* The last allocated slot */
|
||||
uvisor_pool_slot_t tail;
|
||||
|
||||
uvisor_pool_t * pool;
|
||||
} uvisor_pool_queue_t;
|
||||
|
||||
/* Intialize a pool.
|
||||
* Return 0 on success, non-zero otherwise. */
|
||||
UVISOR_EXTERN int uvisor_pool_init(uvisor_pool_t * pool, void * array, size_t stride, size_t num, int blocking);
|
||||
|
||||
/* Initialize a pool queue.
|
||||
* Return 0 on success, non-zero otherwise. */
|
||||
UVISOR_EXTERN int uvisor_pool_queue_init(uvisor_pool_queue_t * pool_queue, uvisor_pool_t * pool, void * array, size_t stride, size_t num, int blocking);
|
||||
|
||||
/* Allocate a slot from the pool. If the pool has no more slots available,
|
||||
* block up to the specified length of time in milliseconds. No blocking will
|
||||
* occur if the timeout is zero or the pool was initialized as non-blocking.
|
||||
* This doesn't put anything in the slot for you. It's up to you to do that.
|
||||
* Return the index of the allocated slot, or UVISOR_POOL_SLOT_INVALID if
|
||||
* timed out waiting for an available slot. This function will spin until the
|
||||
* spin lock serializing access to the pool can be taken. */
|
||||
UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_allocate(uvisor_pool_t * pool, uint32_t timeout_ms);
|
||||
/* Attempt to allocate a slot. This function will fail if the spin lock
|
||||
* serializing access to the pool can not be taken. */
|
||||
UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_try_allocate(uvisor_pool_t * pool);
|
||||
|
||||
/* Enqueue the specified slot into the queue. */
|
||||
UVISOR_EXTERN void uvisor_pool_queue_enqueue(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot);
|
||||
UVISOR_EXTERN int uvisor_pool_queue_try_enqueue(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot);
|
||||
|
||||
/* Free the specified slot back into the pool. Invalid slots are ignored.
|
||||
* Return the slot that was freed, or UVISOR_POOL_SLOT_IS_FREE if the slot was
|
||||
* already freed, or UVISOR_POOL_SLOT_INVALID if the slot being requested to
|
||||
* free is outside the range of the queue. */
|
||||
UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_free(uvisor_pool_t * pool, uvisor_pool_slot_t slot);
|
||||
UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_try_free(uvisor_pool_t * pool, uvisor_pool_slot_t slot);
|
||||
|
||||
/* Remove the specified slot from the queue. This function does not free the
|
||||
* specified slot back into the pool. Return the slot that was dequeued, or
|
||||
* UVISOR_POOL_SLOT_IS_DEQUEUED if the slot was already dequeued, or
|
||||
* UVISOR_POOL_SLOT_INVALID if the slot being requested to dequeue is outside
|
||||
* the range of the queue. */
|
||||
UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_dequeue(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot);
|
||||
|
||||
/* Remove the first slot from the queue. This function does not free the
|
||||
* specified slot back into the pool. Return the slot that was dequeued or
|
||||
* UVISOR_POOL_SLOT_INVALID if the slot being requested to dequeue is outside
|
||||
* the range of the queue. */
|
||||
UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_dequeue_first(uvisor_pool_queue_t * pool_queue);
|
||||
UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_try_dequeue_first(uvisor_pool_queue_t * pool_queue);
|
||||
|
||||
/* Find the first (in queue order) slot that the supplied query function
|
||||
* returns non-zero for. The query function is provided with `context` on every
|
||||
* invocation. This allows query functions to access additional data without
|
||||
* having to use global variables. `uvisor_pool_queue_find_first` is reentrant. */
|
||||
typedef int (*TQueryFN_Ptr)(uvisor_pool_slot_t slot, void * context);
|
||||
UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_find_first(uvisor_pool_queue_t * pool_queue,
|
||||
TQueryFN_Ptr query_fn, void * context);
|
||||
|
||||
/* Inline helper function to make allocating slots for pool queues easier and
|
||||
* better encapsulated (clients don't need to pull the pool out of the pool
|
||||
* queue, or even realize pool_queue is implemented with a pool) */
|
||||
static inline uvisor_pool_slot_t uvisor_pool_queue_allocate(uvisor_pool_queue_t * pool_queue, uint32_t timeout_ms)
|
||||
{
|
||||
return uvisor_pool_allocate(pool_queue->pool, timeout_ms);
|
||||
}
|
||||
|
||||
static inline uvisor_pool_slot_t uvisor_pool_queue_try_allocate(uvisor_pool_queue_t * pool_queue)
|
||||
{
|
||||
return uvisor_pool_try_allocate(pool_queue->pool);
|
||||
}
|
||||
|
||||
/* Inline helper function to make freeing slots for pool queues easier and
|
||||
* better encapsulated (clients don't need to pull the pool out of the pool
|
||||
* queue, or even realize pool_queue is implemented with a pool) */
|
||||
static inline uvisor_pool_slot_t uvisor_pool_queue_free(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot)
|
||||
{
|
||||
return uvisor_pool_free(pool_queue->pool, slot);
|
||||
}
|
||||
|
||||
static inline uvisor_pool_slot_t uvisor_pool_queue_try_free(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot)
|
||||
{
|
||||
return uvisor_pool_try_free(pool_queue->pool, slot);
|
||||
}
|
||||
|
||||
/* Return a pointer to the specified slot within the pool. */
|
||||
static inline void * uvisor_pool_pointer_to(uvisor_pool_t * pool, uvisor_pool_slot_t slot)
|
||||
{
|
||||
if (slot >= pool->num) {
|
||||
return NULL;
|
||||
}
|
||||
return (uint8_t *) pool->array + pool->stride * slot;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int (*init)(uvisor_pool_t *, void *, size_t, size_t, int);
|
||||
int (*queue_init)(uvisor_pool_queue_t *, uvisor_pool_t *, void *, size_t, size_t, int);
|
||||
uvisor_pool_slot_t (*allocate)(uvisor_pool_t *, uint32_t);
|
||||
void (*queue_enqueue)(uvisor_pool_queue_t *, uvisor_pool_slot_t);
|
||||
uvisor_pool_slot_t (*free)(uvisor_pool_t *, uvisor_pool_slot_t);
|
||||
uvisor_pool_slot_t (*queue_dequeue)(uvisor_pool_queue_t *, uvisor_pool_slot_t);
|
||||
uvisor_pool_slot_t (*queue_dequeue_first)(uvisor_pool_queue_t *);
|
||||
uvisor_pool_slot_t (*queue_find_first)(uvisor_pool_queue_t *, TQueryFN_Ptr, void *);
|
||||
} UvisorPoolTable;
|
||||
|
||||
#endif
|
|
@ -17,6 +17,9 @@
|
|||
#ifndef __UVISOR_API_PRIV_SYS_HOOK_EXPORTS_H__
|
||||
#define __UVISOR_API_PRIV_SYS_HOOK_EXPORTS_H__
|
||||
|
||||
/* Predeclaration */
|
||||
typedef struct uvisor_semaphore UvisorSemaphore;
|
||||
|
||||
/*
|
||||
* Privileged system hooks
|
||||
*
|
||||
|
@ -31,18 +34,20 @@ typedef struct {
|
|||
void (*priv_pendsv)(void);
|
||||
void (*priv_systick)(void);
|
||||
uint32_t (*priv_os_suspend)(void);
|
||||
int (*priv_uvisor_semaphore_post)(UvisorSemaphore * semaphore);
|
||||
} UvisorPrivSystemHooks;
|
||||
|
||||
/* Use this macro to register privileged system IRQ hooks. If you don't want to
|
||||
* register a particular privileged system IRQ hook, you can supply NULL for
|
||||
* that hook parameter. */
|
||||
#define UVISOR_SET_PRIV_SYS_HOOKS(priv_svc_0_, priv_pendsv_, priv_systick_, priv_os_suspend_) \
|
||||
#define UVISOR_SET_PRIV_SYS_HOOKS(priv_svc_0_, priv_pendsv_, priv_systick_, priv_os_suspend_, priv_uvisor_semaphore_post_) \
|
||||
UVISOR_EXTERN_C_BEGIN \
|
||||
const UvisorPrivSystemHooks __uvisor_priv_sys_hooks = { \
|
||||
.priv_svc_0 = priv_svc_0_, \
|
||||
.priv_pendsv = priv_pendsv_, \
|
||||
.priv_systick = priv_systick_, \
|
||||
.priv_os_suspend = priv_os_suspend_, \
|
||||
.priv_uvisor_semaphore_post = priv_uvisor_semaphore_post_, \
|
||||
}; \
|
||||
UVISOR_EXTERN_C_END
|
||||
|
||||
|
|
|
@ -17,32 +17,26 @@
|
|||
#ifndef __UVISOR_API_RPC_H__
|
||||
#define __UVISOR_API_RPC_H__
|
||||
|
||||
#include "api/inc/rpc_exports.h"
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/** Specify the maximum number of incoming RPC messages for a box
|
||||
*
|
||||
* @param max_num_incoming_rpc The maximum number of incoming RPC messages for
|
||||
* a box
|
||||
*/
|
||||
/* FIXME This is a dummy implementation. */
|
||||
#define UVISOR_BOX_RPC_MAX_INCOMING(max_num_incoming_rpc)
|
||||
|
||||
/* This is the token to wait on for the result of an asynchronous RPC. */
|
||||
typedef uint32_t uvisor_rpc_result_t;
|
||||
|
||||
typedef uint32_t (*TFN_Ptr)(uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
|
||||
/** Wait for incoming RPC.
|
||||
*
|
||||
* @param fn_ptr_array an array of RPC function targets that this call to
|
||||
* `rpc_fncall_waitfor` should handle RPC to
|
||||
* @param fn_count the number of function targets in this array
|
||||
* @param timeout_ms specifies how long to wait (in ms) for an incoming RPC
|
||||
* message before returning
|
||||
* @param box_id_caller[out] a memory location to store the box ID of the
|
||||
* calling box (the source box of the RPC). This is
|
||||
* set before the RPC is dispatched, so that the RPC
|
||||
* target function can read from this location to
|
||||
* determine the calling box ID. Optional.
|
||||
* @param timeout_ms specifies how long to wait (in ms) for an incoming
|
||||
* RPC message before returning
|
||||
*/
|
||||
UVISOR_EXTERN int rpc_fncall_waitfor(const TFN_Ptr fn_ptr_array[], size_t fn_count, uint32_t timeout_ms);
|
||||
UVISOR_EXTERN int rpc_fncall_waitfor(const TFN_Ptr fn_ptr_array[], size_t fn_count, int * box_id_caller, uint32_t timeout_ms);
|
||||
|
||||
/** Wait for an outgoing RPC to finish.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_RPC_EXPORTS_H__
|
||||
#define __UVISOR_API_RPC_EXPORTS_H__
|
||||
|
||||
#include "api/inc/pool_queue_exports.h"
|
||||
#include "api/inc/uvisor_semaphore_exports.h"
|
||||
#include "api/inc/rpc_gateway_exports.h"
|
||||
|
||||
typedef uint32_t (*TFN_Ptr)(uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
|
||||
#define UVISOR_RESULT_SLOT_BITS 10
|
||||
#define UVISOR_RESULT_SLOT_MASK ((1 << UVISOR_RESULT_SLOT_BITS) - 1)
|
||||
|
||||
#define UVISOR_RESULT_COUNTER_MASK (0xFFFFFFFFUL << UVISOR_RESULT_SLOT_BITS)
|
||||
|
||||
/* Increment by 2 because we never want to overflow into the invalid value. */
|
||||
#define UVISOR_RESULT_COUNTER_INCREMENT (2 << UVISOR_RESULT_SLOT_BITS)
|
||||
|
||||
#define UVISOR_RESULT_INVALID_COUNTER (UVISOR_RESULT_COUNTER_MASK)
|
||||
|
||||
/* This is the token to wait on for the result of an asynchronous RPC. */
|
||||
typedef uint32_t uvisor_rpc_result_t;
|
||||
|
||||
static inline uvisor_pool_slot_t uvisor_result_slot(uvisor_rpc_result_t result)
|
||||
{
|
||||
return result & UVISOR_RESULT_SLOT_MASK;
|
||||
}
|
||||
|
||||
static inline uint32_t uvisor_result_counter(uvisor_rpc_result_t result)
|
||||
{
|
||||
return result & UVISOR_RESULT_COUNTER_MASK;
|
||||
}
|
||||
|
||||
static inline uvisor_rpc_result_t uvisor_result_build(uint32_t counter, uvisor_pool_slot_t slot)
|
||||
{
|
||||
return (counter & UVISOR_RESULT_COUNTER_MASK) | (slot & UVISOR_RESULT_SLOT_MASK);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
/* Who sets this value for caller (outgoing queue), Who sets this value for (incoming queue) callee. */
|
||||
UVISOR_RPC_MESSAGE_STATE_INVALID, /* nobody, nobody */
|
||||
UVISOR_RPC_MESSAGE_STATE_IDLE, /* caller receive function before freeing, uvisor when delivers back */
|
||||
UVISOR_RPC_MESSAGE_STATE_READY_TO_SEND, /* send function, nobody */
|
||||
UVISOR_RPC_MESSAGE_STATE_SENT, /* uvisor, uvisor */
|
||||
UVISOR_RPC_MESSAGE_STATE_DONE, /* waitfor_fngroup function, uvisor when delivers back */
|
||||
} uvisor_rpc_message_state_t;
|
||||
|
||||
typedef struct uvisor_rpc_message {
|
||||
/* NOTE: These are set by the caller, and read by the callee. */
|
||||
uint32_t p0;
|
||||
uint32_t p1;
|
||||
uint32_t p2;
|
||||
uint32_t p3;
|
||||
|
||||
const TRPCGateway * gateway;
|
||||
|
||||
/* The box ID of the other box. For callers, this is the destination box
|
||||
* ID. For callees, this is the source box ID. */
|
||||
int other_box_id;
|
||||
|
||||
/* The semaphore to post to when a result is ready */
|
||||
UvisorSemaphore semaphore;
|
||||
|
||||
/* This cookie keeps track of which result to wait for. It changes
|
||||
* atomically to an invalid cookie when being waited on, to prevent
|
||||
* multiple waits for the same result. */
|
||||
uvisor_rpc_result_t wait_cookie;
|
||||
|
||||
/* This is an extra copy of the above cookie, used by uVisor to verify that
|
||||
* a certain result matches a certain caller. This identifies to uVisor
|
||||
* which RPC it should complete. uVisor must verify this information of
|
||||
* course, to see if this box is currently being called into and is allowed
|
||||
* to complete the RPC. */
|
||||
uvisor_rpc_result_t match_cookie;
|
||||
|
||||
uvisor_rpc_message_state_t state;
|
||||
|
||||
uint32_t result;
|
||||
} uvisor_rpc_message_t;
|
||||
|
||||
typedef struct uvisor_rpc_fn_group {
|
||||
/* A pointer to the function group */
|
||||
TFN_Ptr const * fn_ptr_array;
|
||||
size_t fn_count;
|
||||
|
||||
/* The semaphore to wait on for this function group */
|
||||
UvisorSemaphore semaphore;
|
||||
} uvisor_rpc_fn_group_t;
|
||||
|
||||
#define UVISOR_RPC_OUTGOING_MESSAGE_SLOTS (8)
|
||||
|
||||
#define UVISOR_RPC_INCOMING_MESSAGE_SLOTS (8)
|
||||
|
||||
#define UVISOR_RPC_FN_GROUP_SLOTS (8)
|
||||
|
||||
#define UVISOR_RPC_OUTGOING_MESSAGE_TYPE(slots) \
|
||||
struct { \
|
||||
uvisor_pool_queue_t queue; \
|
||||
uvisor_pool_t pool; \
|
||||
uvisor_pool_queue_entry_t entries[slots]; \
|
||||
uvisor_rpc_message_t messages[slots]; \
|
||||
}
|
||||
|
||||
#define UVISOR_RPC_INCOMING_MESSAGE_TYPE(slots) \
|
||||
struct { \
|
||||
uvisor_pool_queue_t todo_queue; \
|
||||
uvisor_pool_queue_t done_queue; \
|
||||
uvisor_pool_t pool; \
|
||||
uvisor_pool_queue_entry_t entries[slots]; \
|
||||
uvisor_rpc_message_t messages[slots]; \
|
||||
}
|
||||
|
||||
#define UVISOR_RPC_FN_GROUP_TYPE(slots) \
|
||||
struct { \
|
||||
uvisor_pool_queue_t queue; \
|
||||
uvisor_pool_t pool; \
|
||||
uvisor_pool_queue_entry_t entries[slots]; \
|
||||
uvisor_rpc_fn_group_t fn_groups[slots]; \
|
||||
}
|
||||
|
||||
typedef UVISOR_RPC_OUTGOING_MESSAGE_TYPE(UVISOR_RPC_OUTGOING_MESSAGE_SLOTS) uvisor_rpc_outgoing_message_queue_t;
|
||||
typedef UVISOR_RPC_INCOMING_MESSAGE_TYPE(UVISOR_RPC_INCOMING_MESSAGE_SLOTS) uvisor_rpc_incoming_message_queue_t;
|
||||
typedef UVISOR_RPC_FN_GROUP_TYPE(UVISOR_RPC_FN_GROUP_SLOTS) uvisor_rpc_fn_group_queue_t;
|
||||
|
||||
#endif
|
|
@ -22,12 +22,6 @@
|
|||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* ldr pc, [pc, #<label - instr + 4>]
|
||||
* LDR (immediate) - ARMv7M ARM section A7.7.42
|
||||
* 1111;1 00 0; 0 10 1; <Rn - 1111>; <Rt - 1111>; <imm12> (Encoding T3) */
|
||||
#define LDR_PC_PC_IMM_OPCODE(instr, label) \
|
||||
((uint32_t) (0xF000F8DFUL | ((((uint32_t) (label) - ((uint32_t) (instr) + 4)) & 0xFFFUL) << 16)))
|
||||
|
||||
/** Synchronous RPC Gateway
|
||||
*
|
||||
* This macro declares a new function pointer (with no name mangling) named
|
||||
|
@ -40,8 +34,8 @@
|
|||
*
|
||||
* @param box_name[in] The name of the source box as declared in
|
||||
* `UVISOR_BOX_CONFIG`
|
||||
* @param gw_name[in] The new, callable function pointer for performing RPC
|
||||
* @param fn_name[in] The function being designated as an RPC target
|
||||
* @param gw_name[in] The new, callable function pointer for initiating an RPC from the caller's box
|
||||
* @param fn_name[in] The function that will run in the callee's box as an RPC target
|
||||
* @param fn_ret[in] The return type of the function being designated as an
|
||||
* RPC target
|
||||
* @param __VA_ARGS__ The type of each parameter passed to the target
|
||||
|
@ -53,15 +47,17 @@
|
|||
#define UVISOR_BOX_RPC_GATEWAY_SYNC(box_name, gw_name, fn_name, fn_ret, ...) \
|
||||
UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, __VA_ARGS__) \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_DECL(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
|
||||
/* Instanstiate the gateway. This gets resolved at link-time. */ \
|
||||
UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
|
||||
.ldr_pc = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
|
||||
__UVISOR_OFFSETOF(TRPCGateway, function)), \
|
||||
__UVISOR_OFFSETOF(TRPCGateway, caller)), \
|
||||
.magic = UVISOR_RPC_GATEWAY_MAGIC_SYNC, \
|
||||
.box_ptr = (uint32_t) &box_name ## _cfg_ptr, \
|
||||
.function = (uint32_t) _sgw_sync_ ## fn_name, \
|
||||
.target = (uint32_t) fn_name, \
|
||||
.caller = (uint32_t) _sgw_sync_ ## fn_name, \
|
||||
}; \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
|
||||
\
|
||||
/* Pointer to the gateway we just created. The pointer is located in a
|
||||
* discoverable linker section. */ \
|
||||
|
@ -85,8 +81,8 @@
|
|||
*
|
||||
* @param box_name[in] The name of the source box as declared in
|
||||
* `UVISOR_BOX_CONFIG`
|
||||
* @param gw_name[in] The new, callable function pointer for performing RPC
|
||||
* @param fn_name[in] The function being designated as an RPC target
|
||||
* @param gw_name[in] The new, callable function pointer for initiating an RPC from the caller's box
|
||||
* @param fn_name[in] The function that will run in the callee's box as an RPC target
|
||||
* @param fn_ret[in] The return type of the function being designated as an
|
||||
* RPC target
|
||||
* @param __VA_ARGS__ The type of each parameter passed to the target
|
||||
|
@ -98,15 +94,17 @@
|
|||
#define UVISOR_BOX_RPC_GATEWAY_ASYNC(box_name, gw_name, fn_name, fn_ret, ...) \
|
||||
UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, __VA_ARGS__) \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_DECL(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
|
||||
/* Instanstiate the gateway. This gets resolved at link-time. */ \
|
||||
UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
|
||||
.ldr_pc = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
|
||||
__UVISOR_OFFSETOF(TRPCGateway, function)), \
|
||||
__UVISOR_OFFSETOF(TRPCGateway, caller)), \
|
||||
.magic = UVISOR_RPC_GATEWAY_MAGIC_ASYNC, \
|
||||
.box_ptr = (uint32_t) &box_name ## _cfg_ptr, \
|
||||
.function = (uint32_t) _sgw_async_ ## fn_name, \
|
||||
.target = (uint32_t) fn_name, \
|
||||
.caller = (uint32_t) _sgw_async_ ## fn_name, \
|
||||
}; \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
|
||||
\
|
||||
/* Pointer to the gateway we just created. The pointer is located in a
|
||||
* discoverable linker section. */ \
|
||||
|
@ -145,96 +143,130 @@
|
|||
UVISOR_STATIC_ASSERT(sizeof(p2_type) <= sizeof(uint32_t), gw_name ## _param_2_too_big); \
|
||||
UVISOR_STATIC_ASSERT(sizeof(p3_type) <= sizeof(uint32_t), gw_name ## _param_3_too_big);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_DECL(fn_name, gateway, ...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4_DECL, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3_DECL, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2_DECL, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1_DECL, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0_DECL)(fn_name, gateway, __VA_ARGS__)
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, gateway, ...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0)(fn_name, __VA_ARGS__)
|
||||
_UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0)(fn_name, gateway, __VA_ARGS__)
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0_DECL(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(void);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(void) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(0, 0, 0, 0, fp); \
|
||||
return rpc_fncall_sync(0, 0, 0, 0, &gateway); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1_DECL(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(p0, 0, 0, 0, fp); \
|
||||
return rpc_fncall_sync(p0, 0, 0, 0, &gateway); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2_DECL(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(p0, p1, 0, 0, fp); \
|
||||
return rpc_fncall_sync(p0, p1, 0, 0, &gateway); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3_DECL(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(p0, p1, p2, 0, fp); \
|
||||
return rpc_fncall_sync(p0, p1, p2, 0, &gateway); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4_DECL(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4(fn_name, gateway, ...) \
|
||||
static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_sync(p0, p1, p2, p3, fp); \
|
||||
return rpc_fncall_sync(p0, p1, p2, p3, &gateway); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_DECL(fn_name, gateway, ...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4_DECL, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3_DECL, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2_DECL, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1_DECL, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0_DECL)(fn_name, gateway, __VA_ARGS__)
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, gateway, ...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1, \
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0)(fn_name, __VA_ARGS__)
|
||||
_UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0)(fn_name, gateway, __VA_ARGS__)
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0_DECL(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(void);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(void) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(0, 0, 0, 0, fp); \
|
||||
return rpc_fncall_async(0, 0, 0, 0, &gateway); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1_DECL(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(p0, 0, 0, 0, fp); \
|
||||
return rpc_fncall_async(p0, 0, 0, 0, &gateway); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2_DECL(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(p0, p1, 0, 0, fp); \
|
||||
return rpc_fncall_async(p0, p1, 0, 0, &gateway); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3_DECL(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(p0, p1, p2, 0, fp); \
|
||||
return rpc_fncall_async(p0, p1, p2, 0, &gateway); \
|
||||
}
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4(fn_name, ...) \
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4_DECL(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3);
|
||||
|
||||
#define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4(fn_name, gateway, ...) \
|
||||
static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
|
||||
{ \
|
||||
TFN_Ptr fp = (TFN_Ptr) fn_name; \
|
||||
return rpc_fncall_async(p0, p1, p2, p3, fp); \
|
||||
return rpc_fncall_async(p0, p1, p2, p3, &gateway); \
|
||||
}
|
||||
|
||||
/* This function is private to uvisor-lib, but needs to be publicly visible for
|
||||
* the RPC gateway creation macros to work. */
|
||||
UVISOR_EXTERN uint32_t rpc_fncall_sync(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TFN_Ptr fn);
|
||||
UVISOR_EXTERN uint32_t rpc_fncall_sync(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TRPCGateway * gateway);
|
||||
|
||||
/* This function is private to uvisor-lib, but needs to be publicly visible for
|
||||
* the RPC gateway creation macros to work. */
|
||||
UVISOR_EXTERN uvisor_rpc_result_t rpc_fncall_async(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TFN_Ptr fn);
|
||||
UVISOR_EXTERN uvisor_rpc_result_t rpc_fncall_async(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TRPCGateway * gateway);
|
||||
|
||||
#endif /* __UVISOR_API_RPC_GATEWAY_H__ */
|
||||
|
|
|
@ -18,42 +18,28 @@
|
|||
#define __UVISOR_API_RPC_GATEWAY_EXPORTS_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include "api/inc/magic_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* udf imm16
|
||||
* UDF - ARMv7M ARM section A7.7.191
|
||||
* 111 1;0 111;1111; <imm4>; 1 01 0; <imm12> (Encoding T2)
|
||||
*/
|
||||
#define UDF_OPCODE(imm16) \
|
||||
((uint32_t) (0xA000F7F0UL | (((uint32_t) (imm16) & 0xFFFU) << 16U) | (((uint32_t) (imm16) & 0xF000UL) >> 12)))
|
||||
|
||||
/** RPC gateway magics
|
||||
*
|
||||
* The following magics are used to verify an RPC gateway structure. The magics are
|
||||
* chosen to be one of the explicitly undefined Thumb-2 instructions.
|
||||
*/
|
||||
/* TODO Unify all sources of magic (for register gateway, rpc gateway, and
|
||||
* everybody else) */
|
||||
#if defined(__thumb__) && defined(__thumb2__)
|
||||
#define UVISOR_RPC_GATEWAY_MAGIC_ASYNC UDF_OPCODE(0x07C2)
|
||||
#define UVISOR_RPC_GATEWAY_MAGIC_SYNC UDF_OPCODE(0x07C3)
|
||||
#else
|
||||
#error "Unsupported instruction set. The ARM Thumb-2 instruction set must be supported."
|
||||
#endif /* __thumb__ && __thumb2__ */
|
||||
|
||||
/* ldr pc, [pc, #<label - instr + 4>]
|
||||
* LDR (immediate) - ARMv7M ARM section A7.7.42
|
||||
* 1111;1 00 0; 0 10 1; <Rn - 1111>; <Rt - 1111>; <imm12> (Encoding T3) */
|
||||
#define LDR_PC_PC_IMM_OPCODE(instr, label) \
|
||||
((uint32_t) (0xF000F8DFUL | ((((uint32_t) (label) - ((uint32_t) (instr) + 4)) & 0xFFFUL) << 16)))
|
||||
|
||||
/** RPC gateway structure
|
||||
*
|
||||
* This struct is packed because we must ensure that the `ldr_pc` field has no
|
||||
* padding before itself and will be located at a valid instruction location,
|
||||
* and that the `function` field is at a pre-determined offset from the
|
||||
* `ldr_pc` field.
|
||||
* and that the `caller` and `target` field are at a pre-determined offset from
|
||||
* the `ldr_pc` field.
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct RPCGateway {
|
||||
uint32_t ldr_pc;
|
||||
uint32_t magic;
|
||||
uint32_t box_ptr;
|
||||
uint32_t function; /* It's like a pretend literal pool. */
|
||||
uint32_t target;
|
||||
uint32_t caller; /* This is not for use by anything other than the ldr_pc. It's like a pretend literal pool. */
|
||||
} UVISOR_PACKED UVISOR_ALIGN(4) TRPCGateway;
|
||||
|
||||
#endif /* __UVISOR_API_RPC_GATEWAY_EXPORTS_H__ */
|
||||
|
|
|
@ -28,6 +28,13 @@
|
|||
* priorities available to them */
|
||||
#define UVISOR_VIRQ_MAX_PRIORITY ((uint32_t) (1 << __NVIC_PRIO_BITS) - 1 - __UVISOR_NVIC_MIN_PRIORITY)
|
||||
|
||||
/* Reasons for rebooting */
|
||||
typedef enum {
|
||||
RESET_REASON_NO_REASON = 0,
|
||||
RESET_REASON_HALT,
|
||||
__TRESETREASON_MAX /* Always keep the last element of the enum. */
|
||||
} TResetReason;
|
||||
|
||||
/* Offset of NVIC interrupts with respect to handler 0 */
|
||||
#define NVIC_OFFSET 16
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
/* Library header files */
|
||||
#include "api/inc/benchmark.h"
|
||||
#include "api/inc/box_config.h"
|
||||
#include "api/inc/box_id.h"
|
||||
#include "api/inc/debug.h"
|
||||
#include "api/inc/disabled.h"
|
||||
#include "api/inc/error.h"
|
||||
|
@ -35,6 +36,7 @@
|
|||
#include "api/inc/rpc.h"
|
||||
#include "api/inc/rpc_gateway.h"
|
||||
#include "api/inc/secure_access.h"
|
||||
#include "api/inc/uvisor_semaphore.h"
|
||||
|
||||
#else /* defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1 */
|
||||
|
||||
|
@ -64,5 +66,6 @@ UVISOR_EXTERN int uvisor_lib_init(void);
|
|||
#include "api/inc/uvisor_exports.h"
|
||||
#include "api/inc/vmpu_exports.h"
|
||||
#include "api/inc/page_allocator_exports.h"
|
||||
#include "api/inc/pool_queue_exports.h"
|
||||
|
||||
#endif /* __UVISOR_API_UVISOR_LIB_H__ */
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
/* maximum number of boxes allowed: 1 is the minimum (unprivileged box) */
|
||||
#define UVISOR_MAX_BOXES 5U
|
||||
|
||||
#define UVISOR_WAIT_FOREVER (0xFFFFFFFFUL)
|
||||
|
||||
/* extern keyword */
|
||||
#ifdef __cplusplus
|
||||
#define UVISOR_EXTERN extern "C"
|
||||
|
@ -57,6 +59,7 @@
|
|||
#define UVISOR_WEAK __weak
|
||||
#define UVISOR_NORETURN __noreturn
|
||||
#define UVISOR_RAMFUNC __ramfunc
|
||||
#define UVISOR_DEPRECATED
|
||||
#else
|
||||
#define UVISOR_ALIGN(x) __attribute__((aligned(x)))
|
||||
#define UVISOR_FORCEINLINE inline __attribute__((always_inline))
|
||||
|
@ -64,6 +67,7 @@
|
|||
#define UVISOR_WEAK __attribute__((weak))
|
||||
#define UVISOR_NORETURN __attribute__((noreturn))
|
||||
#define UVISOR_RAMFUNC __attribute__ ((section (".ramfunc"), noinline))
|
||||
#define UVISOR_DEPRECATED __attribute__((deprecated))
|
||||
#endif
|
||||
|
||||
/* array count macro */
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_UVISOR_SEMAPHORE_H__
|
||||
#define __UVISOR_API_UVISOR_SEMAPHORE_H__
|
||||
|
||||
#include "api/inc/uvisor_semaphore_exports.h"
|
||||
|
||||
UVISOR_EXTERN int __uvisor_semaphore_init(UvisorSemaphore * semaphore, int32_t count);
|
||||
|
||||
/* This function is not safe to call from interrupt context, even if the
|
||||
* timeout is zero. */
|
||||
UVISOR_EXTERN int __uvisor_semaphore_pend(UvisorSemaphore * semaphore, uint32_t timeout_ms);
|
||||
|
||||
/* This function is safe to call from interrupt context. */
|
||||
UVISOR_EXTERN int __uvisor_semaphore_post(UvisorSemaphore * semaphore);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_UVISOR_SEMAPHORE_EXPORTS_H__
|
||||
#define __UVISOR_API_UVISOR_SEMAPHORE_EXPORTS_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
|
||||
/* This must be big enough for all operating systems uVisor runs on. */
|
||||
#define UVISOR_SEMAPHORE_INTERNAL_SIZE (16)
|
||||
|
||||
/* An opaque structure, that one knows the size of so that they can allocate
|
||||
* memory. */
|
||||
typedef struct uvisor_semaphore {
|
||||
uint8_t internal[UVISOR_SEMAPHORE_INTERNAL_SIZE];
|
||||
} UVISOR_ALIGN(4) UvisorSemaphore;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_UVISOR_SPINLOCK_H__
|
||||
#define __UVISOR_API_UVISOR_SPINLOCK_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
bool acquired;
|
||||
} UvisorSpinlock;
|
||||
|
||||
#endif /* __UVISOR_API_UVISOR_SPINLOCK_H__ */
|
|
@ -18,6 +18,8 @@
|
|||
#define __UVISOR_API_VMPU_EXPORTS_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include "api/inc/pool_queue_exports.h"
|
||||
#include "api/inc/rpc_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* The maximum box namespace length is 37 so that it is exactly big enough for
|
||||
|
@ -148,19 +150,37 @@ typedef struct {
|
|||
UvisorBoxAcl acl;
|
||||
} UVISOR_PACKED UvisorBoxAclItem;
|
||||
|
||||
typedef struct {
|
||||
/* Contains user provided size of box context without guards of buffers. */
|
||||
uint32_t context_size;
|
||||
/* Contains total memory used by the RPC queues (incl. management and pool). */
|
||||
uint32_t rpc_outgoing_message_size;
|
||||
uint32_t rpc_incoming_message_size;
|
||||
uint32_t rpc_fn_group_size;
|
||||
} UVISOR_PACKED uvisor_sizes_t;
|
||||
|
||||
/* The number of additional bss sections per box bss.
|
||||
* The size of each section is stored in the box config, and uVisor core will
|
||||
* iterate over the box bss, split it into sections as defined by the size table
|
||||
* and assign a pointer to beginning of that section into the box index pointer table.
|
||||
*/
|
||||
#define UVISOR_BOX_INDEX_SIZE_COUNT (sizeof(uvisor_sizes_t) / sizeof(uint32_t))
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
|
||||
/* Box stack size includes stack guards and rounding buffer. */
|
||||
uint32_t stack_size;
|
||||
|
||||
/* Contains the size of the index (must be at least sizeof(UvisorBoxIndex)). */
|
||||
uint32_t index_size;
|
||||
/* Contains user provided size of box context without guards of buffers. */
|
||||
uint32_t context_size;
|
||||
/* Contains user provided size of box heap without guards of buffers. */
|
||||
uint32_t heap_size;
|
||||
/* Contains the size of the index (must be at least sizeof(UvisorBoxIndex)). */
|
||||
uint32_t index_size;
|
||||
|
||||
union {
|
||||
uint32_t bss_size[UVISOR_BOX_INDEX_SIZE_COUNT];
|
||||
uvisor_sizes_t sizes;
|
||||
};
|
||||
|
||||
/* Opaque-to-uVisor data that potentially contains uvisor-lib-specific or
|
||||
* OS-specific per-box configuration */
|
||||
|
@ -172,8 +192,17 @@ typedef struct {
|
|||
} UVISOR_PACKED UvisorBoxConfig;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
void * bss_ptr[UVISOR_BOX_INDEX_SIZE_COUNT];
|
||||
struct {
|
||||
/* Pointer to the user context */
|
||||
void * ctx;
|
||||
/* Pointer to the RPC queues */
|
||||
uvisor_rpc_outgoing_message_queue_t * rpc_outgoing_message_queue;
|
||||
uvisor_rpc_incoming_message_queue_t * rpc_incoming_message_queue;
|
||||
uvisor_rpc_fn_group_queue_t * rpc_fn_group_queue;
|
||||
};
|
||||
};
|
||||
/* Pointer to the box heap */
|
||||
void * box_heap;
|
||||
/* Size of the box heap */
|
||||
|
@ -182,6 +211,14 @@ typedef struct {
|
|||
* This is set to `NULL` by uVisor, signalling to the user lib that the
|
||||
* box heap needs to be initialized before use! */
|
||||
void * active_heap;
|
||||
|
||||
/* Counter that helps to avoid waiting on the same RPC message result twice
|
||||
* by accident. */
|
||||
uint32_t rpc_result_counter;
|
||||
|
||||
/* Box ID */
|
||||
int box_id_self;
|
||||
|
||||
/* Pointer to the box config */
|
||||
const UvisorBoxConfig * config;
|
||||
} UVISOR_PACKED UvisorBoxIndex;
|
||||
|
|
|
@ -55,6 +55,10 @@ const void * g_page_heap_end;
|
|||
uint8_t g_page_count_free;
|
||||
/* Contains the total number of available pages. */
|
||||
uint8_t g_page_count_total;
|
||||
/* Contains the shift of the page owner mask. */
|
||||
uint8_t g_page_map_shift;
|
||||
/* Contains the rounded up page end address for ARMv7-M MPU region alignment. */
|
||||
uint32_t g_page_head_end_rounded;
|
||||
|
||||
/* Helper function maps pointer to page id, or UVISOR_PAGE_UNUSED. */
|
||||
uint8_t page_allocator_get_page_from_address(uint32_t address)
|
||||
|
@ -132,12 +136,20 @@ void page_allocator_init(void * const heap_start, void * const heap_end, const u
|
|||
/* Remember the end of the heap. */
|
||||
g_page_heap_end = g_page_heap_start + g_page_count_total * g_page_size;
|
||||
|
||||
DPRINTF("uvisor_page_init:\n.page_heap start 0x%08x\n.page_heap end 0x%08x\n.page_heap available %ukB split into %u pages of %ukB\n\n",
|
||||
g_page_head_end_rounded = vmpu_round_up_region((uint32_t) g_page_heap_end, g_page_size * 8);
|
||||
/* Compute the page map shift.
|
||||
* This initial shift fully left aligns the page map. */
|
||||
g_page_map_shift = UVISOR_PAGE_MAP_COUNT * 32 - g_page_count_total;
|
||||
g_page_map_shift -= (g_page_head_end_rounded - (uint32_t) g_page_heap_end) / g_page_size;
|
||||
|
||||
DPRINTF(
|
||||
"page heap: [0x%08x, 0x%08x] %ukB -> %u %ukB pages\r\n",
|
||||
(unsigned int) g_page_heap_start,
|
||||
(unsigned int) g_page_heap_end,
|
||||
(unsigned int) (g_page_count_free * g_page_size / 1024),
|
||||
(unsigned int) g_page_count_total,
|
||||
(unsigned int) (g_page_size / 1024));
|
||||
(unsigned int) (g_page_size / 1024)
|
||||
);
|
||||
|
||||
/* Force a reset of owner and usage page maps. */
|
||||
memset(g_page_owner_map, 0, sizeof(g_page_owner_map));
|
||||
|
|
|
@ -37,8 +37,10 @@
|
|||
#define UVISOR_PAGE_SIZE_MINIMUM (1024UL)
|
||||
#endif
|
||||
|
||||
/* Defines the number of uint32_t page owner masks in the owner map. */
|
||||
#define UVISOR_PAGE_MAP_COUNT ((UVISOR_PAGE_MAX_COUNT + 31) / 32)
|
||||
/* Defines the number of uint32_t page owner masks in the owner map.
|
||||
* +8 is used for ARMv7-M MPUs, where a shift of up to 7-bits may be required
|
||||
* to align MPU regions. */
|
||||
#define UVISOR_PAGE_MAP_COUNT ((UVISOR_PAGE_MAX_COUNT + 31 + 8) / 32)
|
||||
|
||||
/* The page box_id is the box id which is 8-bit large. */
|
||||
typedef uint8_t page_owner_t;
|
||||
|
@ -46,6 +48,10 @@ typedef uint8_t page_owner_t;
|
|||
#define UVISOR_PAGE_UNUSED ((page_owner_t) (-1))
|
||||
/* Contains the total number of available pages. */
|
||||
extern uint8_t g_page_count_total;
|
||||
/* Contains the shift of the page owner mask. */
|
||||
extern uint8_t g_page_map_shift;
|
||||
/* Contains the ARMv7-MPU rounded page end. */
|
||||
extern uint32_t g_page_head_end_rounded;
|
||||
|
||||
/** Sets the page bit in the page map array.
|
||||
* @param map an array of `uint32_t` containing the page map
|
||||
|
@ -53,7 +59,7 @@ extern uint8_t g_page_count_total;
|
|||
*/
|
||||
static inline void page_allocator_map_set(uint32_t * const map, uint8_t page)
|
||||
{
|
||||
page += UVISOR_PAGE_MAP_COUNT * 32 - g_page_count_total;
|
||||
page += g_page_map_shift;
|
||||
map[page / 32] |= (1UL << (page % 32));
|
||||
}
|
||||
|
||||
|
@ -63,7 +69,7 @@ static inline void page_allocator_map_set(uint32_t * const map, uint8_t page)
|
|||
*/
|
||||
static inline void page_allocator_map_clear(uint32_t * const map, uint8_t page)
|
||||
{
|
||||
page += UVISOR_PAGE_MAP_COUNT * 32 - g_page_count_total;
|
||||
page += g_page_map_shift;
|
||||
map[page / 32] &= ~(1UL << (page % 32));
|
||||
}
|
||||
|
||||
|
@ -75,7 +81,7 @@ static inline void page_allocator_map_clear(uint32_t * const map, uint8_t page)
|
|||
*/
|
||||
static inline int page_allocator_map_get(const uint32_t * const map, uint8_t page)
|
||||
{
|
||||
page += UVISOR_PAGE_MAP_COUNT * 32 - g_page_count_total;
|
||||
page += g_page_map_shift;
|
||||
return (map[page / 32] >> (page % 32)) & 0x1;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
#include "uvisor-lib/uvisor-lib.h"
|
||||
#include "api/inc/pool_queue_exports.h"
|
||||
#include "api/inc/rpc_exports.h"
|
||||
#include "api/inc/uvisor_semaphore.h"
|
||||
#include "mbed_interface.h"
|
||||
#include "cmsis_os.h"
|
||||
#include <stdint.h>
|
||||
|
@ -26,7 +29,92 @@ extern void PendSV_Handler(void);
|
|||
extern void SysTick_Handler(void);
|
||||
extern uint32_t rt_suspend(void);
|
||||
|
||||
UVISOR_SET_PRIV_SYS_HOOKS(SVC_Handler, PendSV_Handler, SysTick_Handler, rt_suspend);
|
||||
UVISOR_SET_PRIV_SYS_HOOKS(SVC_Handler, PendSV_Handler, SysTick_Handler, rt_suspend, __uvisor_semaphore_post);
|
||||
|
||||
extern RtxBoxIndex * const __uvisor_ps;
|
||||
|
||||
void __uvisor_initialize_rpc_queues(void)
|
||||
{
|
||||
UvisorBoxIndex * const index = &__uvisor_ps->index;
|
||||
|
||||
uvisor_pool_slot_t i;
|
||||
|
||||
uvisor_rpc_outgoing_message_queue_t * rpc_outgoing_msg_queue = index->rpc_outgoing_message_queue;
|
||||
uvisor_rpc_incoming_message_queue_t * rpc_incoming_msg_queue = index->rpc_incoming_message_queue;
|
||||
uvisor_rpc_fn_group_queue_t * rpc_fn_group_queue = index->rpc_fn_group_queue;
|
||||
|
||||
/* Initialize the outgoing RPC message queue. */
|
||||
if (uvisor_pool_queue_init(&rpc_outgoing_msg_queue->queue,
|
||||
&rpc_outgoing_msg_queue->pool,
|
||||
rpc_outgoing_msg_queue->messages,
|
||||
sizeof(*rpc_outgoing_msg_queue->messages),
|
||||
UVISOR_RPC_OUTGOING_MESSAGE_SLOTS,
|
||||
UVISOR_POOL_QUEUE_BLOCKING)) {
|
||||
uvisor_error(USER_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
/* Initialize all the result semaphores. */
|
||||
for (i = 0; i < UVISOR_RPC_OUTGOING_MESSAGE_SLOTS; i++) {
|
||||
UvisorSemaphore * semaphore = &rpc_outgoing_msg_queue->messages[i].semaphore;
|
||||
if (__uvisor_semaphore_init(semaphore, 1)) {
|
||||
uvisor_error(USER_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
/* Semaphores are created with their value initialized to count. We
|
||||
* want the semaphore to start at zero. Decrement the semaphore, so it
|
||||
* starts with a value of zero. This will allow the first pend to
|
||||
* block. */
|
||||
if (__uvisor_semaphore_pend(semaphore, 0)) {
|
||||
uvisor_error(USER_NOT_ALLOWED);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the incoming RPC message queues. */
|
||||
if (uvisor_pool_queue_init(&rpc_incoming_msg_queue->todo_queue,
|
||||
&rpc_incoming_msg_queue->pool,
|
||||
rpc_incoming_msg_queue->messages,
|
||||
sizeof(*rpc_incoming_msg_queue->messages),
|
||||
UVISOR_RPC_INCOMING_MESSAGE_SLOTS,
|
||||
UVISOR_POOL_QUEUE_NON_BLOCKING)) {
|
||||
uvisor_error(USER_NOT_ALLOWED);
|
||||
}
|
||||
/* This is a double init of the pool. We need a function that just inits
|
||||
* the queue, not the pool, and init everybody separately. */
|
||||
if (uvisor_pool_queue_init(&rpc_incoming_msg_queue->done_queue,
|
||||
&rpc_incoming_msg_queue->pool,
|
||||
rpc_incoming_msg_queue->messages,
|
||||
sizeof(*rpc_incoming_msg_queue->messages),
|
||||
UVISOR_RPC_INCOMING_MESSAGE_SLOTS,
|
||||
UVISOR_POOL_QUEUE_NON_BLOCKING)) {
|
||||
uvisor_error(USER_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
/* Initialize the function group pool. */
|
||||
if (uvisor_pool_queue_init(&rpc_fn_group_queue->queue,
|
||||
&rpc_fn_group_queue->pool,
|
||||
rpc_fn_group_queue->fn_groups,
|
||||
sizeof(*rpc_fn_group_queue->fn_groups),
|
||||
UVISOR_RPC_FN_GROUP_SLOTS,
|
||||
UVISOR_POOL_QUEUE_BLOCKING)) {
|
||||
uvisor_error(USER_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
/* Initialize all the function group semaphores. */
|
||||
for (i = 0; i < UVISOR_RPC_FN_GROUP_SLOTS; i++) {
|
||||
UvisorSemaphore * semaphore = &rpc_fn_group_queue->fn_groups[i].semaphore;
|
||||
if (__uvisor_semaphore_init(semaphore, 1)) {
|
||||
uvisor_error(USER_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
/* Semaphores are created with their value initialized to count. We
|
||||
* want the semaphore to start at zero. Decrement the semaphore, so it
|
||||
* starts with a value of zero. This will allow the first pend to
|
||||
* block. */
|
||||
if (__uvisor_semaphore_pend(semaphore, 0)) {
|
||||
uvisor_error(USER_NOT_ALLOWED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called by uVisor in unprivileged mode. On this OS, we
|
||||
* create box main threads for the box. */
|
||||
|
@ -36,6 +124,8 @@ void __uvisor_lib_box_init(void * lib_config)
|
|||
osThreadDef_t * flash_thread_def = lib_config;
|
||||
osThreadDef_t thread_def;
|
||||
|
||||
__uvisor_initialize_rpc_queues();
|
||||
|
||||
/* Copy thread definition from flash to RAM. The thread definition is most
|
||||
* likely in flash, so we need to copy it to box-local RAM before we can
|
||||
* modify it. */
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
#include "api/inc/uvisor_semaphore_exports.h"
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include "api/inc/halt_exports.h"
|
||||
#include "cmsis_os.h"
|
||||
#include <string.h>
|
||||
|
||||
typedef struct uvisor_semaphore_internal {
|
||||
osSemaphoreId id;
|
||||
osSemaphoreDef_t def;
|
||||
uint32_t data[2]; /* RTX expects this is 4-byte aligned */
|
||||
} UVISOR_ALIGN(4) uvisor_semaphore_internal_t;
|
||||
|
||||
UVISOR_STATIC_ASSERT(UVISOR_SEMAPHORE_INTERNAL_SIZE >= sizeof(UvisorSemaphore), semaphore_size_too_small);
|
||||
|
||||
int __uvisor_semaphore_init(UvisorSemaphore * s, int32_t count)
|
||||
{
|
||||
uvisor_semaphore_internal_t * semaphore = (uvisor_semaphore_internal_t *) s;
|
||||
|
||||
memset(semaphore->data, 0, sizeof(semaphore->data));
|
||||
semaphore->def.semaphore = semaphore->data;
|
||||
semaphore->id = osSemaphoreCreate(&semaphore->def, count);
|
||||
|
||||
/* Error when semaphore->id is NULL */
|
||||
return semaphore->id == NULL ? UVISOR_ERROR_OUT_OF_STRUCTURES : 0;
|
||||
}
|
||||
|
||||
int __uvisor_semaphore_pend(UvisorSemaphore * s, uint32_t timeout_ms)
|
||||
{
|
||||
uvisor_semaphore_internal_t * semaphore = (uvisor_semaphore_internal_t *) s;
|
||||
|
||||
int32_t num_available_tokens = osSemaphoreWait(semaphore->id, timeout_ms);
|
||||
|
||||
if (num_available_tokens == -1) {
|
||||
return UVISOR_ERROR_INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
if (num_available_tokens == 0) {
|
||||
return UVISOR_ERROR_OUT_OF_STRUCTURES;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __uvisor_semaphore_post(UvisorSemaphore * s) {
|
||||
uvisor_semaphore_internal_t * semaphore = (uvisor_semaphore_internal_t *) s;
|
||||
return osSemaphoreRelease(semaphore->id);
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1353,6 +1353,7 @@ typedef struct
|
|||
#define NVIC_GetActive __NVIC_GetActive
|
||||
#define NVIC_SetPriority __NVIC_SetPriority
|
||||
#define NVIC_GetPriority __NVIC_GetPriority
|
||||
#define NVIC_SystemReset __NVIC_SystemReset
|
||||
#endif /* CMSIS_NVIC_VIRTUAL */
|
||||
|
||||
#ifdef CMSIS_VECTAB_VIRTUAL
|
||||
|
@ -1581,7 +1582,7 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr
|
|||
|
||||
The function initiates a system reset request to reset the MCU.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SystemReset(void)
|
||||
__STATIC_INLINE void __NVIC_SystemReset(void)
|
||||
{
|
||||
__DSB(); /* Ensure all outstanding memory accesses included
|
||||
buffered write are completed before reset */
|
||||
|
|
|
@ -1518,6 +1518,7 @@ typedef struct
|
|||
#define NVIC_GetActive __NVIC_GetActive
|
||||
#define NVIC_SetPriority __NVIC_SetPriority
|
||||
#define NVIC_GetPriority __NVIC_GetPriority
|
||||
#define NVIC_SystemReset __NVIC_SystemReset
|
||||
#endif /* CMSIS_NVIC_VIRTUAL */
|
||||
|
||||
#ifdef CMSIS_VECTAB_VIRTUAL
|
||||
|
@ -1747,7 +1748,7 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr
|
|||
|
||||
The function initiates a system reset request to reset the MCU.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SystemReset(void)
|
||||
__STATIC_INLINE void __NVIC_SystemReset(void)
|
||||
{
|
||||
__DSB(); /* Ensure all outstanding memory accesses included
|
||||
buffered write are completed before reset */
|
||||
|
|
Loading…
Reference in New Issue