1/** 2 * \file 3 * \brief UMP channel support 4 */ 5 6/* 7 * Copyright (c) 2009, 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <inttypes.h> 16#include <if/monitor_blocking_defs.h> 17#include "monitor.h" 18/******* stack-ripped monitor_bind_ump_client_request *******/ 19 20static void monitor_bind_ump_client_request_error(struct monitor_binding *b, 21 struct capref frame, 22 uintptr_t conn_id, 23 uintptr_t domain_id, 24 errval_t err) 25{ 26 errval_t err2; 27 28 err2 = cap_destroy(frame); 29 if (err_is_fail(err2)) { 30 USER_PANIC_ERR(err, "cap_destroy failed"); 31 } 32 33 if (conn_id != 0) { 34 err2 = remote_conn_free(conn_id); 35 if (err_is_fail(err2)) { 36 USER_PANIC_ERR(err2, "remote_conn_free failed"); 37 } 38 } 39 40 err2 = b->tx_vtbl.bind_ump_reply_client(b, NOP_CONT, 0, domain_id, err, 41 NULL_CAP); 42 if (err_is_fail(err2)) { 43 USER_PANIC_ERR(err2, "error reply failed"); 44 } 45} 46 47static void bind_ump_request_handler(struct intermon_binding *b, 48 struct intermon_msg_queue_elem *e); 49 50struct bind_ump_request_state { 51 struct intermon_msg_queue_elem elem; 52 struct intermon_bind_ump_request__tx_args args; 53 struct frame_identity frameid; 54 struct capability capability; 55 struct monitor_binding *mb; 56 struct capref frame; 57 uintptr_t domain_id; 58}; 59 60static void bind_ump_request_cont(struct intermon_binding *intermon_binding, 61 iref_t iref, uintptr_t conn_id, 62 uint32_t channel_length_in, 63 uint32_t channel_length_out, 64 struct frame_identity frameid, 65 struct capability capability, 66 struct monitor_binding *mb, 67 struct capref frame, 68 uintptr_t domain_id) 69{ 70 errval_t err; 71 72 intermon_caprep_t caprep; 73 capability_to_caprep(&capability, &caprep); 74 75 assert((1UL << log2ceil(frameid.bytes)) == frameid.bytes); 76 /* Send the request to the monitor on the server's core */ 77 err = intermon_binding->tx_vtbl. 78 bind_ump_request(intermon_binding, NOP_CONT, iref, conn_id, channel_length_in, 79 channel_length_out, frameid.base, log2ceil(frameid.bytes), 80 caprep); 81 if (err_is_fail(err)) { 82 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 83 struct bind_ump_request_state *me = 84 malloc(sizeof(struct bind_ump_request_state)); 85 struct intermon_state *ist = intermon_binding->st; 86 me->args.iref = iref; 87 me->args.mon_id = conn_id; 88 me->args.channel_length_in = channel_length_in; 89 me->args.channel_length_out = channel_length_out; 90 me->frameid = frameid; 91 me->capability = capability; 92 me->mb = mb; 93 me->frame = frame; 94 me->domain_id = domain_id; 95 me->elem.cont = bind_ump_request_handler; 96 97 err = intermon_enqueue_send(intermon_binding, &ist->queue, 98 get_default_waitset(), &me->elem.queue); 99 assert(err_is_ok(err)); 100 return; 101 } 102 103 USER_PANIC_ERR(err, "failed forwarding UMP bind request"); 104 monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err); 105 } 106} 107 108static void bind_ump_request_handler(struct intermon_binding *b, 109 struct intermon_msg_queue_elem *e) 110{ 111 struct bind_ump_request_state *st = (struct bind_ump_request_state *)e; 112 bind_ump_request_cont(b, st->args.iref, st->args.mon_id, 113 st->args.channel_length_in, 114 st->args.channel_length_out, st->frameid, 115 st->capability, st->mb, st->frame, st->domain_id); 116 free(e); 117} 118 119static void monitor_bind_ump_client_request(struct monitor_binding *mb, 120 iref_t iref, uintptr_t domain_id, 121 struct capref frame, 122 size_t channel_length_in, 123 size_t channel_length_out, 124 struct capref notify) 125{ 126 uint8_t core_id; 127 uintptr_t conn_id = 0; 128 errval_t err; 129 struct remote_conn_state *conn = NULL; 130 131 // Get the core id 132 err = iref_get_core_id(iref, &core_id); 133 if (err_is_fail(err)) { 134 debug_err(__FILE__, __func__, __LINE__, err, "iref_get_core_id failed"); 135 monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err); 136 return; 137 } 138 139 if (core_id == my_core_id) { 140 USER_PANIC("Same-core UMP binding NYI"); 141 } 142 143 /* Identify frame */ 144 struct frame_identity frameid; 145 err = frame_identify(frame, &frameid); 146 if (err_is_fail(err)) { 147 debug_err(__FILE__, __func__, __LINE__, err, "frame_identify failed"); 148 monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err); 149 return; 150 } 151 152 // Identify notify cap 153 struct capability capability; 154 err = monitor_cap_identify(notify, &capability); 155 if (err_is_fail(err)) { 156 USER_PANIC_ERR(err, "monitor_cap_identify failed, ignored"); 157 return; 158 } 159 assert(capability.type == ObjType_Notify_IPI 160 || capability.type == ObjType_Null); 161 /* assert(capability.u.notify.coreid == my_core_id); */ 162 163 /* Forward request to the corresponding monitor */ 164 // Create local state 165 err = remote_conn_alloc(&conn, &conn_id, REMOTE_CONN_UMP); 166 if (err_is_fail(err)) { 167 debug_err(__FILE__, __func__, __LINE__, err, "remote_conn_alloc failed"); 168 monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err); 169 return; 170 } 171 172 err = monitor_remote_relations(frame, RRELS_COPY_BIT, RRELS_COPY_BIT, NULL); 173 if (err_is_fail(err)) { 174 DEBUG_ERR(err, "setting remote copy bit failed"); 175 monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err); 176 return; 177 } 178 179 // Track data 180 conn->domain_id = domain_id; 181 conn->domain_binding = mb; 182 conn->x.ump.frame = frame; 183 conn->core_id = core_id; 184 185 // Get connection to the monitor to forward request to 186 struct intermon_binding *intermon_binding; 187 err = intermon_binding_get(core_id, &intermon_binding); 188 if (err_is_fail(err)) { 189 debug_err(__FILE__, __func__, __LINE__, err, "intermon_binding_get failed"); 190 monitor_bind_ump_client_request_error(mb, frame, conn_id, domain_id, err); 191 return; 192 } 193 194 bind_ump_request_cont(intermon_binding, iref, conn_id, channel_length_in, 195 channel_length_out, frameid, capability, mb, frame, 196 domain_id); 197} 198 199/******* stack-ripped monitor_bind_ump_reply *******/ 200 201static void bind_ump_reply_handler(struct intermon_binding *b, 202 struct intermon_msg_queue_elem *e); 203 204struct bind_ump_reply_state { 205 struct intermon_msg_queue_elem elem; 206 struct intermon_bind_ump_reply__tx_args args; 207 struct capability capability; 208}; 209 210static void bind_ump_reply_cont(struct intermon_binding *mon_binding, 211 uintptr_t your_mon_id, uintptr_t my_mon_id, 212 uintptr_t msgerr, struct capability capability) 213{ 214 errval_t err; 215 216 intermon_caprep_t caprep; 217 capability_to_caprep(&capability, &caprep); 218 219 err = mon_binding->tx_vtbl. 220 bind_ump_reply(mon_binding, NOP_CONT, your_mon_id, my_mon_id, msgerr, 221 caprep); 222 if (err_is_fail(err)) { 223 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 224 struct bind_ump_reply_state *me = 225 malloc(sizeof(struct bind_ump_reply_state)); 226 struct intermon_state *ist = mon_binding->st; 227 me->args.con_id = your_mon_id; 228 me->args.mon_id = my_mon_id; 229 me->args.err = msgerr; 230 me->capability = capability; 231 me->elem.cont = bind_ump_reply_handler; 232 233 err = intermon_enqueue_send(mon_binding, &ist->queue, 234 get_default_waitset(), &me->elem.queue); 235 assert(err_is_ok(err)); 236 return; 237 } 238 239 USER_PANIC_ERR(err, "failed forwarding UMP bind reply"); 240 // cleanup 241 if (err_is_ok(msgerr)) { 242 err = remote_conn_free(my_mon_id); 243 assert(err_is_ok(err)); 244 } 245 } 246} 247 248static void bind_ump_reply_handler(struct intermon_binding *b, 249 struct intermon_msg_queue_elem *e) 250{ 251 struct bind_ump_reply_state *st = (struct bind_ump_reply_state *)e; 252 bind_ump_reply_cont(b, st->args.con_id, st->args.mon_id, st->args.err, 253 st->capability); 254 free(e); 255} 256 257static void monitor_bind_ump_reply(struct monitor_binding *dom_binding, 258 uintptr_t my_mon_id, uintptr_t domain_id, 259 errval_t msgerr, struct capref notify) 260{ 261 errval_t err; 262 263 struct remote_conn_state *conn = remote_conn_lookup(my_mon_id); 264 if (conn == NULL) { 265 USER_PANIC("invalid mon_id in UMP bind reply"); 266 return; 267 } 268 269 uintptr_t your_mon_id = conn->mon_id; 270 struct intermon_binding *mon_binding = conn->mon_binding; 271 272 if (err_is_ok(msgerr)) { 273 /* Connection accepted */ 274 conn->domain_id = domain_id; 275 conn->domain_binding = dom_binding; 276 } else { 277//error: 278 /* Free the cap */ 279 err = cap_destroy(conn->x.ump.frame); 280 assert(err_is_ok(err)); 281 282 err = remote_conn_free(my_mon_id); 283 assert(err_is_ok(err)); 284 } 285 286 // Identify notify cap 287 struct capability capability; 288 err = monitor_cap_identify(notify, &capability); 289 if (err_is_fail(err)) { 290 USER_PANIC_ERR(err, "monitor_cap_identify failed, ignored"); 291 return; 292 } 293 assert(capability.type == ObjType_Notify_IPI 294 || capability.type == ObjType_Null); 295 /* assert(capability.u.notify.coreid == my_core_id); */ 296 297 bind_ump_reply_cont(mon_binding, your_mon_id, my_mon_id, msgerr, capability); 298} 299 300/******* stack-ripped intermon_ump_route_setup_reply *******/ 301 302struct ump_route_setup_reply_state { 303 struct intermon_msg_queue_elem elem; 304 struct intermon_ump_route_setup_reply__tx_args args; 305}; 306 307static void 308intermon_ump_route_setup_reply_handler(struct intermon_binding *b, 309 struct intermon_msg_queue_elem *e); 310 311static void intermon_ump_route_setup_reply_cont(struct intermon_binding *ib, 312 uintptr_t myconid, uintptr_t yourconid, 313 uintptr_t state, errval_t argerr) 314{ 315 errval_t err; 316 317 err = ib->tx_vtbl.ump_route_setup_reply(ib, NOP_CONT, yourconid, myconid, 318 state, argerr); 319 if (err_is_fail(err)) { 320 if(err_no(err) != FLOUNDER_ERR_TX_BUSY) { 321 DEBUG_ERR(err, "non transient error in intermon binding\n"); 322 return; 323 } 324 struct ump_route_setup_reply_state *rst = calloc(1, sizeof(*rst)); 325 if (rst == NULL) { 326 DEBUG_ERR(err, "cannot allocate memory for reply state\n"); 327 return; 328 } 329 330 rst->args.state = state; 331 rst->args.myconid = myconid; 332 rst->args.yourconid = yourconid; 333 rst->args.err = argerr; 334 rst->elem.cont = intermon_ump_route_setup_reply_handler; 335 336 struct intermon_state *ist = ib->st; 337 err = intermon_enqueue_send(ib, &ist->queue, 338 get_default_waitset(), &rst->elem.queue); 339 if (err_is_fail(err)) { 340 DEBUG_ERR(err, "faield to enqueue send"); 341 } 342 } 343} 344 345 346static void 347intermon_ump_route_setup_reply_handler(struct intermon_binding *b, 348 struct intermon_msg_queue_elem *e) 349{ 350 struct ump_route_setup_reply_state *st; 351 352 st = (struct ump_route_setup_reply_state *)e; 353 intermon_ump_route_setup_reply_cont(b, st->args.myconid, st->args.yourconid, 354 st->args.state, st->args.err); 355 free(e); 356} 357 358 359 360static void intermon_ump_route_setup_reply(struct intermon_binding *ib, 361 intermon_con_id_t myconid, 362 intermon_con_id_t yourconid, 363 intermon_mon_id_t state, 364 errval_t err) 365{ 366 struct remote_conn_state *conn = remote_conn_lookup(myconid); 367 368 conn->mon_id = yourconid; 369 assert(conn->domain_binding); 370 371 struct monitor_lmp_binding *lmpb = (struct monitor_lmp_binding *)conn->domain_binding; 372 373 struct monitor_state *st = lmpb->b.st; 374 st->conn = conn; 375 /* send the reply */ 376#ifndef __ARM_ARCH_7A__ 377 struct monitor_blocking_binding *b = (void *) state; 378#else 379 struct monitor_blocking_binding *b = (void *)(uint32_t) state; 380#endif 381 err = b->tx_vtbl.new_monitor_binding_response(b, NOP_CONT, lmpb->chan.local_cap, err); 382} 383 384 385 386/******* stack-ripped intermon_ump_route_setup_request *******/ 387 388struct ump_route_setup_request_state { 389 struct intermon_msg_queue_elem msgq; 390 struct remote_conn_state *cst; 391 struct monitor_blocking_binding *mb; 392}; 393 394static void 395intermon_ump_route_setup_request_handler(struct intermon_binding *b, 396 struct intermon_msg_queue_elem *e) 397{ 398 errval_t err; 399 struct ump_route_setup_request_state *st; 400 401 st = (struct ump_route_setup_request_state *)e; 402 err = ump_route_setup(b, st->mb, st->cst); 403 if (err_is_fail(err)) { 404 struct remote_conn_state *conn = st->cst; 405 assert(conn); 406 struct monitor_lmp_binding *lmpb = (struct monitor_lmp_binding *)conn->domain_binding; 407 monitor_lmp_destroy(lmpb); 408 free(conn->domain_binding); 409 remote_conn_free(remote_conn_get_id(conn)); 410 411 err = st->mb->tx_vtbl.new_monitor_binding_response(st->mb, NOP_CONT, 412 NULL_CAP, err); 413 assert(err_is_ok(err)); 414 } 415 free(e); 416} 417 418 419errval_t ump_route_setup(struct intermon_binding *ib, 420 struct monitor_blocking_binding *mb, 421 struct remote_conn_state *cst) 422{ 423 errval_t err; 424 425 uintptr_t conid = remote_conn_get_id(cst); 426 genpaddr_t ep = cst->x.ump.epid.base; 427 uint16_t type = cst->x.ump.epid.eptype; 428 429 debug_printf("Sending UMP Route Setup Request: conid=%p, mb=%p\n", cst, mb); 430 431 err = ib->tx_vtbl.ump_route_setup_request(ib, NOP_CONT, conid, (uintptr_t)mb, 432 my_core_id, ep, type); 433 if (err_is_fail(err)) { 434 if (err_no(err) != FLOUNDER_ERR_TX_BUSY) { 435 return err; 436 } 437 438 struct ump_route_setup_request_state *rst = calloc(1, sizeof(*rst)); 439 if (rst == NULL) { 440 return LIB_ERR_MALLOC_FAIL; 441 } 442 443 rst->cst = cst; 444 rst->mb = mb; 445 rst->msgq.cont = intermon_ump_route_setup_request_handler; 446 447 struct intermon_state *ist = ib->st; 448 err = intermon_enqueue_send(ib, &ist->queue, get_default_waitset(), 449 &rst->msgq.queue); 450 if(err_is_fail(err)) { 451 free(rst); 452 return err; 453 } 454 } 455 456 return SYS_ERR_OK; 457} 458 459static void intermon_ump_route_setup_request(struct intermon_binding *ib, 460 intermon_con_id_t conid, 461 intermon_mon_id_t state, 462 intermon_coreid_t core, 463 genpaddr_t ep, uint16_t type) 464{ 465 errval_t err = SYS_ERR_OK; 466 467 struct remote_conn_state *conn = remote_conn_lookup_by_ep(ep, type); 468 if (conn == NULL) { 469 debug_printf("XXX NO ENDPOINT FOUND\n"); 470 err = -1; 471 goto out; 472 } 473 474 conn->mon_binding = ib; 475 conn->mon_id = conid; 476 conn->core_id = core; 477 478 out: 479 intermon_ump_route_setup_reply_cont(ib, remote_conn_get_id(conn), conid, 480 state, err); 481} 482 483/******* stack-ripped intermon_bind_ump_request *******/ 484 485static void bind_ump_service_request_handler(struct monitor_binding *b, 486 struct monitor_msg_queue_elem *e); 487 488struct bind_ump_service_request_state { 489 struct monitor_msg_queue_elem elem; 490 struct monitor_bind_ump_service_request__tx_args args; 491 struct intermon_binding *binding; 492 uintptr_t your_mon_id; 493}; 494 495static void bind_ump_service_request_cont(struct monitor_binding *domain_binding, 496 uintptr_t service_id, 497 con_id_t my_mon_id, 498 struct capref frame, 499 uint32_t channel_length_in, 500 uint32_t channel_length_out, 501 struct capref notify_cap, 502 struct intermon_binding *binding, 503 con_id_t your_mon_id) 504{ 505 errval_t err, err2; 506 507 /* Proxy the request */ 508 err = domain_binding->tx_vtbl. 509 bind_ump_service_request(domain_binding, NOP_CONT, service_id, 510 my_mon_id, frame, 511 channel_length_in, channel_length_out, 512 notify_cap); 513 if (err_is_fail(err)) { 514 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 515 struct bind_ump_service_request_state *me = 516 malloc(sizeof(struct bind_ump_service_request_state)); 517 struct monitor_state *ist = domain_binding->st; 518 me->args.service_id = service_id; 519 me->args.mon_id = my_mon_id; 520 me->args.frame = frame; 521 me->args.channel_length_in = channel_length_in; 522 me->args.channel_length_out = channel_length_out; 523 me->args.notify = notify_cap; 524 me->binding = binding; 525 me->your_mon_id = your_mon_id; 526 me->elem.cont = bind_ump_service_request_handler; 527 528 err = monitor_enqueue_send(domain_binding, &ist->queue, 529 get_default_waitset(), &me->elem.queue); 530 assert(err_is_ok(err)); 531 return; 532 } 533 534 err2 = cap_destroy(frame); 535 if (err_is_fail(err2)) { 536 USER_PANIC_ERR(err2, "Cap destroy failed"); 537 } 538 err2 = remote_conn_free(my_mon_id); 539 if (err_is_fail(err2)) { 540 USER_PANIC_ERR(err2, "remote_conn_free failed"); 541 } 542 intermon_caprep_t nullcap = {0,0,0,0}; 543 err2 = binding->tx_vtbl.bind_ump_reply(binding, NOP_CONT, your_mon_id, 0, err, 544 nullcap); 545 if (err_is_fail(err2)) { 546 USER_PANIC_ERR(err2, "Sending bind_ump_reply1 failed"); 547 } 548 } 549} 550 551static void bind_ump_service_request_handler(struct monitor_binding *b, 552 struct monitor_msg_queue_elem *e) 553{ 554 struct bind_ump_service_request_state *st = (struct bind_ump_service_request_state *)e; 555 bind_ump_service_request_cont(b, st->args.service_id, st->args.mon_id, 556 st->args.frame, st->args.channel_length_in, 557 st->args.channel_length_out, st->args.notify, 558 st->binding, st->your_mon_id); 559 free(e); 560} 561 562static void intermon_bind_ump_request(struct intermon_binding *ib, 563 iref_t iref, con_id_t your_mon_id, 564 uint32_t channel_length_in, 565 uint32_t channel_length_out, 566 genpaddr_t framebase, uint8_t framebits, 567 intermon_caprep_t caprep) 568{ 569 errval_t err; 570 571 /* Get client's core_id */ 572 struct intermon_state *ist = ib->st; 573 assert(ist != NULL); 574 coreid_t core_id = ist->core_id; 575 576 /* Construct the frame capability */ 577 struct capability frame_cap = { 578 .type = ObjType_Frame, 579 .rights = CAPRIGHTS_READ_WRITE, // XXX 580 .u.frame = { 581 .base = framebase, 582 .bytes = 1UL << framebits 583 } 584 }; 585 586 // Construct the notify cap 587 struct capref notify_cap = NULL_CAP; 588 struct capability capability; 589 caprep_to_capability(&caprep, &capability); 590 if(capability.type != ObjType_Null) { 591 err = slot_alloc(¬ify_cap); 592 if (err_is_fail(err)) { 593 USER_PANIC_ERR(err, "Failed to allocate slot from channel_alloc"); 594 } 595 err = monitor_cap_create(notify_cap, &capability, core_id); 596 if (err_is_fail(err)) { 597 USER_PANIC_ERR(err, "monitor_cap_create failed"); 598 } 599 } 600 601 // XXX: Put frame cap on a separate allocator as it is not deleted anymore 602 struct capref frame; 603 err = slot_alloc(&frame); 604 if (err_is_fail(err)) { 605 USER_PANIC_ERR(err, "Failed to allocate slot from channel_alloc"); 606 } 607 err = monitor_cap_create(frame, &frame_cap, core_id); 608 if (err_is_fail(err)) { 609 USER_PANIC_ERR(err, "monitor_cap_create failed"); 610 } 611 612 /* Get the server's connection */ 613 struct monitor_binding *domain_binding = NULL; 614 err = iref_get_binding(iref, &domain_binding); 615 assert(err_is_ok(err)); 616 617 /* Get the service id */ 618 uintptr_t service_id = 0; 619 err = iref_get_service_id(iref, &service_id); 620 assert(err_is_ok(err)); 621 622 /* Create a new connection state */ 623 uintptr_t my_mon_id; 624 struct remote_conn_state *con; 625 err = remote_conn_alloc(&con, &my_mon_id, REMOTE_CONN_UMP); 626 assert(err_is_ok(err)); 627 628 // Set the monitor portion of it 629 con->mon_id = your_mon_id; 630 con->mon_binding = ib; 631 con->x.ump.frame = frame; 632 con->core_id = core_id; 633 634 bind_ump_service_request_cont(domain_binding, service_id, my_mon_id, 635 frame, channel_length_in, channel_length_out, 636 notify_cap, ib, your_mon_id); 637} 638 639/******* stack-ripped intermon_bind_ump_reply *******/ 640 641static void bind_ump_reply_client_handler(struct monitor_binding *b, 642 struct monitor_msg_queue_elem *e); 643 644struct bind_ump_reply_client_state { 645 struct monitor_msg_queue_elem elem; 646 struct monitor_bind_ump_reply_client__tx_args args; 647}; 648 649static void bind_ump_reply_client_cont(struct monitor_binding *domain_binding, 650 uintptr_t my_mon_id, 651 uintptr_t domain_id, 652 errval_t msgerr, 653 struct capref notify_cap) 654{ 655 errval_t err; 656 657 err = domain_binding->tx_vtbl. 658 bind_ump_reply_client(domain_binding, NOP_CONT, my_mon_id, domain_id, 659 msgerr, notify_cap); 660 if (err_is_fail(err)) { 661 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 662 struct bind_ump_reply_client_state *me = 663 malloc(sizeof(struct bind_ump_reply_client_state)); 664 struct monitor_state *ist = domain_binding->st; 665 me->args.mon_id = my_mon_id; 666 me->args.conn_id = domain_id; 667 me->args.err = msgerr; 668 me->args.notify = notify_cap; 669 me->elem.cont = bind_ump_reply_client_handler; 670 671 err = monitor_enqueue_send(domain_binding, &ist->queue, 672 get_default_waitset(), &me->elem.queue); 673 assert(err_is_ok(err)); 674 return; 675 } 676 677 USER_PANIC_ERR(err, "UMP bind reply failed"); 678 // cleanup 679 err = remote_conn_free(my_mon_id); 680 if (err_is_fail(err)) { 681 USER_PANIC_ERR(err, "remote_conn_free failed"); 682 } 683 } 684} 685 686static void bind_ump_reply_client_handler(struct monitor_binding *b, 687 struct monitor_msg_queue_elem *e) 688{ 689 struct bind_ump_reply_client_state *st = (struct bind_ump_reply_client_state *)e; 690 bind_ump_reply_client_cont(b, st->args.mon_id, st->args.conn_id, 691 st->args.err, st->args.notify); 692 free(e); 693} 694 695static void intermon_bind_ump_reply(struct intermon_binding *ib, 696 uint64_t my_mon_id, uint64_t your_mon_id, 697 errval_t msgerr, 698 intermon_caprep_t caprep) 699{ 700 errval_t err; 701 struct remote_conn_state *con = remote_conn_lookup(my_mon_id); 702 if (con == NULL) { 703 USER_PANIC_ERR(0, "unknown mon_id in UMP bind reply"); 704 return; 705 } 706 707 uintptr_t domain_id = con->domain_id; 708 struct monitor_binding *domain_binding = con->domain_binding; 709 struct capref notify_cap = NULL_CAP; 710 711 if (err_is_ok(msgerr)) { /* bind succeeded */ 712 con->mon_id = your_mon_id; 713 con->mon_binding = ib; 714 715#if 0 716 /* map in UMP channel state */ 717 void *buf; 718 err = vspace_map_one_frame_attr(&buf, 719 2 * (UMP_CHANNEL_SIZE + con->localchan.size * sizeof(uintptr_t)), 720 con->frame, VREGION_FLAGS_READ, 721 NULL, NULL); 722 if (err_is_fail(err)) { 723 USER_PANIC_ERR(err, "vspace_map_one_frame failed"); 724 // XXX: should not be an assert, but we don't have any way to do 725 // connection teardown here! 726 assert(buf != NULL); 727 } 728 con->sharedchan = buf; 729 con->localchan.buf = buf + 2 * UMP_CHANNEL_SIZE; 730 731 // XXX: Put frame cap on a separate allocator as it is not deleted anymore 732 struct capref frame_copy; 733 err = slot_alloc(&frame_copy); 734 if (err_is_fail(err)) { 735 USER_PANIC_ERR(err, "Failed to allocator slot from channel_alloc"); 736 } 737 err = cap_copy(frame_copy, con->frame); 738 if (err_is_fail(err)) { 739 USER_PANIC_ERR(err, "Failed create copy of frame cap"); 740 } 741 err = cap_destroy(con->frame); 742 if (err_is_fail(err)) { 743 USER_PANIC_ERR(err, "cap_destroy_default failed"); 744 } 745 con->frame = frame_copy; 746#endif 747 748 struct capability capability; 749 caprep_to_capability(&caprep, &capability); 750 751 if(capability.type != ObjType_Null) { 752 // Get core id of sender 753 coreid_t core_id = ((struct intermon_state *)ib->st)->core_id; 754 755 // Construct the notify cap 756 err = slot_alloc(¬ify_cap); 757 if (err_is_fail(err)) { 758 USER_PANIC_ERR(err, "Failed to allocate slot from channel_alloc"); 759 } 760 761 err = monitor_cap_create(notify_cap, &capability, core_id); 762 if (err_is_fail(err)) { 763 USER_PANIC_ERR(err, "monitor_cap_create failed"); 764 } 765 } 766 } else { /* bind refused */ 767 err = cap_destroy(con->x.ump.frame); 768 if (err_is_fail(err)) { 769 USER_PANIC_ERR(err, "cap_destroy_default failed"); 770 } 771 err = remote_conn_free(my_mon_id); 772 assert(err_is_ok(err)); 773 } 774 775 bind_ump_reply_client_cont(domain_binding, my_mon_id, domain_id, msgerr, 776 notify_cap); 777} 778 779errval_t ump_intermon_init(struct intermon_binding *ib) 780{ 781 ib->rx_vtbl.bind_ump_request = intermon_bind_ump_request; 782 ib->rx_vtbl.bind_ump_reply = intermon_bind_ump_reply; 783 ib->rx_vtbl.ump_route_setup_request = intermon_ump_route_setup_request; 784 ib->rx_vtbl.ump_route_setup_reply = intermon_ump_route_setup_reply; 785 return SYS_ERR_OK; 786} 787 788errval_t ump_monitor_init(struct monitor_binding *mb) 789{ 790 mb->rx_vtbl.bind_ump_client_request = monitor_bind_ump_client_request; 791 mb->rx_vtbl.bind_ump_reply_monitor = monitor_bind_ump_reply; 792 return SYS_ERR_OK; 793} 794 795 796 797struct remote_conn_state *local_cst = NULL; 798 799 800errval_t remote_conn_alloc(struct remote_conn_state **con, uintptr_t *con_id, 801 enum remote_conn_type type) 802{ 803 struct remote_conn_state *mem = calloc(1, sizeof(struct remote_conn_state)); 804 assert(mem != NULL); 805 806 *con = mem; 807 *con_id = (uintptr_t)mem; 808 mem->type = type; 809 810 mem->next = local_cst; 811 local_cst = mem; 812 813 return SYS_ERR_OK; 814} 815 816errval_t remote_conn_free(uintptr_t con_id) 817{ 818 struct remote_conn_state *mem = (struct remote_conn_state*)con_id; 819 assert(mem != NULL); 820 821 if (mem->prev) { 822 mem->prev->next = mem->next; 823 } 824 if (mem->next) { 825 mem->next->prev = mem->prev; 826 } 827 free(mem); 828 829 return SYS_ERR_OK; 830} 831 832struct remote_conn_state *remote_conn_lookup(uintptr_t con_id) 833{ 834 return (struct remote_conn_state *)con_id; 835} 836 837struct remote_conn_state *remote_conn_lookup_by_ep(genpaddr_t ep, uint16_t type) 838{ 839 struct remote_conn_state *cst = local_cst; 840 while(cst) { 841 //debug_printf("remote_conn_lookup_by_ep %lx==%lx, %u==%u", 842 // cst->x.ump.epid.base, ep, cst->x.ump.epid.eptype, type); 843 if (cst->x.ump.epid.base == ep && cst->x.ump.epid.eptype == type) { 844 return cst; 845 } 846 cst = cst->next; 847 } 848 849 return NULL; 850} 851