1/** 2 * \file 3 * \brief Code for handling booting additional cores 4 */ 5 6/* 7 * Copyright (c) 2010, 2012, 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 "monitor.h" 16#include <inttypes.h> 17#include <barrelfish_kpi/cpu.h> // for cpu_type_to_archstr() 18 19#if defined(CONFIG_FLOUNDER_BACKEND_UMP) 20/* Use to figure out when all monitors initialized. */ 21int seen_connections = 0; 22 23static errval_t trace_ump_frame_identify(struct capref frame, 24 struct intermon_ump_binding* b, 25 size_t channel_length) 26{ 27 // Identify UMP frame for tracing 28 struct frame_identity umpid; 29 errval_t err = invoke_frame_identify(frame, &umpid); 30 if (err_is_fail(err)) { 31 DEBUG_ERR(err, "invoke frame identity failed"); 32 return err; 33 } 34 35 b->ump_state.chan.recvid = (uintptr_t)umpid.base; 36 b->ump_state.chan.sendid = (uintptr_t) 37 (umpid.base + channel_length); 38 39 return SYS_ERR_OK; 40} 41 42 43/** 44 * \brief Msg handler for booting a given core 45 * 46 * \param id id of the core to boot 47 * \param hwid hardware specific id of the core to boot 48 * \param cpu_type Type of cpu to boot 49 * \param cmdline command-line args for kernel 50 * 51 * \bug Verify that cpu_type matches the elf image 52 */ 53void boot_core_request(struct monitor_binding *b, coreid_t id, 54 struct capref frame) 55{ 56 errval_t err; 57 struct intermon_state *imon_st = NULL; 58 59 struct intermon_binding *ibind; 60 err = intermon_binding_get(id, &ibind); 61 if (err_is_ok(err)) { 62 imon_st = ibind->st; 63 imon_st->originating_client = b; 64 imon_st->capops_ready = false; 65 return; 66 } 67 68 69 // Setup new inter-monitor connection to ourselves 70#ifdef CONFIG_FLOUNDER_BACKEND_UMP_IPI 71 struct intermon_ump_ipi_binding *ump_binding = malloc(sizeof( 72 struct intermon_ump_ipi_binding)); 73#else 74 struct intermon_ump_binding *ump_binding = malloc(sizeof( 75 struct intermon_ump_binding)); 76#endif 77 assert(ump_binding != NULL); 78 79 // map it in 80 void *buf; 81 err = vspace_map_one_frame(&buf, MON_URPC_SIZE, frame, NULL, NULL); 82 if (err_is_fail(err)) { 83 err = err_push(err, LIB_ERR_VSPACE_MAP); 84 goto cleanup; 85 } 86 87#ifdef CONFIG_FLOUNDER_BACKEND_UMP_IPI 88 // Get my arch ID 89 uintptr_t my_arch_id = 0; 90 err = invoke_monitor_get_arch_id(&my_arch_id); 91 assert(err == SYS_ERR_OK); 92 93 // Bootee's notify channel ID is always 1 94 struct capref notify_cap; 95 err = notification_create_cap(1, hwid, ¬ify_cap); 96 assert(err == SYS_ERR_OK); 97 98 // Allocate my own notification caps 99 struct capref ep, my_notify_cap; 100 struct lmp_endpoint *iep; 101 int chanid; 102 err = endpoint_create(LMP_RECV_LENGTH, &ep, &iep); 103 assert(err_is_ok(err)); 104 err = notification_allocate(ep, &chanid); 105 assert(err == SYS_ERR_OK); 106 err = notification_create_cap(chanid, my_arch_id, &my_notify_cap); 107 assert(err == SYS_ERR_OK); 108 109 // init our end of the binding and channel 110 err = intermon_ump_ipi_init(ump_binding, get_default_waitset(), 111 buf, MON_URPC_CHANNEL_LEN, 112 buf + MON_URPC_CHANNEL_LEN, 113 MON_URPC_CHANNEL_LEN, notify_cap, 114 my_notify_cap, ep, iep); 115#else 116 err = intermon_ump_init(ump_binding, get_default_waitset(), 117 buf, MON_URPC_CHANNEL_LEN, 118 (char *)buf + MON_URPC_CHANNEL_LEN, 119 MON_URPC_CHANNEL_LEN); 120#endif 121 if (err_is_fail(err)) { 122 err = err_push(err, LIB_ERR_UMP_CHAN_BIND); 123 goto cleanup; 124 } 125 126 err = trace_ump_frame_identify(frame, ump_binding, 127 MON_URPC_CHANNEL_LEN); 128 if (err_is_fail(err)) { 129 goto cleanup; 130 } 131 132 struct intermon_binding* ib = (struct intermon_binding*)ump_binding; 133 err = intermon_init(ib, id); 134 imon_st = ib->st; 135 imon_st->originating_client = b; 136 imon_st->capops_ready = false; 137 138 return; 139 140cleanup: 141 if (err_is_fail(err)) { 142 // Cleanup 143 DEBUG_ERR(err, "Failed to register intermon binding."); 144 cap_destroy(frame); 145 free(ump_binding); 146 } 147 148 errval_t err2 = b->tx_vtbl.boot_core_reply(b, NOP_CONT, err); 149 if (err_is_fail(err2)) { 150 USER_PANIC_ERR(err2, "sending boot_core_reply failed"); 151 } 152} 153#else 154void boot_core_request(struct monitor_binding *b, coreid_t id, 155 struct capref frame) { 156 printf("%s:%s:%d: unable to handle: boot_core_request\n", 157 __FILE__, __FUNCTION__, __LINE__); 158} 159#endif 160