1/** 2 * \file 3 * \brief Code for handling booting additional cores 4 */ 5 6/* 7 * Copyright (c) 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 "monitor.h" 16 17/** 18 * \brief Initialize monitor running on app cores 19 */ 20errval_t boot_arch_app_core(int argc, char *argv[], 21 coreid_t *ret_parent_coreid, 22 struct intermon_binding **ret_binding) 23 24{ 25 errval_t err; 26 27 assert(argc == 4); 28 29 // core_id of the core that booted this core 30 coreid_t core_id = strtol(argv[1], NULL, 10); 31 *ret_parent_coreid = core_id; 32 33#ifdef CONFIG_FLOUNDER_BACKEND_UMP_IPI 34 // other monitor's channel id 35 assert(strncmp("chanid", argv[2], strlen("chanid")) == 0); 36 int chan_id = strtol(strchr(argv[2], '=') + 1, NULL, 10); 37 38 // arch id of the core that booted us 39 assert(strncmp("archid", argv[3], strlen("archid")) == 0); 40 int arch_id = strtol(strchr(argv[3], '=') + 1, NULL, 10); 41#endif 42 43 // check that the frame is big enough 44 struct capref frame = { 45 .cnode = cnode_task, 46 .slot = TASKCN_SLOT_MON_URPC, 47 }; 48 struct frame_identity frameid; 49 err = invoke_frame_identify(frame, &frameid); 50 if (err_is_fail(err)) { 51 err = err_push(err, LIB_ERR_FRAME_IDENTIFY); 52 return err; 53 } 54 55 size_t framesize = frameid.bytes; 56 if (framesize < 2 * MON_URPC_CHANNEL_LEN) { 57 return LIB_ERR_UMP_FRAME_OVERFLOW; 58 } 59 60 // map it in 61 void *buf; 62 err = vspace_map_one_frame(&buf, framesize, frame, NULL, NULL); 63 if (err_is_fail(err)) { 64 err = err_push(err, LIB_ERR_VSPACE_MAP); 65 return err; 66 } 67 68#ifdef CONFIG_FLOUNDER_BACKEND_UMP_IPI 69 // Create notify cap to other monitor 70 struct capref notify_cap; 71 err = notification_create_cap(chan_id, arch_id, ¬ify_cap); 72 assert(err == SYS_ERR_OK); 73 74 // Allocate my own notification caps 75 struct capref ep, my_notify_cap; 76 struct lmp_endpoint *iep; 77 int chanid; 78 err = endpoint_create(LMP_RECV_LENGTH, &ep, &iep); 79 assert(err_is_ok(err)); 80 err = notification_allocate(ep, &chanid); 81 assert(err == SYS_ERR_OK); 82 assert(chanid == 1); // Make sure it's channel 1 83 uintptr_t my_arch_id; 84 err = invoke_monitor_get_arch_id(&my_arch_id); 85 assert(err == SYS_ERR_OK); 86 err = notification_create_cap(chanid, my_arch_id, &my_notify_cap); 87 assert(err == SYS_ERR_OK); 88 89 // setup our side of the binding 90 struct intermon_ump_ipi_binding *umpb = 91 malloc(sizeof(struct intermon_ump_ipi_binding)); 92 assert(umpb != NULL); 93 94 err = intermon_ump_ipi_init(umpb, get_default_waitset(), 95 buf + MON_URPC_CHANNEL_LEN, 96 MON_URPC_CHANNEL_LEN, 97 buf, MON_URPC_CHANNEL_LEN, notify_cap, 98 my_notify_cap, ep, iep); 99#else 100 struct intermon_ump_binding *umpb; 101 umpb = malloc(sizeof(struct intermon_ump_binding)); 102 assert(umpb != NULL); 103 104 err = intermon_ump_init(umpb, get_default_waitset(), 105 (char *)buf + MON_URPC_CHANNEL_LEN, 106 MON_URPC_CHANNEL_LEN, 107 buf, MON_URPC_CHANNEL_LEN); 108#endif 109 if (err_is_fail(err)) { 110 err = err_push(err, LIB_ERR_UMP_CHAN_BIND); 111 return err; 112 } 113 114 // Identify UMP frame for tracing 115 umpb->ump_state.chan.sendid = (uintptr_t)frameid.base; 116 umpb->ump_state.chan.recvid = 117 (uintptr_t)(frameid.base + MON_URPC_CHANNEL_LEN); 118 119 *ret_binding = &umpb->b; 120 121 return SYS_ERR_OK; 122} 123 124