Skip to content

Commit eeead56

Browse files
authored
Merge pull request #2558 from meriac/master
Update uVisor with new page allocator
2 parents fe1f2b6 + b98227c commit eeead56

File tree

18 files changed

+118
-74
lines changed

18 files changed

+118
-74
lines changed

features/FEATURE_UVISOR/AUTHORS.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
552 Milosch Meriac
2-
457 Alessandro Angelino
1+
553 Milosch Meriac
2+
458 Alessandro Angelino
3+
42 Niklas Hauser
34
40 Jaeden Amero
4-
31 Niklas Hauser
55
3 Hugo Vincent
66
3 JaredCJR
77
3 Jim Huang

features/FEATURE_UVISOR/VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.20.1-alpha
1+
v0.21.0-alpha

features/FEATURE_UVISOR/includes/uvisor/api/inc/box_config.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define __UVISOR_API_BOX_CONFIG_H__
1919

2020
#include "api/inc/uvisor_exports.h"
21+
#include "api/inc/page_allocator_exports.h"
2122
#include <stddef.h>
2223
#include <stdint.h>
2324

@@ -53,6 +54,14 @@ UVISOR_EXTERN const uint32_t __uvisor_mode;
5354
\
5455
extern const __attribute__((section(".keep.uvisor.cfgtbl_ptr_first"), aligned(4))) void * const main_cfg_ptr = &main_cfg;
5556

57+
/* Creates a global page heap with at least `minimum_number_of_pages` each of size `page_size` in bytes.
58+
* The total page heap size is at least `minimum_number_of_pages * page_size`. */
59+
#define UVISOR_SET_PAGE_HEAP(page_size, minimum_number_of_pages) \
60+
const uint32_t __uvisor_page_size = (page_size); \
61+
uint8_t __attribute__((section(".keep.uvisor.page_heap"))) \
62+
main_page_heap_reserved[ (page_size) * (minimum_number_of_pages) ]
63+
64+
5665
/* this macro selects an overloaded macro (variable number of arguments) */
5766
#define __UVISOR_BOX_MACRO(_1, _2, _3, _4, NAME, ...) NAME
5867

features/FEATURE_UVISOR/includes/uvisor/api/inc/page_allocator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,7 @@ UVISOR_EXTERN int uvisor_page_malloc(UvisorPageTable * const table);
3434
*/
3535
UVISOR_EXTERN int uvisor_page_free(const UvisorPageTable * const table);
3636

37+
/* @returns the active page size for one page. */
38+
UVISOR_EXTERN uint32_t uvisor_get_page_size(void);
39+
3740
#endif /* __UVISOR_API_PAGE_ALLOCATOR_H__ */

features/FEATURE_UVISOR/includes/uvisor/api/inc/page_allocator_exports.h

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,9 @@
3030
#define UVISOR_ERROR_PAGE_INVALID_PAGE_OWNER (UVISOR_ERROR_CLASS_PAGE + 5)
3131
#define UVISOR_ERROR_PAGE_INVALID_PAGE_COUNT (UVISOR_ERROR_CLASS_PAGE + 6)
3232

33-
34-
/* Must be a power of 2 for MPU alignment in ARMv7-M with ARM MPU.
35-
* Must be multiple of 32 for K64F MPU. */
36-
#ifndef UVISOR_PAGE_SIZE
37-
#define UVISOR_PAGE_SIZE ((uint32_t) 16 * 1024)
38-
#endif
39-
40-
/* Return the rounded up number of pages required to hold `size`. */
41-
#define UVISOR_PAGES_FOR_SIZE(size) ((size + UVISOR_PAGE_SIZE - 1) / UVISOR_PAGE_SIZE)
42-
43-
/* Create a page table with `count` many entries. */
44-
#define UVISOR_PAGE_TABLE(count) \
45-
struct { \
46-
uint32_t page_size; \
47-
uint32_t page_count; \
48-
void * page_origins[count]; \
49-
}
50-
51-
/* Create a page table with enough pages to hold `size`. */
52-
#define UVISOR_PAGE_TABLE_FOR_SIZE(size) UVISOR_PAGE_TABLE(UVISOR_PAGES_FOR_SIZE(size))
53-
33+
/* Contains the uVisor page size.
34+
* @warning Do not read directly, instead use `uvisor_get_page_size()` accessor! */
35+
UVISOR_EXTERN const uint32_t __uvisor_page_size;
5436

5537
typedef struct {
5638
uint32_t page_size; /* The page size in bytes. Must be multiple of `UVISOR_PAGE_SIZE`! */

features/FEATURE_UVISOR/source/page_allocator.c_inc

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@
4141

4242
#include "page_allocator_config.h"
4343

44-
/* Maps the page to the owning box handle. */
45-
page_owner_t g_page_owner_table[UVISOR_PAGE_TABLE_MAX_COUNT];
44+
/* Contains the page usage mapped by owner. */
45+
uint32_t g_page_owner_map[UVISOR_MAX_BOXES][UVISOR_PAGE_MAP_COUNT];
46+
/* Contains total page usage. */
47+
uint32_t g_page_usage_map[UVISOR_PAGE_MAP_COUNT];
4648
/* Contains the configured page size. */
4749
uint32_t g_page_size;
4850
/* Points to the beginning of the page heap. */
@@ -119,12 +121,16 @@ void page_allocator_init(void * const heap_start, void * const heap_end, const u
119121
g_page_count_total = ((uint32_t) heap_end - start) / g_page_size;
120122
}
121123
/* Clamp page count to table size. */
122-
if (g_page_count_total > UVISOR_PAGE_TABLE_MAX_COUNT) {
123-
g_page_count_total = UVISOR_PAGE_TABLE_MAX_COUNT;
124+
if (g_page_count_total > UVISOR_PAGE_MAX_COUNT) {
125+
DPRINTF("uvisor_page_init: Clamping available page count from %u to %u!\n", g_page_count_total, UVISOR_PAGE_MAX_COUNT);
126+
/* Move the heap start address forward so that the last clamped page is located nearest to the heap end. */
127+
g_page_heap_start += (g_page_count_total - UVISOR_PAGE_MAX_COUNT) * g_page_size;
128+
/* Clamp the page count. */
129+
g_page_count_total = UVISOR_PAGE_MAX_COUNT;
124130
}
125131
g_page_count_free = g_page_count_total;
126132
/* Remember the end of the heap. */
127-
g_page_heap_end = g_page_heap_start + g_page_count_free * g_page_size;
133+
g_page_heap_end = g_page_heap_start + g_page_count_total * g_page_size;
128134

129135
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",
130136
(unsigned int) g_page_heap_start,
@@ -133,11 +139,9 @@ void page_allocator_init(void * const heap_start, void * const heap_end, const u
133139
(unsigned int) g_page_count_total,
134140
(unsigned int) (g_page_size / 1024));
135141

136-
uint32_t page = 0;
137-
for (; page < UVISOR_PAGE_TABLE_MAX_COUNT; page++) {
138-
g_page_owner_table[page] = UVISOR_PAGE_UNUSED;
139-
page_allocator_reset_faults(page);
140-
}
142+
/* Force a reset of owner and usage page maps. */
143+
memset(g_page_owner_map, 0, sizeof(g_page_owner_map));
144+
memset(g_page_usage_map, 0, sizeof(g_page_usage_map));
141145
}
142146

143147
int page_allocator_malloc(UvisorPageTable * const table)
@@ -176,10 +180,20 @@ int page_allocator_malloc(UvisorPageTable * const table)
176180
/* Iterate through the page table and find the empty pages. */
177181
uint32_t page = 0;
178182
for (; (page < g_page_count_total) && pages_required; page++) {
179-
/* If the page is unused, it's entry is UVISOR_PAGE_UNUSED (not NULL!). */
180-
if (g_page_owner_table[page] == UVISOR_PAGE_UNUSED) {
181-
/* Marry this page to the box id. */
182-
g_page_owner_table[page] = box_id;
183+
/* If the page is unused, map_get returns zero. */
184+
if (!page_allocator_map_get(g_page_usage_map, page)) {
185+
/* Remember this page as used. */
186+
page_allocator_map_set(g_page_usage_map, page);
187+
/* Pages of box 0 are accessible to all other boxes! */
188+
if (box_id == 0) {
189+
uint32_t ii = 0;
190+
for (; ii < UVISOR_MAX_BOXES; ii++) {
191+
page_allocator_map_set(g_page_owner_map[ii], page);
192+
}
193+
} else {
194+
/* Otherwise, remember ownership only for active box. */
195+
page_allocator_map_set(g_page_owner_map[box_id], page);
196+
}
183197
/* Reset the fault count for this page. */
184198
page_allocator_reset_faults(page);
185199
/* Get the pointer to the page. */
@@ -243,14 +257,25 @@ int page_allocator_free(const UvisorPageTable * const table)
243257
return UVISOR_ERROR_PAGE_INVALID_PAGE_ORIGIN;
244258
}
245259
/* Check if the page belongs to the caller. */
246-
if (g_page_owner_table[page_index] == box_id) {
247-
g_page_owner_table[page_index] = UVISOR_PAGE_UNUSED;
260+
if (page_allocator_map_get(g_page_owner_map[box_id], page_index)) {
261+
/* Clear the owner and usage page maps for this page. */
262+
page_allocator_map_clear(g_page_usage_map, page_index);
263+
/* If the page was owned by box 0, we need to remove it from all other boxes! */
264+
if (box_id == 0) {
265+
uint32_t ii = 0;
266+
for (; ii < UVISOR_MAX_BOXES; ii++) {
267+
page_allocator_map_clear(g_page_owner_map[ii], page_index);
268+
}
269+
} else {
270+
/* Otherwise, only remove for the active box. */
271+
page_allocator_map_clear(g_page_owner_map[box_id], page_index);
272+
}
248273
g_page_count_free++;
249274
DPRINTF("uvisor_page_free: Freeing page at index %u\n", page_index);
250275
}
251276
else {
252277
/* Abort if the page doesn't belong to the caller. */
253-
if (g_page_owner_table[page_index] == UVISOR_PAGE_UNUSED) {
278+
if (!page_allocator_map_get(g_page_usage_map, page_index)) {
254279
DPRINTF("uvisor_page_free: FAIL: Page %u is not allocated!\n\n", page_index);
255280
} else {
256281
DPRINTF("uvisor_page_free: FAIL: Page %u is not owned by box %u!\n\n", page_index, box_id);

features/FEATURE_UVISOR/source/page_allocator_config.h

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,58 @@
2525
* a relatively low limit to the number of pages.
2626
* By default a maximum of 16 pages are allowed. This can only be overwritten
2727
* by the porting engineer for the current platform. */
28-
#ifndef UVISOR_PAGE_TABLE_MAX_COUNT
29-
#define UVISOR_PAGE_TABLE_MAX_COUNT ((uint32_t) 16)
28+
#ifndef UVISOR_PAGE_MAX_COUNT
29+
#define UVISOR_PAGE_MAX_COUNT (16UL)
3030
#endif
3131
/* The number of pages is decided by the page size. A small page size leads to
3232
* a lot of pages, however, number of pages is capped for efficiency.
3333
* Furthermore, when allocating large continous memory, a too small page size
3434
* will lead to allocation failures. This can only be overwritten
3535
* by the porting engineer for the current platform. */
3636
#ifndef UVISOR_PAGE_SIZE_MINIMUM
37-
#define UVISOR_PAGE_SIZE_MINIMUM ((uint32_t) 1024)
37+
#define UVISOR_PAGE_SIZE_MINIMUM (1024UL)
3838
#endif
3939

40+
/* Defines the number of uint32_t page owner masks in the owner map. */
41+
#define UVISOR_PAGE_MAP_COUNT ((UVISOR_PAGE_MAX_COUNT + 31) / 32)
42+
4043
/* The page box_id is the box id which is 8-bit large. */
4144
typedef uint8_t page_owner_t;
4245
/* Define a unused value for the page table. */
4346
#define UVISOR_PAGE_UNUSED ((page_owner_t) (-1))
47+
/* Contains the total number of available pages. */
48+
extern uint8_t g_page_count_total;
49+
50+
/** Sets the page bit in the page map array.
51+
* @param map an array of `uint32_t` containing the page map
52+
* @param page the index of the page to be set
53+
*/
54+
static inline void page_allocator_map_set(uint32_t * const map, uint8_t page)
55+
{
56+
page += UVISOR_PAGE_MAP_COUNT * 32 - g_page_count_total;
57+
map[page / 32] |= (1UL << (page % 32));
58+
}
59+
60+
/** Clears the page bit in the page map array.
61+
* @param map an array of `uint32_t` containing the page map
62+
* @param page the index of the page to be set
63+
*/
64+
static inline void page_allocator_map_clear(uint32_t * const map, uint8_t page)
65+
{
66+
page += UVISOR_PAGE_MAP_COUNT * 32 - g_page_count_total;
67+
map[page / 32] &= ~(1UL << (page % 32));
68+
}
69+
70+
/** Check if the page bit is set int the page map array.
71+
* @param map an array of `uint32_t` containing the page map
72+
* @param page the index of the page to be set
73+
* @retval 0 if page bit is not set
74+
* @retval 1 if page bit is set
75+
*/
76+
static inline int page_allocator_map_get(const uint32_t * const map, uint8_t page)
77+
{
78+
page += UVISOR_PAGE_MAP_COUNT * 32 - g_page_count_total;
79+
return (map[page / 32] >> (page % 32)) & 0x1;
80+
}
4481

4582
#endif /* __PAGE_ALLOCATOR_CONFIG_H__ */

features/FEATURE_UVISOR/source/rtx/secure_allocator.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@
3232
/* offsetof is a gcc built-in function, this is the manual implementation */
3333
#define OFFSETOF(type, member) ((uint32_t) (&(((type *)(0))->member)))
3434

35-
/* Declare this variable here, so the tier-2 allocator _always_ uses the
36-
* page size that the tier-1 allocator expects! */
37-
const uint32_t __uvisor_page_size = UVISOR_PAGE_SIZE;
38-
3935
/* Internal structure currently only contains the page table. */
4036
typedef struct {
4137
UvisorPageTable table;
@@ -71,10 +67,11 @@ SecureAllocator secure_allocator_create_with_pages(
7167
size_t size,
7268
size_t maximum_malloc_size)
7369
{
70+
const uint32_t page_size = uvisor_get_page_size();
7471
/* The rt_Memory allocator puts one MEMP structure at both the
7572
* beginning and end of the memory pool. */
7673
const size_t block_overhead = 2 * sizeof(MEMP);
77-
const size_t page_size_with_overhead = UVISOR_PAGE_SIZE + block_overhead;
74+
const size_t page_size_with_overhead = page_size + block_overhead;
7875
/* Calculate the integer part of required the page count. */
7976
size_t page_count = size / page_size_with_overhead;
8077
/* Add another page if the remainder is not zero. */
@@ -84,7 +81,7 @@ SecureAllocator secure_allocator_create_with_pages(
8481
DPRINTF("secure_allocator_create_with_pages: Requesting %u pages for at least %uB\n", page_count, size);
8582

8683
/* Compute the maximum allocation within our blocks. */
87-
size_t maximum_allocation_size = UVISOR_PAGE_SIZE - block_overhead;
84+
size_t maximum_allocation_size = page_size - block_overhead;
8885
/* If the required maximum allocation is larger than we can provide, abort. */
8986
if (maximum_malloc_size > maximum_allocation_size) {
9087
DPRINTF("secure_allocator_create_with_pages: Maximum allocation request %uB is larger then available %uB\n\n", maximum_malloc_size, maximum_allocation_size);
@@ -104,7 +101,7 @@ SecureAllocator secure_allocator_create_with_pages(
104101
}
105102

106103
/* Prepare the page table. */
107-
allocator->table.page_size = UVISOR_PAGE_SIZE;
104+
allocator->table.page_size = page_size;
108105
allocator->table.page_count = page_count;
109106
/* Get me some pages. */
110107
if (uvisor_page_malloc((UvisorPageTable *) &(allocator->table))) {
@@ -116,7 +113,7 @@ SecureAllocator secure_allocator_create_with_pages(
116113
/* Initialize a MEMP structure in all pages. */
117114
for(size_t ii = 0; ii < page_count; ii++) {
118115
/* Add each page as a pool. */
119-
rt_init_mem(allocator->table.page_origins[ii], UVISOR_PAGE_SIZE);
116+
rt_init_mem(allocator->table.page_origins[ii], page_size);
120117
DPRINTF("secure_allocator_create_with_pages: Created MEMP allocator %p with offset %d\n", allocator->table.page_origins[ii], 0);
121118
}
122119
DPRINTF("\n");

hal/targets/cmsis/TARGET_Freescale/TARGET_MCU_K64F/TOOLCHAIN_GCC_ARM/MK64FN1M0xxx12.ld

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,16 @@ SECTIONS
227227
__uvisor_bss_end = .;
228228
} > m_data
229229

230+
/* Heap space for the page allocator */
231+
.page_heap (NOLOAD) :
232+
{
233+
. = ALIGN(32);
234+
__uvisor_page_start = .;
235+
KEEP(*(.keep.uvisor.page_heap))
236+
. = ALIGN(32);
237+
__uvisor_page_end = .;
238+
} > m_data_2
239+
230240
__VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts);
231241
__RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0;
232242

@@ -325,21 +335,6 @@ SECTIONS
325335
__uvisor_heap_end = .;
326336
} > m_data_2
327337

328-
.stack :
329-
{
330-
. = ALIGN(8);
331-
. += STACK_SIZE;
332-
__StackTop = .;
333-
} > m_data_2
334-
335-
/* Heap space for the page allocator */
336-
.page_heap (NOLOAD) :
337-
{
338-
__uvisor_page_start = .;
339-
. = ORIGIN(m_data_2) + LENGTH(m_data_2) - 4;
340-
__uvisor_page_end = .;
341-
} > m_data_2
342-
343338
m_usb_bdt USB_RAM_START (NOLOAD) :
344339
{
345340
*(m_usb_bdt)
@@ -352,6 +347,7 @@ SECTIONS
352347
}
353348

354349
/* Initializes stack on the end of block */
350+
__StackTop = ORIGIN(m_data_2) + LENGTH(m_data_2);
355351
__StackLimit = __StackTop - STACK_SIZE;
356352
PROVIDE(__stack = __StackTop);
357353

@@ -365,4 +361,3 @@ SECTIONS
365361
__uvisor_sram_start = ORIGIN(m_data);
366362
__uvisor_sram_end = ORIGIN(m_data_2) + LENGTH(m_data_2);
367363
}
368-

rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -421,12 +421,8 @@ osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 1U,
421421
#define INITIAL_SP (0x20003000UL)
422422

423423
#elif defined(TARGET_K64F)
424-
#if defined(__GNUC__) && !defined(__CC_ARM) /* GCC */
425-
extern uint32_t __StackTop[];
426-
#define INITIAL_SP (__StackTop)
427-
#else
428424
#define INITIAL_SP (0x20030000UL)
429-
#endif
425+
430426
#if defined(__CC_ARM) || defined(__GNUC__)
431427
#define ISR_STACK_SIZE (0x1000)
432428
#endif

0 commit comments

Comments
 (0)