Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions platform/mbed_retarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,9 @@ extern "C" void PREFIX(_exit)(int return_code) {
}

extern "C" void _ttywrch(int ch) {
#if DEVICE_SERIAL
serial_putc(&stdio_uart, ch);
#endif
}
#endif

Expand Down Expand Up @@ -734,6 +736,7 @@ extern "C" int errno;

// Dynamic memory allocation related syscall.
#if defined(TARGET_NUVOTON)

// Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
// __wrap__sbrk() is implemented in:
// TARGET_NUMAKER_PFM_NUC472 targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/nuc472_retarget.c
Expand Down
27 changes: 26 additions & 1 deletion platform/mbed_sdk_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,39 @@
*/
#if !defined(MBED_CONF_RTOS_PRESENT)

#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
/* call_non_secure_rtos is function for v8 architecture to switch to non-secure
* reset handler. Called by secure application main.
*/
typedef void (*non_secure_call) (void) __attribute__((cmse_nonsecure_call));
void call_non_secure_rtos(void)
{
#ifdef TZ_START_NS
non_secure_call ns_reset_handler;

/* Set non-secure main stack (MSP_NS) */
#if defined(__ICCARM__)
asm volatile("MSR SP_NS, %0" :: "r" (*((uint32_t *)(TZ_START_NS))));
#else
__TZ_set_MSP_NS(*((uint32_t *)(TZ_START_NS)));
#endif
/* Get non-secure reset handler */
ns_reset_handler = (non_secure_call)(*((uint32_t *)((TZ_START_NS) + 4U)));
/* Start non-secure state software application */
ns_reset_handler();
#endif
}
#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
* mbed_main(), it is not meant for user code, but for the SDK itself to perform
* initializations before main() is called.
*/
MBED_WEAK void mbed_main(void)
{

#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
call_non_secure_rtos();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this change main of secure thread will never be called, any initialization required needs to be done in mbed_sdk_init.

#endif
}

/* This function can be implemented by the target to perform higher level target initialization
Expand Down
200 changes: 200 additions & 0 deletions platform/mbed_tz_context.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-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.
*/

#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)

#include "cmsis.h"
#include "mbed_rtx.h"
#include "tz_context.h"


/// Number of process slots (threads may call secure library code)
#ifndef TZ_PROCESS_STACK_SLOTS
#define TZ_PROCESS_STACK_SLOTS 8U
#endif

/// Stack size of the secure library code
#ifndef TZ_PROCESS_STACK_SIZE
#define TZ_PROCESS_STACK_SIZE 512U
#endif

typedef struct {
uint32_t sp_top; // stack space top
uint32_t sp_limit; // stack space limit
uint32_t sp; // current stack pointer
} stack_info_t;

static stack_info_t ProcessStackInfo [TZ_PROCESS_STACK_SLOTS];
static uint64_t ProcessStackMemory[TZ_PROCESS_STACK_SLOTS][TZ_PROCESS_STACK_SIZE/8U];
static uint32_t ProcessStackFreeSlot = 0xFFFFFFFFU;


/// Initialize secure context memory system
/// \return execution status (1: success, 0: error)
__attribute__((cmse_nonsecure_entry))
uint32_t TZ_InitContextSystem_S (void)
{
uint32_t n;

if (__get_IPSR() == 0U) {
return 0U; // Thread Mode
}

for (n = 0U; n < TZ_PROCESS_STACK_SLOTS; n++) {
ProcessStackInfo[n].sp = 0U;
ProcessStackInfo[n].sp_limit = (uint32_t)&ProcessStackMemory[n];
ProcessStackInfo[n].sp_top = (uint32_t)&ProcessStackMemory[n] + TZ_PROCESS_STACK_SIZE;
*((uint32_t *)ProcessStackMemory[n]) = n + 1U;
}
*((uint32_t *)ProcessStackMemory[--n]) = 0xFFFFFFFFU;

ProcessStackFreeSlot = 0U;

// Default process stack pointer and stack limit
__set_PSPLIM ((uint32_t)ProcessStackMemory);
__set_PSP ((uint32_t)ProcessStackMemory);

// Privileged Thread Mode using PSP
__set_CONTROL(0x02U);

return 1U; // Success
}


/// Allocate context memory for calling secure software modules in TrustZone
/// \param[in] module identifies software modules called from non-secure mode
/// \return value != 0 id TrustZone memory slot identifier
/// \return value 0 no memory available or internal error
__attribute__((cmse_nonsecure_entry))
TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module)
{
uint32_t slot;

(void)module; // Ignore (fixed Stack size)

if (__get_IPSR() == 0U) {
return 0U; // Thread Mode
}

if (ProcessStackFreeSlot == 0xFFFFFFFFU) {
return 0U; // No slot available
}

slot = ProcessStackFreeSlot;
ProcessStackFreeSlot = *((uint32_t *)ProcessStackMemory[slot]);

ProcessStackInfo[slot].sp = ProcessStackInfo[slot].sp_top;

return (slot + 1U);
}

/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
__attribute__((cmse_nonsecure_entry))
uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id)
{
uint32_t slot;

if (__get_IPSR() == 0U) {
return 0U; // Thread Mode
}

if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
return 0U; // Invalid ID
}

slot = id - 1U;

if (ProcessStackInfo[slot].sp == 0U) {
return 0U; // Inactive slot
}
ProcessStackInfo[slot].sp = 0U;

*((uint32_t *)ProcessStackMemory[slot]) = ProcessStackFreeSlot;
ProcessStackFreeSlot = slot;

return 1U; // Success
}


/// Load secure context (called on RTOS thread context switch)
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
__attribute__((cmse_nonsecure_entry))
uint32_t TZ_LoadContext_S (TZ_MemoryId_t id)
{
uint32_t slot;

if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) {
return 0U; // Thread Mode or using Main Stack for threads
}

if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
return 0U; // Invalid ID
}

slot = id - 1U;

if (ProcessStackInfo[slot].sp == 0U) {
return 0U; // Inactive slot
}

// Setup process stack pointer and stack limit
__set_PSPLIM(ProcessStackInfo[slot].sp_limit);
__set_PSP (ProcessStackInfo[slot].sp);

return 1U; // Success
}


/// Store secure context (called on RTOS thread context switch)
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
__attribute__((cmse_nonsecure_entry))
uint32_t TZ_StoreContext_S (TZ_MemoryId_t id)
{
uint32_t slot;
uint32_t sp;

if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) {
return 0U; // Thread Mode or using Main Stack for threads
}

if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
return 0U; // Invalid ID
}

slot = id - 1U;

if (ProcessStackInfo[slot].sp == 0U) {
return 0U; // Inactive slot
}

sp = __get_PSP();
if ((sp < ProcessStackInfo[slot].sp_limit) ||
(sp > ProcessStackInfo[slot].sp_top)) {
return 0U; // SP out of range
}
ProcessStackInfo[slot].sp = sp;

// Default process stack pointer and stack limit
__set_PSPLIM((uint32_t)ProcessStackMemory);
__set_PSP ((uint32_t)ProcessStackMemory);

return 1U; // Success
}
#endif
6 changes: 6 additions & 0 deletions rtos/TARGET_CORTEX/mbed_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ void mbed_start_main(void)
_main_thread_attr.cb_mem = &_main_obj;
_main_thread_attr.priority = osPriorityNormal;
_main_thread_attr.name = "main_thread";

/* Allow main thread to call secure functions */
#if (__DOMAIN_NS == 1U)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this always defined (shouldn't this check first if its defined then its value) ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is always defined in

#ifndef __DOMAIN_NS

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't worry about it for this PR, but this file is becoming unreadable with more ifdefs than anything else, we should find better way of doing this.

_main_thread_attr.tz_module = 1U;
#endif

osThreadId_t result = osThreadNew((osThreadFunc_t)pre_main, NULL, &_main_thread_attr);
if ((void *)result == NULL) {
error("Pre main thread not created");
Expand Down
18 changes: 18 additions & 0 deletions rtos/TARGET_CORTEX/mbed_rtx_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,22 @@
# define OS_PRIVILEGE_MODE 0
#endif

#define OS_SECURE_CALLABLE_THREAD 1

#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)

/* Number of process slots (threads may call secure library code) */
#ifndef MBED_CONF_APP_TZ_PROCESS_STACK_SLOTS
#define MBED_CONF_APP_TZ_PROCESS_STACK_SLOTS 8U
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why 8? Can we document that

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally it should be number of threads we allow in mbed-os. (Considering all of them have access to secure library). Or do we want to restrict threads from using secure library?

#endif

/* Stack size of the secure library code */
#ifndef MBED_CONF_APP_TZ_PROCESS_STACK_SIZE
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this stack for exactly?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is stack for NSC region. i.e Secure library code executed from non-secure process.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth extending the comment ? Are we using code defaults instead of config - (this could be in the config file set, always present if not overriden) ? All in one place, this can however be fixed, as we already have this mbed_rtx_conf.h file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0xc0170 - In case of secure build, we ignore rtos (mbed_rtx_conf.h) hence I am exploring other correct options to update this flag.

#define MBED_CONF_APP_TZ_PROCESS_STACK_SIZE 512U
#endif

#define TZ_PROCESS_STACK_SLOTS MBED_CONF_APP_TZ_PROCESS_STACK_SLOTS
#define TZ_PROCESS_STACK_SIZE MBED_CONF_APP_TZ_PROCESS_STACK_SIZE
#endif

#endif /* MBED_RTX_CONF_H */
Loading