Update uVisor page allocator and box initialization

pull/2052/head
Milosch Meriac 2016-06-27 22:54:58 +00:00
parent 2a7f02033d
commit 7e006c769e
19 changed files with 160 additions and 92 deletions

View File

@ -1,7 +1,7 @@
513 Milosch Meriac
424 Alessandro Angelino
18 Jaeden Amero
18 Niklas Hauser
511 Milosch Meriac
433 Alessandro Angelino
28 Niklas Hauser
22 Jaeden Amero
3 Hugo Vincent
3 JaredCJR
3 Jim Huang

View File

@ -1 +1 @@
v0.9.17-alpha
v0.9.20-alpha

View File

@ -46,7 +46,6 @@ UVISOR_EXTERN const uint32_t __uvisor_mode;
0, \
0, \
0, \
0, \
NULL, \
acl_list, \
acl_list_count \
@ -78,8 +77,7 @@ UVISOR_EXTERN const uint32_t __uvisor_mode;
sizeof(RtxBoxIndex), \
context_size, \
__uvisor_box_heapsize, \
__uvisor_box_main_function, \
__uvisor_box_main_priority, \
__uvisor_box_lib_config, \
__uvisor_box_namespace, \
acl_list, \
acl_list_count \
@ -123,9 +121,9 @@ UVISOR_EXTERN const uint32_t __uvisor_mode;
/* Use this macro before UVISOR_BOX_CONFIG to define the function the main
* thread of your box will use for its body. If you don't want a main thread,
* too bad: you have to have one. */
#define UVISOR_BOX_MAIN(function, priority) \
static void (*const __uvisor_box_main_function)(void const *) = (function); \
static const int32_t __uvisor_box_main_priority = (priority);
#define UVISOR_BOX_MAIN(function, priority, stack_size) \
static osThreadDef(function, priority, stack_size); \
static const void * const __uvisor_box_lib_config = osThread(function);
#define UVISOR_BOX_HEAPSIZE(heap_size) \
static const uint32_t __uvisor_box_heapsize = heap_size;

View File

@ -114,9 +114,12 @@
#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)
#define UVISOR_SVC_ID_BOX_MAIN_NEXT UVISOR_SVC_FIXED_TABLE(5, 0)
#define UVISOR_SVC_ID_UNVIC_OUT UVISOR_SVC_FIXED_TABLE(0, 0)
/* Deprecated: UVISOR_SVC_ID_CX_IN(nargs) UVISOR_SVC_FIXED_TABLE(1, nargs) */
/* Deprecated: UVISOR_SVC_ID_CX_OUT UVISOR_SVC_FIXED_TABLE(2, 0) */
#define UVISOR_SVC_ID_REGISTER_GATEWAY UVISOR_SVC_FIXED_TABLE(3, 0)
#define UVISOR_SVC_ID_BOX_INIT_FIRST UVISOR_SVC_FIXED_TABLE(4, 0)
#define UVISOR_SVC_ID_BOX_INIT_NEXT UVISOR_SVC_FIXED_TABLE(5, 0)
/* SVC immediate values for hardcoded table (call from privileged) */
#define UVISOR_SVC_ID_UNVIC_IN UVISOR_SVC_FIXED_TABLE(0, 0)

View File

@ -104,13 +104,24 @@
#if defined(UVISOR_PRESENT) && UVISOR_PRESENT == 1
/** Round an address down to the closest 32-byte boundary.
* @param address[in] The address to round.
*/
#define UVISOR_ROUND32_DOWN(address) ((address) & ~0x1FUL)
/** Round an address up to the closest 32-byte boundary.
* @param address[in] The address to round.
*/
#define UVISOR_ROUND32_UP(address) UVISOR_ROUND32_DOWN((address) + 31UL)
#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_REGION_ROUND_DOWN(x) UVISOR_ROUND32_DOWN(x)
#define UVISOR_REGION_ROUND_UP(x) UVISOR_ROUND32_UP(x)
#define UVISOR_STACK_SIZE_ROUND(x) UVISOR_REGION_ROUND_UP((x) + (UVISOR_STACK_BAND_SIZE * 2))
#else
#error "Unknown MPU architecture. uvisor: Check your Makefile. uvisor-lib: Check if uVisor is supported"
@ -158,8 +169,9 @@ typedef struct {
/* Contains user provided size of box heap without guards of buffers. */
uint32_t heap_size;
void (*main_function)(void const *argument);
int32_t main_priority;
/* Opaque-to-uVisor data that potentially contains uvisor-lib-specific or
* OS-specific per-box configuration */
const void * const lib_config;
const char * box_namespace;
const UvisorBoxAclItem * const acl_list;

View File

@ -22,6 +22,7 @@
#include <uvisor.h>
#include "page_allocator.h"
#include "page_allocator_faults.h"
#include "mpu/vmpu_unpriv_access.h"
#include "mpu/vmpu.h"
#include "halt.h"
@ -38,40 +39,31 @@
#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
#include "page_allocator_config.h"
/* 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))
page_owner_t g_page_owner_table[UVISOR_PAGE_TABLE_MAX_COUNT];
/* Contains the configured page size. */
static uint32_t g_page_size;
uint32_t g_page_size;
/* Points to the beginning of the page heap. */
static const void * g_page_heap_start;
const void * g_page_heap_start;
/* Points to the end of the page heap. */
static const void * g_page_heap_end;
const void * g_page_heap_end;
/* Contains the number of free pages. */
static uint8_t g_page_count_free;
uint8_t g_page_count_free;
/* Contains the total number of available pages. */
static uint8_t g_page_count_total;
uint8_t g_page_count_total;
/* Helper function maps pointer to page id, or UVISOR_PAGE_UNUSED. */
uint8_t page_allocator_get_page_from_address(uint32_t address)
{
/* Range check the returned pointer. */
if (address < (uint32_t) g_page_heap_start || address >= (uint32_t) g_page_heap_end) {
return UVISOR_PAGE_UNUSED;
}
/* Compute the index for the pointer. */
return (address - (uint32_t) g_page_heap_start) / g_page_size;
}
void page_allocator_init(void * const heap_start, void * const heap_end, const uint32_t * const page_size)
{
@ -142,8 +134,9 @@ void page_allocator_init(void * const heap_start, void * const heap_end, const u
(unsigned int) (g_page_size / 1024));
uint32_t page = 0;
for (; page < g_page_count_total; page++) {
for (; page < UVISOR_PAGE_TABLE_MAX_COUNT; page++) {
g_page_owner_table[page] = UVISOR_PAGE_UNUSED;
page_allocator_reset_faults(page);
}
}
@ -187,6 +180,8 @@ int page_allocator_malloc(UvisorPageTable * const table)
if (g_page_owner_table[page] == UVISOR_PAGE_UNUSED) {
/* Marry this page to the box id. */
g_page_owner_table[page] = box_id;
/* Reset the fault count for this page. */
page_allocator_reset_faults(page);
/* 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. */
@ -239,14 +234,14 @@ int page_allocator_free(const UvisorPageTable * const table)
int table_size = page_count;
for (; table_size > 0; page_table++, table_size--) {
void * page = (void *) page_table_read((uint32_t) page_table);
/* Compute the index for the pointer. */
uint8_t page_index = page_allocator_get_page_from_address((uint32_t) page);
/* Range check the returned pointer. */
if (page < g_page_heap_start || page >= g_page_heap_end) {
if (page_index == UVISOR_PAGE_UNUSED) {
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;

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __PAGE_ALLOCATOR_CONFIG_H__
#define __PAGE_ALLOCATOR_CONFIG_H__
/* 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. */
/* 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 overwritten
* 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 overwritten
* 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;
/* Define a unused value for the page table. */
#define UVISOR_PAGE_UNUSED ((page_owner_t) (-1))
#endif /* __PAGE_ALLOCATOR_CONFIG_H__ */

View File

@ -0,0 +1,56 @@
/*
* 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 "uvisor-lib/uvisor-lib.h"
#include "mbed_interface.h"
#include "cmsis_os.h"
#include <stdint.h>
#include <string.h>
/* This function is called by uVisor in unprivileged mode. On this OS, we
* create box main threads for the box. */
void __uvisor_lib_box_init(void * lib_config)
{
osThreadId thread_id;
osThreadDef_t * flash_thread_def = lib_config;
osThreadDef_t thread_def;
/* Copy thread definition from flash to RAM. The thread definition is most
* likely in flash, so we need to copy it to box-local RAM before we can
* modify it. */
memcpy(&thread_def, flash_thread_def, sizeof(thread_def));
/* Note that the box main thread stack is separate from the box stack. This
* is because the thread must be created to use a different stack than the
* stack osCreateThread() is called from, as context information is saved
* to the thread stack by the call to osCreateThread(). */
/* Allocate memory for the main thread from the process heap (which is
* private to the process). This memory is never freed, even if the box's
* main thread exits. */
thread_def.stack_pointer = malloc_p(thread_def.stacksize);
if (thread_def.stack_pointer == NULL) {
/* No process heap memory available */
mbed_die();
}
thread_id = osThreadCreate(&thread_def, NULL);
if (thread_id == NULL) {
/* Failed to create thread */
mbed_die();
}
}

View File

@ -1,43 +0,0 @@
/*
* Copyright (c) 2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "uvisor-lib/uvisor-lib.h"
#include "mbed_interface.h"
#include "cmsis_os.h"
#include <stdint.h>
#include <stdlib.h>
/* This function is called by uVisor in unprivileged mode to create box main
* threads. */
void __uvisor_lib_box_main_handler(
void (*function)(void const *),
int32_t priority,
uint32_t stack_pointer,
uint32_t stack_size)
{
osThreadId thread_id;
osThreadDef_t thread_def;
thread_def.pthread = function;
thread_def.tpriority = priority;
thread_def.stacksize = stack_size;
thread_def.stack_pointer = malloc(stack_size); /* XXX */
thread_id = osThreadCreate(&thread_def, NULL);
if (thread_id == NULL) {
mbed_die();
}
}

View File

@ -111,7 +111,8 @@ static void * memory(void * ptr, size_t size, int heap, int operation)
return NULL;
}
/* Check if we need to aquire the mutex. */
int mutexed = (is_kernel_initialized() && (heap == HEAP_PROCESS));
int mutexed = is_kernel_initialized() &&
((heap == HEAP_PROCESS) || __uvisor_ps->index.box_heap == __uvisor_ps->index.active_heap);
void * allocator = (heap == HEAP_PROCESS) ?
(__uvisor_ps->index.box_heap) :
(__uvisor_ps->index.active_heap);

View File

@ -33,6 +33,7 @@
#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)
#define page_allocator_reset_faults(...) {}
/* Forward declaration of the page allocator API. */
int page_allocator_malloc(UvisorPageTable * const table);