Knight KE / Mbed OS Game_Master
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 "api/inc/uvisor_deprecation.h"
00023 #include "mbed_interface.h"
00024 #include "cmsis_os2.h"
00025 #include <stdint.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 /* Register the OS with uVisor */
00030 extern void SVC_Handler(void);
00031 extern void PendSV_Handler(void);
00032 extern void SysTick_Handler(void);
00033 extern int32_t svcRtxKernelLock(void);
00034 
00035 UVISOR_SET_PRIV_SYS_HOOKS(SVC_Handler, PendSV_Handler, SysTick_Handler, svcRtxKernelLock, __uvisor_semaphore_post);
00036 
00037 extern RtxBoxIndex * const __uvisor_ps;
00038 
00039 void __uvisor_initialize_rpc_queues(void)
00040 {
00041 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
00042     // TODO Initialize RPC queues on ARMv8-M (via uvisor_start).
00043     return;
00044 #endif
00045 
00046     UvisorBoxIndex * const index = &__uvisor_ps->index;
00047 
00048     uvisor_pool_slot_t i;
00049 
00050     uvisor_rpc_outgoing_message_queue_t * rpc_outgoing_msg_queue = &(uvisor_rpc(index)->outgoing_message_queue);
00051     uvisor_rpc_incoming_message_queue_t * rpc_incoming_msg_queue = &(uvisor_rpc(index)->incoming_message_queue);
00052     uvisor_rpc_fn_group_queue_t * rpc_fn_group_queue = &(uvisor_rpc(index)->fn_group_queue);
00053 
00054     /* Initialize the outgoing RPC message queue. */
00055     if (uvisor_pool_queue_init(&rpc_outgoing_msg_queue->queue,
00056                                &rpc_outgoing_msg_queue->pool,
00057                                rpc_outgoing_msg_queue->messages,
00058                                sizeof(*rpc_outgoing_msg_queue->messages),
00059                                UVISOR_RPC_OUTGOING_MESSAGE_SLOTS)) {
00060         uvisor_error(USER_NOT_ALLOWED);
00061     }
00062 
00063     /* Initialize all the result semaphores. */
00064     for (i = 0; i < UVISOR_RPC_OUTGOING_MESSAGE_SLOTS; i++) {
00065         UvisorSemaphore * semaphore = &rpc_outgoing_msg_queue->messages[i].semaphore;
00066         if (__uvisor_semaphore_init(semaphore, 1, 0)) {
00067             uvisor_error(USER_NOT_ALLOWED);
00068         }
00069     }
00070 
00071     /* Initialize the incoming RPC message queues. */
00072     if (uvisor_pool_queue_init(&rpc_incoming_msg_queue->todo_queue,
00073                                &rpc_incoming_msg_queue->pool,
00074                                rpc_incoming_msg_queue->messages,
00075                                sizeof(*rpc_incoming_msg_queue->messages),
00076                                UVISOR_RPC_INCOMING_MESSAGE_SLOTS)) {
00077         uvisor_error(USER_NOT_ALLOWED);
00078     }
00079     /* This is a double init of the pool. We need a function that just inits
00080      * the queue, not the pool, and init everybody separately. */
00081     if (uvisor_pool_queue_init(&rpc_incoming_msg_queue->done_queue,
00082                                &rpc_incoming_msg_queue->pool,
00083                                rpc_incoming_msg_queue->messages,
00084                                sizeof(*rpc_incoming_msg_queue->messages),
00085                                UVISOR_RPC_INCOMING_MESSAGE_SLOTS)) {
00086         uvisor_error(USER_NOT_ALLOWED);
00087     }
00088 
00089     /* Initialize the function group pool. */
00090     if (uvisor_pool_queue_init(&rpc_fn_group_queue->queue,
00091                                &rpc_fn_group_queue->pool,
00092                                rpc_fn_group_queue->fn_groups,
00093                                sizeof(*rpc_fn_group_queue->fn_groups),
00094                                UVISOR_RPC_FN_GROUP_SLOTS)) {
00095         uvisor_error(USER_NOT_ALLOWED);
00096     }
00097 
00098     /* Initialize all the function group semaphores. */
00099     for (i = 0; i < UVISOR_RPC_FN_GROUP_SLOTS; i++) {
00100         UvisorSemaphore * semaphore = &rpc_fn_group_queue->fn_groups[i].semaphore;
00101         if (__uvisor_semaphore_init(semaphore, 1, 0)) {
00102             uvisor_error(USER_NOT_ALLOWED);
00103         }
00104     }
00105 }
00106 
00107 /* This function is called by uVisor in unprivileged mode. On this OS, we
00108  * create box main threads for the box. */
00109 void __uvisor_lib_box_init(void * lib_config)
00110 {
00111     osThreadId_t thread_id;
00112     uvisor_box_main_t * box_main = lib_config;
00113     osThreadAttr_t thread_attr = { 0 };
00114 
00115     __uvisor_initialize_rpc_queues();
00116 
00117     thread_attr.name = "uvisor_box_main_thread";
00118     thread_attr.priority = box_main->priority;
00119     thread_attr.stack_size = box_main->stack_size;
00120 
00121     /* Note that the box main thread stack is separate from the box stack. This
00122      * is because the thread must be created to use a different stack than the
00123      * stack osCreateThread() is called from, as context information is saved
00124      * to the thread stack by the call to osCreateThread(). */
00125     /* Allocate memory for the main thread from the box heap. This memory is
00126      * never freed, even if the box's main thread exits. */
00127     thread_attr.stack_mem = malloc(thread_attr.stack_size);
00128     if (thread_attr.stack_mem == NULL) {
00129         /* No process heap memory available for thread stack */
00130         uvisor_error(USER_NOT_ALLOWED);
00131     }
00132 
00133     /* Allocate memory for the main thread control block from the box heap.
00134      * This memory is never freed, even if the box's main thread exits. */
00135     thread_attr.cb_size = sizeof(osRtxThread_t);
00136     thread_attr.cb_mem = malloc(thread_attr.cb_size);
00137     if (thread_attr.cb_mem == NULL) {
00138         /* No process heap memory available for thread control block. */
00139         uvisor_error(USER_NOT_ALLOWED);
00140     }
00141 
00142     thread_id = osThreadNew((osThreadFunc_t) box_main->function, NULL, &thread_attr);
00143 
00144     if (thread_id == NULL) {
00145         /* Failed to create thread */
00146         uvisor_error(USER_NOT_ALLOWED);
00147     }
00148 }