Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers box_init.c Source File

box_init.c

00001 /*
00002  * Copyright (c) 2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #include "uvisor-lib/uvisor-lib.h"
00018 #include "api/inc/pool_queue_exports.h"
00019 #include "api/inc/rpc_exports.h"
00020 #include "api/inc/uvisor_semaphore.h"
00021 #include "api/inc/box_config.h"
00022 #include "mbed_interface.h"
00023 #include "cmsis_os2.h"
00024 #include <stdint.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 
00028 /* Register the OS with uVisor */
00029 extern void SVC_Handler(void);
00030 extern void PendSV_Handler(void);
00031 extern void SysTick_Handler(void);
00032 extern int32_t svcRtxKernelLock(void);
00033 
00034 UVISOR_SET_PRIV_SYS_HOOKS(SVC_Handler, PendSV_Handler, SysTick_Handler, svcRtxKernelLock, __uvisor_semaphore_post);
00035 
00036 extern RtxBoxIndex * const __uvisor_ps;
00037 
00038 void __uvisor_initialize_rpc_queues(void)
00039 {
00040 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
00041     // TODO Initialize RPC queues on ARMv8-M (via uvisor_start).
00042     return;
00043 #endif
00044 
00045     UvisorBoxIndex * const index = &__uvisor_ps->index;
00046 
00047     uvisor_pool_slot_t i;
00048 
00049     uvisor_rpc_outgoing_message_queue_t * rpc_outgoing_msg_queue = &(uvisor_rpc(index)->outgoing_message_queue);
00050     uvisor_rpc_incoming_message_queue_t * rpc_incoming_msg_queue = &(uvisor_rpc(index)->incoming_message_queue);
00051     uvisor_rpc_fn_group_queue_t * rpc_fn_group_queue = &(uvisor_rpc(index)->fn_group_queue);
00052 
00053     /* Initialize the outgoing RPC message queue. */
00054     if (uvisor_pool_queue_init(&rpc_outgoing_msg_queue->queue,
00055                                &rpc_outgoing_msg_queue->pool,
00056                                rpc_outgoing_msg_queue->messages,
00057                                sizeof(*rpc_outgoing_msg_queue->messages),
00058                                UVISOR_RPC_OUTGOING_MESSAGE_SLOTS)) {
00059         uvisor_error(USER_NOT_ALLOWED);
00060     }
00061 
00062     /* Initialize all the result semaphores. */
00063     for (i = 0; i < UVISOR_RPC_OUTGOING_MESSAGE_SLOTS; i++) {
00064         UvisorSemaphore * semaphore = &rpc_outgoing_msg_queue->messages[i].semaphore;
00065         if (__uvisor_semaphore_init(semaphore, 1, 0)) {
00066             uvisor_error(USER_NOT_ALLOWED);
00067         }
00068     }
00069 
00070     /* Initialize the incoming RPC message queues. */
00071     if (uvisor_pool_queue_init(&rpc_incoming_msg_queue->todo_queue,
00072                                &rpc_incoming_msg_queue->pool,
00073                                rpc_incoming_msg_queue->messages,
00074                                sizeof(*rpc_incoming_msg_queue->messages),
00075                                UVISOR_RPC_INCOMING_MESSAGE_SLOTS)) {
00076         uvisor_error(USER_NOT_ALLOWED);
00077     }
00078     /* This is a double init of the pool. We need a function that just inits
00079      * the queue, not the pool, and init everybody separately. */
00080     if (uvisor_pool_queue_init(&rpc_incoming_msg_queue->done_queue,
00081                                &rpc_incoming_msg_queue->pool,
00082                                rpc_incoming_msg_queue->messages,
00083                                sizeof(*rpc_incoming_msg_queue->messages),
00084                                UVISOR_RPC_INCOMING_MESSAGE_SLOTS)) {
00085         uvisor_error(USER_NOT_ALLOWED);
00086     }
00087 
00088     /* Initialize the function group pool. */
00089     if (uvisor_pool_queue_init(&rpc_fn_group_queue->queue,
00090                                &rpc_fn_group_queue->pool,
00091                                rpc_fn_group_queue->fn_groups,
00092                                sizeof(*rpc_fn_group_queue->fn_groups),
00093                                UVISOR_RPC_FN_GROUP_SLOTS)) {
00094         uvisor_error(USER_NOT_ALLOWED);
00095     }
00096 
00097     /* Initialize all the function group semaphores. */
00098     for (i = 0; i < UVISOR_RPC_FN_GROUP_SLOTS; i++) {
00099         UvisorSemaphore * semaphore = &rpc_fn_group_queue->fn_groups[i].semaphore;
00100         if (__uvisor_semaphore_init(semaphore, 1, 0)) {
00101             uvisor_error(USER_NOT_ALLOWED);
00102         }
00103     }
00104 }
00105 
00106 /* This function is called by uVisor in unprivileged mode. On this OS, we
00107  * create box main threads for the box. */
00108 void __uvisor_lib_box_init(void * lib_config)
00109 {
00110     osThreadId_t thread_id;
00111     uvisor_box_main_t * box_main = lib_config;
00112     osThreadAttr_t thread_attr = { 0 };
00113 
00114     __uvisor_initialize_rpc_queues();
00115 
00116     thread_attr.name = "uvisor_box_main_thread";
00117     thread_attr.priority = box_main->priority;
00118     thread_attr.stack_size = box_main->stack_size;
00119 
00120     /* Note that the box main thread stack is separate from the box stack. This
00121      * is because the thread must be created to use a different stack than the
00122      * stack osCreateThread() is called from, as context information is saved
00123      * to the thread stack by the call to osCreateThread(). */
00124     /* Allocate memory for the main thread from the box heap. This memory is
00125      * never freed, even if the box's main thread exits. */
00126     thread_attr.stack_mem = malloc(thread_attr.stack_size);
00127     if (thread_attr.stack_mem == NULL) {
00128         /* No process heap memory available for thread stack */
00129         uvisor_error(USER_NOT_ALLOWED);
00130     }
00131 
00132     /* Allocate memory for the main thread control block from the box heap.
00133      * This memory is never freed, even if the box's main thread exits. */
00134     thread_attr.cb_size = sizeof(osRtxThread_t);
00135     thread_attr.cb_mem = malloc(thread_attr.cb_size);
00136     if (thread_attr.cb_mem == NULL) {
00137         /* No process heap memory available for thread control block. */
00138         uvisor_error(USER_NOT_ALLOWED);
00139     }
00140 
00141     thread_id = osThreadNew((osThreadFunc_t) box_main->function, NULL, &thread_attr);
00142 
00143     if (thread_id == NULL) {
00144         /* Failed to create thread */
00145         uvisor_error(USER_NOT_ALLOWED);
00146     }
00147 }