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