errval_t start_networking(coreid_t core, struct module_info* driver, char* record) { assert(driver != NULL); errval_t err = SYS_ERR_OK; if (is_started(driver)) { return KALUGA_ERR_DRIVER_ALREADY_STARTED; } if (!is_auto_driver(driver)) { return KALUGA_ERR_DRIVER_NOT_AUTO; } struct module_info* netd = find_module("netd"); if (netd == NULL || !is_auto_driver(netd)) { KALUGA_DEBUG("netd not found or not declared as auto."); return KALUGA_ERR_DRIVER_NOT_AUTO; } struct module_info* ngd_mng = find_module("NGD_mng"); if (ngd_mng == NULL || !is_auto_driver(ngd_mng)) { KALUGA_DEBUG("NGD_mng not found or not declared as auto."); return KALUGA_ERR_DRIVER_NOT_AUTO; } err = spawn_program(core, driver->path, driver->argv + 1, environ, 0, &driver->did); if (err_is_fail(err)) { DEBUG_ERR(err, "Spawning %s failed.", driver->path); return err; } // XXX: Manually add cardname (overwrite first (auto) argument) // +Weird convention, e1000n binary but cardname=e1000 char* cardname = strcmp(driver->binary, "e1000n") == 0 ? "e1000" : driver->binary; size_t name_len = strlen("cardname=") + strlen(cardname) + 1; char* card_argument = malloc(name_len); sprintf(card_argument, "cardname=%s", cardname); printf("############# starting network with argiments %s\n", card_argument); // Spawn netd and ngd_mng netd->argv[0] = card_argument; err = spawn_program(core, netd->path, netd->argv, environ, 0, &netd->did); ngd_mng->argv[0] = card_argument; err = spawn_program(core, ngd_mng->path, ngd_mng->argv, environ, 0, &ngd_mng->did); free(card_argument); return err; }
errval_t wait_for_all_spawnds(void) { // Note: The whole wait for all_spawnds_up thing is a hack. // Our overall design goal is a system where cores // come and go dynamically and we do not want / need // to wait for a stable state. // However, some of our code (for example domain spanning) // still assumes a fixed set of cores and will deadlock // otherwise. Therefore we need to fix those parts first. KALUGA_DEBUG("Waiting for acpi"); char* record = NULL; errval_t err = oct_wait_for(&record, "acpi { iref: _ }"); free(record); if (err_is_fail(err)) { return err_push(err, KALUGA_ERR_WAITING_FOR_ACPI); } // No we should be able to get core count // of all cores to estimate the amount of // spawnd's we have to expect (one per core) char** names; size_t count; err = oct_get_names(&names, &count, local_apics); if (err_is_fail(err)) { return err_push(err, KALUGA_ERR_QUERY_LOCAL_APIC); } oct_free_names(names, count); static char* spawnds = "r'spawn.[0-9]+' { iref: _ }"; octopus_trigger_id_t tid; return oct_trigger_existing_and_watch(spawnds, spawnd_change_event, (void*)count, &tid); }
static void spawnd_change_event(octopus_mode_t mode, char* record, void* state) { size_t count = (size_t) state; static coreid_t spawnd_counter = 0; if (mode & OCT_ON_SET) { KALUGA_DEBUG("spawnd found: %s\n", record); spawnd_counter++; if (spawnd_counter == count) { KALUGA_DEBUG("Found enough spawnds, setting all_spawnds_up\n"); errval_t err = oct_set("all_spawnds_up { iref: 0 }"); assert(err_is_ok(err)); } } }
static void cpu_change_event(octopus_mode_t mode, char* record, void* state) { if (mode & OCT_ON_SET) { KALUGA_DEBUG("CPU found: %s\n", record); assert(my_core_id == 0); // TODO(gz): why? uint64_t barrelfish_id, arch_id, enabled = 0; errval_t err = oct_read(record, "_ { barrelfish_id: %d, apic_id: %d, enabled: %d }", &barrelfish_id, &arch_id, &enabled); if (err_is_fail(err)) { DEBUG_ERR(err, "Cannot read record."); assert(!"Illformed core record received"); goto out; } struct module_info* mi = find_module("corectrl"); if (mi != NULL) { err = mi->start_function(0, mi, record); if (err_is_fail(err)) { printf("Boot driver not found. Do not boot discovered CPU %"PRIu64".\n", barrelfish_id); goto out; } assert(err_is_ok(err)); } } if (mode & OCT_ON_DEL) { KALUGA_DEBUG("CPU removed: %s\n", record); assert(!"NYI"); } out: assert(!(mode & OCT_REMOVED)); free(record); }
int main(int argc, char** argv) { vfs_init(); init_environ(); errval_t err; my_core_id = disp_get_core_id(); parse_arguments(argc, argv); err = oct_init(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Initialize octopus service."); } KALUGA_DEBUG("Kaluga: parse boot modules...\n"); err = init_boot_modules(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Parse boot modules."); } add_start_function_overrides(); #ifdef __x86__ // We need to run on core 0 // (we are responsible for booting all the other cores) assert(my_core_id == BSP_CORE_ID); KALUGA_DEBUG("Kaluga running on x86.\n"); err = skb_client_connect(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Connect to SKB."); } // Make sure the driver db is loaded err = skb_execute("[device_db]."); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Device DB not loaded."); } // The current boot protocol needs us to have // knowledge about how many CPUs are available at boot // time in order to start-up properly. char* record = NULL; err = oct_barrier_enter("barrier.acpi", &record, 2); KALUGA_DEBUG("Kaluga: watch_for_cores\n"); err = watch_for_cores(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Watching cores."); } KALUGA_DEBUG("Kaluga: pci_root_bridge\n"); err = watch_for_pci_root_bridge(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Watching PCI root bridges."); } KALUGA_DEBUG("Kaluga: pci_devices\n"); err = watch_for_pci_devices(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Watching PCI devices."); } KALUGA_DEBUG("Kaluga: wait_for_all_spawnds\n"); err = wait_for_all_spawnds(); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Unable to wait for spawnds failed."); } #elif __pandaboard__ debug_printf("Kaluga running on Pandaboard.\n"); err = init_cap_manager(); assert(err_is_ok(err)); err = oct_set("all_spawnds_up { iref: 0 }"); assert(err_is_ok(err)); struct module_info* mi = find_module("fdif"); if (mi != NULL) { err = mi->start_function(0, mi, "hw.arm.omap44xx.fdif {}"); assert(err_is_ok(err)); } mi = find_module("mmchs"); if (mi != NULL) { err = mi->start_function(0, mi, "hw.arm.omap44xx.mmchs {}"); assert(err_is_ok(err)); } mi = find_module("mmchs2"); if (mi != NULL) { err = mi->start_function(0, mi, "hw.arm.omap44xx.mmchs {}"); assert(err_is_ok(err)); } mi = find_module("prcm"); if (mi != NULL) { err = mi->start_function(0, mi, "hw.arm.omap44xx.prcm {}"); assert(err_is_ok(err)); } mi = find_module("serial"); if (mi != NULL) { err = mi->start_function(0, mi, "hw.arm.omap44xx.uart {}"); assert(err_is_ok(err)); } mi = find_module("sdma"); if (mi != NULL) { err = mi->start_function(0, mi, "hw.arm.omap44xx.sdma {}"); assert(err_is_ok(err)); } mi = find_module("usb_manager"); if (mi != NULL) { #define USB_ARM_EHCI_IRQ 109 char *buf = malloc(255); uint8_t offset = 0; mi->cmdargs = buf; mi->argc = 3; mi->argv[0] = mi->cmdargs + 0; snprintf(buf + offset, 255 - offset, "ehci\0"); offset += strlen(mi->argv[0]) + 1; mi->argv[1] = mi->cmdargs + offset; snprintf(buf + offset, 255 - offset, "%u\0", 0xC00); offset += strlen(mi->argv[1]) + 1; mi->argv[2] = mi->cmdargs + offset; snprintf(buf+offset, 255-offset, "%u\0", USB_ARM_EHCI_IRQ); // XXX Use customized start function or add to module info err = mi->start_function(0, mi, "hw.arm.omap44xx.usb {}"); assert(err_is_ok(err)); } #elif __gem5__ printf("Kaluga running on GEM5 armv8.\n"); err = init_cap_manager(); assert(err_is_ok(err)); err = oct_set("all_spawnds_up { iref: 0 }"); assert(err_is_ok(err)); struct module_info* mi = find_module("serial"); if (mi != NULL) { err = mi->start_function(0, mi, "hw.arm.gem5.uart {}"); assert(err_is_ok(err)); } #endif THCFinish(); return EXIT_SUCCESS; }
errval_t start_networking(coreid_t core, struct module_info* driver, char* record) { assert(driver != NULL); errval_t err = SYS_ERR_OK; uint64_t vendor_id, device_id, bus, dev, fun; /* check if we are using the supplied pci address of eth0 */ if (eth0.bus != 0xff || eth0.device != 0xff || eth0.function != 0xff) { err = oct_read(record, "_ { bus: %d, device: %d, function: %d, vendor: %d, device_id: %d }", &bus, &dev, &fun, &vendor_id, &device_id); assert(err_is_ok(err)); if ((eth0.bus != (uint8_t)bus) | (eth0.device != (uint8_t)dev) | (eth0.function != (uint8_t)fun)) { KALUGA_DEBUG("start_networking: skipping card %" PRIu64 ":% "PRIu64 ":% " PRIu64"\n", bus, dev, fun); return KALUGA_ERR_DRIVER_NOT_AUTO; } } if (is_started(driver)) { return KALUGA_ERR_DRIVER_ALREADY_STARTED; } if (!is_auto_driver(driver)) { return KALUGA_ERR_DRIVER_NOT_AUTO; } struct module_info* netd = find_module("netd"); if (netd == NULL || !is_auto_driver(netd)) { KALUGA_DEBUG("netd not found or not declared as auto."); return KALUGA_ERR_DRIVER_NOT_AUTO; } struct module_info* ngd_mng = find_module("NGD_mng"); if (ngd_mng == NULL || !is_auto_driver(ngd_mng)) { KALUGA_DEBUG("NGD_mng not found or not declared as auto."); return KALUGA_ERR_DRIVER_NOT_AUTO; } err = default_start_function(core, driver, record); if (err_is_fail(err)) { DEBUG_ERR(err, "Spawning %s failed.", driver->path); return err; } // XXX: Manually add cardname (overwrite first (auto) argument) // +Weird convention, e1000n binary but cardname=e1000 char* cardname = strcmp(driver->binary, "e1000n") == 0 ? "e1000" : driver->binary; size_t name_len = strlen("cardname=") + strlen(cardname) + 1; char* card_argument = malloc(name_len); sprintf(card_argument, "cardname=%s", cardname); printf("############# starting network with arguments %s\n", card_argument); // Spawn netd and ngd_mng netd->argv[0] = card_argument; err = spawn_program(core, netd->path, netd->argv, environ, 0, get_did_ptr(netd)); ngd_mng->argv[0] = card_argument; err = spawn_program(core, ngd_mng->path, ngd_mng->argv, environ, 0, get_did_ptr(ngd_mng)); free(card_argument); return err; }
errval_t start_boot_driver(coreid_t where, struct module_info* mi, char* record) { assert(mi != NULL); errval_t err = SYS_ERR_OK; if (!is_auto_driver(mi)) { return KALUGA_ERR_DRIVER_NOT_AUTO; } // Construct additional command line arguments containing pci-id. // We need one extra entry for the new argument. uint64_t barrelfish_id, apic_id, cpu_type; char **argv = mi->argv; bool cleanup = false; char barrelfish_id_s[10]; size_t argc = mi->argc; KALUGA_DEBUG("Starting corectrl for %s\n", record); err = oct_read(record, "_ { apic_id: %d, barrelfish_id: %d, type: %d }", &apic_id, &barrelfish_id, &cpu_type); if (err_is_ok(err)) { skb_add_fact("corename(%"PRIu64", %s, apic(%"PRIu64")).", barrelfish_id, cpu_type_to_archstr(cpu_type), apic_id); if (barrelfish_id == my_core_id) { return SYS_ERR_OK; } argv = malloc((argc+5) * sizeof(char *)); memcpy(argv, mi->argv, argc * sizeof(char *)); snprintf(barrelfish_id_s, 10, "%"PRIu64"", barrelfish_id); argv[argc] = "boot"; argc += 1; argv[argc] = barrelfish_id_s; argc += 1; // Copy kernel args over to new core struct module_info* cpu_module = find_module("cpu"); if (cpu_module != NULL && strlen(cpu_module->args) > 1) { KALUGA_DEBUG("%s:%s:%d: Boot with cpu arg %s and barrelfish_id_s=%s\n", __FILE__, __FUNCTION__, __LINE__, cpu_module->args, barrelfish_id_s); argv[argc] = "-a"; argc += 1; argv[argc] = cpu_module->args; argc += 1; } argv[argc] = NULL; cleanup = true; } else { DEBUG_ERR(err, "Malformed CPU record?"); return err; } struct capref task_cap_kernel; task_cap_kernel.cnode = cnode_task; task_cap_kernel.slot = TASKCN_SLOT_KERNELCAP; #ifdef KALUGA_SERVICE_DEBUG struct capability info; err = debug_cap_identify(task_cap_kernel, &info); if (err_is_fail(err)) { USER_PANIC_ERR(err, "Can not identify the capability."); } char buffer[1024]; debug_print_cap(buffer, 1024, &info); KALUGA_DEBUG("%s:%d: capability=%s\n", __FILE__, __LINE__, buffer); #endif struct capref inheritcn_cap; err = alloc_inheritcn_with_caps(&inheritcn_cap, NULL_CAP, NULL_CAP, task_cap_kernel); if (err_is_fail(err)) { DEBUG_ERR(err, "alloc_inheritcn_with_caps failed."); } err = spawn_program_with_caps(where, mi->path, argv, environ, inheritcn_cap, NULL_CAP, SPAWN_FLAGS_NEW_DOMAIN, &mi->did[0]); if (err_is_fail(err)) { DEBUG_ERR(err, "Spawning %s failed.", mi->path); } if (cleanup) { free(argv); } return err; }