3 * \brief Monitor process
7 * Copyright (c) 2007 - 2016, ETH Zurich.
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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
16 #include <barrelfish_kpi/init.h>
17 #include <barrelfish/dispatch.h>
18 #include <barrelfish/deferred.h>
19 #include <barrelfish/domain.h>
20 #include <barrelfish/proc_mgmt_client.h>
21 #include <trace/trace.h>
24 extern char **environ;
27 /* irefs for mem server, name service, ramfs and spawnd*/
28 iref_t mem_serv_iref = 0;
29 iref_t ramfs_serv_iref = 0;
30 iref_t name_serv_iref = 0;
31 iref_t spawn_iref = 0;
32 iref_t monitor_rpc_iref = 0;
34 // Capref to trace cap
35 struct capref trace_cap;
37 /* Set to the core id so no need to load from dispatcher */
38 coreid_t my_core_id = -1;
40 /* Flag to indicate if monitor is running on bsp core */
41 bool bsp_monitor = false;
43 // Flag to indicate whether to update the ram_alloc binding
44 bool update_ram_alloc_binding = false;
49 * \brief Initialize monitor running on bsp core
51 static errval_t boot_bsp_core(int argc, char *argv[])
55 // First argument contains the bootinfo location
56 bi = (struct bootinfo*)strtol(argv[1], NULL, 10);
60 err = monitor_client_setup_mem_serv();
61 assert(err_is_ok(err));
63 /* Wait for mem_serv to advertise its iref to us */
64 while (mem_serv_iref == 0) {
65 messages_wait_and_handle_next();
67 update_ram_alloc_binding = false;
69 /* Can now connect to and use mem_serv */
70 err = ram_alloc_set(NULL);
71 if (err_is_fail(err)) {
72 return err_push(err, LIB_ERR_RAM_ALLOC_SET);
75 // Export ram_alloc service
76 err = mon_ram_alloc_serve();
77 assert(err_is_ok(err));
79 /* Set up monitor rpc channel */
80 err = monitor_rpc_init();
81 if (err_is_fail(err)) {
82 DEBUG_ERR(err, "monitor rpc init failed");
86 /* SKB needs vfs for ECLiPSe so we need to start ramfsd first... */
87 err = spawn_domain("ramfsd");
88 if (err_is_fail(err)) {
89 DEBUG_ERR(err, "failed spawning ramfsd");
92 // XXX: Wait for ramfsd to initialize
93 while (ramfs_serv_iref == 0) {
94 messages_wait_and_handle_next();
97 /* Spawn skb (new nameserver) before other domains */
98 err = spawn_domain("skb");
99 if (err_is_fail(err)) {
100 DEBUG_ERR(err, "failed spawning skb");
103 // XXX: Wait for name_server to initialize
104 while (name_serv_iref == 0) {
105 messages_wait_and_handle_next();
109 snprintf(args, sizeof(args), "0x%016lx 0x%02x", bi->host_msg,
111 char *mgr_argv[MAX_CMDLINE_ARGS + 1];
112 spawn_tokenize_cmdargs(args, mgr_argv, ARRAY_LENGTH(mgr_argv));
113 err = spawn_domain_with_args("xeon_phi", mgr_argv,environ);
114 if (err_is_fail(err)) {
115 DEBUG_ERR(err, "failed spawning xeon_phi");
120 // Connect to octopus
121 err = octopus_client_bind();
122 if (err_is_fail(err)) {
123 DEBUG_ERR(err, "binding to octopus service");
127 // Store BSP KCB cap in octopus
128 debug_printf("Storing BSP KCB in octopus\n");
129 err = octopus_set_bspkcb();
130 if (err_is_fail(err)) {
131 DEBUG_ERR(err, "storing BSP KCB in octopus");
135 // Spawn process manager, to be used by further domains.
136 set_proc_mgmt_binding(NULL);
137 err = spawn_domain("proc_mgmt");
138 if (err_is_fail(err)) {
139 DEBUG_ERR(err, "failed spawning proc_mgmt");
142 // XXX: Wait for proc_mgmt to initialize
143 while (get_proc_mgmt_binding() == NULL) {
144 messages_wait_and_handle_next();
147 /* Spawn boot domains in menu.lst */
148 err = spawn_all_domains();
149 if (err_is_fail(err)) {
150 DEBUG_ERR(err, "spawn_all_domains failed");
154 // XXX: Wait for spawnd to initialize
155 while (spawn_iref == 0) {
156 messages_wait_and_handle_next();
158 // Now tell process manager about our new spawnd.
159 err = proc_mgmt_add_spawnd(spawn_iref, disp_get_core_id());
160 if (err_is_fail(err)) {
161 USER_PANIC_ERR(err, "error sending spawnd iref to process manager");
167 static errval_t boot_app_core(int argc, char *argv[])
169 coreid_t parent_core_id;
170 struct intermon_binding *intermon_binding;
173 /* Create the self endpoint as the kernel doesn't do it */
174 err = cap_retype(cap_selfep, cap_dispatcher, 0, ObjType_EndPoint, 0, 1);
175 if (err_is_fail(err)) {
176 DEBUG_ERR(err, "Retyping dispatcher to self ep failed");
180 err = boot_arch_app_core(argc, argv, &parent_core_id, &intermon_binding);
181 if(err_is_fail(err)) {
185 // connect it to our request handlers
186 intermon_init(intermon_binding, parent_core_id);
188 /* Request memserv and nameserv iref */
189 err = request_mem_serv_iref(intermon_binding);
190 assert(err_is_ok(err));
191 err = request_name_serv_iref(intermon_binding);
192 assert(err_is_ok(err));
194 err = request_ramfs_serv_iref(intermon_binding);
195 assert(err_is_ok(err));
198 #ifdef BARRELFISH_MULTIHOP_CHAN_H
199 // request my part of the routing table
200 err = multihop_request_routing_table(intermon_binding);
201 assert(err_is_ok(err));
202 #endif // BARRELFISH_MULTIHOP_CHAN_H
204 /* initialize self ram alloc */
205 err = mon_ram_alloc_init(parent_core_id, intermon_binding);
206 if (err_is_fail(err)) {
207 return err_push(err, LIB_ERR_RAM_ALLOC_SET);
210 /* with memory alloc running, take part in cap ops */
211 DEBUG_CAPOPS("sending capops_ready to %"PRIuCOREID"\n", parent_core_id);
212 err = intermon_binding->tx_vtbl.capops_ready(intermon_binding, NOP_CONT);
213 if (err_is_fail(err)) {
214 return err_push(err, MON_ERR_SEND_REMOTE_MSG);
216 ((struct intermon_state*)intermon_binding->st)->capops_ready = true;
218 /* Set up monitor rpc channel */
219 err = monitor_rpc_init();
220 if(err_is_fail(err)) {
224 #ifdef TRACING_EXISTS
225 // Request trace caps
226 err = request_trace_caps(intermon_binding);
227 assert(err_is_ok(err));
230 // Connect to octopus
231 err = octopus_client_bind();
232 assert(err_is_ok(err));
234 // Spawn local spawnd
235 err = spawn_spawnd(intermon_binding);
236 if (err_is_fail(err)) {
237 USER_PANIC_ERR(err, "error spawning spawnd");
239 // XXX: Wait for spawnd to initialize
240 while (spawn_iref == 0) {
241 messages_wait_and_handle_next();
243 // Use monitor.0 to tell the process manager about our new spawnd.
244 struct intermon_binding *ib0;
245 err = intermon_binding_get(0, &ib0);
246 if (err_is_fail(err)) {
247 USER_PANIC_ERR(err, "error retrieving intermon_binding for monitor 0");
249 err = ib0->tx_vtbl.add_spawnd(ib0, NOP_CONT, spawn_iref);
250 if (err_is_fail(err)) {
251 USER_PANIC_ERR(err, "error sending add_spawnd request to monitor 0");
254 /* Signal the monitor that booted us that we have initialized */
255 err = intermon_binding->tx_vtbl.monitor_initialized(intermon_binding, NOP_CONT);
256 if (err_is_fail(err)) {
257 return err_push(err, MON_ERR_SEND_REMOTE_MSG);
263 errval_t request_trace_caps(struct intermon_binding *st)
265 errval_t err = st->tx_vtbl.trace_caps_request(st, NOP_CONT);
266 if (err_is_fail(err)) {
267 return err_push(err, MON_ERR_SEND_REMOTE_MSG);
269 while(capref_is_null(trace_cap)) {
270 messages_wait_and_handle_next();
276 errval_t request_mem_serv_iref(struct intermon_binding *st)
278 errval_t err = st->tx_vtbl.mem_serv_iref_request(st, NOP_CONT);
279 if (err_is_fail(err)) {
280 return err_push(err, MON_ERR_SEND_REMOTE_MSG);
282 while(mem_serv_iref == 0) {
283 messages_wait_and_handle_next();
288 errval_t request_name_serv_iref(struct intermon_binding *st)
290 errval_t err = st->tx_vtbl.name_serv_iref_request(st, NOP_CONT);
291 if (err_is_fail(err)) {
292 return err_push(err, MON_ERR_SEND_REMOTE_MSG);
294 while(name_serv_iref == 0) {
295 messages_wait_and_handle_next();
300 errval_t request_ramfs_serv_iref(struct intermon_binding *st)
302 errval_t err = st->tx_vtbl.ramfs_serv_iref_request(st, NOP_CONT);
303 if (err_is_fail(err)) {
304 return err_push(err, MON_ERR_SEND_REMOTE_MSG);
306 while(ramfs_serv_iref == 0) {
307 messages_wait_and_handle_next();
315 #ifdef MONITOR_HEARTBEAT
316 static void mon_heartbeat(void *arg) {
319 debug_printf("my_core_id = %d; curr_core_id = %d\n", my_core_id,
320 disp_get_current_core_id());
321 struct deferred_event *ev = arg;
322 deferred_event_init(ev);
323 // 1 s == 1000 ms == 1e6 us
324 delayus_t one_sec = 15ULL*1000*1000;
325 err = deferred_event_register(ev, get_default_waitset(), one_sec, MKCLOSURE(mon_heartbeat, arg));
326 if (err_is_fail(err)) {
327 DEBUG_ERR(err, "heartbeat");
329 assert(err_is_ok(err));
334 * \brief Use cmdline args to figure out which core the monitor is running on
335 * and which cores to boot.
337 int main(int argc, char *argv[])
339 printf("monitor: invoked as:");
340 for (int i = 0; i < argc; i++) {
341 printf(" %s", argv[i]);
347 /* Initialize the library */
351 err = invoke_kernel_get_core_id(cap_kernel, &my_core_id);
352 assert(err_is_ok(err));
353 disp_set_core_id(my_core_id);
355 // Setup all channels and channel support code
356 err = monitor_client_setup_monitor();
357 assert(err_is_ok(err));
359 if (argc == 2) { /* Bsp monitor */
360 err = boot_bsp_core(argc, argv);
361 if (err_is_fail(err)) {
362 USER_PANIC_ERR(err, "failed to boot BSP core");
365 } else { /* Non bsp monitor */
366 err = boot_app_core(argc, argv);
367 if(err_is_fail(err)) {
368 USER_PANIC_ERR(err, "starting app monitor");
373 #if defined(TRACING_EXISTS) && defined(CONFIG_TRACE)
374 err = trace_my_setup();
375 assert(err_is_ok(err));
376 trace_reset_buffer();
378 struct capref tracecap;
379 err = trace_setup_on_core(&tracecap);
380 if (err_is_fail(err)) {
381 if(err_no(err) != TRACE_ERR_NO_BUFFER) {
382 DEBUG_ERR(err, "trace_setup_on_core failed");
383 printf("Warning: tracing not available on core %d\n", my_core_id);
386 err = invoke_trace_setup(tracecap);
387 if (err_is_fail(err)) {
388 DEBUG_ERR(err, "invoke_trace_setup failed");
389 printf("Warning: tracing not available on core %d\n", my_core_id);
396 #ifdef MONITOR_HEARTBEAT
397 struct deferred_event ev;
402 err = event_dispatch(get_default_waitset());
403 if(err_is_fail(err)) {
404 USER_PANIC_ERR(err, "event_dispatch");
407 if(update_ram_alloc_binding) {
408 update_ram_alloc_binding = false;
410 err = ram_alloc_set(NULL);
411 if(err_is_fail(err)) {
412 DEBUG_ERR(err, "ram_alloc_set to local allocator failed. "
413 "Will stick with intermon memory allocation.");