1/* 2 * Copyright 2016, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(D61_BSD) 11 */ 12 13/*! @file 14 @brief Top-level main module for process server. 15 16 The top level main module of the process server, containing the main function which runs as 17 the initial kernel thread. This function starts up the process server, bootstraps itself, initialises the 18 submodules, and starts the rest of system. 19 20 The process server is responsible for implementing threads and processes, managing memory window 21 segments, exposing anonymous memory dataspaces, and handing off other system resources to the available system 22 processes (such as device and IRQ caps device servers). 23 24 @image html procserv.png 25 26 The process server's anonymous dataspace implementation: 27 <ul> 28 <li>Assumes the connection session is set up, so therefore does not support connection 29 establishment.</li> 30 <li>Ignores the fileName parameter of the open method; makes no sense for anon memory.</li> 31 <li>Reads the nBytes parameter of the open method, as the maximum size of the ram dataspace 32 created. </li> 33 <li>Does NOT implement set_parambuffer, it shares the parambuffer from procserv interface 34 and reads that instead. </li> 35 <li>Supports the parambuffer (set in the procserv interface) coming from a ram dataspace 36 provided by the process server itself. </li> 37 <li>Does not support content initialisation via init_data. Process server cannot provide 38 content for another dataserver in the current implementation.</li> 39 <li>Does support have_data and provide_data. In other words, process server RAM dataspace 40 can have its content initialised by an external dataserver.</li> 41 </ul> 42*/ 43 44#include <stdio.h> 45#include <stdlib.h> 46#include <assert.h> 47 48#include <sel4platsupport/bootinfo.h> 49 50#include "common.h" 51#include "state.h" 52#include "test/test.h" 53#include "dispatchers/proc_syscall.h" 54#include "dispatchers/mem_syscall.h" 55#include "dispatchers/data_syscall.h" 56#include "dispatchers/name_syscall.h" 57#include "dispatchers/fault_handler.h" 58#include "system/process/process.h" 59 60/*! @brief Process server IPC message handler. 61 62 Handles dispatching of all process server IPC messages. Calls each individual dispatcher until 63 the correct dispatcher for the message type has been found. 64 65 @param s The process server global state. 66 @param msg The process server recieved message info. 67 */ 68static void 69proc_server_handle_message(struct procserv_state *s, struct procserv_msg *msg) 70{ 71 int result; 72 int label = seL4_GetMR(0); 73 void *userptr = NULL; 74 (void) result; 75 76 /* Attempt to dispatch to procserv syscall dispatcher. */ 77 if (check_dispatch_syscall(msg, &userptr) == DISPATCH_SUCCESS) { 78 result = rpc_sv_proc_dispatcher(userptr, label); 79 assert(result == DISPATCH_SUCCESS); 80 mem_syscall_postaction(); 81 proc_syscall_postaction(); 82 return; 83 } 84 85 /* Attempt to dispatch to VM fault dispatcher. */ 86 if (check_dispatch_fault(msg, &userptr) == DISPATCH_SUCCESS) { 87 result = dispatch_vm_fault(msg, &userptr); 88 assert(result == DISPATCH_SUCCESS); 89 return; 90 } 91 92 /* Attempt to dispatch to RAM dataspace syscall dispatcher. */ 93 if (check_dispatch_dataspace(msg, &userptr) == DISPATCH_SUCCESS) { 94 result = rpc_sv_data_dispatcher(userptr, label); 95 assert(result == DISPATCH_SUCCESS); 96 mem_syscall_postaction(); 97 return; 98 } 99 100 /* Attempt to dispatch to nameserv syscall dispatcher. */ 101 if (check_dispatch_nameserv(msg, &userptr) == DISPATCH_SUCCESS) { 102 result = rpc_sv_name_dispatcher(userptr, label); 103 assert(result == DISPATCH_SUCCESS); 104 return; 105 } 106 107 /* Unknown message. Block calling client indefinitely. */ 108 dprintf("Unknown message (badge = %d msgInfo = %d syscall = 0x%x).\n", 109 msg->badge, seL4_MessageInfo_get_label(msg->message), label); 110 ROS_ERROR("Process server unknown message. �����(��_o)/��"); 111} 112 113/*! @brief Main process server loop. 114 115 The main loop that the process server goes into and keeps looping until the process server 116 is to exit and the whole system is to by shut down (which is possibly never). It blocks on the 117 process server endpoint and waits for an IPC message, and then handles the dispatching of 118 the message when it recieves one, before looping around and waiting for the next IPC message. 119 120 @return Does not return, runs endlessly. 121*/ 122static int 123proc_server_loop(void) 124{ 125 struct procserv_state *s = &procServ; 126 struct procserv_msg msg = { .state = s }; 127 128 while (1) { 129 dvprintf("procserv blocking for new message...\n"); 130 msg.message = seL4_Recv(s->endpoint.cptr, &msg.badge); 131 proc_server_handle_message(s, &msg); 132 s->faketime++; 133 } 134 135 return 0; 136} 137 138/*! @brief Process server main entry point. */ 139int 140main(void) 141{ 142 initialise(platsupport_get_bootinfo(), &procServ); 143 dprintf("======== RefOS Process Server ========\n"); 144 145 // -----> Run Root Task Testing. 146 #ifdef CONFIG_REFOS_RUN_TESTS 147 test_run_all(); 148 #endif 149 150 // -----> Start RefOS system processes. 151 int error; 152 153 error = proc_load_direct("console_server", 252, "", PID_NULL, 154 PROCESS_PERMISSION_DEVICE_IRQ | PROCESS_PERMISSION_DEVICE_MAP | 155 PROCESS_PERMISSION_DEVICE_IOPORT); 156 if (error) { 157 ROS_WARNING("Procserv could not start console_server."); 158 assert(!"RefOS system startup error."); 159 } 160 161 error = proc_load_direct("file_server", 250, "", PID_NULL, 0x0); 162 if (error) { 163 ROS_WARNING("Procserv could not start file_server."); 164 assert(!"RefOS system startup error."); 165 } 166 167 // -----> Start OS level tests. 168 #ifdef CONFIG_REFOS_RUN_TESTS 169 error = proc_load_direct("test_os", 245, "", PID_NULL, 0x0); 170 if (error) { 171 ROS_WARNING("Procserv could not start test_os."); 172 assert(!"RefOS system startup error."); 173 } 174 #endif 175 176 // -----> Start RefOS timer server. 177 error = proc_load_direct("selfloader", 245, "fileserv/timer_server", PID_NULL, 178 PROCESS_PERMISSION_DEVICE_IRQ | PROCESS_PERMISSION_DEVICE_MAP | 179 PROCESS_PERMISSION_DEVICE_IOPORT); 180 if (error) { 181 ROS_WARNING("Procserv could not start timer_server."); 182 assert(!"RefOS system startup error."); 183 } 184 185 // -----> Start initial task. 186 if (strlen(CONFIG_REFOS_INIT_TASK) > 0) { 187 error = proc_load_direct("selfloader", CONFIG_REFOS_INIT_TASK_PRIO, CONFIG_REFOS_INIT_TASK, 188 PID_NULL, 0x0); 189 if (error) { 190 ROS_WARNING("Procserv could not start initial task."); 191 assert(!"RefOS system startup error."); 192 } 193 } 194 195 return proc_server_loop(); 196} 197