mirror of https://github.com/ARMmbed/mbed-os.git
commit
123d55d803
|
@ -0,0 +1,12 @@
|
|||
519 Milosch Meriac
|
||||
420 Alessandro Angelino
|
||||
16 Niklas Hauser
|
||||
15 Jaeden Amero
|
||||
3 Hugo Vincent
|
||||
3 JaredCJR
|
||||
3 Jim Huang
|
||||
2 tonyyanxuan
|
||||
1 Aksel Skauge Mellbye
|
||||
1 Irit Arkin
|
||||
1 Nathan Chong
|
||||
1 ccli8
|
|
@ -0,0 +1 @@
|
|||
v0.9.14-alpha
|
|
@ -0,0 +1,115 @@
|
|||
###########################################################################
|
||||
#
|
||||
# Copyright (c) 2013-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.
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
# Toolchain
|
||||
PREFIX:=arm-none-eabi-
|
||||
GDB:=$(PREFIX)gdb
|
||||
OBJDUMP:=$(PREFIX)objdump
|
||||
|
||||
# Translate between uVisor namespace and mbed namespace
|
||||
TARGET_TRANSLATION:=MCU_K64F.kinetis EFM32.efm32 STM32F4.stm32
|
||||
TARGET_PREFIX:=../
|
||||
TARGET_SUPPORTED:=$(TARGET_PREFIX)targets/TARGET_UVISOR_SUPPORTED
|
||||
TARGET_UNSUPPORTED:=$(TARGET_PREFIX)targets/TARGET_UVISOR_UNSUPPORTED
|
||||
TARGET_INC:=$(TARGET_PREFIX)includes/uvisor/api
|
||||
TARGET_LIB_SRC:=$(TARGET_PREFIX)source
|
||||
TARGET_LIB_INC:=$(TARGET_PREFIX)includes/uvisor-lib
|
||||
|
||||
# uVisor source directory - hidden from mbed via TARGET_IGNORE
|
||||
UVISOR_GIT_URL:=https://github.com/ARMmbed/uvisor
|
||||
UVISOR_GIT_BRANCH:=dev
|
||||
UVISOR_DIR:=TARGET_IGNORE/uvisor
|
||||
UVISOR_API:=$(UVISOR_DIR)/api
|
||||
UVISOR_GIT_CFG=$(UVISOR_DIR)/.git/config
|
||||
|
||||
# Derive variables from user configuration
|
||||
TARGET_LIST:=$(subst .,,$(suffix $(TARGET_TRANSLATION)))
|
||||
TARGET_LIST_DIR_SRC:=$(addprefix $(UVISOR_API)/lib/,$(TARGET_LIST))
|
||||
TARGET_LIST_DIR_DST:=$(addprefix $(TARGET_SUPPORTED)/,$(TARGET_LIST))
|
||||
TARGET_LIST_RELEASE:=$(addsuffix /release,$(TARGET_LIST_DIR_DST))
|
||||
TARGET_LIST_DEBUG:=$(addsuffix /debug,$(TARGET_LIST_DIR_DST))
|
||||
|
||||
.PHONY: all deploy rsync publish uvisor uvisor-compile clean cache update
|
||||
|
||||
all: uvisor
|
||||
|
||||
uvisor: uvisor-compile publish
|
||||
|
||||
rsync:
|
||||
#
|
||||
# Copying uVisor into mbed library...
|
||||
rm -rf $(TARGET_SUPPORTED)
|
||||
mkdir -p $(TARGET_SUPPORTED)
|
||||
rsync -a --exclude='*.txt' $(TARGET_LIST_DIR_SRC) $(TARGET_SUPPORTED)
|
||||
#
|
||||
# Copying uVisor headers to mbed includes...
|
||||
rm -rf $(TARGET_INC)
|
||||
mkdir -p $(TARGET_INC)
|
||||
rsync -a --delete $(UVISOR_API)/inc $(TARGET_INC)
|
||||
rsync -a --delete $(UVISOR_API)/rtx/inc/ $(TARGET_LIB_INC)/rtx
|
||||
#
|
||||
# Copying uVisor unsupported sources to unsupported target source...
|
||||
mkdir -p $(TARGET_UNSUPPORTED)
|
||||
cp $(UVISOR_API)/src/unsupported.c $(TARGET_UNSUPPORTED)/
|
||||
#
|
||||
# Copying uVisor shared sources to mbed source...
|
||||
rm -rf $(TARGET_LIB_SRC)
|
||||
mkdir -p $(TARGET_LIB_SRC)
|
||||
cp $(UVISOR_DIR)/core/system/src/page_allocator.c $(TARGET_LIB_SRC)/page_allocator.c_inc
|
||||
rsync -a --delete $(UVISOR_API)/rtx/src/ $(TARGET_LIB_SRC)/rtx
|
||||
#
|
||||
# Copying licenses
|
||||
cp $(UVISOR_DIR)/LICENSE* $(TARGET_SUPPORTED)
|
||||
|
||||
TARGET_M%: $(TARGET_SUPPORTED)/*/*/*_m%_*.a
|
||||
@printf "#\n# Copying $@ files...\n"
|
||||
mkdir $(foreach file,$^,$(dir $(file))$@)
|
||||
$(foreach file,$^,mv $(file) $(dir $(file))$@/lib$(notdir $(file));)
|
||||
|
||||
publish: rsync TARGET_M3 TARGET_M4
|
||||
#
|
||||
# Rename release directorires to TARGET_RELEASE filters...
|
||||
$(foreach dir, $(TARGET_LIST_RELEASE),mv $(dir) $(dir $(dir))TARGET_RELEASE;)
|
||||
#
|
||||
# Rename debug directorires to TARGET_DEBUG filters...
|
||||
$(foreach dir, $(TARGET_LIST_DEBUG),mv $(dir) $(dir $(dir))TARGET_DEBUG;)
|
||||
#
|
||||
# Rename target directorires to TARGET_* filters...
|
||||
$(foreach target, $(TARGET_TRANSLATION),mv $(TARGET_SUPPORTED)/$(subst .,,$(suffix $(target))) $(TARGET_SUPPORTED)/TARGET_$(basename $(target));)
|
||||
|
||||
uvisor-compile: $(UVISOR_GIT_CFG)
|
||||
make -C $(UVISOR_DIR)
|
||||
|
||||
update: $(UVISOR_GIT_CFG)
|
||||
#
|
||||
# Updating to latest uVisor library version
|
||||
git -C $(UVISOR_DIR) pull --rebase
|
||||
#
|
||||
# Updating checked out version tag
|
||||
git -C $(UVISOR_DIR) describe --tags --abbrev=40 --dirty > $(TARGET_PREFIX)VERSION.txt
|
||||
#
|
||||
# Updated list of authors, sorted by contributions
|
||||
git -C $(UVISOR_DIR) shortlog -s -n > $(TARGET_PREFIX)AUTHORS.txt
|
||||
|
||||
$(UVISOR_GIT_CFG):
|
||||
rm -rf $(UVISOR_DIR)
|
||||
git clone -b $(UVISOR_GIT_BRANCH) $(UVISOR_GIT_URL) $(UVISOR_DIR)
|
||||
|
||||
clean: $(UVISOR_GIT_CFG)
|
||||
make -C $(UVISOR_DIR) clean
|
|
@ -0,0 +1,6 @@
|
|||
# Rebuilding the uVisor mbed Library
|
||||
|
||||
This directory contains scripts to import and rebuild the latest uVisor library to mbed Classic.
|
||||
uVisor does not need to be re-deployed for normal application development.
|
||||
|
||||
For uVisor development and code contributions please visit the [uVisor repository](https://github.com/ARMmbed/uvisor).
|
|
@ -0,0 +1 @@
|
|||
/uvisor
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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_BOX_INDEX_H__
|
||||
#define __RTX_BOX_INDEX_H__
|
||||
|
||||
#include "cmsis_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* The uvisor box index must be placed at the beginning */
|
||||
UvisorBoxIndex index;
|
||||
|
||||
/* Id of the mutex */
|
||||
osMutexId mutex_id;
|
||||
/* Pointer to the data of the mutex */
|
||||
osMutexDef_t mutex;
|
||||
/* Internal data of the mutex */
|
||||
int32_t mutex_data[4];
|
||||
} RtxBoxIndex;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __RTX_BOX_INDEX_H__ */
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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 __SECURE_ALLOCATOR_H__
|
||||
#define __SECURE_ALLOCATOR_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Contains the allocator data and backing page table. */
|
||||
typedef void * SecureAllocator;
|
||||
|
||||
/** Create an allocator in-place in an existing pool without using pages.
|
||||
* Use this to turn statically allocated memory into a heap.
|
||||
* Or allocate a large piece of memory and then turn that into a heap.
|
||||
*
|
||||
* @param mem Pointer to the origin of the memory pool
|
||||
* @param bytes Length of the memory pool in bytes
|
||||
* @returns the allocator or `NULL` on failure
|
||||
*/
|
||||
SecureAllocator secure_allocator_create_with_pool(
|
||||
void * mem,
|
||||
size_t bytes);
|
||||
|
||||
/** Create an allocator using pages from the page heap.
|
||||
* Use this to request secure dynamic memory for your process.
|
||||
* Note that this memory is not guaranteed to be consecutive, therefore you
|
||||
* must specify the maximum allocation size that you plan to use in this
|
||||
* allocator. This function will then compute the number and size of required
|
||||
* pages and request them from the secure page heap.
|
||||
*
|
||||
* @param total_size The minimal total size of the heap
|
||||
* @param maximum_malloc_size The largest size to be allocated in one chunk
|
||||
* @returns the allocator or `NULL` on failure (out of memory,
|
||||
* maximum malloc size cannot be fulfilled)
|
||||
*/
|
||||
SecureAllocator secure_allocator_create_with_pages(
|
||||
size_t total_size,
|
||||
size_t maximum_malloc_size);
|
||||
|
||||
/** Destroy the allocator and free the backing pages.
|
||||
* An attempt to destroy a memory-pool backed allocator will fail and return
|
||||
* with an error code.
|
||||
*
|
||||
* @retval 0 Allocator successfully destroyed.
|
||||
* @retval -1 Allocator is static (memory-pool), or freeing memory pages failed.
|
||||
*/
|
||||
int secure_allocator_destroy(
|
||||
SecureAllocator allocator);
|
||||
|
||||
/** Drop-in for `malloc`. */
|
||||
void * secure_malloc(
|
||||
SecureAllocator allocator,
|
||||
size_t size);
|
||||
|
||||
/** Drop-in for `realloc`. */
|
||||
void * secure_realloc(
|
||||
SecureAllocator allocator,
|
||||
void * ptr,
|
||||
size_t size);
|
||||
|
||||
/** Drop-in for `free`. */
|
||||
void secure_free(
|
||||
SecureAllocator allocator,
|
||||
void * ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __SECURE_ALLOCATOR_H__ */
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_LIB_UVISOR_LIB_H__
|
||||
#define __UVISOR_LIB_UVISOR_LIB_H__
|
||||
|
||||
/* This file translates mbed-specific pre-processor symbols into
|
||||
* uVisor-specific ones. Then the main uvisor-lib.h file is included. */
|
||||
|
||||
/* mbed uses UVISOR_SUPPORTED to determine whether the full uVisor binaries
|
||||
* should be included or not. This symbol maps to the uVisor-internal symbol
|
||||
* UVISOR_PRESENT. */
|
||||
/* By default uVisor is not supported. */
|
||||
#if !defined(FEATURE_UVISOR) || !defined(TARGET_UVISOR_SUPPORTED) || defined(TARGET_UVISOR_UNSUPPORTED)
|
||||
#define UVISOR_PRESENT 0
|
||||
#else
|
||||
#define UVISOR_PRESENT 1
|
||||
#endif
|
||||
|
||||
/* Detect the target using the mbed-specific symbols and determine the MPU
|
||||
* architecture accordingly. */
|
||||
#if defined(TARGET_KINETIS)
|
||||
#define ARCH_MPU_KINETIS
|
||||
#else
|
||||
#define ARCH_MPU_ARMv7M
|
||||
#endif
|
||||
|
||||
/* 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"
|
||||
|
||||
#endif /* __UVISOR_LIB_UVISOR_LIB_H__ */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2015, 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_BENCHMARK_H__
|
||||
#define __UVISOR_API_BENCHMARK_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
UVISOR_EXTERN void uvisor_benchmark_configure(void);
|
||||
UVISOR_EXTERN void uvisor_benchmark_start(void);
|
||||
UVISOR_EXTERN uint32_t uvisor_benchmark_stop(void);
|
||||
|
||||
#endif /* __UVISOR_API_BENCHMARK_H__ */
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_BOX_CONFIG_H__
|
||||
#define __UVISOR_API_BOX_CONFIG_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
UVISOR_EXTERN const uint32_t __uvisor_mode;
|
||||
|
||||
#define UVISOR_DISABLED 0
|
||||
#define UVISOR_PERMISSIVE 1
|
||||
#define UVISOR_ENABLED 2
|
||||
|
||||
#define UVISOR_SET_MODE(mode) \
|
||||
UVISOR_SET_MODE_ACL_COUNT(mode, NULL, 0)
|
||||
|
||||
#define UVISOR_SET_MODE_ACL(mode, acl_list) \
|
||||
UVISOR_SET_MODE_ACL_COUNT(mode, acl_list, UVISOR_ARRAY_COUNT(acl_list))
|
||||
|
||||
#define UVISOR_SET_MODE_ACL_COUNT(mode, acl_list, acl_list_count) \
|
||||
uint8_t __attribute__((section(".keep.uvisor.bss.boxes"), aligned(32))) __reserved_stack[UVISOR_STACK_BAND_SIZE]; \
|
||||
\
|
||||
UVISOR_EXTERN const uint32_t __uvisor_mode = (mode); \
|
||||
\
|
||||
static const __attribute__((section(".keep.uvisor.cfgtbl"), aligned(4))) UvisorBoxConfig main_cfg = { \
|
||||
UVISOR_BOX_MAGIC, \
|
||||
UVISOR_BOX_VERSION, \
|
||||
0, \
|
||||
sizeof(RtxBoxIndex), \
|
||||
0, \
|
||||
0, \
|
||||
NULL, \
|
||||
acl_list, \
|
||||
acl_list_count \
|
||||
}; \
|
||||
\
|
||||
extern const __attribute__((section(".keep.uvisor.cfgtbl_ptr_first"), aligned(4))) void * const main_cfg_ptr = &main_cfg;
|
||||
|
||||
/* this macro selects an overloaded macro (variable number of arguments) */
|
||||
#define __UVISOR_BOX_MACRO(_1, _2, _3, _4, NAME, ...) NAME
|
||||
|
||||
#define __UVISOR_BOX_CONFIG(box_name, acl_list, acl_list_count, stack_size, context_size) \
|
||||
\
|
||||
uint8_t __attribute__((section(".keep.uvisor.bss.boxes"), aligned(32))) \
|
||||
box_name ## _reserved[ \
|
||||
UVISOR_STACK_SIZE_ROUND( \
|
||||
( \
|
||||
(UVISOR_MIN_STACK(stack_size) + \
|
||||
(context_size) + \
|
||||
(__uvisor_box_heapsize) + \
|
||||
sizeof(RtxBoxIndex) \
|
||||
) \
|
||||
* 8) \
|
||||
/ 6)]; \
|
||||
\
|
||||
static const __attribute__((section(".keep.uvisor.cfgtbl"), aligned(4))) UvisorBoxConfig box_name ## _cfg = { \
|
||||
UVISOR_BOX_MAGIC, \
|
||||
UVISOR_BOX_VERSION, \
|
||||
UVISOR_MIN_STACK(stack_size), \
|
||||
sizeof(RtxBoxIndex), \
|
||||
context_size, \
|
||||
__uvisor_box_heapsize, \
|
||||
__uvisor_box_namespace, \
|
||||
acl_list, \
|
||||
acl_list_count \
|
||||
}; \
|
||||
\
|
||||
extern const __attribute__((section(".keep.uvisor.cfgtbl_ptr"), aligned(4))) void * const box_name ## _cfg_ptr = &box_name ## _cfg;
|
||||
|
||||
#define __UVISOR_BOX_CONFIG_NOCONTEXT(box_name, acl_list, stack_size) \
|
||||
__UVISOR_BOX_CONFIG(box_name, acl_list, UVISOR_ARRAY_COUNT(acl_list), stack_size, 0) \
|
||||
|
||||
#define __UVISOR_BOX_CONFIG_CONTEXT(box_name, acl_list, stack_size, context_type) \
|
||||
__UVISOR_BOX_CONFIG(box_name, acl_list, UVISOR_ARRAY_COUNT(acl_list), stack_size, sizeof(context_type)) \
|
||||
UVISOR_EXTERN context_type *const *const __uvisor_ps;
|
||||
|
||||
#define __UVISOR_BOX_CONFIG_NOACL(box_name, stack_size, context_type) \
|
||||
__UVISOR_BOX_CONFIG(box_name, NULL, 0, stack_size, sizeof(context_type)) \
|
||||
UVISOR_EXTERN context_type *const *const __uvisor_ps;
|
||||
|
||||
#define __UVISOR_BOX_CONFIG_NOACL_NOCONTEXT(box_name, stack_size) \
|
||||
__UVISOR_BOX_CONFIG(box_name, NULL, 0, stack_size, 0)
|
||||
|
||||
#define UVISOR_BOX_CONFIG_ACL(...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, __UVISOR_BOX_CONFIG_CONTEXT, \
|
||||
__UVISOR_BOX_CONFIG_NOCONTEXT, \
|
||||
__UVISOR_BOX_CONFIG_NOACL_NOCONTEXT)(__VA_ARGS__)
|
||||
|
||||
#define UVISOR_BOX_CONFIG_CTX(...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, __UVISOR_BOX_CONFIG_CONTEXT, \
|
||||
__UVISOR_BOX_CONFIG_NOACL, \
|
||||
__UVISOR_BOX_CONFIG_NOACL_NOCONTEXT)(__VA_ARGS__)
|
||||
|
||||
#define UVISOR_BOX_CONFIG(...) \
|
||||
UVISOR_BOX_CONFIG_ACL(__VA_ARGS__)
|
||||
|
||||
/* Use this macro before box defintion (for example, UVISOR_BOX_CONFIG) to
|
||||
* define the name of your box. If you don't want a name, use this macro with
|
||||
* box_namespace as NULL. */
|
||||
#define UVISOR_BOX_NAMESPACE(box_namespace) \
|
||||
static const char *const __uvisor_box_namespace = box_namespace
|
||||
|
||||
#define UVISOR_BOX_HEAPSIZE(heap_size) \
|
||||
static const uint32_t __uvisor_box_heapsize = heap_size;
|
||||
|
||||
#define uvisor_ctx (*__uvisor_ps)
|
||||
|
||||
/* Return the numeric box ID of the current box. */
|
||||
UVISOR_EXTERN int uvisor_box_id_self(void);
|
||||
|
||||
/* Return the numeric box ID of the box that is calling through the most recent
|
||||
* secure gateway. Return -1 if there is no secure gateway calling box. */
|
||||
UVISOR_EXTERN int uvisor_box_id_caller(void);
|
||||
|
||||
/* Copy the box namespace of the specified box ID to the memory provided by
|
||||
* box_namespace. The box_namespace's length must be at least
|
||||
* MAX_BOX_NAMESPACE_LENGTH bytes. Return how many bytes were copied into
|
||||
* box_namespace. Return UVISOR_ERROR_INVALID_BOX_ID if the provided box ID is
|
||||
* invalid. Return UVISOR_ERROR_BUFFER_TOO_SMALL if the provided box_namespace
|
||||
* is too small to hold MAX_BOX_NAMESPACE_LENGTH bytes. Return
|
||||
* UVISOR_ERROR_BOX_NAMESPACE_ANONYMOUS if the box is anonymous. */
|
||||
UVISOR_EXTERN int uvisor_box_namespace(int box_id, char *box_namespace, size_t length);
|
||||
|
||||
#endif /* __UVISOR_API_BOX_CONFIG_H__ */
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_CONTEX_EXPORTS_H__
|
||||
#define __UVISOR_CONTEX_EXPORTS_H__
|
||||
|
||||
/** Maximum number of nested context switches.
|
||||
*
|
||||
* The same state stack is kept for all kinds of context switches that are bound
|
||||
* to a function, for which uVisor keeps an internal state. */
|
||||
#define UVISOR_CONTEXT_MAX_DEPTH 16
|
||||
|
||||
#endif /* __UVISOR_CONTEX_EXPORTS_H__ */
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_DEBUG_H__
|
||||
#define __UVISOR_API_DEBUG_H__
|
||||
|
||||
#include "api/inc/debug_exports.h"
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
|
||||
UVISOR_EXTERN void uvisor_debug_init(const TUvisorDebugDriver * const driver);
|
||||
|
||||
#endif /* __UVISOR_API_DEBUG_H__ */
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_DEBUG_EXPORTS_H__
|
||||
#define __UVISOR_API_DEBUG_EXPORTS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Debug box driver -- Version 0
|
||||
* A constant instance of this struct must be instantiated by the unprivileged
|
||||
* code to setup a debug box.*/
|
||||
typedef struct TUvisorDebugDriver {
|
||||
uint32_t (*get_version)(void);
|
||||
void (*halt_error)(int);
|
||||
} TUvisorDebugDriver;
|
||||
|
||||
/* Number of handlers in the debug box driver */
|
||||
#define DEBUG_BOX_HANDLERS_NUMBER (sizeof(TUvisorDebugDriver) / sizeof(void *))
|
||||
|
||||
#endif /* __UVISOR_API_DEBUG_EXPORTS_H__ */
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_DISABLED_H__
|
||||
#define __UVISOR_API_DISABLED_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
UVISOR_EXTERN void uvisor_disabled_switch_in(const uint32_t *dst_box_cfgtbl_ptr);
|
||||
UVISOR_EXTERN void uvisor_disabled_switch_out(void);
|
||||
|
||||
/* The host OS can override the implementations of these functions in case a
|
||||
* different handling of IRQs is required when uVisor is disabled. */
|
||||
UVISOR_EXTERN void uvisor_disabled_set_vector(uint32_t irqn, uint32_t vector);
|
||||
UVISOR_EXTERN uint32_t uvisor_disabled_get_vector(uint32_t irqn);
|
||||
|
||||
#endif /* __UVISOR_API_DISABLED_H__ */
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_ERROR_H__
|
||||
#define __UVISOR_API_ERROR_H__
|
||||
|
||||
#include "api/inc/halt_exports.h"
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
|
||||
UVISOR_EXTERN void uvisor_error(THaltUserError reason);
|
||||
|
||||
#endif /* __UVISOR_API_ERROR_H__ */
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_EXPORT_TABLE_EXPORTS_H__
|
||||
#define __UVISOR_API_EXPORT_TABLE_EXPORTS_H__
|
||||
|
||||
#include "rt_OsEventObserver.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* If this magic doesn't match what you get in a TUvisorExportTable, then you
|
||||
* didn't find a TUvisorExportTable and all bets are off as to what will be
|
||||
* contained in what you found. */
|
||||
#define UVISOR_EXPORT_MAGIC 0x5C9411B4
|
||||
|
||||
/* This is the export table API version. If this version doesn't match what you
|
||||
* get in TUvisorExportTable, then you need a different header file to
|
||||
* understand the TUvisorExportTable. */
|
||||
#define UVISOR_EXPORT_VERSION 0
|
||||
|
||||
typedef struct {
|
||||
/* magic and version must be present as the first two elements in this
|
||||
* table so that across various versions of the table layout, the table can
|
||||
* be interpreted correctly. */
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
|
||||
OsEventObserver os_event_observer;
|
||||
|
||||
/* This must be the last element of the table so that uvisor-input.S can
|
||||
* export the size statically. */
|
||||
uint32_t size;
|
||||
} TUvisorExportTable;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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_HALT_EXPORTS_H__
|
||||
#define __UVISOR_API_HALT_EXPORTS_H__
|
||||
|
||||
#define UVISOR_ERROR_INVALID_BOX_ID (-2)
|
||||
#define UVISOR_ERROR_BUFFER_TOO_SMALL (-3)
|
||||
#define UVISOR_ERROR_BOX_NAMESPACE_ANONYMOUS (-4)
|
||||
|
||||
|
||||
#define UVISOR_ERROR_CLASS_MASK (0xFFFF0000UL)
|
||||
#define UVISOR_ERROR_MASK (0x0000FFFFUL)
|
||||
|
||||
#define UVISOR_ERROR_CLASS_PAGE (1UL << 16)
|
||||
|
||||
typedef enum {
|
||||
USER_NOT_ALLOWED = 1,
|
||||
} THaltUserError;
|
||||
|
||||
#endif /* __UVISOR_API_HALT_EXPORTS_H__ */
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2015, 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_INTERRUPTS_H__
|
||||
#define __UVISOR_API_INTERRUPTS_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
UVISOR_EXTERN void vIRQ_SetVector(uint32_t irqn, uint32_t vector);
|
||||
UVISOR_EXTERN uint32_t vIRQ_GetVector(uint32_t irqn);
|
||||
UVISOR_EXTERN void vIRQ_EnableIRQ(uint32_t irqn);
|
||||
UVISOR_EXTERN void vIRQ_DisableIRQ(uint32_t irqn);
|
||||
UVISOR_EXTERN void vIRQ_ClearPendingIRQ(uint32_t irqn);
|
||||
UVISOR_EXTERN void vIRQ_SetPendingIRQ(uint32_t irqn);
|
||||
UVISOR_EXTERN uint32_t vIRQ_GetPendingIRQ(uint32_t irqn);
|
||||
UVISOR_EXTERN void vIRQ_SetPriority(uint32_t irqn, uint32_t priority);
|
||||
UVISOR_EXTERN uint32_t vIRQ_GetPriority(uint32_t irqn);
|
||||
UVISOR_EXTERN int vIRQ_GetLevel(void);
|
||||
|
||||
/** Disable all interrupts for the currently active box.
|
||||
*
|
||||
* Calling this function from a box only affects the interrupts of that box.
|
||||
* System interrupts and interrupts owned by other boxes are left untouched.
|
||||
*
|
||||
* Successive calls to this function increase an internal counter that is used
|
||||
* by uVisor to decide when to re-enable IRQs. The related call
|
||||
* ::vIRQ_EnableIRQ() decreases this counter. Only when the counter is 0 the
|
||||
* interrupts are re-enabled for that box.
|
||||
*
|
||||
* This guarantees that code that disables IRQs will not accidentally have them
|
||||
* re-enabled by a nested function that it calls before the expected call to
|
||||
* ::vIRQ_EnableAll(). Example:
|
||||
*
|
||||
* vIRQ_DisableAll(); counter = 1; IRQs are now disabled.
|
||||
* some_function(); counter = 2, then counter = 1; IRQs are still disabled.
|
||||
* vIRQ_EnableAll(); counter = 0; IRQs are now re-enabled.
|
||||
*
|
||||
* where some_function() also has a disable/enable pair. */
|
||||
UVISOR_EXTERN void vIRQ_DisableAll(void);
|
||||
|
||||
/** Re-enable all interrupts that were previously disabled for the currently
|
||||
* active box.
|
||||
*
|
||||
* This function only re-enables interrupt if the uVisor internal counter is set
|
||||
* to 0, to make sure that nested disabling of IRQs is still effective. See
|
||||
* ::vIRQ_DisableAll for more information. */
|
||||
UVISOR_EXTERN void vIRQ_EnableAll(void);
|
||||
|
||||
#endif /* __UVISOR_API_INTERRUPTS_H__ */
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_PAGE_ALLOCATOR_H__
|
||||
#define __UVISOR_API_PAGE_ALLOCATOR_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include "api/inc/page_allocator_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* Allocate a number of requested pages with the requested page size.
|
||||
* @param table.page_size[in] Must be equal to the current page size
|
||||
* @param table.page_count[in] The number of pages to be allocated
|
||||
* @param table.page_origins[out] Pointers to the page origins. The table must be large enough to hold page_count entries.
|
||||
* @returns Non-zero on failure with failure class `UVISOR_ERROR_CLASS_PAGE`. See `UVISOR_ERROR_PAGE_*`.
|
||||
*/
|
||||
UVISOR_EXTERN int uvisor_page_malloc(UvisorPageTable * const table);
|
||||
|
||||
/* Free the pages associated with the table, only if it passes validation.
|
||||
* @returns Non-zero on failure with failure class `UVISOR_ERROR_CLASS_PAGE`. See `UVISOR_ERROR_PAGE_*`.
|
||||
*/
|
||||
UVISOR_EXTERN int uvisor_page_free(const UvisorPageTable * const table);
|
||||
|
||||
#endif /* __UVISOR_API_PAGE_ALLOCATOR_H__ */
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_PAGE_ALLOCATOR_EXPORTS_H__
|
||||
#define __UVISOR_API_PAGE_ALLOCATOR_EXPORTS_H__
|
||||
|
||||
#include "api/inc/halt_exports.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#define UVISOR_ERROR_PAGE_OK (0)
|
||||
#define UVISOR_ERROR_PAGE_OUT_OF_MEMORY (UVISOR_ERROR_CLASS_PAGE + 1)
|
||||
#define UVISOR_ERROR_PAGE_INVALID_PAGE_TABLE (UVISOR_ERROR_CLASS_PAGE + 2)
|
||||
#define UVISOR_ERROR_PAGE_INVALID_PAGE_SIZE (UVISOR_ERROR_CLASS_PAGE + 3)
|
||||
#define UVISOR_ERROR_PAGE_INVALID_PAGE_ORIGIN (UVISOR_ERROR_CLASS_PAGE + 4)
|
||||
#define UVISOR_ERROR_PAGE_INVALID_PAGE_OWNER (UVISOR_ERROR_CLASS_PAGE + 5)
|
||||
#define UVISOR_ERROR_PAGE_INVALID_PAGE_COUNT (UVISOR_ERROR_CLASS_PAGE + 6)
|
||||
|
||||
|
||||
/* Must be a power of 2 for MPU alignment in ARMv7-M with ARM MPU.
|
||||
* Must be multiple of 32 for K64F MPU. */
|
||||
#ifndef UVISOR_PAGE_SIZE
|
||||
#define UVISOR_PAGE_SIZE ((uint32_t) 16 * 1024)
|
||||
#endif
|
||||
|
||||
/* Return the rounded up number of pages required to hold `size`. */
|
||||
#define UVISOR_PAGES_FOR_SIZE(size) ((size + UVISOR_PAGE_SIZE - 1) / UVISOR_PAGE_SIZE)
|
||||
|
||||
/* Create a page table with `count` many entries. */
|
||||
#define UVISOR_PAGE_TABLE(count) \
|
||||
struct { \
|
||||
uint32_t page_size; \
|
||||
uint32_t page_count; \
|
||||
void * page_origins[count]; \
|
||||
}
|
||||
|
||||
/* Create a page table with enough pages to hold `size`. */
|
||||
#define UVISOR_PAGE_TABLE_FOR_SIZE(size) UVISOR_PAGE_TABLE(UVISOR_PAGES_FOR_SIZE(size))
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t page_size; /* The page size in bytes. Must be multiple of `UVISOR_PAGE_SIZE`! */
|
||||
uint32_t page_count; /* The number of pages in the page table. */
|
||||
void * page_origins[1]; /* Table of pointers to the origin of each page. */
|
||||
} UvisorPageTable;
|
||||
|
||||
#endif /* __UVISOR_API_PAGE_ALLOCATOR_EXPORTS_H__ */
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_PRIV_SYS_IRQ_HOOK_EXPORTS_H__
|
||||
#define __UVISOR_API_PRIV_SYS_IRQ_HOOK_EXPORTS_H__
|
||||
|
||||
/*
|
||||
* Privileged system interrupt hooks
|
||||
*
|
||||
* In this version of uVisor, uVisor lives alongside an RTOS that requires
|
||||
* running privileged code. In order for the RTOS to run any privileged code,
|
||||
* uVisor must allow the RTOS to handle a subset of privileged system
|
||||
* interrupts. Only the following system interrupts are hookable. Code called
|
||||
* by these hooks circumvents uVisor security. HANDLE WITH CARE. */
|
||||
typedef struct {
|
||||
void (*priv_svc_0)(void);
|
||||
void (*priv_pendsv)(void);
|
||||
void (*priv_systick)(void);
|
||||
} UvisorPrivSystemIRQHooks;
|
||||
|
||||
/* Use this macro to register privileged system IRQ hooks. If you don't want to
|
||||
* register a particular privileged system IRQ hook, you can supply NULL for
|
||||
* that hook parameter. */
|
||||
#define UVISOR_SET_PRIV_SYS_IRQ_HOOKS(priv_svc_0_, priv_pendsv_, priv_systick_) \
|
||||
UVISOR_EXTERN const UvisorPrivSystemIRQHooks __uvisor_priv_sys_irq_hooks = { \
|
||||
.priv_svc_0 = priv_svc_0_, \
|
||||
.priv_pendsv = priv_pendsv_, \
|
||||
.priv_systick = priv_systick_, \
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2015, 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_REGISTER_GATEWAY_H__
|
||||
#define __UVISOR_API_REGISTER_GATEWAY_H__
|
||||
|
||||
#include "api/inc/register_gateway_exports.h"
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/** Get the offset of a struct member.
|
||||
* @internal
|
||||
*/
|
||||
#define __UVISOR_OFFSETOF(type, member) ((uint32_t) (&(((type *)(0))->member)))
|
||||
|
||||
/** Generate the opcode of the 16-bit Thumb-2 16-bit T2 encoding of the branch
|
||||
* instruction.
|
||||
* @internal
|
||||
* @note The branch instruction is encoded according to the Thumb-2 immediate
|
||||
* encoding rules:
|
||||
* <instr_addr>: B.N <label>
|
||||
* imm = (<label>_addr - PC) / 2
|
||||
* Where:
|
||||
* PC = <instr>_addr + 4
|
||||
* The +4 is to account for the pipelined PC at the time of the branch
|
||||
* instruction. See ARM DDI 0403E.b page A4-102 for more details.
|
||||
* @param instr[in] Address of the branch instruction
|
||||
* @param label[in] Address of the label
|
||||
* @returns the 16-bit encoding of the B.N <label> instruction.
|
||||
*/
|
||||
#define BRANCH_OPCODE(instr, label) \
|
||||
(uint16_t) (0xE000 | (uint8_t) ((((uint32_t) (label) - ((uint32_t) (instr) + 4)) / 2) & 0xFF))
|
||||
|
||||
/** `BX LR` encoding
|
||||
* @internal
|
||||
*/
|
||||
#define BXLR ((uint16_t) 0x4770)
|
||||
|
||||
/** Register Gateway - Read operation
|
||||
*
|
||||
* This macro provides an API to perform 32-bit read operations on restricted
|
||||
* registers. Such accesses are assembled into a read-only flash structure that
|
||||
* is read and validated by uVisor before performing the operation.
|
||||
*
|
||||
* @warning This API currently only supports link-time known value for the
|
||||
* address, operation and mask.
|
||||
*
|
||||
* @param box_name[in] The name of the source box as decalred in
|
||||
* `UVISOR_BOX_CONFIG`.
|
||||
* @param addr[in] The address for the data access.
|
||||
* @param operation[in] The operation to perform at the address for the read. It
|
||||
* is chosen among the `UVISOR_RGW_OP_*` macros.
|
||||
* @param shared[in] True if the gateway can be performed by any box. In this
|
||||
* case, the box_name field does not guarantee exclusivity.
|
||||
* @param mask[in] The mask to apply for the read operation.
|
||||
* @returns The value read from address using the operation and mask provided
|
||||
* (or their respective defaults if they have not been provided).
|
||||
*/
|
||||
#define uvisor_read(box_name, addr, op, shared, msk) \
|
||||
({ \
|
||||
/* Instanstiate the gateway. This gets resolved at link-time. */ \
|
||||
__attribute__((aligned(4))) static TRegisterGateway const register_gateway = { \
|
||||
.svc_opcode = UVISOR_SVC_OPCODE(UVISOR_SVC_ID_REGISTER_GATEWAY), \
|
||||
.branch = BRANCH_OPCODE(__UVISOR_OFFSETOF(TRegisterGateway, branch), \
|
||||
__UVISOR_OFFSETOF(TRegisterGateway, bxlr)), \
|
||||
.magic = UVISOR_REGISTER_GATEWAY_MAGIC, \
|
||||
.box_ptr = (uint32_t) & box_name ## _cfg_ptr, \
|
||||
.address = (uint32_t) addr, \
|
||||
.mask = msk, \
|
||||
.operation = UVISOR_RGW_OP(op, sizeof(*addr), shared), \
|
||||
.bxlr = BXLR \
|
||||
}; \
|
||||
\
|
||||
/* Pointer to the register gateway we just created. The pointer is
|
||||
* located in a discoverable linker section. */ \
|
||||
__attribute__((section(".keep.uvisor.register_gateway_ptr"))) \
|
||||
static uint32_t const register_gateway_ptr = (uint32_t) ®ister_gateway; \
|
||||
(void) register_gateway_ptr; \
|
||||
\
|
||||
/* Call the actual gateway. */ \
|
||||
uint32_t result = ((uint32_t (*)(void)) ((uint32_t) ®ister_gateway | 1))(); \
|
||||
(typeof(*addr)) result; \
|
||||
})
|
||||
|
||||
/** Register Gateway - Write operation
|
||||
*
|
||||
* This macro provides an API to perform 32-bit write operations on restricted
|
||||
* registers. Such accesses are assembled into a read-only flash structure that
|
||||
* is read and validated by uVisor before performing the operation.
|
||||
*
|
||||
* @warning This API currently only supports link-time known value for the
|
||||
* address, operation and mask.
|
||||
*
|
||||
* @param box_name[in] The name of the source box as decalred in
|
||||
* `UVISOR_BOX_CONFIG`.
|
||||
* @param addr[in] The address for the data access.
|
||||
* @param val[in] The value to write at address.
|
||||
* @param operation[in] The operation to perform at the address for the read. It
|
||||
* is chosen among the `UVISOR_RGW_OP_*` macros.
|
||||
* @param shared[in] True if the gateway can be performed by any box. In this
|
||||
* case, the box_name field does not guarantee exclusivity.
|
||||
* @param mask[in] The mask to apply for the write operation.
|
||||
*/
|
||||
#define uvisor_write(box_name, addr, val, op, shared, msk) \
|
||||
{ \
|
||||
/* Instanstiate the gateway. This gets resolved at link-time. */ \
|
||||
__attribute__((aligned(4))) static TRegisterGateway const register_gateway = { \
|
||||
.svc_opcode = UVISOR_SVC_OPCODE(UVISOR_SVC_ID_REGISTER_GATEWAY), \
|
||||
.branch = BRANCH_OPCODE(__UVISOR_OFFSETOF(TRegisterGateway, branch), \
|
||||
__UVISOR_OFFSETOF(TRegisterGateway, bxlr)), \
|
||||
.magic = UVISOR_REGISTER_GATEWAY_MAGIC, \
|
||||
.box_ptr = (uint32_t) & box_name ## _cfg_ptr, \
|
||||
.address = (uint32_t) addr, \
|
||||
.mask = msk, \
|
||||
.operation = UVISOR_RGW_OP(op, sizeof(*addr), shared), \
|
||||
.bxlr = BXLR \
|
||||
}; \
|
||||
\
|
||||
/* Pointer to the register gateway we just created. The pointer is
|
||||
* located in a discoverable linker section. */ \
|
||||
__attribute__((section(".keep.uvisor.register_gateway_ptr"))) \
|
||||
static uint32_t const register_gateway_ptr = (uint32_t) ®ister_gateway; \
|
||||
(void) register_gateway_ptr; \
|
||||
\
|
||||
/* Call the actual gateway.
|
||||
* The value is passed as the first argument. */ \
|
||||
((void (*)(uint32_t)) ((uint32_t) ((uint32_t) ®ister_gateway | 1)))((uint32_t) (val)); \
|
||||
}
|
||||
|
||||
/** Get the selected bits at the target address.
|
||||
* @param box_name[in] Box name as defined by the uVisor box configuration
|
||||
* macro `UVISOR_BOX_CONFIG`
|
||||
* @param address[in] Target address
|
||||
* @param mask[in] Bits to select out of the target address
|
||||
* @returns The value `*address & mask`.
|
||||
*/
|
||||
#define UVISOR_BITS_GET(box_name, address, mask) \
|
||||
/* Register gateway implementation:
|
||||
* *address & mask */ \
|
||||
uvisor_read(box_name, address, UVISOR_RGW_OP_READ_AND, false, mask)
|
||||
|
||||
/** Check the selected bits at the target address.
|
||||
* @param box_name[in] Box name as defined by the uVisor box configuration
|
||||
* macro `UVISOR_BOX_CONFIG`
|
||||
* @param address[in] Address at which to check the bits
|
||||
* @param mask[in] Bits to select out of the target address
|
||||
* @returns The value `(bool) (*address & mask) == mask)`.
|
||||
*/
|
||||
#define UVISOR_BITS_CHECK(box_name, address, mask) \
|
||||
((bool) (UVISOR_BITS_GET(box_name, address, mask) == mask))
|
||||
|
||||
/** Set the selected bits to 1 at the target address.
|
||||
*
|
||||
* Equivalent to: `*address |= mask`.
|
||||
* @param box_name[in] Box name as defined by the uVisor box configuration
|
||||
* macro `UVISOR_BOX_CONFIG`
|
||||
* @param address[in] Target address
|
||||
* @param mask[in] Bits to select out of the target address
|
||||
*/
|
||||
#define UVISOR_BITS_SET(box_name, address, mask) \
|
||||
/* Register gateway implementation:
|
||||
* *address |= (mask & mask) */ \
|
||||
uvisor_write(box_name, address, mask, UVISOR_RGW_OP_WRITE_OR, false, mask)
|
||||
|
||||
/** Clear the selected bits at the target address.
|
||||
*
|
||||
* Equivalent to: `*address &= ~mask`.
|
||||
* @param box_name[in] Box name as defined by the uVisor box configuration
|
||||
* macro `UVISOR_BOX_CONFIG`
|
||||
* @param address[in] Target address
|
||||
* @param mask[in] Bits to select out of the target address
|
||||
*/
|
||||
#define UVISOR_BITS_CLEAR(box_name, address, mask) \
|
||||
/* Register gateway implementation:
|
||||
* *address &= (0x00000000 | ~mask) */ \
|
||||
uvisor_write(box_name, address, 0x00000000, UVISOR_RGW_OP_WRITE_AND, false, mask)
|
||||
|
||||
/** Set the selected bits at the target address to the given value.
|
||||
*
|
||||
* Equivalent to: `*address = (*address & ~mask) | (value & mask)`.
|
||||
* @param box_name[in] Box name as defined by the uVisor box configuration
|
||||
* macro `UVISOR_BOX_CONFIG`
|
||||
* @param address[in] Target address
|
||||
* @param mask[in] Bits to select out of the target address
|
||||
* @param value[in] Value to write at the address location. Note: The value
|
||||
* must be already shifted to the correct bit position
|
||||
*/
|
||||
#define UVISOR_BITS_SET_VALUE(box_name, address, mask, value) \
|
||||
/* Register gateway implementation:
|
||||
* *address = (*address & ~mask) | (value & mask) */ \
|
||||
uvisor_write(box_name, address, value, UVISOR_RGW_OP_WRITE_REPLACE, false, mask)
|
||||
|
||||
/** Toggle the selected bits at the target address.
|
||||
*
|
||||
* Equivalent to: `*address ^= mask`.
|
||||
* @param box_name[in] Box name as defined by the uVisor box configuration
|
||||
* macro `UVISOR_BOX_CONFIG`
|
||||
* @param address[in] Target address
|
||||
* @param mask[in] Bits to select out of the target address
|
||||
*/
|
||||
#define UVISOR_BITS_TOGGLE(box_name, address, mask) \
|
||||
/* Register gateway implementation:
|
||||
* *address ^= (0xFFFFFFFF & mask) */ \
|
||||
uvisor_write(box_name, address, 0xFFFFFFFF, UVISOR_RGW_OP_WRITE_XOR, false, mask)
|
||||
|
||||
#endif /* __UVISOR_API_REGISTER_GATEWAY_H__ */
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_REGISTER_GATEWAY_EXPORTS_H__
|
||||
#define __UVISOR_API_REGISTER_GATEWAY_EXPORTS_H__
|
||||
|
||||
/** Register gateway magic
|
||||
*
|
||||
* The following magic is used to verify a register gateway structure. It has
|
||||
* been generated starting from the ARM Thumb/Thumb-2 invalid opcode.
|
||||
* ARM Thumb (with the Thumb-2 extension): 0xF7FxAxxx (32 bits)
|
||||
* The 'x's can be freely chosen (they have been chosen randomly here). This
|
||||
* requires the Thumb-2 extensions because otherwise only 16 bits opcodes are
|
||||
* accepted.
|
||||
*/
|
||||
#if defined(__thumb__) && defined(__thumb2__)
|
||||
#define UVISOR_REGISTER_GATEWAY_MAGIC 0xF7F3A89E
|
||||
#else
|
||||
#error "Unsupported instruction set. The ARM Thumb-2 instruction set must be supported."
|
||||
#endif /* __thumb__ && __thumb2__ */
|
||||
|
||||
/** Register gateway structure
|
||||
*
|
||||
* This struct is packed because we must ensure that the `svc_opcode` field has
|
||||
* no padding before itself, and that the `bxlr` field is at a pre-determined
|
||||
* offset from the `branch` field.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t svc_opcode;
|
||||
uint16_t branch;
|
||||
uint32_t magic;
|
||||
uint32_t box_ptr;
|
||||
uint32_t address;
|
||||
uint32_t mask;
|
||||
uint16_t operation;
|
||||
uint16_t bxlr;
|
||||
} UVISOR_PACKED __attribute__((aligned(4))) TRegisterGateway;
|
||||
|
||||
/** Register gateway operation - Masks
|
||||
* @internal
|
||||
* These are used to extract the operation fields.
|
||||
*/
|
||||
#define __UVISOR_RGW_OP_TYPE_MASK ((uint16_t) 0x00FF)
|
||||
#define __UVISOR_RGW_OP_TYPE_POS 0
|
||||
#define __UVISOR_RGW_OP_WIDTH_MASK ((uint16_t) 0x3F00)
|
||||
#define __UVISOR_RGW_OP_WIDTH_POS 8
|
||||
#define __UVISOR_RGW_OP_SHARED_MASK ((uint16_t) 0x8000)
|
||||
#define __UVISOR_RGW_OP_SHARED_POS 15
|
||||
|
||||
/** Register gateway operations
|
||||
* The user can specify the following properties:
|
||||
* - Access type: read/write, and-, or-, xor-, replac-ed.
|
||||
* - Access width: 8, 16, 32 bits.
|
||||
* - Access shared: Whether the gateway can be shared with other boxes.
|
||||
* These parameters are stored in a 16-bit value as follows:
|
||||
*
|
||||
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
* | |__________________| |____________________|
|
||||
* | | |
|
||||
* shared width type
|
||||
*
|
||||
* @note The operation value must be hardcoded.
|
||||
*/
|
||||
#define UVISOR_RGW_OP(type, width, shared) \
|
||||
((uint16_t) ((((uint16_t) (type) << __UVISOR_RGW_OP_TYPE_POS) & __UVISOR_RGW_OP_TYPE_MASK) | \
|
||||
(((uint16_t) (width) << __UVISOR_RGW_OP_WIDTH_POS) & __UVISOR_RGW_OP_WIDTH_MASK) | \
|
||||
(((uint16_t) (shared) << __UVISOR_RGW_OP_SHARED_POS) & __UVISOR_RGW_OP_SHARED_MASK)))
|
||||
|
||||
/** Register gateway operation - Type */
|
||||
#define UVISOR_RGW_OP_READ 0 /**< value = *address */
|
||||
#define UVISOR_RGW_OP_READ_AND 1 /**< value = *address & mask */
|
||||
#define UVISOR_RGW_OP_WRITE 2 /**< *address = value */
|
||||
#define UVISOR_RGW_OP_WRITE_AND 3 /**< *address &= value | mask */
|
||||
#define UVISOR_RGW_OP_WRITE_OR 4 /**< *address |= value & ~mask */
|
||||
#define UVISOR_RGW_OP_WRITE_XOR 5 /**< *address ^= value & mask */
|
||||
#define UVISOR_RGW_OP_WRITE_REPLACE 6 /**< *address = (*address & ~mask) | (value & mask) */
|
||||
|
||||
#endif /* __UVISOR_API_REGISTER_GATEWAY_EXPORTS_H__ */
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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_SECURE_ACCESS_H__
|
||||
#define __UVISOR_API_SECURE_ACCESS_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include "api/inc/vmpu_exports.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static UVISOR_FORCEINLINE void uvisor_write32(uint32_t volatile * volatile addr, uint32_t val)
|
||||
{
|
||||
UVISOR_ASM_MEMORY_ACCESS(str, uint32_t, addr, val);
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE void uvisor_write16(uint16_t volatile * volatile addr, uint16_t val)
|
||||
{
|
||||
UVISOR_ASM_MEMORY_ACCESS(strh, uint16_t, addr, val);
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE void uvisor_write8(uint8_t volatile * volatile addr, uint8_t val)
|
||||
{
|
||||
UVISOR_ASM_MEMORY_ACCESS(strb, uint8_t, addr, val);
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE uint32_t uvisor_read32(uint32_t volatile * volatile addr)
|
||||
{
|
||||
return UVISOR_ASM_MEMORY_ACCESS(ldr, uint32_t, addr);
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE uint16_t uvisor_read16(uint16_t volatile * volatile addr)
|
||||
{
|
||||
return UVISOR_ASM_MEMORY_ACCESS(ldrh, uint16_t, addr);
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE uint8_t uvisor_read8(uint8_t volatile * volatile addr)
|
||||
{
|
||||
return UVISOR_ASM_MEMORY_ACCESS(ldrb, uint8_t, addr);
|
||||
}
|
||||
|
||||
/* The switch statement will be optimised away since the compiler already knows
|
||||
* the sizeof_type. */
|
||||
static UVISOR_FORCEINLINE void __address_write(size_t sizeof_type, volatile uint32_t *addr, uint32_t val)
|
||||
{
|
||||
switch(sizeof_type) {
|
||||
case 4:
|
||||
uvisor_write32((volatile uint32_t * volatile) addr, (uint32_t) val);
|
||||
break;
|
||||
case 2:
|
||||
uvisor_write16((volatile uint16_t * volatile) addr, (uint16_t) val);
|
||||
break;
|
||||
case 1:
|
||||
uvisor_write8((volatile uint8_t * volatile) addr, (uint8_t) val);
|
||||
break;
|
||||
default:
|
||||
uvisor_error(USER_NOT_ALLOWED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define ADDRESS_WRITE(type, addr, val) __address_write(sizeof(type), (volatile uint32_t *) addr, (uint32_t) val)
|
||||
|
||||
/* the conditional statement will be optimised away since the compiler already
|
||||
* knows the sizeof(type) */
|
||||
#define ADDRESS_READ(type, addr) \
|
||||
(sizeof(type) == 4 ? uvisor_read32((uint32_t volatile * volatile) (addr)) : \
|
||||
sizeof(type) == 2 ? uvisor_read16((uint16_t volatile * volatile) (addr)) : \
|
||||
sizeof(type) == 1 ? uvisor_read8((uint8_t volatile * volatile) (addr)) : 0)
|
||||
|
||||
#define UNION_READ(type, addr, fieldU, fieldB) \
|
||||
({ \
|
||||
type res; \
|
||||
res.fieldU = ADDRESS_READ(type, addr); \
|
||||
res.fieldB; \
|
||||
})
|
||||
|
||||
#endif /* __UVISOR_API_SECURE_ACCESS_H__ */
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_SVC_EXPORTS_H__
|
||||
#define __UVISOR_API_SVC_EXPORTS_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* An SVCall takes a 8bit immediate, which is used as follows:
|
||||
*
|
||||
* For fast APIs:
|
||||
*
|
||||
* 7 6 5 4 3 2 1 0
|
||||
* .---.---.---.---.---.---.---.---.
|
||||
* | 1 | N | N | N | h | h | h | h |
|
||||
* '---'---'---'---'---'---'---'---'
|
||||
* | |_______| |___________|
|
||||
* | | |
|
||||
* | | |
|
||||
* | | |
|
||||
* | | (h) Handler index in the hardcoded table (max 16)
|
||||
* | |
|
||||
* | (N) Number of arguments to pass to the handler (max 4)
|
||||
* |
|
||||
* SVCall mode: Fast
|
||||
*
|
||||
* For slow APIs:
|
||||
*
|
||||
* 7 6 5 4 3 2 1 0
|
||||
* .---.---.---.---.---.---.---.---.
|
||||
* | 0 | c | c | c | c | c | c | c |
|
||||
* '---'---'---'---'---'---'---'---'
|
||||
* | |_______________________|
|
||||
* | |
|
||||
* | |
|
||||
* | (c) Handler index in the custom table (max 128)
|
||||
* |
|
||||
* SVCall mode: Slow
|
||||
*/
|
||||
|
||||
/* 1 bit of the SVCall imm8 field is used to determine the mode, fast/slow. */
|
||||
#define UVISOR_SVC_MODE_FAST 1
|
||||
#define UVISOR_SVC_MODE_SLOW 0
|
||||
#define UVISOR_SVC_MODE_BIT 7
|
||||
#define UVISOR_SVC_MODE_MASK ((uint8_t) (1 << UVISOR_SVC_MODE_BIT))
|
||||
#define UVISOR_SVC_MODE(mode) ((uint8_t) (((mode) << UVISOR_SVC_MODE_BIT) & UVISOR_SVC_MODE_MASK))
|
||||
|
||||
/* 7 or 4 bits of the SVCall imm8 field are used to determine the table index,
|
||||
* depending on the mode, fast/slow. */
|
||||
#define UVISOR_SVC_FAST_INDEX_MAX (1 << 4)
|
||||
#define UVISOR_SVC_SLOW_INDEX_MAX (1 << 7)
|
||||
#define UVISOR_SVC_FAST_INDEX_BIT 0
|
||||
#define UVISOR_SVC_FAST_INDEX_MASK ((uint8_t) (0xF << UVISOR_SVC_FAST_INDEX_BIT))
|
||||
#define UVISOR_SVC_SLOW_INDEX_BIT 0
|
||||
#define UVISOR_SVC_SLOW_INDEX_MASK ((uint8_t) (0x7F << UVISOR_SVC_SLOW_INDEX_BIT))
|
||||
#define UVISOR_SVC_FAST_INDEX(index) ((uint8_t) (((index) << UVISOR_SVC_FAST_INDEX_BIT) & UVISOR_SVC_FAST_INDEX_MASK))
|
||||
#define UVISOR_SVC_SLOW_INDEX(index) ((uint8_t) (((index) << UVISOR_SVC_SLOW_INDEX_BIT) & UVISOR_SVC_SLOW_INDEX_MASK))
|
||||
|
||||
/* When the SVC mode is "fast", the imm8 field also contains a specification of
|
||||
* the call interface (number of arguments).
|
||||
* This is needed for context switches, since the stack manipulation routines
|
||||
* need to know how many arguments to copy from source to destination. */
|
||||
#define UVISOR_SVC_FAST_NARGS_BIT 4
|
||||
#define UVISOR_SVC_FAST_NARGS_MASK ((uint8_t) (0x7 << UVISOR_SVC_FAST_NARGS_BIT))
|
||||
#define UVISOR_SVC_FAST_NARGS_SET(nargs) ((uint8_t) (((nargs) << UVISOR_SVC_FAST_NARGS_BIT) & UVISOR_SVC_FAST_NARGS_MASK))
|
||||
#define UVISOR_SVC_FAST_NARGS_GET(svc_id) (((uint8_t) (svc_id) & UVISOR_SVC_FAST_NARGS_MASK) >> UVISOR_SVC_FAST_NARGS_BIT)
|
||||
|
||||
/* Macros to build the SVCall imm8 field.
|
||||
* For slow APIs only the SVC handler index is needed.
|
||||
* For fast APIs the SVC handler index and the number of arguments are needed. */
|
||||
#define UVISOR_SVC_CUSTOM_TABLE(index) ((uint8_t) (UVISOR_SVC_MODE(UVISOR_SVC_MODE_SLOW) | \
|
||||
UVISOR_SVC_SLOW_INDEX(index)))
|
||||
#define UVISOR_SVC_FIXED_TABLE(index, nargs) ((uint8_t) (UVISOR_SVC_MODE(UVISOR_SVC_MODE_FAST) | \
|
||||
UVISOR_SVC_FAST_INDEX(index) | \
|
||||
UVISOR_SVC_FAST_NARGS_SET(nargs)))
|
||||
|
||||
/* SVC immediate values for custom table */
|
||||
#define UVISOR_SVC_ID_ISR_SET UVISOR_SVC_CUSTOM_TABLE(1)
|
||||
#define UVISOR_SVC_ID_ISR_GET UVISOR_SVC_CUSTOM_TABLE(2)
|
||||
#define UVISOR_SVC_ID_IRQ_ENABLE UVISOR_SVC_CUSTOM_TABLE(3)
|
||||
#define UVISOR_SVC_ID_IRQ_DISABLE UVISOR_SVC_CUSTOM_TABLE(4)
|
||||
#define UVISOR_SVC_ID_IRQ_PEND_CLR UVISOR_SVC_CUSTOM_TABLE(5)
|
||||
#define UVISOR_SVC_ID_IRQ_PEND_SET UVISOR_SVC_CUSTOM_TABLE(6)
|
||||
#define UVISOR_SVC_ID_IRQ_PEND_GET UVISOR_SVC_CUSTOM_TABLE(7)
|
||||
#define UVISOR_SVC_ID_IRQ_PRIO_SET UVISOR_SVC_CUSTOM_TABLE(8)
|
||||
#define UVISOR_SVC_ID_IRQ_PRIO_GET UVISOR_SVC_CUSTOM_TABLE(9)
|
||||
#define UVISOR_SVC_ID_BENCHMARK_CFG UVISOR_SVC_CUSTOM_TABLE(10)
|
||||
#define UVISOR_SVC_ID_BENCHMARK_RST UVISOR_SVC_CUSTOM_TABLE(11)
|
||||
#define UVISOR_SVC_ID_BENCHMARK_STOP UVISOR_SVC_CUSTOM_TABLE(12)
|
||||
#define UVISOR_SVC_ID_HALT_USER_ERR UVISOR_SVC_CUSTOM_TABLE(13)
|
||||
#define UVISOR_SVC_ID_IRQ_LEVEL_GET UVISOR_SVC_CUSTOM_TABLE(14)
|
||||
#define UVISOR_SVC_ID_BOX_ID_SELF UVISOR_SVC_CUSTOM_TABLE(15)
|
||||
#define UVISOR_SVC_ID_BOX_ID_CALLER UVISOR_SVC_CUSTOM_TABLE(16)
|
||||
#define UVISOR_SVC_ID_BOX_NAMESPACE_FROM_ID UVISOR_SVC_CUSTOM_TABLE(17)
|
||||
#define UVISOR_SVC_ID_DEBUG_REBOOT UVISOR_SVC_CUSTOM_TABLE(18)
|
||||
#define UVISOR_SVC_ID_DEBUG_REGISTER_BOX UVISOR_SVC_CUSTOM_TABLE(19)
|
||||
#define UVISOR_SVC_ID_IRQ_DISABLE_ALL UVISOR_SVC_CUSTOM_TABLE(20)
|
||||
#define UVISOR_SVC_ID_IRQ_ENABLE_ALL UVISOR_SVC_CUSTOM_TABLE(21)
|
||||
#define UVISOR_SVC_ID_PAGE_MALLOC UVISOR_SVC_CUSTOM_TABLE(22)
|
||||
#define UVISOR_SVC_ID_PAGE_FREE UVISOR_SVC_CUSTOM_TABLE(23)
|
||||
|
||||
/* SVC immediate values for hardcoded table (call from unprivileged) */
|
||||
#define UVISOR_SVC_ID_UNVIC_OUT UVISOR_SVC_FIXED_TABLE(0, 0)
|
||||
#define UVISOR_SVC_ID_REGISTER_GATEWAY UVISOR_SVC_FIXED_TABLE(3, 0)
|
||||
|
||||
/* SVC immediate values for hardcoded table (call from privileged) */
|
||||
#define UVISOR_SVC_ID_UNVIC_IN UVISOR_SVC_FIXED_TABLE(0, 0)
|
||||
|
||||
/** Generate the SVCall opcode from the SVC ID. */
|
||||
#define UVISOR_SVC_OPCODE(id) ((uint16_t) 0xDF00 | (uint8_t) ((id) & 0xFF))
|
||||
|
||||
/* macro to execute an SVCall; additional metadata can be provided, which will
|
||||
* be appended right after the svc instruction */
|
||||
/* note: the macro is implicitly overloaded to allow 0 to 4 32bits arguments */
|
||||
#if defined(__CC_ARM)
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
#define UVISOR_SVC(id, metadata, ...) \
|
||||
({ \
|
||||
UVISOR_MACRO_REGS_ARGS(uint32_t, ##__VA_ARGS__); \
|
||||
UVISOR_MACRO_REGS_RETVAL(uint32_t, res); \
|
||||
asm volatile( \
|
||||
"svc %[svc_id]\n" \
|
||||
metadata \
|
||||
: UVISOR_MACRO_GCC_ASM_OUTPUT(res) \
|
||||
: UVISOR_MACRO_GCC_ASM_INPUT(__VA_ARGS__), \
|
||||
[svc_id] "I" ((id) & 0xFF) \
|
||||
); \
|
||||
res; \
|
||||
})
|
||||
|
||||
#define UVISOR_FUNCTION_CALL(dst_fn, ...) \
|
||||
({ \
|
||||
UVISOR_MACRO_REGS_ARGS(uint32_t, ##__VA_ARGS__); \
|
||||
UVISOR_MACRO_REGS_RETVAL(uint32_t, res); \
|
||||
asm volatile( \
|
||||
"bl " UVISOR_TO_STRING(dst_fn) "\n" \
|
||||
: UVISOR_MACRO_GCC_ASM_OUTPUT(res) \
|
||||
: UVISOR_MACRO_GCC_ASM_INPUT(__VA_ARGS__) \
|
||||
); \
|
||||
res; \
|
||||
})
|
||||
|
||||
#endif /* defined(__CC_ARM) || defined(__GNUC__) */
|
||||
|
||||
#endif /* __UVISOR_API_SVC_EXPORTS_H__ */
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_UNSUPPORTED_H__
|
||||
#define __UVISOR_API_UNSUPPORTED_H__
|
||||
|
||||
#include "uvisor/api/inc/uvisor_exports.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* uVisor hook for unsupported platforms */
|
||||
UVISOR_EXTERN void uvisor_init(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Re-definitions from:
|
||||
******************************************************************************/
|
||||
|
||||
/* uvisor-lib/box-config.h */
|
||||
|
||||
UVISOR_EXTERN const uint32_t __uvisor_mode;
|
||||
|
||||
#define UVISOR_DISABLED 0
|
||||
|
||||
#define UVISOR_SET_MODE(mode) \
|
||||
UVISOR_SET_MODE_ACL_COUNT(mode, NULL, 0)
|
||||
|
||||
#define UVISOR_SET_MODE_ACL(mode, acl_list) \
|
||||
UVISOR_SET_MODE_ACL_COUNT(mode, acl_list, UVISOR_ARRAY_COUNT(acl_list))
|
||||
|
||||
#define UVISOR_SET_MODE_ACL_COUNT(mode, acl_list, acl_list_count) \
|
||||
UVISOR_EXTERN const uint32_t __uvisor_mode = UVISOR_DISABLED; \
|
||||
static const void *main_acl = acl_list; \
|
||||
extern const __attribute__((section(".keep.uvisor.cfgtbl_ptr_first"), aligned(4))) void * const main_cfg_ptr = &main_acl;
|
||||
|
||||
#define __UVISOR_BOX_CONFIG_NOCONTEXT(box_name, acl_list, stack_size) \
|
||||
static const void *box_acl_ ## box_name = acl_list; \
|
||||
extern const __attribute__((section(".keep.uvisor.cfgtbl_ptr"), aligned(4))) void * const box_name ## _cfg_ptr = &box_acl_ ## box_name;
|
||||
|
||||
#define __UVISOR_BOX_CONFIG_CONTEXT(box_name, acl_list, stack_size, context_type) \
|
||||
context_type box_ctx_ ## box_name; \
|
||||
context_type * const uvisor_ctx = &box_ctx_ ## box_name; \
|
||||
static const void *box_acl_ ## box_name = acl_list; \
|
||||
const __attribute__((section(".keep.uvisor.cfgtbl_ptr"), aligned(4))) volatile void *box_name ## _cfg_ptr = \
|
||||
&box_acl_ ## box_name;
|
||||
|
||||
#define __UVISOR_BOX_MACRO(_1, _2, _3, _4, NAME, ...) NAME
|
||||
#define UVISOR_BOX_CONFIG(...) \
|
||||
__UVISOR_BOX_MACRO(__VA_ARGS__, __UVISOR_BOX_CONFIG_CONTEXT, \
|
||||
__UVISOR_BOX_CONFIG_NOCONTEXT)(__VA_ARGS__)
|
||||
|
||||
#define UVISOR_BOX_CONFIG_ACL(...) UVISOR_BOX_CONFIG(__VA_ARGS__)
|
||||
|
||||
#define UVISOR_BOX_CONFIG_CTX(...) UVISOR_BOX_CONFIG(__VA_ARGS__)
|
||||
|
||||
#define UVISOR_BOX_NAMESPACE(...)
|
||||
|
||||
#define UVISOR_BOX_HEAPSIZE(...)
|
||||
|
||||
/* uvisor-lib/interrupts.h */
|
||||
|
||||
#define vIRQ_SetVector(irqn, vector) NVIC_SetVector((IRQn_Type) (irqn), (uint32_t) (vector))
|
||||
#define vIRQ_GetVector(irqn) NVIC_GetVector((IRQn_Type) (irqn))
|
||||
#define vIRQ_EnableIRQ(irqn) NVIC_EnableIRQ((IRQn_Type) (irqn))
|
||||
#define vIRQ_DisableIRQ(irqn) NVIC_DisableIRQ((IRQn_Type) (irqn))
|
||||
#define vIRQ_DisableAll __disable_irq
|
||||
#define vIRQ_EnableAll __enable_irq
|
||||
#define vIRQ_ClearPendingIRQ(irqn) NVIC_ClearPendingIRQ((IRQn_Type) (irqn))
|
||||
#define vIRQ_SetPendingIRQ(irqn) NVIC_SetPendingIRQ((IRQn_Type) (irqn))
|
||||
#define vIRQ_GetPendingIRQ(irqn) NVIC_GetPendingIRQ((IRQn_Type) (irqn))
|
||||
#define vIRQ_SetPriority(irqn, priority) NVIC_SetPriority((IRQn_Type) (irqn), (uint32_t) (priority))
|
||||
#define vIRQ_GetPriority(irqn) NVIC_GetPriority((IRQn_Type) (irqn))
|
||||
|
||||
/* uvisor-lib/register_gateway.h */
|
||||
|
||||
#define UVISOR_OP_READ(op) (op)
|
||||
#define UVISOR_OP_WRITE(op) ((1 << 4) | (op))
|
||||
#define UVISOR_OP_NOP 0x0
|
||||
#define UVISOR_OP_AND 0x1
|
||||
#define UVISOR_OP_OR 0x2
|
||||
#define UVISOR_OP_XOR 0x3
|
||||
|
||||
/* Default mask for whole register operatins */
|
||||
#define __UVISOR_OP_DEFAULT_MASK 0x0
|
||||
|
||||
static UVISOR_FORCEINLINE uint32_t uvisor_read(uint32_t addr, uint32_t op, uint32_t mask)
|
||||
{
|
||||
switch(op)
|
||||
{
|
||||
case UVISOR_OP_READ(UVISOR_OP_NOP):
|
||||
return *((uint32_t *) addr);
|
||||
case UVISOR_OP_READ(UVISOR_OP_AND):
|
||||
return *((uint32_t *) addr) & mask;
|
||||
case UVISOR_OP_READ(UVISOR_OP_OR):
|
||||
return *((uint32_t *) addr) | mask;
|
||||
case UVISOR_OP_READ(UVISOR_OP_XOR):
|
||||
return *((uint32_t *) addr) ^ mask;
|
||||
default:
|
||||
/* FIXME */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define uvisor_read(addr) uvisor_read((uint32_t) (addr), UVISOR_OP_READ(UVISOR_OP_NOP), __UVISOR_OP_DEFAULT_MASK)
|
||||
|
||||
static UVISOR_FORCEINLINE void uvisor_write(uint32_t addr, uint32_t val, uint32_t op, uint32_t mask)
|
||||
{
|
||||
switch(op)
|
||||
{
|
||||
case UVISOR_OP_WRITE(UVISOR_OP_NOP):
|
||||
*((uint32_t *) addr) = val;
|
||||
case UVISOR_OP_WRITE(UVISOR_OP_AND):
|
||||
*((uint32_t *) addr) &= val | ~mask;
|
||||
case UVISOR_OP_WRITE(UVISOR_OP_OR):
|
||||
*((uint32_t *) addr) |= val & mask;
|
||||
case UVISOR_OP_WRITE(UVISOR_OP_XOR):
|
||||
*((uint32_t *) addr) ^= val & mask;
|
||||
default:
|
||||
/* FIXME */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#define uvisor_write(addr, val) uvisor_write((uint32_t) (addr), (uint32_t) (val), \
|
||||
UVISOR_OP_WRITE(UVISOR_OP_NOP), __UVISOR_OP_DEFAULT_MASK)
|
||||
|
||||
/* uvisor-lib/secure_access.h */
|
||||
|
||||
static UVISOR_FORCEINLINE void uvisor_write32(uint32_t volatile *addr, uint32_t val)
|
||||
{
|
||||
*(addr) = val;
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE void uvisor_write16(uint16_t volatile *addr, uint16_t val)
|
||||
{
|
||||
*(addr) = val;
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE void uvisor_write8(uint8_t volatile *addr, uint8_t val)
|
||||
{
|
||||
*(addr) = val;
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE uint32_t uvisor_read32(uint32_t volatile *addr)
|
||||
{
|
||||
return *(addr);
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE uint16_t uvisor_read16(uint16_t volatile *addr)
|
||||
{
|
||||
return *(addr);
|
||||
}
|
||||
|
||||
static UVISOR_FORCEINLINE uint8_t uvisor_read8(uint8_t volatile *addr)
|
||||
{
|
||||
return *(addr);
|
||||
}
|
||||
|
||||
/* The conditional statement will be optimised away since the compiler already
|
||||
* knows the sizeof(type). */
|
||||
#define ADDRESS_READ(type, addr) \
|
||||
(sizeof(type) == 4 ? uvisor_read32((volatile uint32_t *) (addr)) : \
|
||||
sizeof(type) == 2 ? uvisor_read16((volatile uint16_t *) (addr)) : \
|
||||
sizeof(type) == 1 ? uvisor_read8((volatile uint8_t *) (addr)) : 0)
|
||||
|
||||
/* The switch statement will be optimised away since the compiler already knows
|
||||
* the sizeof_type. */
|
||||
static UVISOR_FORCEINLINE void __address_write(size_t sizeof_type, volatile uint32_t *addr, uint32_t val)
|
||||
{
|
||||
switch(sizeof_type) {
|
||||
case 4:
|
||||
uvisor_write32((volatile uint32_t *) addr, (uint32_t) val);
|
||||
break;
|
||||
case 2:
|
||||
uvisor_write16((volatile uint16_t *) addr, (uint16_t) val);
|
||||
break;
|
||||
case 1:
|
||||
uvisor_write8((volatile uint8_t *) addr, (uint8_t) val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define ADDRESS_WRITE(type, addr, val) __address_write(sizeof(type), (volatile uint32_t *) addr, (uint32_t) val)
|
||||
|
||||
#define UNION_READ(type, addr, fieldU, fieldB) ((*((volatile type *) (addr))).fieldB)
|
||||
|
||||
/* uvisor-lib/secure_gateway.h */
|
||||
|
||||
#define secure_gateway(dst_box, dst_fn, ...) dst_fn(__VA_ARGS__)
|
||||
|
||||
#endif /* __UVISOR_API_UNSUPPORTED_H__ */
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_UNVIC_EXPORTS_H__
|
||||
#define __UVISOR_API_UNVIC_EXPORTS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* this value refers to the minimum allowable priority in the physical NVIC
|
||||
* module, but not in the virtualised one (vIRQ) */
|
||||
#define __UVISOR_NVIC_MIN_PRIORITY ((uint32_t) 1)
|
||||
|
||||
/* this is the maximum priority allowed for the vIRQ module */
|
||||
/* users of uVisor APIs can use this to determine the maximum level of
|
||||
* priorities available to them */
|
||||
#define UVISOR_VIRQ_MAX_PRIORITY ((uint32_t) (1 << __NVIC_PRIO_BITS) - 1 - __UVISOR_NVIC_MIN_PRIORITY)
|
||||
|
||||
/* Offset of NVIC interrupts with respect to handler 0 */
|
||||
#define NVIC_OFFSET 16
|
||||
|
||||
#endif /* __UVISOR_API_UNVIC_EXPORTS_H__ */
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_UVISOR_LIB_H__
|
||||
#define __UVISOR_API_UVISOR_LIB_H__
|
||||
|
||||
/* This file includes all the uVisor library header files at once.
|
||||
* If uVisor is used on a host OS that includes unsupported targets, then
|
||||
* unsupported.h is included, which defines a fallback version of those APIs,
|
||||
* with no security feature. */
|
||||
|
||||
#if defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1
|
||||
|
||||
/* Library header files */
|
||||
#include "api/inc/benchmark.h"
|
||||
#include "api/inc/box_config.h"
|
||||
#include "api/inc/debug.h"
|
||||
#include "api/inc/disabled.h"
|
||||
#include "api/inc/error.h"
|
||||
#include "api/inc/interrupts.h"
|
||||
#include "api/inc/register_gateway.h"
|
||||
#include "api/inc/secure_access.h"
|
||||
|
||||
#else /* defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1 */
|
||||
|
||||
#include "api/inc/unsupported.h"
|
||||
|
||||
#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);
|
||||
|
||||
#include "api/inc/page_allocator.h"
|
||||
|
||||
/* Include all exported header files used by uVisor internally.
|
||||
* These are included independently on whether uVisor is supported or not by the
|
||||
* target platform. */
|
||||
#include "api/inc/debug_exports.h"
|
||||
#include "api/inc/context_exports.h"
|
||||
#include "api/inc/export_table_exports.h"
|
||||
#include "api/inc/halt_exports.h"
|
||||
#include "api/inc/register_gateway_exports.h"
|
||||
#include "api/inc/svc_exports.h"
|
||||
#include "api/inc/priv_sys_irq_hook_exports.h"
|
||||
#include "api/inc/unvic_exports.h"
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include "api/inc/vmpu_exports.h"
|
||||
#include "api/inc/page_allocator_exports.h"
|
||||
|
||||
#endif /* __UVISOR_API_UVISOR_LIB_H__ */
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_UVISOR_EXPORTS_H__
|
||||
#define __UVISOR_API_UVISOR_EXPORTS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* maximum number of boxes allowed: 1 is the minimum (unprivileged box) */
|
||||
#define UVISOR_MAX_BOXES 5U
|
||||
|
||||
/* extern keyword */
|
||||
#ifdef __cplusplus
|
||||
#define UVISOR_EXTERN extern "C"
|
||||
#else
|
||||
#define UVISOR_EXTERN extern
|
||||
#endif/*__CPP__*/
|
||||
|
||||
/* asm keyword */
|
||||
#ifndef asm
|
||||
#define asm __asm__
|
||||
#endif
|
||||
|
||||
/* Shared compiler attributes */
|
||||
#if defined(__ICCARM__)
|
||||
#define UVISOR_FORCEINLINE inline
|
||||
#define UVISOR_PACKED __packed
|
||||
#define UVISOR_WEAK __weak
|
||||
#define UVISOR_NORETURN __noreturn
|
||||
#define UVISOR_RAMFUNC __ramfunc
|
||||
#else
|
||||
#define UVISOR_FORCEINLINE inline __attribute__((always_inline))
|
||||
#define UVISOR_PACKED __attribute__((packed))
|
||||
#define UVISOR_WEAK __attribute__((weak))
|
||||
#define UVISOR_NORETURN __attribute__((noreturn))
|
||||
#define UVISOR_RAMFUNC __attribute__ ((section (".ramfunc"), noinline))
|
||||
#endif
|
||||
|
||||
/* array count macro */
|
||||
#define UVISOR_ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
/* convert macro argument to string */
|
||||
/* note: this needs one level of indirection, accomplished with the helper macro
|
||||
* __UVISOR_TO_STRING */
|
||||
#define __UVISOR_TO_STRING(x) #x
|
||||
#define UVISOR_TO_STRING(x) __UVISOR_TO_STRING(x)
|
||||
|
||||
/* select an overloaded macro, so that 0 to 4 arguments can be used */
|
||||
#define __UVISOR_MACRO_SELECT(_0, _1, _2, _3, _4, NAME, ...) NAME
|
||||
|
||||
/* count macro arguments */
|
||||
#define UVISOR_MACRO_NARGS(...) \
|
||||
__UVISOR_MACRO_SELECT(_0, ##__VA_ARGS__, 4, 3, 2, 1, 0)
|
||||
|
||||
/* declare explicit callee-saved registers to hold input arguments (0 to 4) */
|
||||
/* note: sizeof(type) must be less than or equal to 4 */
|
||||
#define UVISOR_MACRO_REGS_ARGS(type, ...) \
|
||||
__UVISOR_MACRO_SELECT(_0, ##__VA_ARGS__, __UVISOR_MACRO_REGS_ARGS4, \
|
||||
__UVISOR_MACRO_REGS_ARGS3, \
|
||||
__UVISOR_MACRO_REGS_ARGS2, \
|
||||
__UVISOR_MACRO_REGS_ARGS1, \
|
||||
__UVISOR_MACRO_REGS_ARGS0)(type, ##__VA_ARGS__)
|
||||
#define __UVISOR_MACRO_REGS_ARGS0(type)
|
||||
#define __UVISOR_MACRO_REGS_ARGS1(type, a0) \
|
||||
register type r0 asm("r0") = (type) a0;
|
||||
#define __UVISOR_MACRO_REGS_ARGS2(type, a0, a1) \
|
||||
register type r0 asm("r0") = (type) a0; \
|
||||
register type r1 asm("r1") = (type) a1;
|
||||
#define __UVISOR_MACRO_REGS_ARGS3(type, a0, a1, a2) \
|
||||
register type r0 asm("r0") = (type) a0; \
|
||||
register type r1 asm("r1") = (type) a1; \
|
||||
register type r2 asm("r2") = (type) a2;
|
||||
#define __UVISOR_MACRO_REGS_ARGS4(type, a0, a1, a2, a3) \
|
||||
register type r0 asm("r0") = (type) a0; \
|
||||
register type r1 asm("r1") = (type) a1; \
|
||||
register type r2 asm("r2") = (type) a2; \
|
||||
register type r3 asm("r3") = (type) a3;
|
||||
|
||||
/* declare explicit callee-saved registers to hold output values */
|
||||
/* note: currently only one output value is allowed, up to 32bits */
|
||||
#define UVISOR_MACRO_REGS_RETVAL(type, name) \
|
||||
register type name asm("r0");
|
||||
|
||||
/* declare callee-saved input/output operands for gcc-style inline asm */
|
||||
/* note: this macro requires that a C variable having the same name of the
|
||||
* corresponding callee-saved register is declared; these operands follow
|
||||
* the official ABI for ARMv7M (e.g. 2 input arguments of 32bits each max,
|
||||
* imply that registers r0 and r1 are used) */
|
||||
/* note: gcc only */
|
||||
/* note: for 0 inputs a dummy immediate is passed to avoid errors on a misplaced
|
||||
* comma in the inline assembly */
|
||||
#ifdef __GNUC__
|
||||
|
||||
#define UVISOR_MACRO_GCC_ASM_INPUT(...) \
|
||||
__UVISOR_MACRO_SELECT(_0, ##__VA_ARGS__, __UVISOR_MACRO_GCC_ASM_INPUT4, \
|
||||
__UVISOR_MACRO_GCC_ASM_INPUT3, \
|
||||
__UVISOR_MACRO_GCC_ASM_INPUT2, \
|
||||
__UVISOR_MACRO_GCC_ASM_INPUT1, \
|
||||
__UVISOR_MACRO_GCC_ASM_INPUT0)(__VA_ARGS__)
|
||||
#define __UVISOR_MACRO_GCC_ASM_INPUT0() [__dummy] "I" (0)
|
||||
#define __UVISOR_MACRO_GCC_ASM_INPUT1(a0) [r0] "r" (r0)
|
||||
#define __UVISOR_MACRO_GCC_ASM_INPUT2(a0, a1) [r0] "r" (r0), [r1] "r" (r1)
|
||||
#define __UVISOR_MACRO_GCC_ASM_INPUT3(a0, a1, a2) [r0] "r" (r0), [r1] "r" (r1), [r2] "r" (r2)
|
||||
#define __UVISOR_MACRO_GCC_ASM_INPUT4(a0, a1, a2, a3) [r0] "r" (r0), [r1] "r" (r1), [r2] "r" (r2), [r3] "r" (r3)
|
||||
|
||||
#define UVISOR_MACRO_GCC_ASM_OUTPUT(name) [res] "=r" (name)
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
/* this macro multiplexes read/write opcodes depending on the number of
|
||||
* arguments */
|
||||
#define UVISOR_ASM_MEMORY_ACCESS(opcode, type, ...) \
|
||||
__UVISOR_MACRO_SELECT(_0, ##__VA_ARGS__, /* no macro for 4 args */ , \
|
||||
/* no macro for 3 args */ , \
|
||||
__UVISOR_ASM_MEMORY_ACCESS_W, \
|
||||
__UVISOR_ASM_MEMORY_ACCESS_R, \
|
||||
/* no macro for 0 args */ )(opcode, type, ##__VA_ARGS__)
|
||||
/* the macros that actually generate the assembly code for the memory access are
|
||||
* toolchain-specific */
|
||||
#if defined(__CC_ARM)
|
||||
|
||||
/* TODO/FIXME */
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
#define __UVISOR_ASM_MEMORY_ACCESS_R(opcode, type, ...) \
|
||||
({ \
|
||||
UVISOR_MACRO_REGS_ARGS(uint32_t, ##__VA_ARGS__); \
|
||||
UVISOR_MACRO_REGS_RETVAL(type, res); \
|
||||
asm volatile( \
|
||||
UVISOR_TO_STRING(opcode)" %[res], [%[r0]]\n" \
|
||||
UVISOR_NOP_GROUP \
|
||||
: UVISOR_MACRO_GCC_ASM_OUTPUT(res) \
|
||||
: UVISOR_MACRO_GCC_ASM_INPUT(__VA_ARGS__) \
|
||||
); \
|
||||
res; \
|
||||
})
|
||||
|
||||
#define __UVISOR_ASM_MEMORY_ACCESS_W(opcode, type, ...) \
|
||||
UVISOR_MACRO_REGS_ARGS(uint32_t, ##__VA_ARGS__); \
|
||||
asm volatile( \
|
||||
UVISOR_TO_STRING(opcode)" %[r1], [%[r0]]\n" \
|
||||
UVISOR_NOP_GROUP \
|
||||
: \
|
||||
: UVISOR_MACRO_GCC_ASM_INPUT(__VA_ARGS__) \
|
||||
);
|
||||
|
||||
#endif /* defined(__CC_ARM) || defined(__GNUC__) */
|
||||
|
||||
#endif /* __UVISOR_API_UVISOR_EXPORTS_H__ */
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __UVISOR_API_VMPU_EXPORTS_H__
|
||||
#define __UVISOR_API_VMPU_EXPORTS_H__
|
||||
|
||||
#include "api/inc/uvisor_exports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* The maximum box namespace length is 37 so that it is exactly big enough for
|
||||
* a human-readable hex string GUID (as formatted by RFC 4122) followed by a
|
||||
* terminating NULL. */
|
||||
#define UVISOR_MAX_BOX_NAMESPACE_LENGTH 37
|
||||
|
||||
/* supervisor user access modes */
|
||||
#define UVISOR_TACL_UEXECUTE 0x0001UL
|
||||
#define UVISOR_TACL_UWRITE 0x0002UL
|
||||
#define UVISOR_TACL_UREAD 0x0004UL
|
||||
#define UVISOR_TACL_UACL (UVISOR_TACL_UREAD |\
|
||||
UVISOR_TACL_UWRITE |\
|
||||
UVISOR_TACL_UEXECUTE)
|
||||
|
||||
/* supervisor access modes */
|
||||
#define UVISOR_TACL_SEXECUTE 0x0008UL
|
||||
#define UVISOR_TACL_SWRITE 0x0010UL
|
||||
#define UVISOR_TACL_SREAD 0x0020UL
|
||||
#define UVISOR_TACL_SACL (UVISOR_TACL_SREAD |\
|
||||
UVISOR_TACL_SWRITE |\
|
||||
UVISOR_TACL_SEXECUTE)
|
||||
|
||||
#define UVISOR_TACL_EXECUTE (UVISOR_TACL_UEXECUTE |\
|
||||
UVISOR_TACL_SEXECUTE)
|
||||
|
||||
/* all possible access control flags */
|
||||
#define UVISOR_TACL_ACCESS (UVISOR_TACL_UACL |\
|
||||
UVISOR_TACL_SACL)
|
||||
|
||||
/* various modes */
|
||||
#define UVISOR_TACL_STACK 0x0040UL
|
||||
#define UVISOR_TACL_SIZE_ROUND_UP 0x0080UL
|
||||
#define UVISOR_TACL_SIZE_ROUND_DOWN 0x0100UL
|
||||
#define UVISOR_TACL_PERIPHERAL 0x0200UL
|
||||
#define UVISOR_TACL_SHARED 0x0400UL
|
||||
#define UVISOR_TACL_USER 0x0800UL
|
||||
#define UVISOR_TACL_IRQ 0x1000UL
|
||||
|
||||
#if defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1
|
||||
|
||||
/* subregion mask for ARMv7M */
|
||||
#if defined(ARCH_MPU_ARMv7M)
|
||||
#define UVISOR_TACL_SUBREGIONS_POS 24
|
||||
#define UVISOR_TACL_SUBREGIONS_MASK (0xFFUL << UVISOR_TACL_SUBREGIONS_POS)
|
||||
#define UVISOR_TACL_SUBREGIONS(x) ( (((uint32_t) (x)) << UVISOR_TACL_SUBREGIONS_POS) & UVISOR_TACL_SUBREGIONS_MASK )
|
||||
#endif
|
||||
|
||||
#endif /* defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1 */
|
||||
|
||||
#define UVISOR_TACLDEF_SECURE_BSS (UVISOR_TACL_UREAD |\
|
||||
UVISOR_TACL_UWRITE |\
|
||||
UVISOR_TACL_SREAD |\
|
||||
UVISOR_TACL_SWRITE |\
|
||||
UVISOR_TACL_SIZE_ROUND_UP)
|
||||
|
||||
#define UVISOR_TACLDEF_SECURE_CONST (UVISOR_TACL_UREAD |\
|
||||
UVISOR_TACL_SREAD |\
|
||||
UVISOR_TACL_SIZE_ROUND_UP)
|
||||
|
||||
#define UVISOR_TACLDEF_DATA UVISOR_TACLDEF_SECURE_BSS
|
||||
|
||||
#define UVISOR_TACLDEF_PERIPH (UVISOR_TACL_PERIPHERAL |\
|
||||
UVISOR_TACL_UREAD |\
|
||||
UVISOR_TACL_UWRITE |\
|
||||
UVISOR_TACL_SREAD |\
|
||||
UVISOR_TACL_SWRITE |\
|
||||
UVISOR_TACL_SIZE_ROUND_UP)
|
||||
|
||||
#define UVISOR_TACLDEF_STACK (UVISOR_TACL_STACK |\
|
||||
UVISOR_TACL_UREAD |\
|
||||
UVISOR_TACL_UWRITE |\
|
||||
UVISOR_TACL_SREAD |\
|
||||
UVISOR_TACL_SWRITE)
|
||||
|
||||
#define UVISOR_PAD32(x) (32 - (sizeof(x) & ~0x1FUL))
|
||||
#define UVISOR_BOX_MAGIC 0x42CFB66FUL
|
||||
#define UVISOR_BOX_VERSION 100
|
||||
#define UVISOR_STACK_BAND_SIZE 128
|
||||
#define UVISOR_MEM_SIZE_ROUND(x) UVISOR_REGION_ROUND_UP(x)
|
||||
|
||||
#define UVISOR_MIN_STACK_SIZE 1024
|
||||
#define UVISOR_MIN_STACK(x) (((x) < UVISOR_MIN_STACK_SIZE) ? UVISOR_MIN_STACK_SIZE : (x))
|
||||
|
||||
#if defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1
|
||||
|
||||
#if defined(ARCH_MPU_ARMv7M)
|
||||
#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)
|
||||
#define UVISOR_REGION_ROUND_DOWN(x) ((x) & ~0x1FUL)
|
||||
#define UVISOR_REGION_ROUND_UP(x) UVISOR_REGION_ROUND_DOWN((x) + 31UL)
|
||||
#define UVISOR_STACK_SIZE_ROUND(x) UVISOR_REGION_ROUND_UP((x) + (UVISOR_STACK_BAND_SIZE * 2))
|
||||
#else
|
||||
#error "Unknown MPU architecture. uvisor: Check your Makefile. uvisor-lib: Check if uVisor is supported"
|
||||
#endif
|
||||
|
||||
#else /* defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1 */
|
||||
|
||||
#define UVISOR_REGION_ROUND_DOWN(x) (x)
|
||||
#define UVISOR_REGION_ROUND_UP(x) (x)
|
||||
#define UVISOR_STACK_SIZE_ROUND(x) (x)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef UVISOR_BOX_STACK_SIZE
|
||||
#define UVISOR_BOX_STACK_SIZE UVISOR_MIN_STACK_SIZE
|
||||
#endif/*UVISOR_BOX_STACK*/
|
||||
|
||||
/* NOPs added for write buffering synchronization (2 are for dsb. 16bits) */
|
||||
#define UVISOR_NOP_CNT (2 + 3)
|
||||
#define UVISOR_NOP_GROUP \
|
||||
"dsb\n" \
|
||||
"nop\n" \
|
||||
"nop\n" \
|
||||
"nop\n"
|
||||
|
||||
typedef uint32_t UvisorBoxAcl;
|
||||
|
||||
typedef struct {
|
||||
void * param1;
|
||||
uint32_t param2;
|
||||
UvisorBoxAcl acl;
|
||||
} UVISOR_PACKED UvisorBoxAclItem;
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
|
||||
/* Box stack size includes stack guards and rounding buffer. */
|
||||
uint32_t stack_size;
|
||||
|
||||
/* Contains the size of the index (must be at least sizeof(UvisorBoxIndex)). */
|
||||
uint32_t index_size;
|
||||
/* Contains user provided size of box context without guards of buffers. */
|
||||
uint32_t context_size;
|
||||
/* Contains user provided size of box heap without guards of buffers. */
|
||||
uint32_t heap_size;
|
||||
|
||||
const char * box_namespace;
|
||||
const UvisorBoxAclItem * const acl_list;
|
||||
uint32_t acl_count;
|
||||
} UVISOR_PACKED UvisorBoxConfig;
|
||||
|
||||
typedef struct {
|
||||
/* Pointer to the user context */
|
||||
void * ctx;
|
||||
/* Pointer to the box heap */
|
||||
void * box_heap;
|
||||
/* Size of the box heap */
|
||||
uint32_t box_heap_size;
|
||||
/* Pointer to the currently active heap.
|
||||
* This is set to `NULL` by uVisor, signalling to the user lib that the
|
||||
* box heap needs to be initialized before use! */
|
||||
void * active_heap;
|
||||
/* Pointer to the box config */
|
||||
const UvisorBoxConfig * config;
|
||||
} UVISOR_PACKED UvisorBoxIndex;
|
||||
|
||||
/*
|
||||
* only use this macro for rounding const values during compile time:
|
||||
* for variables please use uvisor_region_bits(x) instead
|
||||
*/
|
||||
#define UVISOR_REGION_BITS(x) (((x)<=32UL)?5:(((x)<=64UL)?\
|
||||
6:(((x)<=128UL)?7:(((x)<=256UL)?8:(((x)<=512UL)?9:(((x)<=1024UL)?\
|
||||
10:(((x)<=2048UL)?11:(((x)<=4096UL)?12:(((x)<=8192UL)?\
|
||||
13:(((x)<=16384UL)?14:(((x)<=32768UL)?15:(((x)<=65536UL)?\
|
||||
16:(((x)<=131072UL)?17:(((x)<=262144UL)?18:(((x)<=524288UL)?\
|
||||
19:(((x)<=1048576UL)?20:(((x)<=2097152UL)?21:(((x)<=4194304UL)?\
|
||||
22:(((x)<=8388608UL)?23:(((x)<=16777216UL)?24:(((x)<=33554432UL)?\
|
||||
25:(((x)<=67108864UL)?26:(((x)<=134217728UL)?27:(((x)<=268435456UL)?\
|
||||
28:(((x)<=536870912UL)?29:(((x)<=1073741824UL)?30:(((x)<=2147483648UL)?\
|
||||
31:32)))))))))))))))))))))))))))
|
||||
|
||||
#if defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1
|
||||
static UVISOR_FORCEINLINE int vmpu_bits(uint32_t size)
|
||||
{
|
||||
return 32 - __builtin_clz(size);
|
||||
}
|
||||
#endif /* defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1 */
|
||||
|
||||
#endif /* __UVISOR_API_VMPU_EXPORTS_H__ */
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* This file can be compiled externally to provide the page allocator algorithm
|
||||
* for devices NOT supported by uVisor. For this purpose this file is copied as
|
||||
* is into the target build folder and compiled by the target build system. */
|
||||
#if defined(UVISOR_PRESENT) && (UVISOR_PRESENT == 1)
|
||||
|
||||
#include <uvisor.h>
|
||||
#include "page_allocator.h"
|
||||
#include "mpu/vmpu_unpriv_access.h"
|
||||
#include "mpu/vmpu.h"
|
||||
#include "halt.h"
|
||||
#include "context.h"
|
||||
|
||||
/* Since the page table memory is provided by the user, all accesses to it
|
||||
* are depriviledged! */
|
||||
#define page_table_read vmpu_unpriv_uint32_read
|
||||
#define page_table_write vmpu_unpriv_uint32_write
|
||||
/* For uVisor in supported mode the page allocator is always called through a
|
||||
* SVC call, which automagically serializes access to it. */
|
||||
#define UVISOR_PAGE_ALLOCATOR_MUTEX_AQUIRE {}
|
||||
#define UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE {}
|
||||
|
||||
#endif /* defined(UVISOR_PRESENT) && (UVISOR_PRESENT == 1) */
|
||||
|
||||
/* We can only protect a small number of pages efficiently, so there should be
|
||||
* a relatively low limit to the number of pages.
|
||||
* By default a maximum of 16 pages are allowed. This can only be overridden
|
||||
* by the porting engineer for the current platform. */
|
||||
#ifndef UVISOR_PAGE_TABLE_MAX_COUNT
|
||||
#define UVISOR_PAGE_TABLE_MAX_COUNT ((uint32_t) 16)
|
||||
#endif
|
||||
/* The number of pages is decided by the page size. A small page size leads to
|
||||
* a lot of pages, however, number of pages is capped for efficiency.
|
||||
* Furthermore, when allocating large continous memory, a too small page size
|
||||
* will lead to allocation failures. This can only be overridden
|
||||
* by the porting engineer for the current platform. */
|
||||
#ifndef UVISOR_PAGE_SIZE_MINIMUM
|
||||
#define UVISOR_PAGE_SIZE_MINIMUM ((uint32_t) 1024)
|
||||
#endif
|
||||
|
||||
/* The page box_id is the box id which is 8-bit large. */
|
||||
typedef uint8_t page_owner_t;
|
||||
/* Maps the page to the owning box handle. */
|
||||
static page_owner_t g_page_owner_table[UVISOR_PAGE_TABLE_MAX_COUNT];
|
||||
/* Define a unused value for the page table. */
|
||||
#define UVISOR_PAGE_UNUSED ((page_owner_t) (-1))
|
||||
|
||||
/* Contains the configured page size. */
|
||||
static uint32_t g_page_size;
|
||||
/* Points to the beginning of the page heap. */
|
||||
static const void * g_page_heap_start;
|
||||
/* Points to the end of the page heap. */
|
||||
static const void * g_page_heap_end;
|
||||
/* Contains the number of free pages. */
|
||||
static uint8_t g_page_count_free;
|
||||
/* Contains the total number of available pages. */
|
||||
static uint8_t g_page_count_total;
|
||||
|
||||
|
||||
void page_allocator_init(void * const heap_start, void * const heap_end, const uint32_t * const page_size)
|
||||
{
|
||||
/* Make sure the UVISOR_PAGE_UNUSED is definitely NOT a valid box id. */
|
||||
if (vmpu_is_box_id_valid(UVISOR_PAGE_UNUSED)) {
|
||||
HALT_ERROR(SANITY_CHECK_FAILED,
|
||||
"UVISOR_PAGE_UNUSED (%u) must not be a valid box id!\n",
|
||||
UVISOR_PAGE_UNUSED);
|
||||
}
|
||||
if (!page_size || !vmpu_public_flash_addr((uint32_t) page_size)) {
|
||||
HALT_ERROR(SANITY_CHECK_FAILED,
|
||||
"Page size pointer (0x%08x) is not in flash memory.\n",
|
||||
(unsigned int) page_size);
|
||||
}
|
||||
if (!heap_start || !vmpu_sram_addr((uint32_t) heap_start)) {
|
||||
HALT_ERROR(SANITY_CHECK_FAILED,
|
||||
"Page heap start pointer (0x%08x) is not in sram memory.\n",
|
||||
(unsigned int) heap_start);
|
||||
}
|
||||
if (!heap_end || !vmpu_sram_addr((uint32_t) heap_end)) {
|
||||
HALT_ERROR(SANITY_CHECK_FAILED,
|
||||
"Page heap end pointer (0x%08x) is not in sram memory.\n",
|
||||
(unsigned int) heap_end);
|
||||
}
|
||||
if (heap_end < heap_start) {
|
||||
HALT_ERROR(SANITY_CHECK_FAILED,
|
||||
"Page heap end pointer (0x%08x) is smaller than heap start pointer (0x%08x).\n",
|
||||
(unsigned int) heap_end,
|
||||
(unsigned int) heap_start);
|
||||
}
|
||||
if ((*page_size < UVISOR_PAGE_SIZE_MINIMUM) || !vmpu_is_region_size_valid(*page_size)) {
|
||||
HALT_ERROR(SANITY_CHECK_FAILED,
|
||||
"Page size (%uB) not supported by this platform!\n",
|
||||
*page_size);
|
||||
}
|
||||
|
||||
uint32_t start = vmpu_round_up_region((uint32_t) heap_start, *page_size);
|
||||
if (start == 0) {
|
||||
HALT_ERROR(SANITY_CHECK_FAILED,
|
||||
"Page heap start address 0x%08x cannot be aligned with page size %uB!\n",
|
||||
(unsigned int) heap_start,
|
||||
(unsigned int) *page_size);
|
||||
}
|
||||
|
||||
g_page_size = *page_size;
|
||||
/* This is the page heap start address. */
|
||||
g_page_heap_start = (void *) start;
|
||||
|
||||
/* How many pages can we fit in here? */
|
||||
if (start > (0xFFFFFFFFUL - g_page_size) || (start + g_page_size) > (uint32_t) heap_end) {
|
||||
g_page_count_total = 0;
|
||||
} else {
|
||||
g_page_count_total = ((uint32_t) heap_end - start) / g_page_size;
|
||||
}
|
||||
/* Clamp page count to table size. */
|
||||
if (g_page_count_total > UVISOR_PAGE_TABLE_MAX_COUNT) {
|
||||
g_page_count_total = UVISOR_PAGE_TABLE_MAX_COUNT;
|
||||
}
|
||||
g_page_count_free = g_page_count_total;
|
||||
/* Remember the end of the heap. */
|
||||
g_page_heap_end = g_page_heap_start + g_page_count_free * g_page_size;
|
||||
|
||||
DPRINTF("uvisor_page_init:\n.page_heap start 0x%08x\n.page_heap end 0x%08x\n.page_heap available %ukB split into %u pages of %ukB\n\n",
|
||||
(unsigned int) g_page_heap_start,
|
||||
(unsigned int) g_page_heap_end,
|
||||
(unsigned int) (g_page_count_free * g_page_size / 1024),
|
||||
(unsigned int) g_page_count_total,
|
||||
(unsigned int) (g_page_size / 1024));
|
||||
|
||||
uint32_t page = 0;
|
||||
for (; page < g_page_count_total; page++) {
|
||||
g_page_owner_table[page] = UVISOR_PAGE_UNUSED;
|
||||
}
|
||||
}
|
||||
|
||||
int page_allocator_malloc(UvisorPageTable * const table)
|
||||
{
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_AQUIRE;
|
||||
uint32_t pages_required = page_table_read((uint32_t) &(table->page_count));
|
||||
uint32_t page_size = page_table_read((uint32_t) &(table->page_size));
|
||||
/* Check if the user even wants any pages. */
|
||||
if (pages_required == 0) {
|
||||
DPRINTF("uvisor_page_malloc: FAIL: No pages requested!\n\n");
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_INVALID_PAGE_COUNT;
|
||||
}
|
||||
/* Check if we can fulfill the requested page size. */
|
||||
if (page_size != g_page_size) {
|
||||
DPRINTF("uvisor_page_malloc: FAIL: Requested page size %uB is not the configured page size %uB!\n\n", page_size, g_page_size);
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_INVALID_PAGE_SIZE;
|
||||
}
|
||||
/* Check if we have enough pages available. */
|
||||
if (pages_required > g_page_count_free) {
|
||||
DPRINTF("uvisor_page_malloc: FAIL: Cannot serve %u pages with only %u free pages!\n\n", pages_required, g_page_count_free);
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Get the calling box id. */
|
||||
const page_owner_t box_id = g_active_box;
|
||||
DPRINTF("uvisor_page_malloc: Requesting %u pages with size %uB for box %u\n", pages_required, page_size, box_id);
|
||||
|
||||
/* Update the free pages count. */
|
||||
g_page_count_free -= pages_required;
|
||||
/* Point to the first entry in the table. */
|
||||
void * * page_table = &(table->page_origins[0]);
|
||||
|
||||
/* Iterate through the page table and find the empty pages. */
|
||||
uint32_t page = 0;
|
||||
for (; (page < g_page_count_total) && pages_required; page++) {
|
||||
/* If the page is unused, it's entry is UVISOR_PAGE_UNUSED (not NULL!). */
|
||||
if (g_page_owner_table[page] == UVISOR_PAGE_UNUSED) {
|
||||
/* Marry this page to the box id. */
|
||||
g_page_owner_table[page] = box_id;
|
||||
/* Get the pointer to the page. */
|
||||
void * ptr = (void *) g_page_heap_start + page * g_page_size;
|
||||
/* Zero the entire page before handing it out. */
|
||||
memset(ptr, 0, g_page_size);
|
||||
/* Write the pages address to the table in the first page. */
|
||||
page_table_write((uint32_t) page_table, (uint32_t) ptr);
|
||||
page_table++;
|
||||
/* One less page required. */
|
||||
pages_required--;
|
||||
DPRINTF("uvisor_page_malloc: Found an empty page 0x%08x entry at index %u\n", (unsigned int) ptr, page);
|
||||
}
|
||||
}
|
||||
DPRINTF("uvisor_page_malloc: %u free pages remaining.\n\n", g_page_count_free);
|
||||
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_OK;
|
||||
}
|
||||
|
||||
int page_allocator_free(const UvisorPageTable * const table)
|
||||
{
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_AQUIRE;
|
||||
if (g_page_count_free == g_page_count_total) {
|
||||
DPRINTF("uvisor_page_free: FAIL: There are no pages to free!\n\n");
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_INVALID_PAGE_TABLE;
|
||||
}
|
||||
uint32_t page_count = page_table_read((uint32_t) &(table->page_count));
|
||||
uint32_t page_size = page_table_read((uint32_t) &(table->page_size));
|
||||
if (page_size != g_page_size) {
|
||||
DPRINTF("uvisor_page_free: FAIL: Requested page size %uB is not the configured page size %uB!\n\n", page_size, g_page_size);
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_INVALID_PAGE_SIZE;
|
||||
}
|
||||
if (page_count == 0) {
|
||||
DPRINTF("uvisor_page_free: FAIL: Pointer table is empty!\n\n");
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_INVALID_PAGE_COUNT;
|
||||
}
|
||||
if (page_count > (unsigned) (g_page_count_total - g_page_count_free)) {
|
||||
DPRINTF("uvisor_page_free: FAIL: Pointer table too large!\n\n");
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_INVALID_PAGE_TABLE;
|
||||
}
|
||||
|
||||
/* Get the calling box id. */
|
||||
const page_owner_t box_id = g_active_box;
|
||||
/* Iterate over the table and validate each pointer. */
|
||||
void * const * page_table = &(table->page_origins[0]);
|
||||
|
||||
int table_size = page_count;
|
||||
for (; table_size > 0; page_table++, table_size--) {
|
||||
void * page = (void *) page_table_read((uint32_t) page_table);
|
||||
/* Range check the returned pointer. */
|
||||
if (page < g_page_heap_start || page >= g_page_heap_end) {
|
||||
DPRINTF("uvisor_page_free: FAIL: Pointer 0x%08x does not belong to any page!\n\n", (unsigned int) page);
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_INVALID_PAGE_ORIGIN;
|
||||
}
|
||||
/* Compute the index for the pointer. */
|
||||
uint32_t page_index = (page - g_page_heap_start) / g_page_size;
|
||||
/* Check if the page belongs to the caller. */
|
||||
if (g_page_owner_table[page_index] == box_id) {
|
||||
g_page_owner_table[page_index] = UVISOR_PAGE_UNUSED;
|
||||
g_page_count_free++;
|
||||
DPRINTF("uvisor_page_free: Freeing page at index %u\n", page_index);
|
||||
}
|
||||
else {
|
||||
/* Abort if the page doesn't belong to the caller. */
|
||||
if (g_page_owner_table[page_index] == UVISOR_PAGE_UNUSED) {
|
||||
DPRINTF("uvisor_page_free: FAIL: Page %u is not allocated!\n\n", page_index);
|
||||
} else {
|
||||
DPRINTF("uvisor_page_free: FAIL: Page %u is not owned by box %u!\n\n", page_index, box_id);
|
||||
}
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_INVALID_PAGE_OWNER;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF("uvisor_page_free: %u free pages available.\n\n", g_page_count_free);
|
||||
UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE;
|
||||
return UVISOR_ERROR_PAGE_OK;
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "cmsis_os.h"
|
||||
#include "uvisor-lib/uvisor-lib.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#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
|
||||
|
||||
/* Use printf with caution inside malloc: printf may allocate memory itself,
|
||||
so using printf in malloc may lead to recursive calls! */
|
||||
#define DPRINTF(...) {};
|
||||
|
||||
extern RtxBoxIndex * const __uvisor_ps;
|
||||
|
||||
/** @retval 0 The kernel is not initialized.
|
||||
* @retval 1 The kernel is initialized.. */
|
||||
static int is_kernel_initialized()
|
||||
{
|
||||
static uint8_t kernel_running = 0;
|
||||
if (kernel_running) {
|
||||
return 1;
|
||||
}
|
||||
if (osKernelRunning()) {
|
||||
kernel_running = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_allocator()
|
||||
{
|
||||
int ret = 0;
|
||||
if (__uvisor_ps == NULL) {
|
||||
#if defined(UVISOR_PRESENT) && (UVISOR_PRESENT == 1)
|
||||
return -1;
|
||||
#else
|
||||
extern void secure_malloc_init(void);
|
||||
secure_malloc_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((__uvisor_ps->mutex_id == NULL) && is_kernel_initialized()) {
|
||||
/* Point the mutex pointer to the data. */
|
||||
__uvisor_ps->mutex.mutex = &(__uvisor_ps->mutex_data);
|
||||
/* Create mutex if not already done. */
|
||||
__uvisor_ps->mutex_id = osMutexCreate(&(__uvisor_ps->mutex));
|
||||
/* Mutex failed to be created. */
|
||||
if (__uvisor_ps->mutex_id == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (__uvisor_ps->index.active_heap == NULL) {
|
||||
/* We need to initialize the process heap. */
|
||||
if (__uvisor_ps->index.box_heap != NULL) {
|
||||
/* Lock the mutex during initialization. */
|
||||
int kernel_initialized = is_kernel_initialized();
|
||||
if (kernel_initialized) {
|
||||
osMutexWait(__uvisor_ps->mutex_id, osWaitForever);
|
||||
}
|
||||
/* Initialize the process heap. */
|
||||
SecureAllocator allocator = secure_allocator_create_with_pool(
|
||||
__uvisor_ps->index.box_heap,
|
||||
__uvisor_ps->index.box_heap_size);
|
||||
/* Set the allocator. */
|
||||
ret = allocator ? 0 : -1;
|
||||
__uvisor_ps->index.active_heap = allocator;
|
||||
/* Release the mutex. */
|
||||
if (kernel_initialized) {
|
||||
osMutexRelease(__uvisor_ps->mutex_id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DPRINTF("uvisor_allocator: No process heap available!\n");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void * memory(void * ptr, size_t size, int heap, int operation)
|
||||
{
|
||||
/* Buffer the return value. */
|
||||
void * ret = NULL;
|
||||
/* Initialize allocator. */
|
||||
if (init_allocator()) {
|
||||
return NULL;
|
||||
}
|
||||
/* Check if we need to aquire the mutex. */
|
||||
int mutexed = (is_kernel_initialized() && (heap == HEAP_PROCESS));
|
||||
void * allocator = (heap == HEAP_PROCESS) ?
|
||||
(__uvisor_ps->index.box_heap) :
|
||||
(__uvisor_ps->index.active_heap);
|
||||
|
||||
/* Aquire the mutex if required.
|
||||
* TODO: Mutex use is very coarse here. It may be sufficient to guard
|
||||
* the `rt_alloc_mem` and `rt_free_mem` functions in `uvisor_allocator.c`.
|
||||
* However, it is simpler to do it here for now. */
|
||||
if (mutexed) {
|
||||
osMutexWait(__uvisor_ps->mutex_id, osWaitForever);
|
||||
}
|
||||
/* Perform the required operation. */
|
||||
switch(operation)
|
||||
{
|
||||
case OP_MALLOC:
|
||||
ret = secure_malloc(allocator, size);
|
||||
break;
|
||||
case OP_REALLOC:
|
||||
ret = secure_realloc(allocator, ptr, size);
|
||||
break;
|
||||
case OP_FREE:
|
||||
secure_free(allocator, ptr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Release the mutex if required. */
|
||||
if (mutexed) {
|
||||
osMutexRelease(__uvisor_ps->mutex_id);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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__)
|
||||
void * __wrap__malloc_r(struct _reent * r, size_t size) {
|
||||
return memory(r, size, HEAP_ACTIVE, OP_MALLOC);
|
||||
}
|
||||
void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size) {
|
||||
(void)r;
|
||||
return memory(ptr, size, HEAP_ACTIVE, OP_REALLOC);
|
||||
}
|
||||
void __wrap__free_r(struct _reent * r, void * ptr) {
|
||||
(void)r;
|
||||
memory(ptr, 0, HEAP_ACTIVE, OP_FREE);
|
||||
}
|
||||
#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."
|
||||
#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);
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rt_TypeDef.h"
|
||||
#include "rt_Memory.h"
|
||||
|
||||
#include "secure_allocator.h"
|
||||
#include "uvisor-lib/uvisor-lib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Use printf with caution inside malloc: printf may allocate memory itself,
|
||||
so using printf in malloc may lead to recursive calls! */
|
||||
#define DPRINTF(...) {}
|
||||
|
||||
/* offsetof is a gcc built-in function, this is the manual implementation */
|
||||
#define OFFSETOF(type, member) ((uint32_t) (&(((type *)(0))->member)))
|
||||
|
||||
/* Declare this variable here, so the tier-2 allocator _always_ uses the
|
||||
* page size that the tier-1 allocator expects! */
|
||||
const uint32_t __uvisor_page_size = UVISOR_PAGE_SIZE;
|
||||
|
||||
/* Internal structure currently only contains the page table. */
|
||||
typedef struct {
|
||||
UvisorPageTable table;
|
||||
} SecureAllocatorInternal;
|
||||
|
||||
static inline UvisorPageTable * table(SecureAllocator allocator) {
|
||||
return &(((SecureAllocatorInternal *) allocator)->table);
|
||||
}
|
||||
|
||||
SecureAllocator secure_allocator_create_with_pool(
|
||||
void * mem,
|
||||
size_t bytes)
|
||||
{
|
||||
SecureAllocatorInternal * allocator = mem;
|
||||
/* Signal that this is non-page allocated memory. */
|
||||
allocator->table.page_size = bytes;
|
||||
allocator->table.page_count = 0;
|
||||
/* The internal rt_Memory MEMP structure must be placed AFTER table.page_origins[0] !!! */
|
||||
size_t offset = OFFSETOF(SecureAllocatorInternal, table.page_origins) + sizeof(((UvisorPageTable) {0}).page_origins);
|
||||
/* Create MEMP structure inside the memory. */
|
||||
if (rt_init_mem(mem + offset, bytes - offset)) {
|
||||
/* Abort if failed. */
|
||||
DPRINTF("secure_allocator_create_with_pool: MEMP allocator creation failed\n\n");
|
||||
return NULL;
|
||||
}
|
||||
/* Remember the MEMP pointer though. */
|
||||
allocator->table.page_origins[0] = mem + offset;
|
||||
DPRINTF("secure_allocator_create_with_pool: Created MEMP allocator %p with offset %d\n\n", mem + offset, offset);
|
||||
return allocator;
|
||||
}
|
||||
|
||||
SecureAllocator secure_allocator_create_with_pages(
|
||||
size_t size,
|
||||
size_t maximum_malloc_size)
|
||||
{
|
||||
/* The rt_Memory allocator puts one MEMP structure at both the
|
||||
* beginning and end of the memory pool. */
|
||||
const size_t block_overhead = 2 * sizeof(MEMP);
|
||||
const size_t page_size_with_overhead = UVISOR_PAGE_SIZE + block_overhead;
|
||||
/* Calculate the integer part of required the page count. */
|
||||
size_t page_count = size / page_size_with_overhead;
|
||||
/* Add another page if the remainder is not zero. */
|
||||
if (size - page_count * page_size_with_overhead) {
|
||||
page_count++;
|
||||
}
|
||||
DPRINTF("secure_allocator_create_with_pages: Requesting %u pages for at least %uB\n", page_count, size);
|
||||
|
||||
/* Compute the maximum allocation within our blocks. */
|
||||
size_t maximum_allocation_size = UVISOR_PAGE_SIZE - block_overhead;
|
||||
/* If the required maximum allocation is larger than we can provide, abort. */
|
||||
if (maximum_malloc_size > maximum_allocation_size) {
|
||||
DPRINTF("secure_allocator_create_with_pages: Maximum allocation request %uB is larger then available %uB\n\n", maximum_malloc_size, maximum_allocation_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Compute the required memory size for the page table. */
|
||||
size_t allocator_type_size = sizeof(SecureAllocatorInternal);
|
||||
/* Add size for each additional page. */
|
||||
allocator_type_size += (page_count - 1) * sizeof(((UvisorPageTable) {0}).page_origins);
|
||||
/* Allocate this much memory. */
|
||||
SecureAllocatorInternal * const allocator = malloc(allocator_type_size);
|
||||
/* If malloc failed, abort. */
|
||||
if (allocator == NULL) {
|
||||
DPRINTF("secure_allocator_create_with_pages: SecureAllocatorInternal failed to be allocated!\n\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Prepare the page table. */
|
||||
allocator->table.page_size = UVISOR_PAGE_SIZE;
|
||||
allocator->table.page_count = page_count;
|
||||
/* Get me some pages. */
|
||||
if (uvisor_page_malloc((UvisorPageTable *) &(allocator->table))) {
|
||||
free(allocator);
|
||||
DPRINTF("secure_allocator_create_with_pages: Not enough free pages available!\n\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize a MEMP structure in all pages. */
|
||||
for(size_t ii = 0; ii < page_count; ii++) {
|
||||
/* Add each page as a pool. */
|
||||
rt_init_mem(allocator->table.page_origins[ii], UVISOR_PAGE_SIZE);
|
||||
DPRINTF("secure_allocator_create_with_pages: Created MEMP allocator %p with offset %d\n", allocator->table.page_origins[ii], 0);
|
||||
}
|
||||
DPRINTF("\n");
|
||||
/* Aaaand across the line. */
|
||||
return (SecureAllocator) allocator;
|
||||
}
|
||||
|
||||
int secure_allocator_destroy(
|
||||
SecureAllocator allocator)
|
||||
{
|
||||
DPRINTF("secure_allocator_destroy: Destroying MEMP allocator at %p\n", table(allocator)->page_origins[0]);
|
||||
|
||||
/* Check if we are working on statically allocated memory. */
|
||||
SecureAllocatorInternal * alloc = (SecureAllocatorInternal * const) allocator;
|
||||
if (alloc->table.page_count == 0) {
|
||||
DPRINTF("secure_allocator_destroy: %p is not page-backed memory, not freeing!\n", allocator);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Free all pages. */
|
||||
if (uvisor_page_free(&(alloc->table))) {
|
||||
DPRINTF("secure_allocator_destroy: Unable to free pages!\n\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Free the allocator structure. */
|
||||
free(allocator);
|
||||
|
||||
DPRINTF("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void * secure_malloc(
|
||||
SecureAllocator allocator,
|
||||
size_t size)
|
||||
{
|
||||
size_t index = 0;
|
||||
do {
|
||||
/* Search in this page. */
|
||||
void * mem = rt_alloc_mem(table(allocator)->page_origins[index], size);
|
||||
/* Return if we found something. */
|
||||
if (mem) {
|
||||
DPRINTF("secure_malloc: Found %4uB in page %u at %p\n", size, index, mem);
|
||||
return mem;
|
||||
}
|
||||
/* Otherwise, go to the next page. */
|
||||
index++;
|
||||
} /* Continue search if more pages are available. */
|
||||
while (index < table(allocator)->page_count);
|
||||
|
||||
DPRINTF("secure_malloc: Out of memory in allocator %p \n", allocator);
|
||||
/* We found nothing. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * secure_realloc(
|
||||
SecureAllocator allocator,
|
||||
void * ptr,
|
||||
size_t new_size)
|
||||
{
|
||||
/* TODO: THIS IS A NAIVE IMPLEMENTATION, which always allocates new
|
||||
memory, and copies the memory, then frees the old memory. */
|
||||
|
||||
/* Allocate new memory. */
|
||||
void * new_ptr = secure_malloc(allocator, new_size);
|
||||
/* If memory allocation failed, abort. */
|
||||
if (new_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Passing NULL as ptr is legal, realloc acts as malloc then. */
|
||||
if (ptr) {
|
||||
/* Get the size of the ptr memory. */
|
||||
size_t size = ((MEMP *) ((uint32_t) ptr - sizeof(MEMP)))->len;
|
||||
/* Copy the memory to the new location, min(new_size, size). */
|
||||
memcpy(new_ptr, ptr, new_size < size ? new_size : size);
|
||||
/* Free the previous memory. */
|
||||
secure_free(allocator, ptr);
|
||||
}
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void secure_free(
|
||||
SecureAllocator allocator,
|
||||
void * ptr)
|
||||
{
|
||||
size_t index = 0;
|
||||
do {
|
||||
/* Search in this page. */
|
||||
int ret = rt_free_mem(table(allocator)->page_origins[index], ptr);
|
||||
/* Return if free was successful. */
|
||||
if (ret == 0) {
|
||||
DPRINTF("secure_free: Freed %p in page %u.\n", ptr, index);
|
||||
return;
|
||||
}
|
||||
/* Otherwise, go to the next page. */
|
||||
index++;
|
||||
} /* Continue search if more pages are available. */
|
||||
while (index < table(allocator)->page_count);
|
||||
|
||||
DPRINTF("secure_free: %p not found in allocator %p!\n", ptr, allocator);
|
||||
/* We found nothing. */
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
#include "uvisor-lib/uvisor-lib.h"
|
||||
|
||||
#if !(defined(UVISOR_PRESENT) && (UVISOR_PRESENT == 1))
|
||||
|
||||
#include <string.h> /* for memset */
|
||||
|
||||
/* Forward declaration of the page allocator API. */
|
||||
extern void page_allocator_init(void * const heap_start, void * const heap_end, const uint32_t * const page_size);
|
||||
|
||||
extern uint32_t __end__[]; /* __heap_start */
|
||||
extern uint32_t __HeapLimit[]; /* __heap_end */
|
||||
|
||||
extern uint32_t __StackLimit[]; /* bottom of stack */
|
||||
|
||||
/* There is only one box index for box 0. */
|
||||
RtxBoxIndex * __uvisor_ps;
|
||||
|
||||
static void box_index_init(void *box_bss, uint32_t heap_size)
|
||||
{
|
||||
const uint32_t index_size = sizeof(RtxBoxIndex);
|
||||
/* Adjust size for overhead of box index */
|
||||
heap_size -= index_size;
|
||||
|
||||
/* The box index is at the beginning of the bss section */
|
||||
RtxBoxIndex *const indexOS = box_bss;
|
||||
/* Zero the _entire_ index, so that we know to initialize the mutex on
|
||||
* first use! */
|
||||
memset(box_bss, 0, index_size);
|
||||
/* Initialize user context */
|
||||
indexOS->index.ctx = NULL;
|
||||
/* Initialize box heap */
|
||||
indexOS->index.box_heap = box_bss + index_size;
|
||||
indexOS->index.box_heap_size = heap_size;
|
||||
/* Active heap pointer is NULL */
|
||||
indexOS->index.active_heap = NULL;
|
||||
|
||||
/* There is no box config for unsupported! */
|
||||
indexOS->index.config = NULL;
|
||||
|
||||
/* Set the index */
|
||||
__uvisor_ps = indexOS;
|
||||
}
|
||||
|
||||
void secure_malloc_init(void)
|
||||
{
|
||||
/* get the main heap size from the linker script */
|
||||
uint32_t heap_size = ((uint32_t) __HeapLimit -
|
||||
(uint32_t) __end__);
|
||||
/* Main heap size is aligned to page boundaries n*UVISOR_PAGE_SIZE */
|
||||
uint32_t heap_start = (uint32_t) __StackLimit - heap_size;
|
||||
/* align the start address of the main heap to a page boundary */
|
||||
heap_start &= ~(UVISOR_PAGE_SIZE - 1);
|
||||
/* adjust the heap size to the new heap start address */
|
||||
heap_size = (uint32_t) __StackLimit - heap_start;
|
||||
|
||||
/* page heap now extends from the previous main heap start address
|
||||
* to the new main heap start address */
|
||||
extern uint32_t __uvisor_page_size;
|
||||
page_allocator_init(__end__, (void *) heap_start, &__uvisor_page_size);
|
||||
box_index_init((void *) heap_start, heap_size);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
#include "uvisor-lib/uvisor-lib.h"
|
||||
|
||||
#if !(defined(UVISOR_PRESENT) && (UVISOR_PRESENT == 1))
|
||||
|
||||
#include "cmsis.h"
|
||||
|
||||
/* This is the fallback implementation for using the page allocator from uVisor
|
||||
* inside an OS as a normal function.
|
||||
* Be aware that the page allocator is not re-entrant, so the OS must provide a
|
||||
* mutex implementation to enable thread-safety!
|
||||
*/
|
||||
#define DPRINTF(...) {}
|
||||
#define g_active_box 0
|
||||
#define vmpu_is_box_id_valid(...) 0
|
||||
#define vmpu_public_flash_addr(...) 1
|
||||
#define vmpu_sram_addr(...) 1
|
||||
#define HALT_ERROR(id, ...) {}
|
||||
#define UVISOR_PAGE_ALLOCATOR_MUTEX_AQUIRE page_allocator_mutex_aquire()
|
||||
#define UVISOR_PAGE_ALLOCATOR_MUTEX_RELEASE osMutexRelease(g_page_allocator_mutex_id)
|
||||
|
||||
/* Forward declaration of the page allocator API. */
|
||||
int page_allocator_malloc(UvisorPageTable * const table);
|
||||
int page_allocator_free(const UvisorPageTable * const table);
|
||||
|
||||
int uvisor_page_malloc(UvisorPageTable *const table)
|
||||
{
|
||||
return page_allocator_malloc(table);
|
||||
}
|
||||
|
||||
int uvisor_page_free(const UvisorPageTable *const table)
|
||||
{
|
||||
return page_allocator_free(table);
|
||||
}
|
||||
|
||||
/* Implement mutex for page allocator. */
|
||||
static osMutexId g_page_allocator_mutex_id = NULL;
|
||||
static int32_t g_page_allocator_mutex_data[4];
|
||||
static const osMutexDef_t g_page_allocator_mutex = { g_page_allocator_mutex_data };
|
||||
|
||||
static void page_allocator_mutex_aquire()
|
||||
{
|
||||
if (g_page_allocator_mutex_id == NULL) {
|
||||
/* Create mutex if not already done. */
|
||||
g_page_allocator_mutex_id = osMutexCreate(&g_page_allocator_mutex);
|
||||
if (g_page_allocator_mutex_id == NULL) {
|
||||
/* Mutex failed to be created. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
osMutexWait(g_page_allocator_mutex_id, osWaitForever);
|
||||
}
|
||||
|
||||
/* Alignment of MPU regions is not required anymore, however we still require
|
||||
* a 32B alignment, to have some page size granularity. */
|
||||
static inline int vmpu_is_region_size_valid(uint32_t size)
|
||||
{
|
||||
return ((size & ~31) == size);
|
||||
}
|
||||
static inline uint32_t vmpu_round_up_region(uint32_t addr, uint32_t size)
|
||||
{
|
||||
if (!vmpu_is_region_size_valid(size)) {
|
||||
return 0;
|
||||
}
|
||||
const uint32_t mask = size - 1;
|
||||
/* Adding the mask can overflow. */
|
||||
const uint32_t rounded_addr = addr + mask;
|
||||
/* Check for overflow. */
|
||||
if (rounded_addr < addr) {
|
||||
/* This means the address was too large to align. */
|
||||
return 0;
|
||||
}
|
||||
/* Mask the rounded address to get the aligned address. */
|
||||
return (rounded_addr & ~mask);
|
||||
}
|
||||
static inline uint32_t page_table_read(uint32_t addr)
|
||||
{
|
||||
return *((uint32_t *) addr);
|
||||
}
|
||||
static inline void page_table_write(uint32_t addr, uint32_t data)
|
||||
{
|
||||
*((uint32_t *) addr) = data;
|
||||
}
|
||||
|
||||
/* Include the original page allocator source directly. */
|
||||
#include "../page_allocator.c_inc"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,26 @@
|
|||
Copyright (c) 2013-2016 ARM Limited
|
||||
|
||||
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.
|
||||
|
||||
License Exceptions:
|
||||
|
||||
- 3-clause BSD License (see LICENSE-BSD.txt):
|
||||
|
||||
- core/cmsis/inc/arm* and core/cmsis/inc/core*:
|
||||
Copyright (c) 2009-2016 ARM Limited
|
||||
|
||||
- core/cmsis/inc/mpu_kinetis.h:
|
||||
Copyright (c) 1997-2014 Freescale Semiconductor, Inc
|
||||
|
||||
- core/lib/printf:
|
||||
Copyright (c) 2004, 2012 Kustaa Nyholm / SpareTimeLabs
|
|
@ -0,0 +1,27 @@
|
|||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
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.
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed.h"
|
||||
|
||||
EXTERN void uvisor_disabled_set_vector(uint32_t irqn, uint32_t vector)
|
||||
{
|
||||
NVIC_SetVector((IRQn_Type) irqn, vector);
|
||||
}
|
||||
|
||||
EXTERN uint32_t uvisor_disabled_get_vector(uint32_t irqn)
|
||||
{
|
||||
return NVIC_GetVector((IRQn_Type) irqn);
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
#include "uvisor-lib/uvisor-lib.h"
|
||||
#include "rt_OsEventObserver.h"
|
||||
|
||||
#if !(defined(UVISOR_PRESENT) && (UVISOR_PRESENT == 1))
|
||||
|
||||
/* Note: This file is not included in the uVisor release library. Instead, the
|
||||
* host OS needs to compile it separately if a platform does not support
|
||||
* uVisor (but uVisor API header files are still used). */
|
||||
|
||||
/* uVisor hook for unsupported platforms */
|
||||
UVISOR_EXTERN void uvisor_init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
extern RtxBoxIndex * __uvisor_ps;
|
||||
|
||||
static void thread_switch(void *context)
|
||||
{
|
||||
if (context == NULL) return;
|
||||
|
||||
/* If the active_heap is NULL, then the process heap needs to be
|
||||
* initialized. The initializer sets the active heap itself. */
|
||||
if (__uvisor_ps->index.active_heap) {
|
||||
__uvisor_ps->index.active_heap = context;
|
||||
}
|
||||
}
|
||||
|
||||
static OsEventObserver os_event_observer = {
|
||||
.version = 0,
|
||||
.pre_start = 0,
|
||||
.thread_create = 0,
|
||||
.thread_destroy = 0,
|
||||
.thread_switch = thread_switch,
|
||||
};
|
||||
|
||||
int uvisor_lib_init(void)
|
||||
{
|
||||
osRegisterForOsEvents(&os_event_observer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -412,6 +412,48 @@ extern "C" WEAK void __cxa_pure_virtual(void) {
|
|||
|
||||
#endif
|
||||
|
||||
#if defined(TOOLCHAIN_GCC)
|
||||
#ifdef FEATURE_UVISOR
|
||||
#include "uvisor-lib/uvisor-lib.h"
|
||||
#endif/* FEATURE_UVISOR */
|
||||
|
||||
#ifndef FEATURE_UVISOR
|
||||
extern "C" {
|
||||
void * __wrap__malloc_r(struct _reent * r, size_t size) {
|
||||
extern void * __real__malloc_r(struct _reent * r, size_t size);
|
||||
return __real__malloc_r(r, size);
|
||||
}
|
||||
void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size) {
|
||||
extern void * __real__realloc_r(struct _reent * r, void * ptr, size_t size);
|
||||
return __real__realloc_r(r, ptr, size);
|
||||
}
|
||||
void __wrap__free_r(struct _reent * r, void * ptr) {
|
||||
extern void __real__free_r(struct _reent * r, void * ptr);
|
||||
__real__free_r(r, ptr);
|
||||
}
|
||||
}
|
||||
#endif/* FEATURE_UVISOR */
|
||||
|
||||
extern "C" WEAK void software_init_hook_rtos(void)
|
||||
{
|
||||
// Do nothing by default.
|
||||
}
|
||||
|
||||
extern "C" void software_init_hook(void)
|
||||
{
|
||||
#ifdef FEATURE_UVISOR
|
||||
int return_code;
|
||||
|
||||
return_code = uvisor_lib_init();
|
||||
if (return_code) {
|
||||
mbed_die();
|
||||
}
|
||||
#endif/* FEATURE_UVISOR */
|
||||
|
||||
software_init_hook_rtos();
|
||||
}
|
||||
#endif
|
||||
|
||||
// ****************************************************************************
|
||||
// mbed_main is a function that is called before main()
|
||||
// mbed_sdk_init() is also a function that is called before main(), but unlike
|
||||
|
|
|
@ -92,6 +92,12 @@ SECTIONS
|
|||
/* The program code and other data goes into internal flash */
|
||||
.text :
|
||||
{
|
||||
/* uVisor code and data */
|
||||
. = ALIGN(4);
|
||||
__uvisor_main_start = .;
|
||||
*(.uvisor.main)
|
||||
__uvisor_main_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
|
@ -175,9 +181,6 @@ SECTIONS
|
|||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} > m_text
|
||||
|
||||
__etext = .; /* define a global symbol at end of code */
|
||||
__DATA_ROM = .; /* Symbol is used by startup for data initialization */
|
||||
|
||||
.interrupts_ram :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
|
@ -189,11 +192,44 @@ SECTIONS
|
|||
__interrupts_ram_end__ = .; /* Define a global symbol at data end */
|
||||
} > m_data
|
||||
|
||||
/* Ensure that the uVisor BSS section is put first after the relocated
|
||||
* interrupt table in SRAM. */
|
||||
/* Note: The uVisor expects this section at a fixed location, as specified by
|
||||
* the porting process configuration parameter: SRAM_OFFSET. */
|
||||
__UVISOR_SRAM_OFFSET = 0x400;
|
||||
__UVISOR_BSS_START = ORIGIN(m_data) + __UVISOR_SRAM_OFFSET;
|
||||
ASSERT(__interrupts_ram_end__ <= __UVISOR_BSS_START,
|
||||
"The ISR relocation region overlaps with the uVisor BSS section.")
|
||||
.uvisor.bss (NOLOAD):
|
||||
{
|
||||
. = ALIGN(32);
|
||||
__uvisor_bss_start = .;
|
||||
|
||||
/* protected uvisor main bss */
|
||||
. = ALIGN(32);
|
||||
__uvisor_bss_main_start = .;
|
||||
KEEP(*(.keep.uvisor.bss.main))
|
||||
. = ALIGN(32);
|
||||
__uvisor_bss_main_end = .;
|
||||
|
||||
/* protected uvisor secure boxes bss */
|
||||
. = ALIGN(32);
|
||||
__uvisor_bss_boxes_start = .;
|
||||
KEEP(*(.keep.uvisor.bss.boxes))
|
||||
. = ALIGN(32);
|
||||
__uvisor_bss_boxes_end = .;
|
||||
|
||||
. = ALIGN(32);
|
||||
__uvisor_bss_end = .;
|
||||
} > m_data
|
||||
|
||||
__VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts);
|
||||
__RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0;
|
||||
|
||||
.data : AT(__DATA_ROM)
|
||||
.data :
|
||||
{
|
||||
PROVIDE(__etext = LOADADDR(.data)); /* Define a global symbol at end of code, */
|
||||
PROVIDE(__DATA_ROM = LOADADDR(.data)); /* Symbol is used by startup for data initialization. */
|
||||
. = ALIGN(4);
|
||||
__DATA_RAM = .;
|
||||
__data_start__ = .; /* create a global symbol at data start */
|
||||
|
@ -202,12 +238,57 @@ SECTIONS
|
|||
KEEP(*(.jcr*))
|
||||
. = ALIGN(4);
|
||||
__data_end__ = .; /* define a global symbol at data end */
|
||||
} > m_data_2
|
||||
} > m_data_2 AT > m_text
|
||||
|
||||
__DATA_END = __DATA_ROM + (__data_end__ - __data_start__);
|
||||
text_end = ORIGIN(m_text) + LENGTH(m_text);
|
||||
ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data")
|
||||
|
||||
/* uVisor configuration section
|
||||
* This section must be located after all other flash regions. */
|
||||
.uvisor.secure :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
__uvisor_secure_start = .;
|
||||
|
||||
/* uVisor secure boxes configuration tables */
|
||||
. = ALIGN(32);
|
||||
__uvisor_cfgtbl_start = .;
|
||||
KEEP(*(.keep.uvisor.cfgtbl))
|
||||
. = ALIGN(32);
|
||||
__uvisor_cfgtbl_end = .;
|
||||
|
||||
/* Pointers to the uVisor secure boxes configuration tables */
|
||||
/* Note: Do not add any further alignment here, as uVisor will need to have
|
||||
* access to the exact list of pointers. */
|
||||
__uvisor_cfgtbl_ptr_start = .;
|
||||
KEEP(*(.keep.uvisor.cfgtbl_ptr_first))
|
||||
KEEP(*(.keep.uvisor.cfgtbl_ptr))
|
||||
__uvisor_cfgtbl_ptr_end = .;
|
||||
|
||||
/* Pointers to all boxes register gateways. These are grouped here to allow
|
||||
* discoverability and firmware verification. */
|
||||
__uvisor_register_gateway_ptr_start = .;
|
||||
KEEP(*(.keep.uvisor.register_gateway_ptr))
|
||||
__uvisor_register_gateway_ptr_end = .;
|
||||
|
||||
. = ALIGN(32);
|
||||
__uvisor_secure_end = .;
|
||||
} > m_text
|
||||
|
||||
/* Uninitialized data section
|
||||
* This region is not initialized by the C/C++ library and can be used to
|
||||
* store state across soft reboots. */
|
||||
.uninitialized (NOLOAD):
|
||||
{
|
||||
. = ALIGN(32);
|
||||
__uninitialized_start = .;
|
||||
*(.uninitialized)
|
||||
KEEP(*(.keep.uninitialized))
|
||||
. = ALIGN(32);
|
||||
__uninitialized_end = .;
|
||||
} > m_data_2
|
||||
|
||||
USB_RAM_GAP = DEFINED(__usb_ram_size__) ? __usb_ram_size__ : 0x800;
|
||||
/* Uninitialized data section */
|
||||
.bss :
|
||||
|
@ -230,18 +311,29 @@ SECTIONS
|
|||
.heap :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__uvisor_heap_start = .;
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
__HeapBase = .;
|
||||
. += HEAP_SIZE;
|
||||
__HeapLimit = .;
|
||||
__heap_limit = .; /* Add for _sbrk */
|
||||
__uvisor_heap_end = .;
|
||||
} > m_data_2
|
||||
|
||||
.stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
. += STACK_SIZE;
|
||||
__StackTop = .;
|
||||
} > m_data_2
|
||||
|
||||
/* Heap space for the page allocator */
|
||||
.page_heap (NOLOAD) :
|
||||
{
|
||||
__uvisor_page_start = .;
|
||||
. = ORIGIN(m_data_2) + LENGTH(m_data_2) - 4;
|
||||
__uvisor_page_end = .;
|
||||
} > m_data_2
|
||||
|
||||
m_usb_bdt USB_RAM_START (NOLOAD) :
|
||||
|
@ -256,12 +348,17 @@ SECTIONS
|
|||
}
|
||||
|
||||
/* Initializes stack on the end of block */
|
||||
__StackTop = ORIGIN(m_data_2) + LENGTH(m_data_2);
|
||||
__StackLimit = __StackTop - STACK_SIZE;
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region m_data_2 overflowed with stack and heap")
|
||||
|
||||
/* Provide the physical memory boundaries for uVisor. */
|
||||
__uvisor_flash_start = ORIGIN(m_interrupts);
|
||||
__uvisor_flash_end = ORIGIN(m_text) + LENGTH(m_text);
|
||||
__uvisor_sram_start = ORIGIN(m_data);
|
||||
__uvisor_sram_end = ORIGIN(m_data_2) + LENGTH(m_data_2);
|
||||
}
|
||||
|
||||
|
|
|
@ -332,6 +332,15 @@ Reset_Handler:
|
|||
ldr r0,=SystemInit
|
||||
blx r0
|
||||
#endif
|
||||
|
||||
/* The call to uvisor_init() happens independently of uVisor being enabled or
|
||||
* not, so it is conditionally compiled only based on FEATURE_UVISOR. */
|
||||
#ifdef FEATURE_UVISOR
|
||||
/* Call uvisor_init() */
|
||||
ldr r0, =uvisor_init
|
||||
blx r0
|
||||
#endif /* FEATURE_UVISOR */
|
||||
|
||||
/* Loop to copy data from read only memory to RAM. The ranges
|
||||
* of copy from/to are specified by following symbols evaluated in
|
||||
* linker script.
|
||||
|
|
|
@ -339,7 +339,7 @@ void pre_main(void) {
|
|||
main(0, NULL);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void software_init_hook (void) {
|
||||
__attribute__((naked)) void software_init_hook_rtos (void) {
|
||||
__asm (
|
||||
".syntax unified\n"
|
||||
".thumb\n"
|
||||
|
|
|
@ -447,7 +447,7 @@ __asm void __rt_entry (void) {
|
|||
|
||||
#elif defined (__GNUC__)
|
||||
|
||||
__attribute__((naked)) void software_init_hook (void) {
|
||||
__attribute__((naked)) void software_init_hook_rtos (void) {
|
||||
__asm (
|
||||
".syntax unified\n"
|
||||
".arm\n"
|
||||
|
|
|
@ -122,7 +122,11 @@ uint32_t const os_tickfreq = OS_CLOCK;
|
|||
uint16_t const os_tickus_i = OS_CLOCK/1000000;
|
||||
uint16_t const os_tickus_f = (((uint64_t)(OS_CLOCK-1000000*(OS_CLOCK/1000000)))<<16)/1000000;
|
||||
uint32_t const os_trv = OS_TRV;
|
||||
#if defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)
|
||||
uint8_t const os_flags = 0;
|
||||
#else /* defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED) */
|
||||
uint8_t const os_flags = OS_RUNPRIV;
|
||||
#endif /* defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED) */
|
||||
|
||||
/* Export following defines to uVision debugger. */
|
||||
__USED uint32_t const CMSIS_RTOS_API_Version = osCMSIS;
|
||||
|
@ -655,7 +659,7 @@ void pre_main(void) {
|
|||
main(0, NULL);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void software_init_hook (void) {
|
||||
__attribute__((naked)) void software_init_hook_rtos (void) {
|
||||
__asm (
|
||||
"bl osKernelInitialize\n"
|
||||
#ifdef __MBED_CMSIS_RTOS_CM
|
||||
|
|
|
@ -317,6 +317,8 @@ const osThreadDef_t os_thread_def_##name = \
|
|||
/// \return thread ID for reference by other functions or NULL in case of error.
|
||||
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument);
|
||||
|
||||
osThreadId osThreadContextCreate (const osThreadDef_t *thread_def, void *argument, void *context);
|
||||
|
||||
/// Return the thread ID of the current running thread.
|
||||
/// \return thread ID for reference by other functions or NULL in case of error.
|
||||
osThreadId osThreadGetId (void);
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "rt_MemBox.h"
|
||||
#include "rt_Memory.h"
|
||||
#include "rt_HAL_CM.h"
|
||||
#include "rt_OsEventObserver.h"
|
||||
|
||||
#include "cmsis_os.h"
|
||||
|
||||
|
@ -458,7 +459,7 @@ SVC_0_1(svcKernelRunning, int32_t, RET_int32_t)
|
|||
SVC_0_1(svcKernelSysTick, uint32_t, RET_uint32_t)
|
||||
|
||||
static void sysThreadError (osStatus status);
|
||||
osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument);
|
||||
osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument, void *context);
|
||||
osMessageQId svcMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id);
|
||||
|
||||
// Kernel Control Service Calls
|
||||
|
@ -488,7 +489,7 @@ osStatus svcKernelInitialize (void) {
|
|||
if (os_initialized == 0U) {
|
||||
// Create OS Timers resources (Message Queue & Thread)
|
||||
osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
|
||||
osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL);
|
||||
osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL, NULL);
|
||||
}
|
||||
|
||||
sysThreadError(osOK);
|
||||
|
@ -504,6 +505,10 @@ osStatus svcKernelStart (void) {
|
|||
|
||||
if (os_running) { return osOK; }
|
||||
|
||||
if (osEventObs && osEventObs->pre_start) {
|
||||
osEventObs->pre_start();
|
||||
}
|
||||
|
||||
rt_tsk_prio(0U, os_tsk.run->prio_base); // Restore priority
|
||||
if (os_tsk.run->task_id == 0xFFU) { // Idle Thread
|
||||
__set_PSP(os_tsk.run->tsk_stack + (8U*4U)); // Setup PSP
|
||||
|
@ -616,7 +621,7 @@ static void sysThreadError (osStatus status) {
|
|||
__NO_RETURN void osThreadExit (void);
|
||||
|
||||
// Thread Service Calls declarations
|
||||
SVC_2_1(svcThreadCreate, osThreadId, const osThreadDef_t *, void *, RET_pointer)
|
||||
SVC_3_1(svcThreadCreate, osThreadId, const osThreadDef_t *, void *, void *, RET_pointer)
|
||||
SVC_0_1(svcThreadGetId, osThreadId, RET_pointer)
|
||||
SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET_osStatus)
|
||||
SVC_0_1(svcThreadYield, osStatus, RET_osStatus)
|
||||
|
@ -626,7 +631,7 @@ SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET
|
|||
// Thread Service Calls
|
||||
|
||||
/// Create a thread and add it to Active Threads and set it to state READY
|
||||
osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument) {
|
||||
osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument, void *context) {
|
||||
P_TCB ptcb;
|
||||
OS_TID tsk;
|
||||
void *stk;
|
||||
|
@ -683,6 +688,12 @@ osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument) {
|
|||
|
||||
*((uint32_t *)ptcb->tsk_stack + 13) = (uint32_t)osThreadExit;
|
||||
|
||||
if (osEventObs && osEventObs->thread_create) {
|
||||
ptcb->context = osEventObs->thread_create(ptcb->task_id, context);
|
||||
} else {
|
||||
ptcb->context = context;
|
||||
}
|
||||
|
||||
return ptcb;
|
||||
}
|
||||
|
||||
|
@ -712,6 +723,10 @@ osStatus svcThreadTerminate (osThreadId thread_id) {
|
|||
stk = ptcb->priv_stack ? ptcb->stack : NULL; // Private stack
|
||||
#endif
|
||||
|
||||
if (osEventObs && osEventObs->thread_destroy) {
|
||||
osEventObs->thread_destroy(ptcb->context);
|
||||
}
|
||||
|
||||
res = rt_tsk_delete(ptcb->task_id); // Delete task
|
||||
|
||||
if (res == OS_R_NOK) {
|
||||
|
@ -776,14 +791,17 @@ osPriority svcThreadGetPriority (osThreadId thread_id) {
|
|||
|
||||
/// Create a thread and add it to Active Threads and set it to state READY
|
||||
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument) {
|
||||
if (__get_IPSR() != 0U) {
|
||||
return osThreadContextCreate(thread_def, argument, NULL);
|
||||
}
|
||||
osThreadId osThreadContextCreate (const osThreadDef_t *thread_def, void *argument, void *context) {
|
||||
if (__get_IPSR() != 0U) {
|
||||
return NULL; // Not allowed in ISR
|
||||
}
|
||||
if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
|
||||
// Privileged and not running
|
||||
return svcThreadCreate(thread_def, argument);
|
||||
return svcThreadCreate(thread_def, argument, context);
|
||||
} else {
|
||||
return __svcThreadCreate(thread_def, argument);
|
||||
return __svcThreadCreate(thread_def, argument, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* CMSIS-RTOS - RTX
|
||||
*----------------------------------------------------------------------------
|
||||
* Name: rt_OsEventObserver.c
|
||||
* Purpose: OS Event Callbacks for CMSIS RTOS
|
||||
* Rev.: VX.XX
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* - Neither the name of ARM nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "rt_OsEventObserver.h"
|
||||
|
||||
/*
|
||||
* _____ _____ ____ __ _____
|
||||
* | ___|_ _\ \/ / \/ | ____|
|
||||
* | |_ | | \ /| |\/| | _|
|
||||
* | _| | | / \| | | | |___
|
||||
* |_| |___/_/\_\_| |_|_____|
|
||||
*
|
||||
* FIXME:
|
||||
* The osEventObs variable must be in protected memory. If not every box
|
||||
* and box 0 can modify osEventObs to point to any handler to run code
|
||||
* privileged. This issue is tracked at
|
||||
* <https://github.com/ARMmbed/uvisor/issues/235>.
|
||||
*/
|
||||
const OsEventObserver *osEventObs;
|
||||
|
||||
void osRegisterForOsEvents(const OsEventObserver *observer)
|
||||
{
|
||||
osEventObs = observer;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* CMSIS-RTOS - RTX
|
||||
*----------------------------------------------------------------------------
|
||||
* Name: os_events.h
|
||||
* Purpose: OS Event Callbacks for CMSIS RTOS
|
||||
* Rev.: VX.XX
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 1999-2009 KEIL, 2009-2016 ARM Germany GmbH
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* - Neither the name of ARM nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*---------------------------------------------------------------------------*/
|
||||
#ifndef _RT_OS_EVENT_OBSERVER_H
|
||||
#define _RT_OS_EVENT_OBSERVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
void (*pre_start)(void);
|
||||
void *(*thread_create)(int thread_id, void *context);
|
||||
void (*thread_destroy)(void *context);
|
||||
void (*thread_switch)(void *context);
|
||||
} OsEventObserver;
|
||||
extern const OsEventObserver *osEventObs;
|
||||
|
||||
void osRegisterForOsEvents(const OsEventObserver *observer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -40,6 +40,7 @@
|
|||
#include "rt_MemBox.h"
|
||||
#include "rt_Robin.h"
|
||||
#include "rt_HAL_CM.h"
|
||||
#include "rt_OsEventObserver.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Global Variables
|
||||
|
@ -101,6 +102,9 @@ void rt_switch_req (P_TCB p_new) {
|
|||
/* Switch to next task (identified by "p_new"). */
|
||||
os_tsk.new_tsk = p_new;
|
||||
p_new->state = RUNNING;
|
||||
if (osEventObs && osEventObs->thread_switch) {
|
||||
osEventObs->thread_switch(p_new->context);
|
||||
}
|
||||
DBG_TASK_SWITCH(p_new->task_id);
|
||||
}
|
||||
|
||||
|
@ -402,6 +406,10 @@ void rt_sys_init (FUNCP first_task, U32 prio_stksz, void *stk) {
|
|||
os_tsk.run = &os_idle_TCB;
|
||||
os_tsk.run->state = RUNNING;
|
||||
|
||||
/* Set the current thread to idle, so that on exit from this SVCall we do not
|
||||
* de-reference a NULL TCB. */
|
||||
rt_switch_req(&os_idle_TCB);
|
||||
|
||||
/* Initialize ps queue */
|
||||
os_psq->first = 0U;
|
||||
os_psq->last = 0U;
|
||||
|
|
|
@ -79,6 +79,7 @@ typedef struct OS_TCB {
|
|||
|
||||
/* Task entry point used for uVision debugger */
|
||||
FUNCP ptask; /* Task entry address */
|
||||
void *context; /* Pointer to thread context */
|
||||
} *P_TCB;
|
||||
#define TCB_STACKF 37 /* 'stack_frame' offset */
|
||||
#define TCB_TSTACK 44 /* 'tsk_stack' offset */
|
||||
|
|
Loading…
Reference in New Issue