3 * \brief Code responsible for booting application cores
7 * Copyright (c) 2007, 2008, 2009, 2010, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
20 #include <barrelfish/barrelfish.h>
21 #include <barrelfish/cpu_arch.h>
23 #include <if/monitor_defs.h>
25 #include <octopus/octopus.h>
30 // TODO: Needed because of we have to send
31 // boot_initialize_request after all cores have booted
32 // It's a hack (see monitors boot.c)
33 static coreid_t cores_on_boot = 0;
34 static coreid_t core_counter = 1; // BSP already up
35 static bool cores_booted = false;
37 static errval_t new_mon_msg(struct mon_msg_state** mms, send_handler_fn s)
39 *mms = malloc(sizeof(struct mon_msg_state));
41 return LIB_ERR_MALLOC_FAIL;
50 static void send_boot_initialize_request(struct monitor_binding* b,
51 struct mon_msg_state* mm)
55 err = b->tx_vtbl.boot_initialize_request(b,
58 if (err_is_fail(err)) {
59 if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
60 enqueue_msg_state(b, mm);
63 USER_PANIC_ERR(err, "kaluga: sending %s failed!", __FUNCTION__);
67 static void boot_core_reply(struct monitor_binding *st, errval_t msgerr)
69 static coreid_t core_boot_replies = 1; // BSP Monitor already running
70 if (err_is_fail(msgerr)) {
71 USER_PANIC_ERR(msgerr, "msgerr in boot_core_reply, exiting\n");
74 KALUGA_DEBUG("boot_core_reply: core_boot_replies=%d, cores_on_boot=%d\n",
75 core_boot_replies+1, cores_on_boot);
77 if (++core_boot_replies == cores_on_boot) {
78 struct monitor_binding *mb = get_monitor_binding();
79 struct mon_msg_state *mms = NULL;
80 errval_t err = new_mon_msg(&mms, send_boot_initialize_request);
81 assert(err_is_ok(err));
83 KALUGA_DEBUG("before boot send...\n");
88 static void boot_initialize_reply(struct monitor_binding *st)
90 KALUGA_DEBUG("boot_initialize_reply\n");
92 errval_t err = oct_set("all_spawnds_up { iref: 0 }");
93 assert(err_is_ok(err));
97 static void send_boot_core_request(struct monitor_binding* b,
98 struct mon_msg_state* mm)
102 struct module_info* mi = find_module("cpu");
103 err = b->tx_vtbl.boot_core_request(b, MKCONT(free, mm), mm->core_id,
104 mm->arch_id, CURRENT_CPU_TYPE, mi->complete_line);
106 if (err_is_fail(err)) {
107 if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
108 enqueue_msg_state(b, mm);
111 USER_PANIC_ERR(err, "device_manager: sending %s failed!", __FUNCTION__);
115 static inline void configure_monitor_binding(void)
117 struct monitor_binding* mb = get_monitor_binding();
118 mb->rx_vtbl.boot_core_reply = boot_core_reply;
119 mb->rx_vtbl.boot_initialize_reply = boot_initialize_reply;
123 static void cpu_change_event(octopus_mode_t mode, char* record, void* state)
125 if (mode & OCT_ON_SET) {
126 KALUGA_DEBUG("CPU found: %s\n", record);
128 uint64_t cpu_id, arch_id, enabled = 0;
129 errval_t err = oct_read(record, "_ { cpu_id: %d, id: %d, enabled: %d }",
130 &cpu_id, &arch_id, &enabled);
131 if (err_is_fail(err)) {
132 DEBUG_ERR(err, "Cannot read record.");
133 assert(!"Illformed core record received");
137 // cpu_id may vary so we can't really use this
138 // to enumerate cores...
139 assert(my_core_id == 0);
140 static coreid_t core_id = 1;
142 if (arch_id != my_arch_id && enabled) {
143 struct monitor_binding* mb = get_monitor_binding();
145 struct mon_msg_state* mms = NULL;
146 err = new_mon_msg(&mms, send_boot_core_request);
147 assert(err_is_ok(err));
149 mms->core_id = core_id++;
150 mms->arch_id = arch_id;
152 (*(coreid_t*) state) += 1;
154 // XXX: copied this line from spawnd bsp_bootup,
155 // not sure why x86_64 is hardcoded here but it
157 skb_add_fact("corename(%d, x86_64, apic(%lu)).",
158 mms->core_id, mms->arch_id);
162 if (mode & OCT_ON_DEL) {
163 KALUGA_DEBUG("CPU removed: %s\n", record);
168 assert(!(mode & OCT_REMOVED));
172 errval_t watch_for_cores(void)
174 configure_monitor_binding();
176 static char* local_apics = "r'hw\\.apic\\.[0-9]+' { cpu_id: _, "
179 octopus_trigger_id_t tid;
180 errval_t err = trigger_existing_and_watch(local_apics, cpu_change_event,
181 &core_counter, &tid);
182 cores_on_boot = core_counter;
184 if (err_is_ok(err)) {
185 if (cores_on_boot == 1) {
186 // No additional cores found
187 // XXX: We simulate a boot initialize reply to set the
188 // all_spawnds_up record. The whole app monitor boot protocol will
189 // most likely change in the future and render this unnecessary.
190 boot_initialize_reply(NULL);
194 // Wait until all cores found are booted, this ensures
195 // we won't deadlock in case we start a driver on
196 // a core that is not ready
198 while (!cores_booted) {
199 messages_wait_and_handle_next();
205 static void ioapic_change_event(octopus_mode_t mode, char* record, void* state)
207 if (mode & OCT_ON_SET) {
208 struct module_info* mi = find_module("ioapic");
210 // Pass apic id as 1st argument
211 static const char* fmt = "apicid=%u";
212 int len = snprintf(NULL, 0, fmt, my_arch_id);
213 char* apic_arg = malloc(len+1);
214 snprintf(apic_arg, len+1, fmt, my_arch_id);
216 mi->argv[2] = apic_arg;
217 errval_t err = mi->start_function(my_core_id, mi, record);
220 switch (err_no(err)) {
222 KALUGA_DEBUG("Spawned I/O APIC driver: %s\n", mi->binary);
225 case KALUGA_ERR_DRIVER_ALREADY_STARTED:
226 KALUGA_DEBUG("%s already running.\n", mi->binary);
229 case KALUGA_ERR_DRIVER_NOT_AUTO:
230 KALUGA_DEBUG("%s not declared as auto, ignore.\n", mi->binary);
234 DEBUG_ERR(err, "Unhandled error while starting %s\n", mi->binary);
239 else if (mode & OCT_ON_DEL) {
240 KALUGA_DEBUG("Removed I/O APIC?");
248 errval_t watch_for_ioapic(void)
250 KALUGA_DEBUG("watch_for_ioapic\n");
251 static char* io_apics = "r'hw.ioapic.[0-9]+' { id: _, address: _, "
254 octopus_trigger_id_t tid;
255 return trigger_existing_and_watch(io_apics, ioapic_change_event,
256 &core_counter, &tid);