mirror of https://github.com/ARMmbed/mbed-os.git
commit
40042f0b00
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
v0.27.0-23-g8231ae897dadbb1c3eeb79ae2103d308d28c7e14
|
||||
v0.28.1
|
||||
|
|
|
@ -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__ */
|
|
@ -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,
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
/* The uVisor API main header file will use the above definitions. */
|
||||
#include "uvisor/api/inc/uvisor-lib.h"
|
||||
#include "uvisor-lib/rtx/process_malloc.h"
|
||||
#include "uvisor-lib/rtx/rtx_box_index.h"
|
||||
#include "uvisor-lib/rtx/secure_allocator.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 <stdint.h>
|
||||
|
||||
#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;
|
||||
|
||||
|
|
|
@ -22,15 +22,16 @@
|
|||
#include "api/inc/rpc_exports.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/reent.h>
|
||||
|
||||
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), \
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 <stdint.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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
/** 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__ */
|
|
@ -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 <stddef.h>
|
||||
|
||||
/* 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
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define __UVISOR_API_UVISOR_EXPORTS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* 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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "mbed_interface.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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);
|
||||
|
|
|
@ -23,12 +23,13 @@
|
|||
#include <stdio.h>
|
||||
#include <reent.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <stdint.h>
|
||||
|
||||
/* 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 */
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
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.
|
@ -80,6 +80,7 @@ void mbed_stats_heap_get(mbed_stats_heap_t *stats)
|
|||
|
||||
extern "C" {
|
||||
void * __real__malloc_r(struct _reent * r, size_t size);
|
||||
void * __real__memalign_r(struct _reent * r, size_t alignment, size_t bytes);
|
||||
void * __real__realloc_r(struct _reent * r, void * ptr, size_t size);
|
||||
void __real__free_r(struct _reent * r, void * ptr);
|
||||
void* __real__calloc_r(struct _reent * r, size_t nmemb, size_t size);
|
||||
|
@ -178,8 +179,6 @@ extern "C" void __wrap__free_r(struct _reent * r, void * ptr) {
|
|||
#endif // #ifdef MBED_MEM_TRACING_ENABLED
|
||||
}
|
||||
|
||||
#endif // if !defined(FEATURE_UVISOR)
|
||||
|
||||
extern "C" void * __wrap__calloc_r(struct _reent * r, size_t nmemb, size_t size) {
|
||||
void *ptr = NULL;
|
||||
#ifdef MBED_HEAP_STATS_ENABLED
|
||||
|
@ -200,6 +199,12 @@ extern "C" void * __wrap__calloc_r(struct _reent * r, size_t nmemb, size_t size)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
extern "C" void * __wrap__memalign_r(struct _reent * r, size_t alignment, size_t bytes) {
|
||||
return __real__memalign_r(r, alignment, bytes);
|
||||
}
|
||||
|
||||
#endif // if !defined(FEATURE_UVISOR)
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* ARMCC memory allocation wrappers */
|
||||
|
|
|
@ -73,12 +73,27 @@ SVC_ContextSave:
|
|||
STR R12,[R1,#TCB_SP_OFS] // Store SP
|
||||
|
||||
SVC_ContextSwitch:
|
||||
#ifdef FEATURE_UVISOR
|
||||
CPSID I // The call to the thread switch helper and PSP loading must be atomic.
|
||||
#endif
|
||||
/* The call to thread_switch_helper can clobber R2 and R3, but we don't
|
||||
* want to clobber R2 or R3. We can't save R2 and R3 to the stack (as
|
||||
* the stack we save them onto is likely to be inaccessible after the
|
||||
* call to thread_switch_helper). So, we just re-obtain the values from
|
||||
* osRtxInfo again. */
|
||||
BL thread_switch_helper
|
||||
LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
|
||||
LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next
|
||||
|
||||
STR R2,[R3] // osRtxInfo.thread.run: curr = next
|
||||
|
||||
SVC_ContextRestore:
|
||||
LDR R0,[R2,#TCB_SP_OFS] // Load SP
|
||||
LDMIA R0!,{R4-R11} // Restore R4..R11
|
||||
MSR PSP,R0 // Set PSP
|
||||
#ifdef FEATURE_UVISOR
|
||||
CPSIE I // The PSP has been set. Re-enable interrupts.
|
||||
#endif
|
||||
MVN LR,#~0xFFFFFFFD // Set EXC_RETURN value
|
||||
|
||||
SVC_Exit:
|
||||
|
|
|
@ -91,6 +91,18 @@ SVC_ContextSave:
|
|||
STRB LR, [R1,#TCB_SF_OFS] // Store stack frame information
|
||||
|
||||
SVC_ContextSwitch:
|
||||
#ifdef FEATURE_UVISOR
|
||||
CPSID I // The call to the thread switch helper and PSP loading must be atomic.
|
||||
#endif
|
||||
/* The call to thread_switch_helper can clobber R2 and R3, but we don't
|
||||
* want to clobber R2 or R3. We can't save R2 and R3 to the stack (as
|
||||
* the stack we save them onto is likely to be inaccessible after the
|
||||
* call to thread_switch_helper). So, we just re-obtain the values from
|
||||
* osRtxInfo again. */
|
||||
BL thread_switch_helper
|
||||
LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
|
||||
LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next
|
||||
|
||||
STR R2,[R3] // osRtxInfo.thread.run: curr = next
|
||||
|
||||
SVC_ContextRestore:
|
||||
|
@ -105,6 +117,9 @@ SVC_ContextRestore:
|
|||
#endif
|
||||
LDMIA R0!,{R4-R11} // Restore R4..R11
|
||||
MSR PSP,R0 // Set PSP
|
||||
#ifdef FEATURE_UVISOR
|
||||
CPSIE I // The PSP has been set. Re-enable interrupts.
|
||||
#endif
|
||||
|
||||
SVC_Exit:
|
||||
BX LR // Exit from handler
|
||||
|
|
|
@ -426,9 +426,12 @@ void osRtxThreadSwitch (os_thread_t *thread) {
|
|||
osRtxInfo.thread.run.next = thread;
|
||||
osRtxThreadStackCheck();
|
||||
EvrRtxThreadSwitch(thread);
|
||||
}
|
||||
|
||||
/// Notify the OS event observer of an imminent thread switch.
|
||||
void thread_switch_helper(void) {
|
||||
if (osEventObs && osEventObs->thread_switch) {
|
||||
osEventObs->thread_switch(thread->context);
|
||||
osEventObs->thread_switch(osRtxInfo.thread.run.next->context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"c": ["-std=gnu99"],
|
||||
"cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"],
|
||||
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
|
||||
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r",
|
||||
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r",
|
||||
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit",
|
||||
"-Wl,-n"]
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"c": ["-std=gnu99"],
|
||||
"cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"],
|
||||
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
|
||||
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r",
|
||||
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r",
|
||||
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit",
|
||||
"-Wl,-n"]
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"c": ["-std=gnu99"],
|
||||
"cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"],
|
||||
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
|
||||
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r",
|
||||
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r",
|
||||
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit",
|
||||
"-Wl,-n"]
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue