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>
27 #include <trace/trace.h>
28 #include <barrelfish/spawn_client.h>
30 #include <hw_records.h>
34 static const char *processor_regex = HW_PROCESSOR_GENERIC_REGEX;
36 static void cpu_change_event(octopus_mode_t mode, char* record, void* state)
38 if (mode & OCT_ON_SET) {
39 KALUGA_DEBUG("CPU found: %s\n", record);
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",
52 /* find the corectrl module for the given cpu type */
53 struct module_info* mi = find_corectrl_for_cpu_type((enum cpu_type)type);
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",
63 if (mode & OCT_ON_DEL) {
64 KALUGA_DEBUG("CPU removed: %s\n", record);
69 assert(!(mode & OCT_REMOVED));
72 errval_t watch_for_cores(void)
74 octopus_trigger_id_t tid;
75 return oct_trigger_existing_and_watch(processor_regex, cpu_change_event,
79 // State for delayed cleanup of inherit cnode
80 struct inheritcn_del_st {
82 octopus_trigger_id_t tid;
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)
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);
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);
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");
108 assert(err_is_ok(err));
113 errval_t start_boot_driver(coreid_t where, struct module_info* mi,
114 char* record, struct driver_argument * int_arg)
119 if (!is_auto_driver(mi)) {
120 return KALUGA_ERR_DRIVER_NOT_AUTO;
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;
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)) {
136 * XXX: change this to a generic cpuhwid instead of apic!
138 skb_add_fact("corename(%"PRIu64", %s, apic(%"PRIu64")).",
139 barrelfish_id, cpu_type_to_archstr(cpu_type), hw_id);
141 /* we are already running */
142 if (barrelfish_id == my_core_id) {
147 printf("CPU %" PRIu64 " is not enabled. Skipping driver initialization\n",
152 argv = malloc((argc+5) * sizeof(char *));
153 memcpy(argv, mi->argv, argc * sizeof(char *));
154 snprintf(barrelfish_id_s, 10, "%"PRIu64"", barrelfish_id);
158 argv[argc] = barrelfish_id_s;
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);
167 argv[argc] = cpu_module->args;
175 DEBUG_ERR(err, "Malformed CPU record?");
179 struct capref task_cap_kernel;
180 task_cap_kernel.cnode = cnode_task;
181 task_cap_kernel.slot = TASKCN_SLOT_KERNELCAP;
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.");
190 debug_print_cap(buffer, 1024, &info);
191 KALUGA_DEBUG("%s:%d: capability=%s\n", __FILE__, __LINE__, buffer);
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.");
201 err = spawn_program_with_caps(where, mi->path, argv,
202 environ, inheritcn_cap,
203 NULL_CAP, SPAWN_FLAGS_NEW_DOMAIN,
205 if (err_is_fail(err)) {
206 DEBUG_ERR(err, "Spawning %s failed.", mi->path);
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
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)) {
232 static void spawnd_change_event(octopus_mode_t mode, char* record, void* state)
234 size_t count = (size_t) state;
235 static coreid_t spawnd_counter = 0;
237 if (mode & OCT_ON_SET) {
238 KALUGA_DEBUG("spawnd found: %s\n", record);
241 if (spawnd_counter == count) {
242 KALUGA_DEBUG("Found enough spawnds, setting all_spawnds_up\n");
243 debug_printf("Found enough spawnds, setting all_spawnds_up\n");
244 errval_t err = oct_set("all_spawnds_up { iref: 0 }");
245 assert(err_is_ok(err));
250 errval_t wait_for_all_spawnds(void)
252 // Note: The whole wait for all_spawnds_up thing is a hack.
253 // Our overall design goal is a system where cores
254 // come and go dynamically and we do not want / need
255 // to wait for a stable state.
256 // However, some of our code (for example domain spanning)
257 // still assumes a fixed set of cores and will deadlock
258 // otherwise. Therefore we need to fix those parts first.
260 #if !defined(__ARM_ARCH_7A__)
261 KALUGA_DEBUG("Waiting for acpi");
263 err = oct_wait_for(&record, "acpi { iref: _ }");
264 if (err_is_fail(err)) {
265 return err_push(err, KALUGA_ERR_WAITING_FOR_ACPI);
269 // No we should be able to get core count
270 // of all cores to estimate the amount of
271 // spawnd's we have to expect (one per core)
274 err = oct_get_names(&names, &count, processor_regex);
275 if (err_is_fail(err)) {
276 return err_push(err, KALUGA_ERR_QUERY_LOCAL_APIC);
278 oct_free_names(names, count);
280 static char* spawnds = "r'spawn.[0-9]+' { iref: _ }";
281 octopus_trigger_id_t tid;
282 return oct_trigger_existing_and_watch(spawnds, spawnd_change_event, (void*)count, &tid);