kaluga: remove debug printf
[barrelfish] / usr / kaluga / start_cpu.c
1 /**
2  * \file
3  * \brief Code responsible for booting application cores
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 <stdlib.h>
16 #include <stdbool.h>
17 #include <stdio.h>
18 #include <assert.h>
19
20 #include <barrelfish/barrelfish.h>
21 #include <barrelfish/cpu_arch.h>
22
23 #include <if/monitor_defs.h>
24
25 #include <octopus/octopus.h>
26 #include <skb/skb.h>
27 #include <trace/trace.h>
28 #include <barrelfish/spawn_client.h>
29
30 #include <hw_records.h>
31
32 #include "kaluga.h"
33
34 static const char *processor_regex = HW_PROCESSOR_GENERIC_REGEX;
35
36 static void cpu_change_event(octopus_mode_t mode, char* record, void* state)
37 {
38     if (mode & OCT_ON_SET) {
39         KALUGA_DEBUG("CPU found: %s\n", record);
40
41         /* try to extract basic information from the record */
42         uint64_t barrelfish_id, type, hw_id, enabled = 0;
43         errval_t err = oct_read(record, "_ { " HW_PROCESSOR_GENERIC_FIELDS " }",
44                                 &enabled, &barrelfish_id, &hw_id, &type);
45         if (err_is_fail(err)) {
46             DEBUG_ERR(err, "Cannot read record.");
47             printf("Malformed CPU record. Do not boot discovered CPU %"PRIu64".\n",
48                     barrelfish_id);
49             goto out;
50         }
51
52         /* find the corectrl module for the given cpu type */
53         struct module_info* mi = find_corectrl_for_cpu_type((enum cpu_type)type);
54         if (mi != NULL) {
55             err = mi->start_function(0, mi, record, NULL);
56             if (err_is_fail(err)) {
57                 printf("Boot driver not found. Do not boot discovered CPU %"PRIu64".\n",
58                        barrelfish_id);
59                 goto out;
60             }
61         }
62     }
63     if (mode & OCT_ON_DEL) {
64         KALUGA_DEBUG("CPU removed: %s\n", record);
65         assert(!"NYI");
66     }
67
68 out:
69     assert(!(mode & OCT_REMOVED));
70 }
71
72 errval_t watch_for_cores(void)
73 {
74     octopus_trigger_id_t tid;
75     return oct_trigger_existing_and_watch(processor_regex, cpu_change_event,
76                                           NULL, &tid);
77 }
78
79 // State for delayed cleanup of inherit cnode
80 struct inheritcn_del_st {
81     struct capref        capref;
82     octopus_trigger_id_t tid;
83     coreid_t             coreid;
84 };
85
86 // Trigger function: gets called when spanwd on core n is up to delete
87 // associated inherit cnode that was given to `corectrl boot n`.
88 static void delete_inheritcn(octopus_mode_t mode, char *record, void *state)
89 {
90     errval_t err;
91     struct inheritcn_del_st *st = state;
92     if (mode & OCT_ON_SET) {
93         KALUGA_DEBUG("spawnd up for %d: deleting inheritcn\n", st->coreid);
94         err = cap_delete(st->capref);
95         if (err_is_fail(err)) {
96             DEBUG_ERR(err, "deleting inheritcn for %d\n", st->coreid);
97         }
98         assert(err_is_ok(err));
99         err = slot_free(st->capref);
100         if (err_is_fail(err)) {
101             DEBUG_ERR(err, "freeing slot for %d\n", st->coreid);
102         }
103         assert(err_is_ok(err));
104         err = oct_remove_trigger(st->tid);
105         if (err_is_fail(err)) {
106             DEBUG_ERR(err, "removing trigger");
107         }
108         assert(err_is_ok(err));
109         free(state);
110     }
111 }
112
113 errval_t start_boot_driver(coreid_t where, struct module_info* mi,
114         char* record, struct driver_argument * int_arg)
115 {
116     assert(mi != NULL);
117     errval_t err;
118
119     if (!is_auto_driver(mi)) {
120         return KALUGA_ERR_DRIVER_NOT_AUTO;
121     }
122
123     // Construct additional command line arguments containing pci-id.
124     // We need one extra entry for the new argument.
125     char **argv = mi->argv;
126     bool cleanup = false;
127     char barrelfish_id_s[10];
128     size_t argc = mi->argc;
129
130     KALUGA_DEBUG("Starting corectrl for %s\n", record);
131     uint64_t barrelfish_id, cpu_type, hw_id, enabled = 0;
132     err = oct_read(record, "_ { " HW_PROCESSOR_GENERIC_FIELDS " }",
133                             &enabled, &barrelfish_id, &hw_id, &cpu_type);
134     if (err_is_ok(err)) {
135         /*
136          * XXX: change this to a generic cpuhwid instead of apic!
137          */
138         skb_add_fact("corename(%"PRIu64", %s, apic(%"PRIu64")).",
139                      barrelfish_id, cpu_type_to_archstr(cpu_type), hw_id);
140
141         /* we are already running */
142         if (barrelfish_id == my_core_id) {
143             return SYS_ERR_OK;
144         }
145
146         if (!enabled) {
147             printf("CPU %" PRIu64 " is not enabled. Skipping driver initialization\n",
148                     barrelfish_id);
149             return SYS_ERR_OK;
150         }
151
152         argv = malloc((argc+5) * sizeof(char *));
153         memcpy(argv, mi->argv, argc * sizeof(char *));
154         snprintf(barrelfish_id_s, 10, "%"PRIu64"", barrelfish_id);
155
156         argv[argc] = "boot";
157         argc += 1;
158         argv[argc] = barrelfish_id_s;
159         argc += 1;
160         // Copy kernel args over to new core
161         struct module_info* cpu_module = find_module("cpu");
162         if (cpu_module != NULL && strlen(cpu_module->args) > 1) {
163             KALUGA_DEBUG("%s:%s:%d: Boot with cpu arg %s and barrelfish_id_s=%s\n",
164                          __FILE__, __FUNCTION__, __LINE__, cpu_module->args, barrelfish_id_s);
165             argv[argc] = "-a";
166             argc += 1;
167             argv[argc] = cpu_module->args;
168             argc += 1;
169         }
170         argv[argc] = NULL;
171
172         cleanup = true;
173     }
174     else {
175         DEBUG_ERR(err, "Malformed CPU record?");
176         return err;
177     }
178
179     struct capref task_cap_kernel;
180     task_cap_kernel.cnode = cnode_task;
181     task_cap_kernel.slot = TASKCN_SLOT_KERNELCAP;
182
183 #ifdef KALUGA_SERVICE_DEBUG
184     struct capability info;
185     err = debug_cap_identify(task_cap_kernel, &info);
186     if (err_is_fail(err)) {
187         USER_PANIC_ERR(err, "Can not identify the capability.");
188     }
189     char buffer[1024];
190     debug_print_cap(buffer, 1024, &info);
191     KALUGA_DEBUG("%s:%d: capability=%s\n", __FILE__, __LINE__, buffer);
192 #endif
193
194     struct capref inheritcn_cap;
195     err = alloc_inheritcn_with_caps(&inheritcn_cap,
196                                     NULL_CAP, NULL_CAP, task_cap_kernel);
197     if (err_is_fail(err)) {
198         DEBUG_ERR(err, "alloc_inheritcn_with_caps failed.");
199     }
200
201     err = spawn_program_with_caps(where, mi->path, argv,
202                                   environ, inheritcn_cap,
203                                   NULL_CAP, SPAWN_FLAGS_NEW_DOMAIN,
204                                   &mi->did[0]);
205     if (err_is_fail(err)) {
206         DEBUG_ERR(err, "Spawning %s failed.", mi->path);
207     }
208
209     if (cleanup) {
210         free(argv);
211     }
212
213     // Cannot just delete inherit cnode capability here, as deleting any CNode
214     // copy will always delete all copies of the CNode. Store inherit cnode
215     // cap in octopus, and delete it when the matching spawnd is up
216     char spawnd[32];
217     snprintf(spawnd, 32, "spawn.%s", barrelfish_id_s);
218     struct inheritcn_del_st *tstate = calloc(1, sizeof(*tstate));
219     tstate->capref = inheritcn_cap;
220     tstate->coreid = barrelfish_id;
221     errval_t err2 = oct_trigger_existing_and_watch(spawnd, delete_inheritcn,
222                                                    tstate, &tstate->tid);
223     if (err_is_fail(err2)) {
224         free(tstate);
225         return err2;
226     }
227
228     return err;
229 }
230
231
232 static void spawnd_change_event(octopus_mode_t mode, char* record, void* state)
233 {
234     size_t count = (size_t) state;
235     static coreid_t spawnd_counter = 0;
236
237     if (mode & OCT_ON_SET) {
238         KALUGA_DEBUG("spawnd found: %s\n", record);
239         spawnd_counter++;
240
241         if (spawnd_counter == count) {
242             KALUGA_DEBUG("Found enough spawnds, setting all_spawnds_up\n");
243             errval_t err = oct_set("all_spawnds_up { iref: 0 }");
244             assert(err_is_ok(err));
245         }
246     }
247 }
248
249 errval_t wait_for_all_spawnds(void)
250 {
251     // Note: The whole wait for all_spawnds_up thing is a hack.
252     // Our overall design goal is a system where cores
253     // come and go dynamically and we do not want / need
254     // to wait for a stable state.
255     // However, some of our code (for example domain spanning)
256     // still assumes a fixed set of cores and will deadlock
257     // otherwise. Therefore we need to fix those parts first.
258     errval_t err;
259 #if !defined(__ARM_ARCH_7A__)
260     KALUGA_DEBUG("Waiting for acpi");
261     char* record = NULL;
262     err = oct_wait_for(&record, "acpi { iref: _ }");
263     if (err_is_fail(err)) {
264         return err_push(err, KALUGA_ERR_WAITING_FOR_ACPI);
265     }
266 #endif
267
268     // No we should be able to get core count
269     // of all cores to estimate the amount of
270     // spawnd's we have to expect (one per core)
271     char** names;
272     size_t count;
273     err = oct_get_names(&names, &count, processor_regex);
274     if (err_is_fail(err)) {
275         return err_push(err, KALUGA_ERR_QUERY_LOCAL_APIC);
276     }
277     oct_free_names(names, count);
278
279     static char* spawnds = "r'spawn.[0-9]+' { iref: _ }";
280     octopus_trigger_id_t tid;
281     return oct_trigger_existing_and_watch(spawnds, spawnd_change_event, (void*)count, &tid);
282 }