631b888545866a298097ace6fb416331a59e7576
[barrelfish] / usr / monitor / main.c
1 /**
2  * \file
3  * \brief Monitor process
4  */
5
6 /*
7  * Copyright (c) 2007 - 2016, 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include "monitor.h"
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>
22
23 #ifdef __k1om__
24 extern char **environ;
25 #endif
26
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;
33
34 // Capref to trace cap
35 struct capref trace_cap;
36
37 /* Set to the core id so no need to load from dispatcher */
38 coreid_t my_core_id = -1;
39
40 /* Flag to indicate if monitor is running on bsp core */
41 bool bsp_monitor = false;
42
43 // Flag to indicate whether to update the ram_alloc binding
44 bool update_ram_alloc_binding = false;
45
46 struct bootinfo *bi;
47
48 /**
49  * \brief Initialize monitor running on bsp core
50  */
51 static errval_t boot_bsp_core(int argc, char *argv[])
52 {
53     errval_t err;
54
55     // First argument contains the bootinfo location
56     bi = (struct bootinfo*)strtol(argv[1], NULL, 10);
57
58     bsp_monitor = true;
59
60     err = monitor_client_setup_mem_serv();
61     assert(err_is_ok(err));
62
63     /* Wait for mem_serv to advertise its iref to us */
64     while (mem_serv_iref == 0) {
65         messages_wait_and_handle_next();
66     }
67     update_ram_alloc_binding = false;
68
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);
73     }
74
75     // Export ram_alloc service
76     err = mon_ram_alloc_serve();
77     assert(err_is_ok(err));
78
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");
83         return err;
84     }
85
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");
90         return err;
91     }
92     // XXX: Wait for ramfsd to initialize
93     while (ramfs_serv_iref == 0) {
94         messages_wait_and_handle_next();
95     }
96
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");
101         return err;
102     }
103     // XXX: Wait for name_server to initialize
104     while (name_serv_iref == 0) {
105         messages_wait_and_handle_next();
106     }
107 #ifdef __k1om__
108     char args[40];
109     snprintf(args, sizeof(args), "0x%016lx 0x%02x", bi->host_msg,
110              bi->host_msg_bits);
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");
116         return err;
117     }
118 #endif
119
120     // Connect to octopus
121     err = octopus_client_bind();
122     if (err_is_fail(err)) {
123         DEBUG_ERR(err, "binding to octopus service");
124         return err;
125     }
126
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");
132         return err;
133     }
134
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");
140         return err;
141     }
142     // XXX: Wait for proc_mgmt to initialize
143     while (get_proc_mgmt_binding() == NULL) {
144         messages_wait_and_handle_next();
145     }
146
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");
151         return err;
152     }
153
154     // XXX: Wait for spawnd to initialize
155     while (spawn_iref == 0) {
156         messages_wait_and_handle_next();
157     }
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");
162     }
163
164     return SYS_ERR_OK;
165 }
166
167 static errval_t boot_app_core(int argc, char *argv[])
168 {
169     coreid_t parent_core_id;
170     struct intermon_binding *intermon_binding;
171     errval_t err;
172
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");
177         return err;
178     }
179
180     err = boot_arch_app_core(argc, argv, &parent_core_id, &intermon_binding);
181     if(err_is_fail(err)) {
182         return err;
183     }
184
185     // connect it to our request handlers
186     intermon_init(intermon_binding, parent_core_id);
187
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));
193
194     err = request_ramfs_serv_iref(intermon_binding);
195     assert(err_is_ok(err));
196
197
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
203
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);
208     }
209
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);
215     }
216     ((struct intermon_state*)intermon_binding->st)->capops_ready = true;
217
218     /* Set up monitor rpc channel */
219     err = monitor_rpc_init();
220     if(err_is_fail(err)) {
221         return err;
222     }
223
224 #ifdef TRACING_EXISTS
225     // Request trace caps
226     err = request_trace_caps(intermon_binding);
227     assert(err_is_ok(err));
228 #endif
229
230     // Connect to octopus
231     err = octopus_client_bind();
232     assert(err_is_ok(err));
233
234     // Spawn local spawnd
235     err = spawn_spawnd(intermon_binding);
236     if (err_is_fail(err)) {
237         USER_PANIC_ERR(err, "error spawning spawnd");
238     }
239     // XXX: Wait for spawnd to initialize
240     while (spawn_iref == 0) {
241         messages_wait_and_handle_next();
242     }
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");
248     }
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");
252     }
253
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);
258     }
259
260     return SYS_ERR_OK;
261 }
262
263 errval_t request_trace_caps(struct intermon_binding *st)
264 {
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);
268     }
269     while(capref_is_null(trace_cap)) {
270         messages_wait_and_handle_next();
271     }
272
273     return SYS_ERR_OK;
274 }
275
276 errval_t request_mem_serv_iref(struct intermon_binding *st)
277 {
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);
281     }
282     while(mem_serv_iref == 0) {
283         messages_wait_and_handle_next();
284     }
285     return SYS_ERR_OK;
286 }
287
288 errval_t request_name_serv_iref(struct intermon_binding *st)
289 {
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);
293     }
294     while(name_serv_iref == 0) {
295         messages_wait_and_handle_next();
296     }
297     return SYS_ERR_OK;
298 }
299
300 errval_t request_ramfs_serv_iref(struct intermon_binding *st)
301 {
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);
305     }
306     while(ramfs_serv_iref == 0) {
307         messages_wait_and_handle_next();
308     }
309     return SYS_ERR_OK;
310 }
311
312
313 void ipi_test(void);
314
315 #ifdef MONITOR_HEARTBEAT
316 static void mon_heartbeat(void *arg) {
317     assert(arg != NULL);
318     errval_t err;
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");
328     }
329     assert(err_is_ok(err));
330 }
331 #endif
332
333 /**
334  * \brief Use cmdline args to figure out which core the monitor is running on
335  * and which cores to boot.
336  */
337 int main(int argc, char *argv[])
338 {
339     printf("monitor: invoked as:");
340     for (int i = 0; i < argc; i++) {
341         printf(" %s", argv[i]);
342     }
343     printf("\n");
344
345     errval_t err;
346
347     /* Initialize the library */
348     bench_init();
349
350     /* Set core id */
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);
354
355     // Setup all channels and channel support code
356     err = monitor_client_setup_monitor();
357     assert(err_is_ok(err));
358
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");
363             return EXIT_FAILURE;
364         }
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");
369             return EXIT_FAILURE;
370         }
371     }
372
373 #if defined(TRACING_EXISTS) && defined(CONFIG_TRACE)
374     err = trace_my_setup();
375     assert(err_is_ok(err));
376     trace_reset_buffer();
377
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);
384         }
385     } else {
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);
390         }
391     }
392 #endif // tracing
393
394     domain_mgmt_init();
395
396 #ifdef MONITOR_HEARTBEAT
397     struct deferred_event ev;
398     mon_heartbeat(&ev);
399 #endif
400
401     for(;;) {
402         err = event_dispatch(get_default_waitset());
403         if(err_is_fail(err)) {
404             USER_PANIC_ERR(err, "event_dispatch");
405         }
406
407         if(update_ram_alloc_binding) {
408             update_ram_alloc_binding = false;
409
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.");
414             }
415         }
416     }
417 }