1/** \file 2 * \brief Monitor's connection with the dispatchers on the same core 3 */ 4 5/* 6 * Copyright (c) 2009, 2010, 2011, 2013, ETH Zurich. 7 * All rights reserved. 8 * 9 * This file is distributed under the terms in the attached LICENSE file. 10 * If you do not find this file, copies can be found by writing to: 11 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 12 */ 13 14#include "monitor.h" 15#include <barrelfish/cap_predicates.h> 16#include <barrelfish/debug.h> // XXX: To set the cap_identify_reply handler 17#include <barrelfish/sys_debug.h> // XXX: for sys_debug_send_ipi 18#include <trace/trace.h> 19#include <trace_definitions/trace_defs.h> 20#include <if/mem_defs.h> 21#include <if/proc_mgmt_defs.h> 22#include <barrelfish/monitor_client.h> 23#include <barrelfish/spawn_client.h> 24#include <barrelfish/syscalls.h> 25#include <barrelfish_kpi/distcaps.h> 26#include <if/monitor_loopback_defs.h> 27#include <if/monitor_defs.h> 28#include <if/monitor_blocking_defs.h> 29#include "capops.h" 30#include "caplock.h" 31#include "send_cap.h" 32 33// the monitor's loopback binding to itself 34static struct monitor_binding monitor_self_binding; 35 36/* ---------------------- MULTIBOOT REQUEST CODE START ---------------------- */ 37 38struct multiboot_cap_state { 39 struct monitor_msg_queue_elem elem; 40 cslot_t slot; 41}; 42 43struct proc_mgmt_bind_st { 44 errval_t err; 45 bool present; 46}; 47 48static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot); 49 50static void ms_multiboot_cap_request_handler(struct monitor_binding *b, 51 struct monitor_msg_queue_elem *e) 52{ 53 struct multiboot_cap_state *ms = (struct multiboot_cap_state*)e; 54 ms_multiboot_cap_request(b, ms->slot); 55 free(ms); 56} 57 58static void ms_multiboot_cap_request(struct monitor_binding *b, cslot_t slot) 59{ 60 errval_t err1, err2; 61 62 struct capref cap = { 63 .cnode = cnode_module, 64 .slot = slot, 65 }; 66 67 // Call frame_identify to check if cap exists 68 struct frame_identity id; 69 err1 = frame_identify(cap, &id); 70 if (err_is_fail(err1)) { 71 err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, NULL_CAP, err1); 72 } else { 73 err2 = b->tx_vtbl.multiboot_cap_reply(b, NOP_CONT, cap, err1); 74 } 75 if (err_is_fail(err2)) { 76 if (err_no(err2) == FLOUNDER_ERR_TX_BUSY) { 77 struct monitor_state *mon_state = b->st; 78 struct multiboot_cap_state *ms = 79 malloc(sizeof(struct multiboot_cap_state)); 80 assert(ms); 81 ms->slot = slot; 82 ms->elem.cont = ms_multiboot_cap_request_handler; 83 err1 = monitor_enqueue_send(b, &mon_state->queue, 84 get_default_waitset(), &ms->elem.queue); 85 if (err_is_fail(err1)) { 86 USER_PANIC_ERR(err1, "monitor_enqueue_send failed"); 87 } 88 } else { 89 USER_PANIC_ERR(err2, "sending multiboot_cap_reply failed"); 90 } 91 } 92} 93 94/* ----------------------- MULTIBOOT REQUEST CODE END ----------------------- */ 95 96static void alloc_iref_reply_handler(struct monitor_binding *b, 97 struct monitor_msg_queue_elem *e); 98 99struct alloc_iref_reply_state { 100 struct monitor_msg_queue_elem elem; 101 struct monitor_alloc_iref_reply__tx_args args; 102 struct monitor_binding *b; 103}; 104 105static void alloc_iref_reply_cont(struct monitor_binding *b, 106 uintptr_t service_id, 107 iref_t iref, errval_t reterr) 108{ 109 errval_t err; 110 111 err = b->tx_vtbl.alloc_iref_reply(b, NOP_CONT, service_id, iref, reterr); 112 if (err_is_fail(err)) { 113 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 114 struct alloc_iref_reply_state *me = 115 malloc(sizeof(struct alloc_iref_reply_state)); 116 assert(me != NULL); 117 struct monitor_state *ist = b->st; 118 assert(ist != NULL); 119 me->args.service_id = service_id; 120 me->args.iref = iref; 121 me->args.err = reterr; 122 me->b = b; 123 me->elem.cont = alloc_iref_reply_handler; 124 125 err = monitor_enqueue_send(b, &ist->queue, 126 get_default_waitset(), &me->elem.queue); 127 if (err_is_fail(err)) { 128 USER_PANIC_ERR(err, "monitor_enqueue_send failed"); 129 } 130 return; 131 } 132 133 USER_PANIC_ERR(err, "reply failed"); 134 } 135} 136 137static void alloc_iref_reply_handler(struct monitor_binding *b, 138 struct monitor_msg_queue_elem *e) 139{ 140 struct alloc_iref_reply_state *st = (struct alloc_iref_reply_state *)e; 141 alloc_iref_reply_cont(b, st->args.service_id, st->args.iref, 142 st->args.err); 143 free(e); 144} 145 146static void alloc_iref_request(struct monitor_binding *b, 147 uintptr_t service_id) 148{ 149 errval_t reterr; 150 151 iref_t iref = 0; 152 reterr = iref_alloc(b, service_id, &iref); 153 alloc_iref_reply_cont(b, service_id, iref, reterr); 154} 155 156 157static void get_service_id_reply_handler(struct monitor_binding *b, 158 struct monitor_msg_queue_elem *e); 159 160struct get_service_id_reply_state { 161 struct monitor_msg_queue_elem elem; 162 struct monitor_get_service_id_reply__tx_args args; 163 struct monitor_binding *b; 164}; 165 166static void get_service_id_reply_cont(struct monitor_binding *b, errval_t reterr, 167 iref_t iref, uintptr_t service_id) 168{ 169 errval_t err; 170 171 err = b->tx_vtbl.get_service_id_reply(b, NOP_CONT, reterr, iref, service_id); 172 if (err_is_fail(err)) { 173 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 174 struct get_service_id_reply_state *me = 175 malloc(sizeof(struct get_service_id_reply_state)); 176 assert(me != NULL); 177 struct monitor_state *ist = b->st; 178 assert(ist != NULL); 179 me->args.err = reterr; 180 me->args.iref = iref; 181 me->args.service_id = service_id; 182 me->b = b; 183 me->elem.cont = get_service_id_reply_handler; 184 185 err = monitor_enqueue_send(b, &ist->queue, 186 get_default_waitset(), &me->elem.queue); 187 if (err_is_fail(err)) { 188 USER_PANIC_ERR(err, "monitor_enqueue_send failed"); 189 } 190 return; 191 } 192 193 USER_PANIC_ERR(err, "reply failed"); 194 } 195} 196 197static void get_service_id_reply_handler(struct monitor_binding *b, 198 struct monitor_msg_queue_elem *e) 199{ 200 struct get_service_id_reply_state *st = (struct get_service_id_reply_state *)e; 201 get_service_id_reply_cont(b, st->args.err, st->args.iref, st->args.service_id); 202 free(e); 203} 204 205static void get_service_id_request(struct monitor_binding *b, iref_t iref) 206{ 207 errval_t err; 208 struct monitor_binding *serv_binding = NULL; 209 210 /* Look up core_id from the iref */ 211 uint8_t core_id; 212 iref_get_core_id(iref, &core_id); 213 214 // Return error if service on different core 215 if (core_id != my_core_id) { 216 get_service_id_reply_cont(b, MON_ERR_IDC_BIND_NOT_SAME_CORE, iref, 0); 217 return; 218 } 219 220 /* Lookup the server's connection to monitor */ 221 err = iref_get_binding(iref, &serv_binding); 222 if (err_is_fail(err)) { 223 get_service_id_reply_cont(b, err, iref, 0); 224 return; 225 } 226 227 /* Lookup the server's service_id */ 228 uintptr_t service_id; 229 err = iref_get_service_id(iref, &service_id); 230 get_service_id_reply_cont(b, err, iref, service_id); 231} 232 233/******* stack-ripped bind_lmp_service_request *******/ 234 235static void bind_lmp_client_request_error_handler(struct monitor_binding *b, 236 struct monitor_msg_queue_elem *e); 237 238struct bind_lmp_client_request_error_state { 239 struct monitor_msg_queue_elem elem; 240 struct monitor_bind_lmp_reply_client__tx_args args; 241 struct monitor_binding *serv_binding; 242 struct capref ep; 243}; 244 245static void bind_lmp_client_request_error(struct monitor_binding *b, 246 errval_t err, uintptr_t domain_id, 247 struct monitor_binding *serv_binding, 248 struct capref ep) 249{ 250 errval_t err2; 251 252 err2 = b->tx_vtbl.bind_lmp_reply_client(b, NOP_CONT, err, 0, domain_id, 253 NULL_CAP); 254 if (err_is_fail(err2)) { 255 if(err_no(err2) == FLOUNDER_ERR_TX_BUSY) { 256 struct bind_lmp_client_request_error_state *me = 257 malloc(sizeof(struct bind_lmp_client_request_error_state)); 258 assert(me != NULL); 259 struct monitor_state *ist = b->st; 260 assert(ist != NULL); 261 me->args.err = err; 262 me->args.conn_id = domain_id; 263 me->serv_binding = serv_binding; 264 me->ep = ep; 265 me->elem.cont = bind_lmp_client_request_error_handler; 266 267 err = monitor_enqueue_send(b, &ist->queue, 268 get_default_waitset(), &me->elem.queue); 269 if (err_is_fail(err)) { 270 USER_PANIC_ERR(err, "monitor_enqueue_send failed"); 271 } 272 return; 273 } 274 275 USER_PANIC_ERR(err2, "error reply failed"); 276 USER_PANIC_ERR(err, "The reason for lmp failure"); 277 } 278 279 /* Delete the EP cap */ 280 // Do not delete the cap if client or service is monitor itself 281 if (b != &monitor_self_binding && serv_binding != &monitor_self_binding) { 282 err = cap_destroy(ep); 283 if (err_is_fail(err)) { 284 USER_PANIC_ERR(err, "cap_destroy failed"); 285 } 286 } 287} 288 289static void bind_lmp_client_request_error_handler(struct monitor_binding *b, 290 struct monitor_msg_queue_elem *e) 291{ 292 struct bind_lmp_client_request_error_state *st = (struct bind_lmp_client_request_error_state *)e; 293 bind_lmp_client_request_error(b, st->args.err, st->args.conn_id, 294 st->serv_binding, st->ep); 295 free(e); 296} 297 298static void bind_lmp_service_request_handler(struct monitor_binding *b, 299 struct monitor_msg_queue_elem *e); 300 301struct bind_lmp_service_request_state { 302 struct monitor_msg_queue_elem elem; 303 struct monitor_bind_lmp_service_request__tx_args args; 304 struct monitor_binding *b; 305 uintptr_t domain_id; 306}; 307 308static void bind_lmp_service_request_cont(struct monitor_binding *serv_binding, 309 uintptr_t service_id, uintptr_t con_id, 310 size_t buflen, struct capref ep, 311 struct monitor_binding *b, 312 uintptr_t domain_id) 313{ 314 errval_t err, err2; 315 316 struct monitor_state *ist = serv_binding->st; 317 struct event_closure send_cont = NOP_CONT; 318 struct capref *capp = NULL; 319 320 if (serv_binding != &monitor_self_binding && b != &monitor_self_binding) { 321 // save EP cap to be destroyed after the send is done 322 capp = caprefdup(ep); 323 send_cont = MKCONT(destroy_outgoing_cap, capp); 324 } 325 326 err = serv_binding->tx_vtbl. 327 bind_lmp_service_request(serv_binding, send_cont, service_id, 328 con_id, buflen, ep); 329 if (err_is_fail(err)) { 330 free(capp); 331 332 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 333 struct bind_lmp_service_request_state *me = 334 malloc(sizeof(struct bind_lmp_service_request_state)); 335 assert(me != NULL); 336 me->args.service_id = service_id; 337 me->args.mon_id = con_id; 338 me->args.buflen = buflen; 339 me->args.ep = ep; 340 me->b = b; 341 me->domain_id = domain_id; 342 me->elem.cont = bind_lmp_service_request_handler; 343 344 err = monitor_enqueue_send(serv_binding, &ist->queue, 345 get_default_waitset(), &me->elem.queue); 346 if (err_is_fail(err)) { 347 USER_PANIC_ERR(err, "monitor_enqueue_send failed"); 348 } 349 return; 350 } 351 352 err2 = lmp_conn_free(con_id); 353 if (err_is_fail(err2)) { 354 USER_PANIC_ERR(err2, "lmp_conn_free failed"); 355 } 356 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep); 357 return; 358 } 359} 360 361static void bind_lmp_service_request_handler(struct monitor_binding *b, 362 struct monitor_msg_queue_elem *e) 363{ 364 struct bind_lmp_service_request_state *st = (struct bind_lmp_service_request_state *)e; 365 bind_lmp_service_request_cont(b, st->args.service_id, st->args.mon_id, 366 st->args.buflen, st->args.ep, st->b, 367 st->domain_id); 368 free(e); 369} 370 371static void bind_lmp_client_request(struct monitor_binding *b, 372 iref_t iref, uintptr_t domain_id, 373 size_t buflen, struct capref ep) 374{ 375 errval_t err; 376 struct monitor_binding *serv_binding = NULL; 377 378 /* Look up core_id from the iref */ 379 uint8_t core_id; 380 err = iref_get_core_id(iref, &core_id); 381 if (err_is_fail(err)) { 382 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep); 383 return; 384 } 385 386 // Return error if service on different core 387 if (core_id != my_core_id) { 388 err = MON_ERR_IDC_BIND_NOT_SAME_CORE; 389 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep); 390 return; 391 } 392 393 /* Lookup the server's connection to monitor */ 394 err = iref_get_binding(iref, &serv_binding); 395 if (err_is_fail(err)) { 396 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep); 397 return; 398 } 399 400 /* Lookup the server's service_id */ 401 uintptr_t service_id; 402 err = iref_get_service_id(iref, &service_id); 403 if (err_is_fail(err)) { 404 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep); 405 return; 406 } 407 408 /* Check for intra-domain connection */ 409 if (b == serv_binding) { 410 bind_lmp_client_request_error(b, MON_ERR_IDC_BIND_LOCAL, domain_id, serv_binding, ep); 411 return; 412 } 413 414 /* Allocate a new monitor connection */ 415 uintptr_t con_id; 416 struct lmp_conn_state *conn; 417 err = lmp_conn_alloc(&conn, &con_id); 418 if (err_is_fail(err)) { 419 bind_lmp_client_request_error(b, err, domain_id, serv_binding, ep); 420 return; 421 } 422 423 conn->domain_id = domain_id; 424 conn->domain_binding = b; 425 426 /* Send request to the server */ 427 bind_lmp_service_request_cont(serv_binding, service_id, con_id, buflen, ep, 428 b, domain_id); 429} 430 431/******* stack-ripped bind_lmp_reply *******/ 432 433static void bind_lmp_reply_client_handler(struct monitor_binding *b, 434 struct monitor_msg_queue_elem *e); 435 436struct bind_lmp_reply_client_state { 437 struct monitor_msg_queue_elem elem; 438 struct monitor_bind_lmp_reply_client__tx_args args; 439 struct monitor_binding *b; 440}; 441 442static void bind_lmp_reply_client_cont(struct monitor_binding *client_binding, 443 errval_t msgerr, uintptr_t mon_conn_id, 444 uintptr_t client_conn_id, 445 struct capref ep, 446 struct monitor_binding *b) 447{ 448 errval_t err; 449 450 struct monitor_state *ist = client_binding->st; 451 struct event_closure send_cont = NOP_CONT; 452 struct capref *capp = NULL; 453 454 if (client_binding != &monitor_self_binding && b != &monitor_self_binding) { 455 // save EP cap to be destroyed after the send is done 456 capp = caprefdup(ep); 457 send_cont = MKCONT(destroy_outgoing_cap, capp); 458 } 459 460 err = client_binding->tx_vtbl. 461 bind_lmp_reply_client(client_binding, send_cont, 462 SYS_ERR_OK, mon_conn_id, client_conn_id, ep); 463 if (err_is_fail(err)) { 464 free(capp); 465 466 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 467 struct bind_lmp_reply_client_state *me = 468 malloc(sizeof(struct bind_lmp_reply_client_state)); 469 assert(me != NULL); 470 me->args.err = msgerr; 471 me->args.mon_id = mon_conn_id; 472 me->args.conn_id = client_conn_id; 473 me->args.ep = ep; 474 me->b = b; 475 me->elem.cont = bind_lmp_reply_client_handler; 476 477 err = monitor_enqueue_send(client_binding, &ist->queue, 478 get_default_waitset(), &me->elem.queue); 479 if (err_is_fail(err)) { 480 USER_PANIC_ERR(err, "monitor_enqueue_send failed"); 481 } 482 return; 483 } 484 485 USER_PANIC_ERR(err, "failed sending IDC bind reply"); 486 } 487 488 if(err_is_fail(msgerr)) { 489 return; 490 } 491} 492 493static void bind_lmp_reply_client_handler(struct monitor_binding *b, 494 struct monitor_msg_queue_elem *e) 495{ 496 struct bind_lmp_reply_client_state *st = (struct bind_lmp_reply_client_state *)e; 497 bind_lmp_reply_client_cont(b, st->args.err, st->args.mon_id, st->args.conn_id, 498 st->args.ep, st->b); 499 free(e); 500} 501 502static void bind_lmp_reply(struct monitor_binding *b, 503 errval_t msgerr, uintptr_t mon_conn_id, 504 uintptr_t user_conn_id, struct capref ep) 505{ 506 errval_t err; 507 struct monitor_binding *client_binding = NULL; 508 509 struct lmp_conn_state *conn = lmp_conn_lookup(mon_conn_id); 510 if (conn == NULL) { 511 DEBUG_ERR(0, "invalid connection ID"); 512 goto cleanup; 513 } 514 515 client_binding = conn->domain_binding; 516 uintptr_t client_conn_id = conn->domain_id; 517 518 err = lmp_conn_free(mon_conn_id); 519 assert(err_is_ok(err)); 520 521 if (err_is_fail(msgerr)) { 522 bind_lmp_reply_client_cont(client_binding, msgerr, 0, client_conn_id, 523 ep, b); 524 } else { 525 bind_lmp_reply_client_cont(client_binding, SYS_ERR_OK, mon_conn_id, 526 client_conn_id, ep, b); 527 } 528 return; 529 530cleanup: 531 /* Delete the ep cap */ 532 // XXX: Do not delete the cap if client or service is monitor 533 if (client_binding != &monitor_self_binding && b != &monitor_self_binding) { 534 err = cap_destroy(ep); 535 if (err_is_fail(err)) { 536 USER_PANIC_ERR(err, "cap_destroy failed"); 537 } 538 } 539} 540 541/* ---------------------- NEW MONITOR BINDING CODE START -------------------- */ 542 543struct new_monitor_binding_reply_state { 544 struct monitor_msg_queue_elem elem; 545 struct monitor_new_monitor_binding_reply__tx_args args; 546}; 547 548static void 549new_monitor_binding_reply_cont(struct monitor_binding *b, 550 errval_t reterr, struct capref retcap, 551 uintptr_t st); 552 553static void new_monitor_binding_reply_handler(struct monitor_binding *b, 554 struct monitor_msg_queue_elem *e) 555{ 556 struct new_monitor_binding_reply_state *st = 557 (struct new_monitor_binding_reply_state *)e; 558 new_monitor_binding_reply_cont(b, st->args.err, st->args.ep, st->args.st); 559 free(st); 560} 561 562static void 563new_monitor_binding_reply_cont(struct monitor_binding *b, 564 errval_t reterr, struct capref retcap, 565 uintptr_t st) 566{ 567 errval_t err = 568 b->tx_vtbl.new_monitor_binding_reply(b, NOP_CONT, reterr, retcap, st); 569 570 if (err_is_fail(err)) { 571 if (err_no(err) == FLOUNDER_ERR_TX_BUSY) { 572 struct monitor_state *ms = b->st; 573 struct new_monitor_binding_reply_state *me = 574 malloc(sizeof(struct new_monitor_binding_reply_state)); 575 assert(me != NULL); 576 me->args.err = reterr; 577 me->args.ep = retcap; 578 me->args.st = st; 579 me->elem.cont = new_monitor_binding_reply_handler; 580 err = monitor_enqueue_send(b, &ms->queue, 581 get_default_waitset(), &me->elem.queue); 582 if (err_is_fail(err)) { 583 USER_PANIC_ERR(err, "monitor_enqueue_send failed"); 584 } 585 return; 586 } 587 588 USER_PANIC_ERR(err, "failed to send new_monitor_binding_reply"); 589 } 590} 591 592/** 593 * \brief Setup a new idc channel between monitor and domain 594 * 595 * \bug on error send message back to domain 596 */ 597static void new_monitor_binding_request(struct monitor_binding *b, uintptr_t st) 598{ 599 struct capref retcap = NULL_CAP; 600 errval_t err, reterr = SYS_ERR_OK; 601 602 struct monitor_lmp_binding *lmpb = 603 malloc(sizeof(struct monitor_lmp_binding)); 604 assert(lmpb != NULL); 605 606 // setup our end of the binding 607 err = monitor_client_lmp_accept(lmpb, get_default_waitset(), 608 DEFAULT_LMP_BUF_WORDS); 609 if (err_is_fail(err)) { 610 free(lmpb); 611 reterr = err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT); 612 goto out; 613 } 614 615 retcap = lmpb->chan.local_cap; 616 monitor_server_init(&lmpb->b); 617 618out: 619 new_monitor_binding_reply_cont(b, reterr, retcap, st); 620} 621 622/* ---------------------- NEW MONITOR BINDING CODE END ---------------------- */ 623 624static void get_mem_iref_request(struct monitor_binding *b) 625{ 626 errval_t err; 627 628 // Mem serv not registered yet 629 assert(mem_serv_iref != 0); 630 631 err = b->tx_vtbl.get_mem_iref_reply(b, NOP_CONT, mem_serv_iref); 632 if (err_is_fail(err)) { 633 USER_PANIC_ERR(err, "reply failed"); 634 } 635} 636 637static void get_name_iref_request(struct monitor_binding *b, uintptr_t st) 638{ 639 errval_t err; 640 err = b->tx_vtbl.get_name_iref_reply(b, NOP_CONT, name_serv_iref, st); 641 if (err_is_fail(err)) { 642 USER_PANIC_ERR(err, "reply failed"); 643 } 644} 645 646static void get_ramfs_iref_request(struct monitor_binding *b, uintptr_t st) 647{ 648 errval_t err; 649 err = b->tx_vtbl.get_ramfs_iref_reply(b, NOP_CONT, ramfs_serv_iref, st); 650 if (err_is_fail(err)) { 651 USER_PANIC_ERR(err, "reply failed"); 652 } 653} 654 655static void set_mem_iref_request(struct monitor_binding *b, 656 iref_t iref) 657{ 658 mem_serv_iref = iref; 659 update_ram_alloc_binding = true; 660} 661 662 663 664static void get_monitor_rpc_ep_request(struct monitor_binding *b, 665 uintptr_t st_arg) 666{ 667 errval_t err; 668 669 struct capref ep = NULL_CAP; 670 err = monitor_rpc_server_create_endpoint(&ep, b); 671 672 err = b->tx_vtbl.get_monitor_rpc_ep_reply(b, NOP_CONT, err, ep, st_arg); 673 assert(err_is_ok(err)); 674} 675 676 677void set_monitor_rpc_iref(iref_t iref) 678{ 679 if (monitor_rpc_iref != 0) { 680 // Called multiple times, return error 681 DEBUG_ERR(0, "Attempt to reset monitor rpc IREF ignored"); 682 return; 683 } 684 685 monitor_rpc_iref = iref; 686} 687 688 689static void set_name_iref_request(struct monitor_binding *b, 690 iref_t iref) 691{ 692 if (name_serv_iref != 0) { 693 // Called multiple times, return error 694 DEBUG_ERR(0, "Attempt to reset name serv IREF ignored"); 695 return; 696 } 697 698 name_serv_iref = iref; 699} 700 701static void set_ramfs_iref_request(struct monitor_binding *b, 702 iref_t iref) 703{ 704 if (ramfs_serv_iref != 0) { 705 // Called multiple times, return error 706 DEBUG_ERR(0, "Attempt to reset name serv IREF ignored"); 707 return; 708 } 709 710 ramfs_serv_iref = iref; 711} 712 713static void proc_mgmt_bind_cont(void *st, 714 errval_t err, 715 struct proc_mgmt_binding *b) 716{ 717 struct proc_mgmt_bind_st* bind_st = (struct proc_mgmt_bind_st*) st; 718 assert(!bind_st->present); 719 bind_st->err = err; 720 bind_st->present = true; 721} 722 723static void set_proc_mgmt_ep_request(struct monitor_binding *b, 724 struct capref ep) 725{ 726 // We got the endpoint which the process manager has allocated for us. 727 // Time to set up our part of the LMP connection and finish the handshake. 728 struct proc_mgmt_lmp_binding *lmpb = 729 malloc(sizeof(struct proc_mgmt_lmp_binding)); 730 assert(lmpb != NULL); 731 732 set_proc_mgmt_binding(&lmpb->b); 733 734 struct proc_mgmt_bind_st bind_st = { 735 .present = false 736 }; 737 errval_t err = proc_mgmt_client_lmp_bind(lmpb, 738 ep, 739 proc_mgmt_bind_cont, 740 &bind_st, 741 get_default_waitset(), 742 DEFAULT_LMP_BUF_WORDS); 743 if (err_is_fail(err)) { 744 USER_PANIC_ERR(err, "proc_mgmt_client_lmp_bind"); 745 } 746 747 // Dispatch events on the waitset until proc_mgmt binding completes. 748 while (!bind_st.present) { 749 err = event_dispatch(get_default_waitset()); 750 if (err_is_fail(err)) { 751 USER_PANIC_ERR(err, "monitor event dispatch"); 752 } 753 } 754 755 if(err_is_fail(bind_st.err)) { 756 USER_PANIC_ERR(err, "during proc_mgmt bind initialization"); 757 } 758 759 proc_mgmt_rpc_client_init(&lmpb->b); 760} 761 762static void set_spawn_iref_request(struct monitor_binding *b, iref_t iref) 763{ 764 if (spawn_iref != 0) { 765 // Called multiple times, return error 766 DEBUG_ERR(0, "Attempt to reset spawn IREF ignored"); 767 return; 768 } 769 770 spawn_iref = iref; 771} 772 773struct send_cap_st { 774 struct intermon_msg_queue_elem qe; // must be first 775 uintptr_t my_mon_id; 776 struct capref cap; 777 uint32_t capid; 778 uint8_t give_away; 779 struct captx_prepare_state captx_state; 780 intermon_captx_t captx; 781}; 782 783static void 784cap_send_tx_cont(struct intermon_binding *b, 785 struct intermon_msg_queue_elem *e) 786{ 787 DEBUG_CAPOPS("%s: %p %p\n", __FUNCTION__, b, e); 788 errval_t send_err; 789 struct send_cap_st *st = (struct send_cap_st*)e; 790 struct remote_conn_state *conn = remote_conn_lookup(st->my_mon_id); 791 send_err = intermon_cap_send_request__tx(b, NOP_CONT, conn->mon_id, 792 st->capid, st->captx); 793 if (err_is_fail(send_err)) { 794 DEBUG_ERR(send_err, "sending cap_send_request failed"); 795 } 796 free(st); 797} 798 799static void 800cap_send_request_tx_cont(errval_t err, struct captx_prepare_state *captx_st, 801 intermon_captx_t *captx, void *st_) 802{ 803 DEBUG_CAPOPS("%s: %s [%p]\n", __FUNCTION__, err_getstring(err), __builtin_return_address(0)); 804 errval_t queue_err; 805 struct send_cap_st *send_st = (struct send_cap_st*)st_; 806 807 if (err_is_fail(err)) { 808 // XXX: should forward error here 809 DEBUG_ERR(err, "preparing cap tx failed"); 810 free(send_st); 811 return; 812 } 813 814 send_st->captx = *captx; 815 816 DEBUG_CAPOPS("%s: enqueueing send\n", __FUNCTION__); 817 send_st->qe.cont = cap_send_tx_cont; 818 struct remote_conn_state *conn = remote_conn_lookup(send_st->my_mon_id); 819 struct intermon_binding *binding = conn->mon_binding; 820 struct intermon_state *inter_st = (struct intermon_state*)binding->st; 821 queue_err = intermon_enqueue_send(binding, &inter_st->queue, 822 binding->waitset, 823 (struct msg_queue_elem*)send_st); 824 if (err_is_fail(queue_err)) { 825 DEBUG_ERR(queue_err, "enqueuing cap_send_request failed"); 826 free(send_st); 827 } 828} 829 830static void 831cap_send_request(struct monitor_binding *b, uintptr_t my_mon_id, 832 struct capref cap, uint32_t capid) 833{ 834 DEBUG_CAPOPS("cap_send_request\n"); 835 errval_t err; 836 837 struct remote_conn_state *conn; 838 if (my_mon_id == 0x0) { 839 assert(b->st); 840 struct monitor_state *st = b->st; 841 conn = st->conn; 842 assert(conn); 843 my_mon_id = remote_conn_get_id(conn); 844 } else { 845 conn = remote_conn_lookup(my_mon_id); 846 } 847 848 struct send_cap_st *st; 849 st = calloc(1, sizeof(*st)); 850 if (!st) { 851 err = LIB_ERR_MALLOC_FAIL; 852 DEBUG_ERR(err, "Failed to allocate cap_send_request state"); 853 // XXX: should forward error here 854 return; 855 } 856 st->my_mon_id = my_mon_id; 857 st->cap = cap; 858 st->capid = capid; 859 860 captx_prepare_send(cap, conn->core_id, true, &st->captx_state, 861 cap_send_request_tx_cont, st); 862} 863 864static void span_domain_request(struct monitor_binding *mb, 865 uintptr_t domain_id, uint8_t core_id, 866 struct capref vroot, struct capref disp) 867{ 868 errval_t err, err2; 869 870 trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN0, core_id); 871 872 struct span_state *state; 873 uintptr_t state_id; 874 875 err = span_state_alloc(&state, &state_id); 876 if (err_is_fail(err)) { 877 err_push(err, MON_ERR_SPAN_STATE_ALLOC); 878 goto reply; 879 } 880 881 state->core_id = core_id; 882 state->vroot = vroot; 883 state->mb = mb; 884 state->domain_id = domain_id; 885 886 trace_event(TRACE_SUBSYS_MONITOR, TRACE_EVENT_MONITOR_SPAN1, core_id); 887 888 /* Look up the destination monitor */ 889 struct intermon_binding *ib; 890 err = intermon_binding_get(core_id, &ib); 891 if (err_is_fail(err)) { 892 goto reply; 893 } 894 895 /* Idenfity vroot */ 896 struct capability vroot_cap; 897 err = monitor_cap_identify(vroot, &vroot_cap); 898 if (err_is_fail(err)) { 899 err_push(err, MON_ERR_CAP_IDENTIFY); 900 goto reply; 901 } 902 if (vroot_cap.type != ObjType_VNode_x86_64_pml4) { /* Check type */ 903 err = MON_ERR_WRONG_CAP_TYPE; 904 goto reply; 905 } 906 907 /* Identify the dispatcher frame */ 908 struct frame_identity frameid; 909 err = frame_identify(disp, &frameid); 910 if (err_is_fail(err)) { 911 err_push(err, LIB_ERR_FRAME_IDENTIFY); 912 goto reply; 913 } 914 915 err = monitor_remote_relations(disp, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL); 916 if (err_is_fail(err)) { 917 USER_PANIC_ERR(err, "monitor_remote_relations failed"); 918 return; 919 } 920 err = monitor_remote_relations(vroot, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL); 921 if (err_is_fail(err)) { 922 USER_PANIC_ERR(err, "monitor_remote_relations failed"); 923 return; 924 } 925 926 assert((1UL << log2ceil(frameid.bytes)) == frameid.bytes); 927 /* Send msg to destination monitor */ 928 err = ib->tx_vtbl.span_domain_request(ib, NOP_CONT, state_id, 929 get_address(&vroot_cap), 930 frameid.base, frameid.bytes); 931 932 if (err_is_fail(err)) { 933 err_push(err, MON_ERR_SEND_REMOTE_MSG); 934 goto reply; 935 } 936 goto cleanup; 937 938 reply: 939 err2 = mb->tx_vtbl.span_domain_reply(mb, NOP_CONT, err, domain_id); 940 if (err_is_fail(err2)) { 941 // XXX: Cleanup? 942 USER_PANIC_ERR(err2, "Failed to reply to the user domain"); 943 } 944 if(state_id != 0) { 945 err2 = span_state_free(state_id); 946 if (err_is_fail(err2)) { 947 USER_PANIC_ERR(err2, "Failed to free span state"); 948 } 949 } 950 951 cleanup: 952 err2 = cap_destroy(vroot); 953 if (err_is_fail(err2)) { 954 USER_PANIC_ERR(err2, "Failed to destroy span_vroot cap"); 955 } 956 err2 = cap_destroy(disp); 957 if (err_is_fail(err2)) { 958 USER_PANIC_ERR(err2, "Failed to destroy disp cap"); 959 } 960} 961 962static void migrate_dispatcher_request(struct monitor_binding *b, 963 coreid_t coreid, struct capref vroot, 964 struct capref disp) 965{ 966 printf("%s:%d\n", __FUNCTION__, __LINE__); 967} 968 969 970 971struct monitor_rx_vtbl the_table = { 972 .alloc_iref_request = alloc_iref_request, 973 .get_service_id_request = get_service_id_request, 974 975 .bind_lmp_client_request= bind_lmp_client_request, 976 .bind_lmp_reply_monitor = bind_lmp_reply, 977 978 .boot_core_request = boot_core_request, 979 .multiboot_cap_request = ms_multiboot_cap_request, 980 981 .new_monitor_binding_request = new_monitor_binding_request, 982 983 .get_mem_iref_request = get_mem_iref_request, 984 .get_name_iref_request = get_name_iref_request, 985 .get_ramfs_iref_request = get_ramfs_iref_request, 986 .set_mem_iref_request = set_mem_iref_request, 987 .set_name_iref_request = set_name_iref_request, 988 .set_ramfs_iref_request = set_ramfs_iref_request, 989 .set_proc_mgmt_ep_request = set_proc_mgmt_ep_request, 990 .set_spawn_iref_request = set_spawn_iref_request, 991 .get_monitor_rpc_ep_request = get_monitor_rpc_ep_request, 992 993 .cap_send_request = cap_send_request, 994 .cap_move_request = cap_send_request, 995 996 .span_domain_request = span_domain_request, 997 998 .migrate_dispatcher_request = migrate_dispatcher_request, 999}; 1000 1001errval_t monitor_client_setup(struct spawninfo *si) 1002{ 1003 errval_t err; 1004 1005 struct monitor_lmp_binding *b = 1006 malloc(sizeof(struct monitor_lmp_binding)); 1007 assert(b != NULL); 1008 1009 // setup our end of the binding 1010 err = monitor_client_lmp_accept(b, get_default_waitset(), 1011 DEFAULT_LMP_BUF_WORDS); 1012 if (err_is_fail(err)) { 1013 free(b); 1014 return err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT); 1015 } 1016 1017 // copy the endpoint cap to the recipient 1018 struct capref dest = { 1019 .cnode = si->taskcn, 1020 .slot = TASKCN_SLOT_MONITOREP, 1021 }; 1022 1023 err = cap_copy(dest, b->chan.local_cap); 1024 if (err_is_fail(err)) { 1025 // TODO: destroy binding 1026 return err_push(err, LIB_ERR_CAP_COPY); 1027 } 1028 1029 // Copy the performance monitoring cap to all spawned processes. 1030 struct capref src; 1031 dest.cnode = si->taskcn; 1032 dest.slot = TASKCN_SLOT_PERF_MON; 1033 src.cnode = cnode_task; 1034 src.slot = TASKCN_SLOT_PERF_MON; 1035 err = cap_copy(dest, src); 1036 if (err_is_fail(err)) { 1037 return err_push(err, INIT_ERR_COPY_PERF_MON); 1038 } 1039 1040 // copy our receive vtable to the binding 1041 monitor_server_init(&b->b); 1042 1043 return SYS_ERR_OK; 1044} 1045 1046errval_t monitor_client_setup_mem_serv(void) 1047{ 1048 /* construct special-case LMP connection to mem_serv */ 1049 static struct monitor_lmp_binding mcb; 1050 struct waitset *ws = get_default_waitset(); 1051 errval_t err; 1052 1053 err = monitor_client_lmp_accept(&mcb, ws, DEFAULT_LMP_BUF_WORDS); 1054 if(err_is_fail(err)) { 1055 USER_PANIC_ERR(err, "monitor_client_setup_mem_serv"); 1056 } 1057 assert(err_is_ok(err)); 1058 1059 /* Send the cap for this endpoint to init, who will pass it to the monitor */ 1060 err = lmp_ep_send0(cap_initep, 0, mcb.chan.local_cap); 1061 if (err_is_fail(err)) { 1062 USER_PANIC_ERR(err, "lmp_ep_send0 failed"); 1063 } 1064 1065 // copy our receive vtable to the binding 1066 monitor_server_init(&mcb.b); 1067 1068 // XXX: handle messages (ie. block) until the monitor binding is ready 1069 while (capref_is_null(mcb.chan.remote_cap)) { 1070 err = event_dispatch(ws); 1071 if (err_is_fail(err)) { 1072 DEBUG_ERR(err, "in event_dispatch waiting for mem_serv binding"); 1073 return err_push(err, LIB_ERR_EVENT_DISPATCH); 1074 } 1075 } 1076 1077 return SYS_ERR_OK; 1078} 1079 1080/// Setup a dummy monitor binding that "sends" all requests to the local handlers 1081errval_t monitor_client_setup_monitor(void) 1082{ 1083 monitor_loopback_init(&monitor_self_binding); 1084 monitor_server_init(&monitor_self_binding); 1085 set_monitor_binding(&monitor_self_binding); 1086 caplock_init(get_default_waitset()); 1087 idc_init(); 1088 // XXX: Need a waitset here or loopback won't work as expected 1089 // when binding to the ram_alloc service 1090 monitor_self_binding.mutex.equeue.waitset = get_default_waitset(); 1091 1092 return SYS_ERR_OK; 1093} 1094 1095errval_t monitor_server_init(struct monitor_binding *b) 1096{ 1097 struct monitor_state *lst = calloc(1, sizeof(struct monitor_state)); 1098 assert(lst != NULL); 1099 lst->queue.head = lst->queue.tail = NULL; 1100 1101 // copy our receive vtable to the new binding 1102 b->rx_vtbl = the_table; 1103 b->st = lst; 1104 // TODO: set error_handler 1105 1106#ifdef CONFIG_INTERCONNECT_DRIVER_UMP 1107 errval_t err; 1108 err = ump_monitor_init(b); 1109 if (err_is_fail(err)) { 1110 USER_PANIC_ERR(err, "ump_monitor_init failed"); 1111 } 1112#endif 1113 1114#ifdef CONFIG_INTERCONNECT_DRIVER_MULTIHOP 1115 errval_t err2; 1116 err2 = multihop_monitor_init(b); 1117 if (err_is_fail(err2)) { 1118 USER_PANIC_ERR(err2, "multihop_monitor_init failed"); 1119 } 1120#endif // CONFIG_INTERCONNECT_DRIVER_MULTIHOP 1121 1122#ifdef CONFIG_TRACE 1123 errval_t err3; 1124 err3 = bfscope_monitor_init(b); 1125 if (err_is_fail(err3)) { 1126 USER_PANIC_ERR(err3, "bfscope_monitor_init failed"); 1127 } 1128 1129 err3 = trace_monitor_init(b); 1130 if (err_is_fail(err3)) { 1131 USER_PANIC_ERR(err3, "trace_monitor_init failed"); 1132 } 1133#endif // CONFIG_TRACE 1134 1135 return monitor_server_arch_init(b); 1136} 1137