diff --git a/features/FEATURE_UVISOR/AUTHORS.txt b/features/FEATURE_UVISOR/AUTHORS.txt index fcf7f1b030..855e67a72a 100644 --- a/features/FEATURE_UVISOR/AUTHORS.txt +++ b/features/FEATURE_UVISOR/AUTHORS.txt @@ -1,7 +1,7 @@ + 597 Alessandro Angelino 592 Milosch Meriac - 554 Alessandro Angelino - 105 Jaeden Amero - 65 Niklas Hauser + 144 Jaeden Amero + 80 Niklas Hauser 5 Irit Arkin 3 JaredCJR 3 AnotherButler diff --git a/features/FEATURE_UVISOR/VERSION.txt b/features/FEATURE_UVISOR/VERSION.txt index a57af0501c..244df55dde 100644 --- a/features/FEATURE_UVISOR/VERSION.txt +++ b/features/FEATURE_UVISOR/VERSION.txt @@ -1 +1 @@ -v0.27.0-23-g8231ae897dadbb1c3eeb79ae2103d308d28c7e14 +v0.28.1 diff --git a/features/FEATURE_UVISOR/includes/uvisor-lib/rtx/process_malloc.h b/features/FEATURE_UVISOR/includes/uvisor-lib/rtx/process_malloc.h deleted file mode 100644 index 1cf14ff3d4..0000000000 --- a/features/FEATURE_UVISOR/includes/uvisor-lib/rtx/process_malloc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 __RTX_PROCESS_MALLOC_H__ -#define __RTX_PROCESS_MALLOC_H__ - -#include "secure_allocator.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Allocate memory on the process heap. */ -void * malloc_p(size_t size); -/* Reallocate memory on the process heap. */ -void * realloc_p(void * ptr, size_t size); -/* Free memory on the process heap. */ -void free_p(void * ptr); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* __RTX_PROCESS_MALLOC_H__ */ diff --git a/features/FEATURE_UVISOR/includes/uvisor-lib/rtx/secure_allocator.h b/features/FEATURE_UVISOR/includes/uvisor-lib/rtx/secure_allocator.h index 75a58b43ba..d25010942f 100644 --- a/features/FEATURE_UVISOR/includes/uvisor-lib/rtx/secure_allocator.h +++ b/features/FEATURE_UVISOR/includes/uvisor-lib/rtx/secure_allocator.h @@ -70,6 +70,18 @@ void * secure_malloc( SecureAllocator allocator, size_t size); +/** Drop-in for `aligned_alloc`. */ +void * secure_aligned_alloc( + SecureAllocator allocator, + size_t alignment, + size_t size); + +/** Drop-in for `calloc`. */ +void * secure_calloc( + SecureAllocator allocator, + size_t nmemb, + size_t size); + /** Drop-in for `realloc`. */ void * secure_realloc( SecureAllocator allocator, diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/api.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/api.h index 8340d234bc..abdee03d98 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/api.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/api.h @@ -19,11 +19,12 @@ #include "rt_OsEventObserver.h" #include "api/inc/uvisor_exports.h" -#include "api/inc/unvic_exports.h" +#include "api/inc/virq_exports.h" #include "api/inc/debug_exports.h" #include "api/inc/halt_exports.h" #include "api/inc/pool_queue_exports.h" #include "api/inc/page_allocator_exports.h" +#include "api/inc/uvisor_spinlock_exports.h" #include #define UVISOR_API_MAGIC 0x5C9411B4 @@ -37,7 +38,7 @@ typedef struct { uint32_t magic; uint32_t (*get_version)(uint32_t); - void (*init)(void); + void (*init)(uint32_t caller); void (*irq_enable)(uint32_t irqn); void (*irq_disable)(uint32_t irqn); @@ -60,17 +61,23 @@ typedef struct { void (*debug_init)(const TUvisorDebugDriver * const driver); void (*error)(THaltUserError reason); + void (*start)(void); void (*vmpu_mem_invalidate)(void); - int (*pool_init)(uvisor_pool_t *, void *, size_t, size_t, int); - int (*pool_queue_init)(uvisor_pool_queue_t *, uvisor_pool_t *, void *, size_t, size_t, int); - uvisor_pool_slot_t (*pool_allocate)(uvisor_pool_t *, uint32_t); + int (*pool_init)(uvisor_pool_t *, void *, size_t, size_t); + int (*pool_queue_init)(uvisor_pool_queue_t *, uvisor_pool_t *, void *, size_t, size_t); + uvisor_pool_slot_t (*pool_allocate)(uvisor_pool_t *); void (*pool_queue_enqueue)(uvisor_pool_queue_t *, uvisor_pool_slot_t); uvisor_pool_slot_t (*pool_free)(uvisor_pool_t *, uvisor_pool_slot_t); uvisor_pool_slot_t (*pool_queue_dequeue)(uvisor_pool_queue_t *, uvisor_pool_slot_t); uvisor_pool_slot_t (*pool_queue_dequeue_first)(uvisor_pool_queue_t *); uvisor_pool_slot_t (*pool_queue_find_first)(uvisor_pool_queue_t *, TQueryFN_Ptr, void *); + void (*spin_init)(UvisorSpinlock * spinlock); + bool (*spin_trylock)(UvisorSpinlock * spinlock); + void (*spin_lock)(UvisorSpinlock * spinlock); + void (*spin_unlock)(UvisorSpinlock * spinlock); + OsEventObserver os_event_observer; } UVISOR_PACKED UvisorApi; diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/box_config.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/box_config.h index 1c7e5e7b2d..a75ba03cfc 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/box_config.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/box_config.h @@ -22,15 +22,16 @@ #include "api/inc/rpc_exports.h" #include #include +#include UVISOR_EXTERN const uint32_t __uvisor_mode; UVISOR_EXTERN void const * const public_box_cfg_ptr; -typedef struct { - void (*function)(const void *); - size_t priority; - size_t stack_size; -} uvisor_box_main_t; +/* All pointers in the box index need to be 4-byte aligned. + * We therefore also need to round up all sizes to 4-byte multiples to + * provide the space to be able to align the pointers to 4-bytes. */ +#define __UVISOR_BOX_ROUND_4(size) \ + (((size) + 3UL) & ~3UL) #define UVISOR_DISABLED 0 #define UVISOR_PERMISSIVE 1 @@ -53,7 +54,9 @@ typedef struct { { \ sizeof(RtxBoxIndex), \ 0, \ + 0, \ sizeof(uvisor_rpc_t), \ + sizeof(uvisor_ipc_t), \ 0, \ }, \ 0, \ @@ -83,12 +86,13 @@ typedef struct { UVISOR_STACK_SIZE_ROUND( \ ( \ (UVISOR_MIN_STACK(stack_size) + \ - (context_size) + \ - (__uvisor_box_heapsize) + \ - sizeof(RtxBoxIndex) + \ - sizeof(uvisor_rpc_outgoing_message_queue_t) + \ - sizeof(uvisor_rpc_incoming_message_queue_t) + \ - sizeof(uvisor_rpc_fn_group_queue_t) \ + __UVISOR_BOX_ROUND_4(context_size) + \ + __UVISOR_BOX_ROUND_4(__uvisor_box_heapsize) + \ + __UVISOR_BOX_ROUND_4(sizeof(RtxBoxIndex)) + \ + __UVISOR_BOX_ROUND_4(sizeof(uvisor_rpc_outgoing_message_queue_t)) + \ + __UVISOR_BOX_ROUND_4(sizeof(uvisor_rpc_incoming_message_queue_t)) + \ + __UVISOR_BOX_ROUND_4(sizeof(uvisor_rpc_fn_group_queue_t)) + \ + __UVISOR_BOX_ROUND_4(sizeof(struct _reent)) \ ) \ * 8) \ / 6)]; \ @@ -99,7 +103,9 @@ typedef struct { { \ sizeof(RtxBoxIndex), \ context_size, \ + sizeof(struct _reent), \ sizeof(uvisor_rpc_t), \ + sizeof(uvisor_ipc_t), \ __uvisor_box_heapsize, \ }, \ UVISOR_MIN_STACK(stack_size), \ diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/cmsis_nvic_virtual.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/cmsis_nvic_virtual.h index c490a9b8ad..ba7b1e681d 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/cmsis_nvic_virtual.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/cmsis_nvic_virtual.h @@ -18,18 +18,37 @@ #define __UVISOR_API_NVIC_VIRTUAL_H__ #include "api/inc/interrupts.h" -#include "api/inc/unvic_exports.h" +#include "api/inc/virq_exports.h" -#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping -#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping -#define NVIC_EnableIRQ vIRQ_EnableIRQ -#define NVIC_DisableIRQ vIRQ_DisableIRQ -#define NVIC_GetPendingIRQ vIRQ_GetPendingIRQ -#define NVIC_SetPendingIRQ vIRQ_SetPendingIRQ -#define NVIC_ClearPendingIRQ vIRQ_ClearPendingIRQ -#define NVIC_GetActive __NVIC_GetActive -#define NVIC_SetPriority vIRQ_SetPriority -#define NVIC_GetPriority vIRQ_GetPriority -#define NVIC_SystemReset() vIRQ_SystemReset(RESET_REASON_NO_REASON) +/* The NVIC APIs are only wrapped on ARMv7-M. */ +#if !defined(ARCH_CORE_ARMv8M) && !defined(TARGET_M33) + +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ vIRQ_EnableIRQ +#define NVIC_DisableIRQ vIRQ_DisableIRQ +#define NVIC_GetPendingIRQ vIRQ_GetPendingIRQ +#define NVIC_SetPendingIRQ vIRQ_SetPendingIRQ +#define NVIC_ClearPendingIRQ vIRQ_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority vIRQ_SetPriority +#define NVIC_GetPriority vIRQ_GetPriority +#define NVIC_SystemReset() vIRQ_SystemReset(RESET_REASON_NO_REASON) + +#else + +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority +#define NVIC_SystemReset() __NVIC_SystemReset() + +#endif #endif /* __UVISOR_API_NVIC_VIRTUAL_H__ */ diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/cmsis_vectab_virtual.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/cmsis_vectab_virtual.h index 5dfbfccc0a..0d66fb1707 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/cmsis_vectab_virtual.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/cmsis_vectab_virtual.h @@ -19,7 +19,17 @@ #include "api/inc/interrupts.h" -#define NVIC_SetVector vIRQ_SetVector -#define NVIC_GetVector vIRQ_GetVector +/* The NVIC APIs are only wrapped on ARMv7-M. */ +#if !defined(ARCH_CORE_ARMv8M) && !defined(TARGET_M33) + +#define NVIC_SetVector vIRQ_SetVector +#define NVIC_GetVector vIRQ_GetVector + +#else + +#define NVIC_SetVector __NVIC_SetVector +#define NVIC_GetVector __NVIC_GetVector + +#endif #endif /* __UVISOR_API_VECTAB_VIRTUAL_H__ */ diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/halt_exports.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/halt_exports.h index 89de61bdd3..997868e717 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/halt_exports.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/halt_exports.h @@ -49,6 +49,7 @@ typedef enum { FAULT_USAGE, FAULT_HARD, FAULT_DEBUG, + FAULT_SECURE, __THALTERROR_MAX /* always keep as the last element of the enum */ } THaltError; diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/interrupts.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/interrupts.h index 3ede2b6c26..ef310822a0 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/interrupts.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/interrupts.h @@ -17,7 +17,7 @@ #ifndef __UVISOR_API_INTERRUPTS_H__ #define __UVISOR_API_INTERRUPTS_H__ -#include "api/inc/unvic_exports.h" +#include "api/inc/virq_exports.h" #include "api/inc/uvisor_exports.h" #include "api/inc/api.h" #include diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/ipc.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/ipc.h new file mode 100644 index 0000000000..19a737a2b5 --- /dev/null +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/ipc.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, 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_IPC_H__ +#define __UVISOR_API_IPC_H__ + +#include "api/inc/ipc_exports.h" +#include "api/inc/uvisor_exports.h" +#include +#include + + +/** Wait for any of the specified IPC operations to complete. + * + * @note This function currently spins, burning through power. + * + * @param[in] wait_tokens a bitfield of tokens to wait on + * @param[out] done_tokens a bitfield which tokens completed + * @param[in] timeout_ms how long to wait (in ms) for an IPC operation + * before returning. 0 means don't wait at all. Any + * other value means wait forever. + * @return 0 on success, non-zero error code otherwise + */ +UVISOR_EXTERN int ipc_waitforany(uint32_t wait_tokens, uint32_t * done_tokens, uint32_t timeout_ms); + +/** Wait for all of the specified IPC operations to complete. + * + * @note This function currently spins, burning through power. + * + * @param[in] wait_tokens a bitfield of tokens to wait on + * @param[out] done_tokens a bitfield which tokens completed + * @param[in] timeout_ms how long to wait (in ms) for an IPC operation + * before returning. 0 means don't wait at all. + * Any other value means wait forever. + * @return 0 on success, non-zero error code otherwise + */ +UVISOR_EXTERN int ipc_waitforall(uint32_t wait_tokens, uint32_t * done_tokens, uint32_t timeout_ms); + +/** Asynchronously send an IPC message + * + * @note The memory used for sending the message (pointed to by msg) must be + * valid until after the send is complete. + * + * @param[in] desc an IPC descriptor for the message + * @param[in] msg the message to send + * + * @return 0 on success, non-zero error code otherwise + * */ +UVISOR_EXTERN int ipc_send(uvisor_ipc_desc_t * desc, const void * msg); + +/** Asynchronously receive an IPC message + * + * @note The memory used for receiving the message (pointed to by msg) must be + * valid until after the receive is complete. + * + * @param[inout] desc an IPC descriptor for the message + * @param[out] msg the memory to copy the message to + * + * @return 0 on success, non-zero error code otherwise + */ +UVISOR_EXTERN int ipc_recv(uvisor_ipc_desc_t * desc, void * msg); + +#endif /* __UVISOR_API_IPC_H__ */ diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/ipc_exports.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/ipc_exports.h new file mode 100644 index 0000000000..dde7879727 --- /dev/null +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/ipc_exports.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017, 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_IPC_EXPORTS_H__ +#define __UVISOR_API_IPC_EXPORTS_H__ + +#include "api/inc/pool_queue_exports.h" +#include "api/inc/uvisor_spinlock_exports.h" +#include "api/inc/vmpu_exports.h" +#include + +/* Use the invalid box ID to mean "receive from any" box. */ +#define UVISOR_BOX_ID_ANY UVISOR_BOX_ID_INVALID + +#define UVISOR_IPC_SEND_SLOTS 16 +#define UVISOR_IPC_RECV_SLOTS 16 + +/* The value UVISOR_IPC_INVALID_TOKEN is defined to should be useful as a null + * token, and preferably not having any other legitimate use. Due to the + * internal bitfield representation of tokens, it makes a lot of sense to use 0 + * as the null token. ipc_allocate_token() returns 0 if no tokens are + * available. Freeing 0 bits means nothing ('&= ~0' is a no-op). No other value + * makes as much sense to use as 0. If tokens become represented internally as + * something other than a bitfield, it would make sense to reconsider the value + * used here. */ +#define UVISOR_IPC_INVALID_TOKEN 0 + +typedef enum uvisor_ipc_io_state { + UVISOR_IPC_IO_STATE_INVALID, + UVISOR_IPC_IO_STATE_IDLE, + UVISOR_IPC_IO_STATE_READY_TO_SEND, /* Enqueued and waiting for delivery */ + UVISOR_IPC_IO_STATE_READY_TO_RECV, /* Enqueued and waiting for delivery */ + UVISOR_IPC_IO_STATE_VALID, /* uVisor has copied the message */ +} uvisor_ipc_io_state_t; + +/* IPC Descriptor Structure */ +/* When sending: + * @param[in] box_id the ID of the destination box + * @param[in] port the port to send the message to + * @param[in] len the length of the message + * @param[out] token a token that can be used to wait at a later time for + * the send to complete + */ +/* When receiving before a message has been received: + * @param[in] box_id an ID of a box that is allowed to send to this box, or + * UVISOR_BOX_ID_ANY to allow messages from any box + * @param[in] port the port to listen for messages on + * @param[in] len the maximum length of message to receive + * @param[out] token a token that can be used to wait at a later time for + * the recv to complete + * + * When receiving after a message has been received: + * @param[out] box_id the box ID of the sender + * @param[out] port the port the message arrived on + * @param[out] len the length of the message + * @param[out] token not modified + */ +typedef struct uvisor_ipc_desc { + int box_id; + size_t port; + size_t len; + uint32_t token; +} uvisor_ipc_desc_t; + +/* IPC IO Request Structure */ +typedef struct uvisor_ipc_io { + uvisor_ipc_desc_t * desc; + void * msg; + uvisor_ipc_io_state_t state; +} uvisor_ipc_io_t; + +#define UVISOR_IPC_SEND_TYPE(slots) \ + struct { \ + uvisor_pool_queue_t queue; \ + uvisor_pool_t pool; \ + uvisor_pool_queue_entry_t entries[slots]; \ + uvisor_ipc_io_t io[slots]; \ + } + +#define UVISOR_IPC_RECV_TYPE(slots) \ + struct { \ + uvisor_pool_queue_t queue; \ + uvisor_pool_t pool; \ + uvisor_pool_queue_entry_t entries[slots]; \ + uvisor_ipc_io_t io[slots]; \ + } + +typedef UVISOR_IPC_SEND_TYPE(UVISOR_IPC_SEND_SLOTS) uvisor_ipc_send_queue_t; +typedef UVISOR_IPC_RECV_TYPE(UVISOR_IPC_RECV_SLOTS) uvisor_ipc_recv_queue_t; + +typedef struct uvisor_ipc { + uvisor_ipc_send_queue_t send_queue; + uvisor_ipc_recv_queue_t recv_queue; + UvisorSpinlock tokens_lock; /* Protect access to tokens. */ + uint32_t allocated_tokens; /* Endpoints read and write. */ + uint32_t completed_tokens; /* uVisor and endpoints read and write. */ +} uvisor_ipc_t; + +static inline uvisor_ipc_t * uvisor_ipc(UvisorBoxIndex * const index) +{ + return (uvisor_ipc_t *) index->bss.address_of.ipc; +} + +#endif diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/linker_exports.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/linker_exports.h new file mode 100644 index 0000000000..2597fdc38f --- /dev/null +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/linker_exports.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017, 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_LINKER_EXPORTS_H__ +#define __UVISOR_API_LINKER_EXPORTS_H__ + +/* FIXME Consider supporting other aliasing schemes. This is dependent on the + * IDAU implementation. Not all aliasing is guaranteed to work the same way. We + * currently only support a 1-bit MSB IDAU. */ +#if defined (ARCH_CORE_ARMv8M) || defined (TARGET_M33) +# define SECURE_ALIAS_OFFSET 0x10000000 +#else +# define SECURE_ALIAS_OFFSET 0 +#endif + +/** @returns the non-secure alias of the input address. */ +#define UVISOR_GET_NS_ALIAS(addr) ((typeof(addr)) ((uint32_t) (addr) & ~SECURE_ALIAS_OFFSET)) +/** @returns the secure alias of the input address. */ +#define UVISOR_GET_S_ALIAS(addr) ((typeof(addr)) ((uint32_t) (addr) | SECURE_ALIAS_OFFSET)) +/** @returns `true` if address is a secure alias. */ +#define UVISOR_IS_S_ALIAS(addr) ((uint32_t) (addr) & SECURE_ALIAS_OFFSET) +/** @returns an address targeting the non-secure state. */ +#define UVISOR_GET_NS_ADDRESS(addr) ((addr) & ~1UL) + +/** @returns the secure alias of the input address for uVisor core builds, and + * the non-secure alias for non-uVisor core builds. + * This is useful for code shared across secure and non-secure aliases. */ +#if UVISOR_CORE_BUILD +#define UVISOR_AUTO_ALIAS(addr) UVISOR_GET_S_ALIAS(addr) +#else +#define UVISOR_AUTO_ALIAS(addr) UVISOR_GET_NS_ALIAS(addr) +#endif + +/** @returns the secure alias of the input address for uVisor core builds, and + * assumes the addr supplied is already a non-secure alias for non-uVisor core builds. + * This is useful for code shared across secure and non-secure aliases. */ +#if UVISOR_CORE_BUILD +#define UVISOR_AUTO_NS_ALIAS(addr) UVISOR_GET_S_ALIAS(addr) +#else +#define UVISOR_AUTO_NS_ALIAS(addr) addr +#endif + +#endif diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/pool_queue_exports.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/pool_queue_exports.h index 38f1f139d4..7175e81d1d 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/pool_queue_exports.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/pool_queue_exports.h @@ -68,12 +68,6 @@ typedef struct uvisor_pool { /* 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; @@ -81,9 +75,6 @@ typedef struct uvisor_pool { /* 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; @@ -108,20 +99,17 @@ typedef struct uvisor_pool_queue { /* 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); +UVISOR_EXTERN int uvisor_pool_init(uvisor_pool_t * pool, void * array, size_t stride, size_t num); /* 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); +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); -/* 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); +/* Allocate a slot from the pool. 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 there is no 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); /* 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); @@ -142,6 +130,7 @@ UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_try_free(uvisor_pool_t * pool, uvis * 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_try_dequeue(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot); 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 @@ -156,15 +145,17 @@ UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_try_dequeue_first(uvisor_pool * 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_try_find_first(uvisor_pool_queue_t * pool_queue, + TQueryFN_Ptr query_fn, 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) +static inline uvisor_pool_slot_t uvisor_pool_queue_allocate(uvisor_pool_queue_t * pool_queue) { - return uvisor_pool_allocate(pool_queue->pool, timeout_ms); + return uvisor_pool_allocate(pool_queue->pool); } static inline uvisor_pool_slot_t uvisor_pool_queue_try_allocate(uvisor_pool_queue_t * pool_queue) diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/priv_sys_hook_exports.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/priv_sys_hooks_exports.h similarity index 100% rename from features/FEATURE_UVISOR/includes/uvisor/api/inc/priv_sys_hook_exports.h rename to features/FEATURE_UVISOR/includes/uvisor/api/inc/priv_sys_hooks_exports.h diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor-lib.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor-lib.h index edb0ba2289..4cfbd95054 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor-lib.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor-lib.h @@ -34,6 +34,7 @@ #include "api/inc/interrupts.h" #include "api/inc/register_gateway.h" #include "api/inc/rpc.h" +#include "api/inc/ipc.h" #include "api/inc/rpc_gateway.h" #include "api/inc/secure_access.h" #include "api/inc/uvisor_semaphore.h" @@ -45,10 +46,14 @@ #endif /* defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1 */ -/* The host startup needs to call this after osKernelInitialize to initialize - * uvisor-lib. The function can fail. It's up the the host startup to decide - * what to do with any failures. */ -UVISOR_EXTERN int uvisor_lib_init(void); +/* On ARMv7-M, the host startup needs to call this after osKernelInitialize to + * initialize uvisor-lib. The function can fail. It's up the the host startup + * to decide what to do with any failures. */ +UVISOR_EXTERN int uvisor_lib_init(void); /* FIXME: Remove this when we move ARMv7-M to the hypervisor model. */ + +/* The host startup needs to call this after osKernelInitialize to start + * uVisor. The function will halt if errors are encountered. */ +UVISOR_EXTERN void uvisor_start(void); #include "api/inc/page_allocator.h" @@ -60,8 +65,8 @@ UVISOR_EXTERN int uvisor_lib_init(void); #include "api/inc/halt_exports.h" #include "api/inc/register_gateway_exports.h" #include "api/inc/rpc_gateway_exports.h" -#include "api/inc/priv_sys_hook_exports.h" -#include "api/inc/unvic_exports.h" +#include "api/inc/priv_sys_hooks_exports.h" +#include "api/inc/virq_exports.h" #include "api/inc/uvisor_exports.h" #include "api/inc/vmpu_exports.h" #include "api/inc/page_allocator_exports.h" diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor_exports.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor_exports.h index bf2afe5c9e..7f933eeff0 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor_exports.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor_exports.h @@ -18,6 +18,7 @@ #define __UVISOR_API_UVISOR_EXPORTS_H__ #include +#include /* maximum number of boxes allowed: 1 is the minimum (unprivileged box) */ #define UVISOR_MAX_BOXES 5U @@ -190,4 +191,10 @@ #endif /* defined(__CC_ARM) || defined(__GNUC__) */ +typedef struct { + void (*function)(const void *); + size_t priority; + size_t stack_size; +} uvisor_box_main_t; + #endif /* __UVISOR_API_UVISOR_EXPORTS_H__ */ diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor_spinlock_exports.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor_spinlock_exports.h index f7ae3a4495..66209ada7b 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor_spinlock_exports.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/uvisor_spinlock_exports.h @@ -24,4 +24,19 @@ typedef struct { bool acquired; } UvisorSpinlock; +/* This function is safe to call from interrupt context. */ +UVISOR_EXTERN void uvisor_spin_init(UvisorSpinlock * spinlock); + +/* Attempt to spin lock once. Return true if the lock was obtained, false if + * otherwise. This function is safe to call from interrupt context. */ +UVISOR_EXTERN bool uvisor_spin_trylock(UvisorSpinlock * spinlock); + +/* Spin in a tight loop until the lock is obtained. This function is safe to + * call from interrupt context, but probably not wise. */ +UVISOR_EXTERN void uvisor_spin_lock(UvisorSpinlock * spinlock); + +/* Unlock the spin lock. This function is safe to call from interrupt context. + * */ +UVISOR_EXTERN void uvisor_spin_unlock(UvisorSpinlock * spinlock); + #endif /* __UVISOR_API_UVISOR_SPINLOCK_H__ */ diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/unvic_exports.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/virq_exports.h similarity index 100% rename from features/FEATURE_UVISOR/includes/uvisor/api/inc/unvic_exports.h rename to features/FEATURE_UVISOR/includes/uvisor/api/inc/virq_exports.h diff --git a/features/FEATURE_UVISOR/includes/uvisor/api/inc/vmpu_exports.h b/features/FEATURE_UVISOR/includes/uvisor/api/inc/vmpu_exports.h index 980186a5e9..00627c571d 100644 --- a/features/FEATURE_UVISOR/includes/uvisor/api/inc/vmpu_exports.h +++ b/features/FEATURE_UVISOR/includes/uvisor/api/inc/vmpu_exports.h @@ -116,7 +116,7 @@ #define UVISOR_REGION_ROUND_DOWN(x) ((x) & ~((1UL << UVISOR_REGION_BITS(x)) - 1)) #define UVISOR_REGION_ROUND_UP(x) (1UL << UVISOR_REGION_BITS(x)) #define UVISOR_STACK_SIZE_ROUND(x) UVISOR_REGION_ROUND_UP(x) -#elif defined(ARCH_MPU_KINETIS) +#elif defined(ARCH_MPU_ARMv8M) || defined(ARCH_MPU_KINETIS) #define UVISOR_REGION_ROUND_DOWN(x) UVISOR_ROUND32_DOWN(x) #define UVISOR_REGION_ROUND_UP(x) UVISOR_ROUND32_UP(x) #define UVISOR_STACK_SIZE_ROUND(x) UVISOR_REGION_ROUND_UP((x) + (UVISOR_STACK_BAND_SIZE * 2)) @@ -157,7 +157,9 @@ typedef struct { typedef struct uvisor_bss_sections_t { uint32_t index; uint32_t context; + uint32_t newlib_reent; uint32_t rpc; + uint32_t ipc; uint32_t heap; } UVISOR_PACKED UvisorBssSections; diff --git a/features/FEATURE_UVISOR/source/rtx/box_init.c b/features/FEATURE_UVISOR/source/rtx/box_init.c index 63f257243f..f707151503 100644 --- a/features/FEATURE_UVISOR/source/rtx/box_init.c +++ b/features/FEATURE_UVISOR/source/rtx/box_init.c @@ -22,6 +22,7 @@ #include "mbed_interface.h" #include "cmsis_os2.h" #include +#include #include /* Register the OS with uVisor */ @@ -36,6 +37,11 @@ extern RtxBoxIndex * const __uvisor_ps; void __uvisor_initialize_rpc_queues(void) { +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + // TODO Initialize RPC queues on ARMv8-M (via uvisor_start). + return; +#endif + UvisorBoxIndex * const index = &__uvisor_ps->index; uvisor_pool_slot_t i; @@ -49,8 +55,7 @@ void __uvisor_initialize_rpc_queues(void) &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_RPC_OUTGOING_MESSAGE_SLOTS)) { uvisor_error(USER_NOT_ALLOWED); } @@ -67,8 +72,7 @@ void __uvisor_initialize_rpc_queues(void) &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_RPC_INCOMING_MESSAGE_SLOTS)) { uvisor_error(USER_NOT_ALLOWED); } /* This is a double init of the pool. We need a function that just inits @@ -77,8 +81,7 @@ void __uvisor_initialize_rpc_queues(void) &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_RPC_INCOMING_MESSAGE_SLOTS)) { uvisor_error(USER_NOT_ALLOWED); } @@ -87,8 +90,7 @@ void __uvisor_initialize_rpc_queues(void) &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_RPC_FN_GROUP_SLOTS)) { uvisor_error(USER_NOT_ALLOWED); } @@ -119,20 +121,18 @@ void __uvisor_lib_box_init(void * lib_config) * is because the thread must be created to use a different stack than the * stack osCreateThread() is called from, as context information is saved * to the thread stack by the call to osCreateThread(). */ - /* Allocate memory for the main thread from the process heap (which is - * private to the process). This memory is never freed, even if the box's - * main thread exits. */ - thread_attr.stack_mem = malloc_p(thread_attr.stack_size); + /* Allocate memory for the main thread from the box heap. This memory is + * never freed, even if the box's main thread exits. */ + thread_attr.stack_mem = malloc(thread_attr.stack_size); if (thread_attr.stack_mem == NULL) { /* No process heap memory available for thread stack */ uvisor_error(USER_NOT_ALLOWED); } - /* Allocate memory for the main thread control block from the process heap - * (which is private to the process). This memory is never freed, even if - * the box's main thread exits. */ + /* Allocate memory for the main thread control block from the box heap. + * This memory is never freed, even if the box's main thread exits. */ thread_attr.cb_size = sizeof(osRtxThread_t); - thread_attr.cb_mem = malloc_p(thread_attr.cb_size); + thread_attr.cb_mem = malloc(thread_attr.cb_size); if (thread_attr.cb_mem == NULL) { /* No process heap memory available for thread control block. */ uvisor_error(USER_NOT_ALLOWED); diff --git a/features/FEATURE_UVISOR/source/rtx/rtx_malloc_wrapper.c b/features/FEATURE_UVISOR/source/rtx/rtx_malloc_wrapper.c index ddb90ba931..d701fbd5b7 100644 --- a/features/FEATURE_UVISOR/source/rtx/rtx_malloc_wrapper.c +++ b/features/FEATURE_UVISOR/source/rtx/rtx_malloc_wrapper.c @@ -23,12 +23,13 @@ #include #include -#define OP_MALLOC 0 -#define OP_REALLOC 1 -#define OP_FREE 2 - -#define HEAP_ACTIVE 0 -#define HEAP_PROCESS 1 +/* + * These are the C standard memory functions: + * - void *calloc(size_t nmemb, size_t size); + * - void free(void *ptr); + * - void *malloc(size_t size); + * - void *realloc(void *ptr, size_t size); +*/ /* Use printf with caution inside malloc: printf may allocate memory itself, so using printf in malloc may lead to recursive calls! */ @@ -40,6 +41,14 @@ extern RtxBoxIndex * const __uvisor_ps; * @retval 1 The kernel is initialized.. */ static int is_kernel_initialized() { + /* TODO: Bare-bone boxes must not call any RTX2 functions for now. + * Each box should instead provide `heap_lock` and `heap_unlock` functions + * as part of the box context. These would just be empty for boxes without + * the need for heap locking. */ + if (__uvisor_ps->index.box_id_self != 0) { + return 0; + } + static uint8_t kernel_running = 0; if (kernel_running) { return 1; @@ -106,7 +115,16 @@ static int init_allocator() return ret; } -static void * memory(void * ptr, size_t size, int heap, int operation) +typedef enum { + MEMOP_MALLOC, + MEMOP_MEMALIGN, + MEMOP_CALLOC, + MEMOP_REALLOC, + MEMOP_FREE +} MemoryOperation; + + +static void * memory(MemoryOperation operation, uint32_t * args) { /* Buffer the return value. */ void * ret = NULL; @@ -115,12 +133,8 @@ static void * memory(void * ptr, size_t size, int heap, int operation) return NULL; } /* Check if we need to aquire the mutex. */ - int mutexed = is_kernel_initialized() && - ((heap == HEAP_PROCESS) || - (void *) __uvisor_ps->index.bss.address_of.heap == __uvisor_ps->index.active_heap); - void * allocator = (heap == HEAP_PROCESS) ? - ((void *) __uvisor_ps->index.bss.address_of.heap) : - (__uvisor_ps->index.active_heap); + int mutexed = is_kernel_initialized(); + void * allocator = __uvisor_ps->index.active_heap; /* Aquire the mutex if required. * TODO: Mutex use is very coarse here. It may be sufficient to guard @@ -132,14 +146,20 @@ static void * memory(void * ptr, size_t size, int heap, int operation) /* Perform the required operation. */ switch(operation) { - case OP_MALLOC: - ret = secure_malloc(allocator, size); + case MEMOP_MALLOC: + ret = secure_malloc(allocator, (size_t) args[0]); break; - case OP_REALLOC: - ret = secure_realloc(allocator, ptr, size); + case MEMOP_MEMALIGN: + ret = secure_aligned_alloc(allocator, (size_t) args[0], (size_t) args[1]); break; - case OP_FREE: - secure_free(allocator, ptr); + case MEMOP_CALLOC: + ret = secure_calloc(allocator, (size_t) args[0], (size_t) args[1]); + break; + case MEMOP_REALLOC: + ret = secure_realloc(allocator, (void *) args[0], (size_t) args[1]); + break; + case MEMOP_FREE: + secure_free(allocator, (void *) args[0]); break; default: break; @@ -152,42 +172,36 @@ static void * memory(void * ptr, size_t size, int heap, int operation) } /* Wrapped memory management functions. */ -#if defined (__CC_ARM) -void * $Sub$$_malloc_r(struct _reent * r, size_t size) { - return memory(r, size, HEAP_ACTIVE, OP_MALLOC); -} -void * $Sub$$_realloc_r(struct _reent * r, void * ptr, size_t size) { - (void)r; - return memory(ptr, size, HEAP_ACTIVE, OP_REALLOC); -} -void $Sub$$_free_r(struct _reent * r, void * ptr) { - (void)r; - memory(ptr, 0, HEAP_ACTIVE, OP_FREE); -} -#elif defined (__GNUC__) +#if defined (__GNUC__) + void * __wrap__malloc_r(struct _reent * r, size_t size) { - return memory(r, size, HEAP_ACTIVE, OP_MALLOC); + (void) r; + return memory(MEMOP_MALLOC, (uint32_t *) &size); +} +void * __wrap__memalign_r(struct _reent * r, size_t alignment, size_t bytes) { + (void) r; + uint32_t args[2] = {(uint32_t) alignment, (uint32_t) bytes}; + return memory(MEMOP_MEMALIGN, args); +} +void * __wrap__calloc_r(struct _reent * r, size_t nmemb, size_t size) { + (void) r; + uint32_t args[2] = {(uint32_t) nmemb, (uint32_t) size}; + return memory(MEMOP_CALLOC, args); } void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size) { - (void)r; - return memory(ptr, size, HEAP_ACTIVE, OP_REALLOC); + (void) r; + uint32_t args[2] = {(uint32_t) ptr, (uint32_t) size}; + return memory(MEMOP_REALLOC, args); } void __wrap__free_r(struct _reent * r, void * ptr) { - (void)r; - memory(ptr, 0, HEAP_ACTIVE, OP_FREE); + (void) r; + memory(MEMOP_FREE, (uint32_t *) &ptr); } + +#elif defined (__CC_ARM) +/* TODO: Find out how to do function wrapping for ARMCC. See microlib libc. */ +# warning "Using uVisor allocator is not available for ARMCC. Falling back to default allocator." #elif defined (__ICCARM__) /* TODO: Find out how to do function wrapping for IARCC. */ -/* TODO: newlib allocator is not thread-safe! */ -# warning "Using uVisor allocator is not available for IARCC. Falling back to newlib allocator." +# warning "Using uVisor allocator is not available for IARCC. Falling back to default allocator." #endif - -void * malloc_p(size_t size) { - return memory(NULL, size, HEAP_PROCESS, OP_MALLOC); -} -void * realloc_p(void * ptr, size_t size) { - return memory(ptr, size, HEAP_PROCESS, OP_REALLOC); -} -void free_p(void * ptr) { - memory(ptr, 0, HEAP_PROCESS, OP_FREE); -} diff --git a/features/FEATURE_UVISOR/source/rtx/secure_allocator.c b/features/FEATURE_UVISOR/source/rtx/secure_allocator.c index dccbdbfcf5..3b39972d8a 100644 --- a/features/FEATURE_UVISOR/source/rtx/secure_allocator.c +++ b/features/FEATURE_UVISOR/source/rtx/secure_allocator.c @@ -205,6 +205,40 @@ void * secure_malloc( return NULL; } +void * secure_aligned_alloc( + SecureAllocator allocator, + size_t alignment, + size_t size) +{ + /* Alignment must be a power of two! */ + if (alignment & ((1UL << ((31UL - __builtin_clz(alignment)) - 1)))) { + return NULL; + } + /* TODO: THIS IS A NAIVE IMPLEMENTATION, which wastes much memory. */ + void * ptr = secure_malloc(allocator, size + alignment - 1); + if (ptr == NULL) { + return NULL; + } + return (void *) (((uint32_t) ptr + alignment - 1) & ~(alignment - 1)); +} + +void * secure_calloc( + SecureAllocator allocator, + size_t nmemb, + size_t size) +{ + if ((uint64_t) nmemb * size > SIZE_MAX) { + /* (size * nmemb) has overflowed. */ + return NULL; + } + void * ptr = secure_malloc(allocator, size * nmemb); + if (ptr == NULL) { + return NULL; + } + memset(ptr, 0, size * nmemb); + return ptr; +} + void * secure_realloc( SecureAllocator allocator, void * ptr, diff --git a/features/FEATURE_UVISOR/source/rtx/tz_context.c b/features/FEATURE_UVISOR/source/rtx/tz_context.c new file mode 100644 index 0000000000..0f9cbc4899 --- /dev/null +++ b/features/FEATURE_UVISOR/source/rtx/tz_context.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, 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. + */ + +#include "tz_context.h" +#include + +/* Provide do-nothing stubs for RTX's trustzone context saving hooks. uVisor + * doesn't use these on ARMv8-M. */ + +uint32_t TZ_InitContextSystem_S(void) { + return 1; /* Success */ +} + +TZ_MemoryId_t TZ_AllocModuleContext_S(TZ_ModuleId_t module) { + return 1; /* Always hand out slot 1. */ +} + +uint32_t TZ_FreeModuleContext_S(TZ_MemoryId_t id) { + return 1; /* Success */ +} + +uint32_t TZ_LoadContext_S(TZ_MemoryId_t id) { + return 1; /* Success */ +} + +uint32_t TZ_StoreContext_S(TZ_MemoryId_t id) { + return 1; /* Success */ +} diff --git a/features/FEATURE_UVISOR/source/rtx/unsupported_page_allocator.c b/features/FEATURE_UVISOR/source/rtx/unsupported_page_allocator.c index c0423a97ab..62708609f7 100644 --- a/features/FEATURE_UVISOR/source/rtx/unsupported_page_allocator.c +++ b/features/FEATURE_UVISOR/source/rtx/unsupported_page_allocator.c @@ -54,7 +54,7 @@ int uvisor_page_free(const UvisorPageTable *const table) static osMutexId_t g_page_allocator_mutex_id = NULL; static osRtxMutex_t g_page_allocator_mutex_data; static osMutexDef_t g_page_allocator_mutex_attr = { - .name = "uvisor_page_alloc_mutex", + .name = "uvisor_malloc_mutex", .attr_bits = 0, /* Non-recursive */ .cb_mem = &g_page_allocator_mutex_data, .cb_size = sizeof(g_page_allocator_mutex_data) diff --git a/features/FEATURE_UVISOR/source/rtx/uvisor_semaphore.c b/features/FEATURE_UVISOR/source/rtx/uvisor_semaphore.c index 4372b2fd07..e064031f6e 100644 --- a/features/FEATURE_UVISOR/source/rtx/uvisor_semaphore.c +++ b/features/FEATURE_UVISOR/source/rtx/uvisor_semaphore.c @@ -19,6 +19,7 @@ int __uvisor_semaphore_init(UvisorSemaphore * s, uint32_t max_count, uint32_t in memset(&semaphore->data, 0, sizeof(semaphore->data)); memset(&semaphore->attr, 0, sizeof(semaphore->attr)); + semaphore->attr.name = "uvisor_semaphore"; semaphore->attr.cb_size = sizeof(semaphore->data); semaphore->attr.cb_mem = &semaphore->data; semaphore->id = osSemaphoreNew(max_count, initial_count, &semaphore->attr); diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_ARM_BEETLE_SOC/TARGET_DEBUG/TARGET_M3/libconfiguration_beetle_cortex_m3_0x20000000_0x140.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_ARM_BEETLE_SOC/TARGET_DEBUG/TARGET_M3/libconfiguration_beetle_cortex_m3_0x20000000_0x140.a index 244b33917d..8f9b6f38cd 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_ARM_BEETLE_SOC/TARGET_DEBUG/TARGET_M3/libconfiguration_beetle_cortex_m3_0x20000000_0x140.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_ARM_BEETLE_SOC/TARGET_DEBUG/TARGET_M3/libconfiguration_beetle_cortex_m3_0x20000000_0x140.a differ diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_ARM_BEETLE_SOC/TARGET_RELEASE/TARGET_M3/libconfiguration_beetle_cortex_m3_0x20000000_0x140.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_ARM_BEETLE_SOC/TARGET_RELEASE/TARGET_M3/libconfiguration_beetle_cortex_m3_0x20000000_0x140.a index 0a9c228580..ac57791758 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_ARM_BEETLE_SOC/TARGET_RELEASE/TARGET_M3/libconfiguration_beetle_cortex_m3_0x20000000_0x140.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_ARM_BEETLE_SOC/TARGET_RELEASE/TARGET_M3/libconfiguration_beetle_cortex_m3_0x20000000_0x140.a differ diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_DEBUG/TARGET_M3/libconfiguration_efm32_cortex_m3_p1.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_DEBUG/TARGET_M3/libconfiguration_efm32_cortex_m3_p1.a index 48ef62b4be..c5485d679f 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_DEBUG/TARGET_M3/libconfiguration_efm32_cortex_m3_p1.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_DEBUG/TARGET_M3/libconfiguration_efm32_cortex_m3_p1.a differ diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_DEBUG/TARGET_M4/libconfiguration_efm32_cortex_m4_p1.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_DEBUG/TARGET_M4/libconfiguration_efm32_cortex_m4_p1.a index 7ee1f06268..d22c9c56e5 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_DEBUG/TARGET_M4/libconfiguration_efm32_cortex_m4_p1.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_DEBUG/TARGET_M4/libconfiguration_efm32_cortex_m4_p1.a differ diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_RELEASE/TARGET_M3/libconfiguration_efm32_cortex_m3_p1.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_RELEASE/TARGET_M3/libconfiguration_efm32_cortex_m3_p1.a index 5074eee338..38984ca10e 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_RELEASE/TARGET_M3/libconfiguration_efm32_cortex_m3_p1.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_RELEASE/TARGET_M3/libconfiguration_efm32_cortex_m3_p1.a differ diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_RELEASE/TARGET_M4/libconfiguration_efm32_cortex_m4_p1.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_RELEASE/TARGET_M4/libconfiguration_efm32_cortex_m4_p1.a index 17b0845abf..0e842ca39b 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_RELEASE/TARGET_M4/libconfiguration_efm32_cortex_m4_p1.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_EFM32/TARGET_RELEASE/TARGET_M4/libconfiguration_efm32_cortex_m4_p1.a differ diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_MCU_K64F/TARGET_DEBUG/TARGET_M4/libconfiguration_kinetis_cortex_m4_0x1fff0000.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_MCU_K64F/TARGET_DEBUG/TARGET_M4/libconfiguration_kinetis_cortex_m4_0x1fff0000.a index 8bab147392..5c33ee6c8a 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_MCU_K64F/TARGET_DEBUG/TARGET_M4/libconfiguration_kinetis_cortex_m4_0x1fff0000.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_MCU_K64F/TARGET_DEBUG/TARGET_M4/libconfiguration_kinetis_cortex_m4_0x1fff0000.a differ diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_MCU_K64F/TARGET_RELEASE/TARGET_M4/libconfiguration_kinetis_cortex_m4_0x1fff0000.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_MCU_K64F/TARGET_RELEASE/TARGET_M4/libconfiguration_kinetis_cortex_m4_0x1fff0000.a index 0cd6833945..11acdce49c 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_MCU_K64F/TARGET_RELEASE/TARGET_M4/libconfiguration_kinetis_cortex_m4_0x1fff0000.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_MCU_K64F/TARGET_RELEASE/TARGET_M4/libconfiguration_kinetis_cortex_m4_0x1fff0000.a differ diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_STM32F4/TARGET_DEBUG/TARGET_M4/libconfiguration_stm32_cortex_m4_0x10000000_0x0.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_STM32F4/TARGET_DEBUG/TARGET_M4/libconfiguration_stm32_cortex_m4_0x10000000_0x0.a index a001ff6b22..e2a71c43ee 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_STM32F4/TARGET_DEBUG/TARGET_M4/libconfiguration_stm32_cortex_m4_0x10000000_0x0.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_STM32F4/TARGET_DEBUG/TARGET_M4/libconfiguration_stm32_cortex_m4_0x10000000_0x0.a differ diff --git a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_STM32F4/TARGET_RELEASE/TARGET_M4/libconfiguration_stm32_cortex_m4_0x10000000_0x0.a b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_STM32F4/TARGET_RELEASE/TARGET_M4/libconfiguration_stm32_cortex_m4_0x10000000_0x0.a index 2a27c33d90..d65a2a27c9 100644 Binary files a/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_STM32F4/TARGET_RELEASE/TARGET_M4/libconfiguration_stm32_cortex_m4_0x10000000_0x0.a and b/features/FEATURE_UVISOR/targets/TARGET_UVISOR_SUPPORTED/TARGET_STM32F4/TARGET_RELEASE/TARGET_M4/libconfiguration_stm32_cortex_m4_0x10000000_0x0.a differ