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