1/** 2 * \file 3 * \brief init process. 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include "init.h" 16#include <stdlib.h> 17#include <trace/trace.h> 18#include <barrelfish/morecore.h> 19#include <barrelfish/dispatcher_arch.h> 20#include <barrelfish/lmp_chan.h> 21 22static coreid_t my_core_id; 23 24#if defined(__k1om__) 25# define MONITOR_NAME BF_BINARY_PREFIX "k1om/sbin/monitor" 26# define MEM_SERV_NAME BF_BINARY_PREFIX "k1om/sbin/mem_serv" 27#elif defined(__x86_64__) 28# define MONITOR_NAME BF_BINARY_PREFIX "x86_64/sbin/monitor" 29# define MEM_SERV_NAME BF_BINARY_PREFIX "x86_64/sbin/mem_serv" 30#elif defined(__i386__) 31# define MONITOR_NAME BF_BINARY_PREFIX "x86_32/sbin/monitor" 32# define MEM_SERV_NAME BF_BINARY_PREFIX "x86_32/sbin/mem_serv" 33#elif defined(__ARM_ARCH_7A__) 34# define MONITOR_NAME BF_BINARY_PREFIX "armv7/sbin/monitor" 35# define MEM_SERV_NAME BF_BINARY_PREFIX "armv7/sbin/mem_serv" 36#elif defined(__ARM_ARCH_8A__) 37# define MONITOR_NAME BF_BINARY_PREFIX "armv8/sbin/monitor" 38# define MEM_SERV_NAME BF_BINARY_PREFIX "armv8/sbin/mem_serv" 39#else 40# error Unknown architecture 41#endif 42 43const char *multiboot_strings; 44 45struct bootinfo *bi; 46 47/// Channels to monitor and mem_serv 48static struct lmp_chan monitor_chan, mem_serv_chan; 49 50/// State of caps received from monitor and mem_serv 51static struct { 52 int pos; 53 bool done; 54} recv_state; 55 56/* handler function that runs when we get a message from either the mem_serv or 57 * monitor channels. once we've received caps from both, we send them to each 58 * other's opposite to allow them to construct a proper point-to-point channel 59 */ 60static void init_recv_handler(void *arg) 61{ 62 struct lmp_chan *lc = arg; 63 struct lmp_recv_msg msg = LMP_RECV_MSG_INIT; 64 struct capref cap; 65 errval_t err; 66 67 err = lmp_chan_recv(lc, &msg, &cap); 68 if (err_is_fail(err)) { 69 if (lmp_err_is_transient(err)) { 70 // re-register 71 struct event_closure recv_handler = { 72 .handler = init_recv_handler, 73 .arg = arg, 74 }; 75 struct waitset *ws = get_default_waitset(); 76 err = lmp_chan_register_recv(lc, ws, recv_handler); 77 if (err_is_fail(err)) { 78 DEBUG_ERR(err, "in lmp_chan_register_recv"); 79 abort(); 80 } 81 } else { 82 DEBUG_ERR(err, "in lmp_chan_recv"); 83 abort(); 84 } 85 } 86 87 assert(!capref_is_null(cap)); 88 assert(recv_state.pos < 2); 89 90 // store cap 91 lc->remote_cap = cap; 92 93 // if we now have both caps, send them to each other 94 if (++recv_state.pos == 2) { 95 err = lmp_chan_send0(&monitor_chan, 0, mem_serv_chan.remote_cap); 96 if (err_is_fail(err)) { 97 DEBUG_ERR(err, "sending cap to monitor"); 98 abort(); 99 } 100 101 err = lmp_chan_send0(&mem_serv_chan, 0, monitor_chan.remote_cap); 102 if (err_is_fail(err)) { 103 DEBUG_ERR(err, "sending cap to mem_serv"); 104 abort(); 105 } 106 107 recv_state.done = true; 108 } 109} 110 111/** 112 * \brief Spawn essential initial domains. 113 */ 114static errval_t bootstrap(int argc, char *argv[]) 115{ 116 errval_t err; 117 118 /* Initialize tracing */ 119 err = trace_init(); 120 if (err_is_fail(err)) { 121 DEBUG_ERR(err, "error initializing trace buffer"); 122 printf("Warning: tracing not available\n"); 123 } 124 #if defined(CONFIG_TRACE) 125 err = trace_my_setup(); 126 if (err_is_fail(err)) { 127 DEBUG_ERR(err, "error setting up tracing in init"); 128 printf("Warning: tracing not available\n"); 129 } else { 130 // Initialize the pointers 131 trace_reset_all(); 132 // Enable all subsystems by default. 133 trace_set_all_subsys_enabled(true); 134 } 135 #endif 136 137 /* Load mem_serv */ 138 printf("Spawning memory server (%s)...\n", MEM_SERV_NAME); 139 struct spawninfo mem_serv_si; 140 err = spawn_load_with_bootinfo(&mem_serv_si, bi, MEM_SERV_NAME, my_core_id); 141 if (err_is_fail(err)) { 142 return err_push(err, INIT_ERR_SPAWN_MEM_SERV); 143 } 144 145 /* Initialize mem_serv */ 146 err = initialize_mem_serv(&mem_serv_si); 147 if (err_is_fail(err)) { 148 return err_push(err, INIT_ERR_INIT_MEM_SERV); 149 } 150 151 /* Load monitor */ 152 printf("Spawning monitor (%s)...\n", MONITOR_NAME); 153 struct spawninfo monitor_si; 154 err = spawn_load_with_bootinfo(&monitor_si, bi, MONITOR_NAME, my_core_id); 155 if (err_is_fail(err)) { 156 return err_push(err, INIT_ERR_SPAWN_MONITOR); 157 } 158 159 /* unmap bootinfo mem */ 160 err = multiboot_cleanup_mapping(); 161 if (err_is_fail(err)) { 162 //return err_push(err, INIT_ERR_UNMAP_BOOTINFO); 163 return err; 164 } 165 166 /* Initialize monitor */ 167 err = initialize_monitor(&monitor_si); 168 if (err_is_fail(err)) { 169 return err_push(err, INIT_ERR_INIT_MONITOR); 170 } 171 172 // Allocate an incoming LMP endpoint for each spawned domain 173 err = lmp_chan_accept(&monitor_chan, DEFAULT_LMP_BUF_WORDS, NULL_CAP); 174 if (err_is_fail(err)) { 175 return err_push(err, INIT_ERR_SETUP_MONITOR_CHAN); 176 } 177 178 err = lmp_chan_alloc_recv_slot(&monitor_chan); 179 if (err_is_fail(err)) { 180 return err_push(err, LIB_ERR_LMP_ALLOC_RECV_SLOT); 181 } 182 183 err = lmp_chan_accept(&mem_serv_chan, DEFAULT_LMP_BUF_WORDS, NULL_CAP); 184 if (err_is_fail(err)) { 185 return err_push(err, INIT_ERR_SETUP_MEM_SERV_CHAN); 186 } 187 188 err = lmp_chan_alloc_recv_slot(&mem_serv_chan); 189 if (err_is_fail(err)) { 190 return err_push(err, LIB_ERR_LMP_ALLOC_RECV_SLOT); 191 } 192 193 // Register receive handlers for these channels 194 struct waitset *ws = get_default_waitset(); 195 196 struct event_closure recv_handler = { 197 .handler = init_recv_handler, 198 .arg = &monitor_chan, 199 }; 200 err = lmp_chan_register_recv(&monitor_chan, ws, recv_handler); 201 if (err_is_fail(err)) { 202 return err_push(err, LIB_ERR_CHAN_REGISTER_RECV); 203 } 204 205 recv_handler.arg = &mem_serv_chan; 206 err = lmp_chan_register_recv(&mem_serv_chan, ws, recv_handler); 207 if (err_is_fail(err)) { 208 return err_push(err, LIB_ERR_CHAN_REGISTER_RECV); 209 } 210 211 /* Give EP to monitor */ 212 struct capref cap_dest; 213 cap_dest.cnode = monitor_si.taskcn; 214 cap_dest.slot = TASKCN_SLOT_INITEP; 215 err = cap_copy(cap_dest, monitor_chan.local_cap); 216 if (err_is_fail(err)) { 217 return err_push(err, INIT_ERR_COPY_EP_TO_MEM_SERV); 218 } 219 220 /* Give EP to mem_serv */ 221 cap_dest.cnode = mem_serv_si.taskcn; 222 cap_dest.slot = TASKCN_SLOT_INITEP; 223 err = cap_copy(cap_dest, mem_serv_chan.local_cap); 224 if (err_is_fail(err)) { 225 return err_push(err, INIT_ERR_COPY_EP_TO_MONITOR); 226 } 227 228 /* Make monitor runnable */ 229 err = spawn_run(&monitor_si); 230 if (err_is_fail(err)) { 231 return err_push(err, INIT_ERR_RUN_MONITOR); 232 } 233 234 /* Make mem_serv runnable */ 235 err = spawn_run(&mem_serv_si); 236 if (err_is_fail(err)) { 237 return err_push(err, INIT_ERR_RUN_MEM_SERV); 238 } 239 240 err = spawn_free(&monitor_si); 241 if (err_is_fail(err)) { 242 return err_push(err, INIT_ERR_FREE_MONITOR); 243 } 244 245 err = spawn_free(&mem_serv_si); 246 if (err_is_fail(err)) { 247 return err_push(err, INIT_ERR_FREE_MEM_SERV); 248 } 249 250 return SYS_ERR_OK; 251} 252 253int main(int argc, char *argv[]) 254{ 255 printf("init: invoked as:"); 256 for (int i = 0; i < argc; i++) { 257 printf(" %s", argv[i]); 258 } 259 printf("\n"); 260 261 errval_t err; 262 263 // First argument contains the bootinfo location 264 bi = (struct bootinfo*)strtol(argv[1], NULL, 10); 265 266 /* Set the core id in the disp_priv struct */ 267 err = invoke_kernel_get_core_id(cap_kernel, &my_core_id); 268 assert(err_is_ok(err)); 269 disp_set_core_id(my_core_id); 270 271 /* Create our endpoint to self */ 272 err = cap_retype(cap_selfep, cap_dispatcher, 0, ObjType_EndPoint, 0, 1); 273 if (err_is_fail(err)) { 274 DEBUG_ERR(err, "Failed to create our endpoint to self"); 275 abort(); 276 } 277 278 /* Initialize local memory allocator */ 279 err = initialize_ram_alloc(); 280 if (err_is_fail(err)) { 281 DEBUG_ERR(err, "Failed to init ram alloc"); 282 abort(); 283 } 284 285 /* Spawn essential initial domains */ 286 err = bootstrap(argc, argv); 287 if (err_is_fail(err)) { 288 DEBUG_ERR(err, "Failed bootstrap"); 289 abort(); 290 } 291 292 /* hang around only until we proxy the endpoint caps */ 293 struct waitset *default_ws = get_default_waitset(); 294 while (!recv_state.done) { 295 err = event_dispatch(default_ws); 296 if (err_is_fail(err)) { 297 DEBUG_ERR(err, "in event_dispatch"); 298 abort(); 299 } 300 } 301 302 return EXIT_SUCCESS; 303} 304