1/* 2 * Copyright (c) 2014 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <string.h> 11#include <stdio.h> 12#include <barrelfish/barrelfish.h> 13#include <barrelfish/nameservice_client.h> 14#include <octopus/octopus.h> 15#include <flounder/flounder_txqueue.h> 16 17#include <if/xeon_phi_defs.h> 18 19#include <xeon_phi/xeon_phi.h> 20#include <xeon_phi/xeon_phi_client.h> 21#include <xeon_phi/xeon_phi_domain.h> 22 23#include "xeon_phi_client_internal.h" 24 25#ifdef XEON_PHI_DEBUG_MSG 26#define DEBUG_XPHI(x...) debug_printf("[xphi-client] " x); 27#else 28#define DEBUG_XPHI(x...) 29#endif 30#define PRINTF_XPHI(x...) debug_printf("[xphi-client] " x); 31 32/** 33 * enumeration of all possible states of the service exporting process 34 */ 35enum xpm_svc_state 36{ 37 XPM_SVC_STATE_INVALID, 38 XPM_SVC_STATE_BINDING, 39 XPM_SVC_STATE_BIND_OK, 40 XPM_SVC_STATE_BIND_FAIL, 41 XPM_SVC_STATE_REGISTERING, 42 XPM_SVC_STATE_REGISTER_OK, 43 XPM_SVC_STATE_REGISTER_FAIL, 44 XPM_SVC_STATE_CONNECTED 45}; 46 47struct xeon_phi_client 48{ 49 struct xeon_phi_binding *binding; 50 struct tx_queue txq; 51 volatile uint8_t rpc_wait_reply; 52 uint64_t rpc_data; 53 errval_t rpc_err; 54 struct capref rpc_cap; 55 errval_t err; 56 xphi_id_t xid; 57 enum xpm_svc_state state; 58}; 59 60struct xeon_phi_client *xphi_svc[XEON_PHI_NUM_MAX] = { 61 0 62}; 63 64uint8_t xphi_present[XEON_PHI_NUM_MAX] = { 65 0 66}; 67 68static struct xeon_phi_callbacks client_cb; 69 70struct xphi_msg_st 71{ 72 struct txq_msg_st common; 73 /* union of arguments */ 74 union 75 { 76 struct 77 { 78 const char *name; 79 xphi_dom_id_t domid; 80 coreid_t core; 81 } domain; 82 struct 83 { 84 xphi_id_t xid; 85 coreid_t core; 86 uint8_t flags; 87 char *cmdline; 88 size_t cmdlen; 89 struct capref cap; 90 } spawn; 91 struct 92 { 93 xphi_id_t xid; 94 xphi_dom_id_t domid; 95 } kill; 96 struct 97 { 98 xphi_id_t xid; 99 struct capref msgframe; 100 xphi_chan_type_t type; 101 xphi_dom_id_t domid; 102 uint64_t usrdata; 103 } open; 104 struct 105 { 106 struct capref mem; 107 } dma_register; 108 struct 109 { 110 uint64_t to; 111 uint64_t from; 112 uint64_t length; 113 } dma_memcpy; 114 struct 115 { 116 uint64_t arg; 117 } get_nodeid; 118 struct { 119 uint64_t bytes; 120 } alloc; 121 } args; 122}; 123 124/* 125 * 126 */ 127static inline errval_t check_online(uint8_t xid) 128{ 129 errval_t err; 130 if (xphi_present[xid]) { 131 return SYS_ERR_OK; 132 } 133 134#ifdef __k1om__ 135 if (xid == disp_xeon_phi_id()) { 136 xphi_present[xid] = 1; 137 return SYS_ERR_OK; 138 } 139#endif 140 141 char buf[20]; 142 snprintf(buf, 20, "xeon_phi.%u.ready", xid); 143 xphi_dom_id_t result; 144 err = xeon_phi_domain_blocking_lookup(buf, &result); 145 if (err_is_fail(err) || result != 0xcafebabe) { 146 USER_PANIC_ERR(err, "result: %lx, %x", result, (uint32_t )result); 147 } 148 149 xphi_present[xid] = 1; 150 151 return err; 152} 153 154/* 155 * --------------------------------------------------------------------------- 156 * RPC management 157 * --------------------------------------------------------------------------- 158 */ 159 160/** 161 * \brief starts a new RPC to the DMA service 162 * 163 * \param chan the DMA channel to start the RPC on 164 * 165 * \returns 1 if the RPC transaction could be started 166 * 0 if there was already a transaction in process 167 */ 168static inline uint8_t rpc_start(struct xeon_phi_client *cl) 169{ 170 if (!cl->rpc_wait_reply) { 171 cl->rpc_wait_reply = 0x1; 172 return 1; 173 } 174 return 0; 175} 176 177/** 178 * \brief waits until the started transaction is finished 179 * 180 * \param chan the DMA channel 181 */ 182static inline void rpc_wait_done(struct xeon_phi_client *cl) 183{ 184 while (cl->rpc_wait_reply == 0x1) { 185 messages_wait_and_handle_next(); 186 } 187} 188 189/** 190 * \brief signals the completion of the RPC 191 * 192 * \param chan the DMA channel 193 */ 194static inline void rpc_done(struct xeon_phi_client *cl) 195{ 196 cl->rpc_wait_reply = 0x2; 197} 198 199/** 200 * \brief signals the completion of the RPC 201 * 202 * \param chan the DMA channel 203 */ 204static inline void rpc_clear(struct xeon_phi_client *cl) 205{ 206 cl->rpc_wait_reply = 0x0; 207} 208 209/* 210 * ---------------------------------------------------------------------------- 211 * Send handlers 212 * ---------------------------------------------------------------------------- 213 */ 214 215static errval_t domain_init_call_tx(struct txq_msg_st *msg_st) 216{ 217 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 218 size_t length = strlen(st->args.domain.name) + 1; 219 return xeon_phi_domain_init_call__tx(msg_st->queue->binding, TXQCONT(msg_st), 220 (domainid_t) st->args.domain.domid, 221 st->args.domain.core, st->args.domain.name, 222 length); 223} 224#ifdef __k1om__ 225static errval_t domain_register_call_tx(struct txq_msg_st *msg_st) 226{ 227 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 228 size_t length = strlen(st->args.domain.name) + 1; 229 return xeon_phi_domain_register_call__tx(msg_st->queue->binding, TXQCONT(msg_st), 230 st->args.domain.name, length, 231 st->args.domain.domid); 232} 233static errval_t domain_lookup_call_tx(struct txq_msg_st *msg_st) 234{ 235 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 236 size_t length = strlen(st->args.domain.name) + 1; 237 return xeon_phi_domain_lookup_call__tx(msg_st->queue->binding, TXQCONT(msg_st), 238 st->args.domain.name, length); 239} 240 241static errval_t domain_wait_call_tx(struct txq_msg_st *msg_st) 242{ 243 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 244 size_t length = strlen(st->args.domain.name) + 1; 245 return xeon_phi_domain_wait_call__tx(msg_st->queue->binding, TXQCONT(msg_st), 246 st->args.domain.name, length); 247} 248#endif 249 250static errval_t spawn_call_tx(struct txq_msg_st *msg_st) 251{ 252 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 253 return xeon_phi_spawn_call__tx(msg_st->queue->binding, TXQCONT(msg_st), 254 st->args.spawn.xid, st->args.spawn.core, 255 st->args.spawn.cmdline, st->args.spawn.cmdlen, 256 st->args.spawn.flags); 257} 258 259static errval_t spawn_with_cap_call_tx(struct txq_msg_st *msg_st) 260{ 261 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 262 return xeon_phi_spawn_with_cap_call__tx(msg_st->queue->binding, TXQCONT(msg_st), 263 st->args.spawn.xid, st->args.spawn.core, 264 st->args.spawn.cmdline, 265 st->args.spawn.cmdlen, 266 st->args.spawn.flags, 267 st->args.spawn.cap); 268} 269 270static errval_t kill_call_tx(struct txq_msg_st *msg_st) 271{ 272 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 273 return xeon_phi_kill_call__tx(msg_st->queue->binding, TXQCONT(msg_st), 274 st->args.kill.xid, st->args.kill.domid); 275} 276 277static errval_t chan_open_request_call_tx(struct txq_msg_st *msg_st) 278{ 279 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 280 return xeon_phi_chan_open_request_call__tx(msg_st->queue->binding, 281 TXQCONT(msg_st), st->args.open.xid, 282 st->args.open.msgframe, 283 st->args.open.type, 284 st->args.open.domid, 285 st->args.open.usrdata); 286} 287 288static errval_t dma_register_call_tx(struct txq_msg_st *msg_st) 289{ 290 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 291 return xeon_phi_dma_register_call__tx(msg_st->queue->binding, 292 TXQCONT(msg_st), 293 st->args.dma_register.mem); 294} 295 296static errval_t dma_memcpy_call_tx(struct txq_msg_st *msg_st) 297{ 298 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 299 return xeon_phi_dma_memcpy_call__tx(msg_st->queue->binding, 300 TXQCONT(msg_st), 301 st->args.dma_memcpy.to, 302 st->args.dma_memcpy.from, 303 st->args.dma_memcpy.length); 304} 305 306static errval_t get_nodeid_call_tx(struct txq_msg_st *msg_st) 307{ 308 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 309 return xeon_phi_get_nodeid_call__tx(msg_st->queue->binding, 310 TXQCONT(msg_st), 311 st->args.get_nodeid.arg); 312} 313 314static errval_t chan_open_response_tx(struct txq_msg_st *msg_st) 315{ 316 return xeon_phi_chan_open_response__tx(msg_st->queue->binding, TXQCONT(msg_st), 317 msg_st->err); 318} 319 320static errval_t alloc_mem_call_tx(struct txq_msg_st *msg_st) 321{ 322 struct xphi_msg_st *st = (struct xphi_msg_st *) msg_st; 323 return xeon_phi_alloc_mem_call__tx(msg_st->queue->binding, TXQCONT(msg_st), 324 st->args.alloc.bytes); 325} 326 327/* 328 * ---------------------------------------------------------------------------- 329 * Receive Handlers 330 * ---------------------------------------------------------------------------- 331 */ 332static void domain_lookup_response_rx(struct xeon_phi_binding *b, 333 xphi_dom_id_t domid, 334 errval_t msgerr) 335{ 336 DEBUG_XPHI("domain_lookup_response_rx: %lx, %s\n", domid, err_getstring(msgerr)); 337 338 struct xeon_phi_client *cl = b->st; 339 assert(cl); 340 341 cl->rpc_err = msgerr; 342 cl->rpc_data = domid; 343 344 rpc_done(cl); 345} 346 347static void domain_wait_response_rx(struct xeon_phi_binding *b, 348 xphi_dom_id_t domid, 349 errval_t msgerr) 350{ 351 DEBUG_XPHI("domain_wait_response_rx: %lx, %s\n", domid, err_getstring(msgerr)); 352 353 struct xeon_phi_client *cl = b->st; 354 assert(cl); 355 356 cl->rpc_err = msgerr; 357 cl->rpc_data = domid; 358 359 rpc_done(cl); 360} 361 362static void domain_init_response_rx(struct xeon_phi_binding *b, 363 errval_t msgerr) 364{ 365 DEBUG_XPHI("domain_init_response_rx: %s\n", err_getstring(msgerr)); 366 367 struct xeon_phi_client *cl = b->st; 368 assert(cl); 369 assert(cl->state == XPM_SVC_STATE_REGISTERING); 370 371 cl->rpc_err = msgerr; 372 373 rpc_done(cl); 374} 375 376static void domain_register_response_rx(struct xeon_phi_binding *b, 377 errval_t msgerr) 378{ 379 DEBUG_XPHI("domain_regoster_response_rx: %s\n", err_getstring(msgerr)); 380 381 struct xeon_phi_client *cl = b->st; 382 assert(cl); 383 assert(cl->state == XPM_SVC_STATE_REGISTERING); 384 385 cl->rpc_err = msgerr; 386 387 rpc_done(cl); 388} 389 390static void spawn_response_rx(struct xeon_phi_binding *b, 391 uint64_t domainid, 392 errval_t msgerr) 393{ 394 DEBUG_XPHI("spawn_response_rx: %lx %s\n", domainid, err_getstring(msgerr)); 395 396 struct xeon_phi_client *cl = b->st; 397 assert(cl); 398 assert(cl->state == XPM_SVC_STATE_CONNECTED); 399 400 cl->rpc_err = msgerr; 401 cl->rpc_data = domainid; 402 403 rpc_done(cl); 404} 405 406static void spawn_with_cap_response_rx(struct xeon_phi_binding *b, 407 uint64_t domainid, 408 errval_t msgerr) 409{ 410 DEBUG_XPHI("spawn_with_cap_response_rx: %lx %s\n", domainid, 411 err_getstring(msgerr)); 412 413 struct xeon_phi_client *cl = b->st; 414 assert(cl); 415 assert(cl->state == XPM_SVC_STATE_CONNECTED); 416 417 cl->rpc_err = msgerr; 418 cl->rpc_data = domainid; 419 420 rpc_done(cl); 421} 422 423static void kill_response_rx(struct xeon_phi_binding *b, 424 errval_t msgerr) 425{ 426 DEBUG_XPHI("kill_response_rx: %s\n", err_getstring(msgerr)); 427 428 struct xeon_phi_client *cl = b->st; 429 assert(cl); 430 assert(cl->state == XPM_SVC_STATE_CONNECTED); 431 432 cl->rpc_err = msgerr; 433 434 rpc_done(cl); 435} 436 437static void dma_register_response_rx(struct xeon_phi_binding *b, 438 uint64_t devaddr, 439 errval_t msgerr) 440{ 441 DEBUG_XPHI("dma_register_response_rx: %s\n", err_getstring(msgerr)); 442 443 struct xeon_phi_client *cl = b->st; 444 assert(cl); 445 assert(cl->state == XPM_SVC_STATE_CONNECTED); 446 447 cl->rpc_err = msgerr; 448 cl->rpc_data = devaddr; 449 450 rpc_done(cl); 451} 452 453static void dma_memcpy_response_rx(struct xeon_phi_binding *b, 454 errval_t msgerr) 455{ 456 DEBUG_XPHI("dma_memcpy_response_rx: %s\n", err_getstring(msgerr)); 457 458 struct xeon_phi_client *cl = b->st; 459 assert(cl); 460 assert(cl->state == XPM_SVC_STATE_CONNECTED); 461 462 cl->rpc_err = msgerr; 463 464 rpc_done(cl); 465} 466 467static void get_nodeid_response_rx(struct xeon_phi_binding *b, 468 int32_t nodeid) 469{ 470 DEBUG_XPHI("get_nodeid_response_rx: %s\n", err_getstring(msgerr)); 471 472 struct xeon_phi_client *cl = b->st; 473 assert(cl); 474 assert(cl->state == XPM_SVC_STATE_CONNECTED); 475 476 477 cl->rpc_err = SYS_ERR_OK; 478 cl->rpc_data = (uint64_t)nodeid; 479 480 rpc_done(cl); 481} 482 483 484 485 486static void chan_open_request_response_rx(struct xeon_phi_binding *b, 487 errval_t msgerr) 488{ 489 DEBUG_XPHI("chan_open_request_response_rx: %s\n", err_getstring(msgerr)); 490 491 struct xeon_phi_client *cl = b->st; 492 assert(cl); 493 assert(cl->state == XPM_SVC_STATE_CONNECTED); 494 495 cl->rpc_err = msgerr; 496 497 rpc_done(cl); 498} 499 500static void alloc_mem_response_rx(struct xeon_phi_binding *b, 501 struct capref cap, 502 errval_t msgerr) 503{ 504 debug_printf("alloc_mem_response_rx: %s\n", err_getstring(msgerr)); 505 506 struct xeon_phi_client *cl = b->st; 507 assert(cl); 508 assert(cl->state == XPM_SVC_STATE_CONNECTED); 509 510 cl->rpc_err = msgerr; 511 cl->rpc_cap = cap; 512 513 rpc_done(cl); 514} 515 516static void chan_open_call_rx(struct xeon_phi_binding *b, 517 uint64_t domain, 518 uint64_t usrdata, 519 struct capref msgframe, 520 uint8_t type) 521{ 522 DEBUG_XPHI("chan_open_request_call_rx: from domain:%lx, type:%u\n", domain, type); 523 524 struct xeon_phi_client *cl = b->st; 525 assert(cl); 526 assert(cl->state == XPM_SVC_STATE_CONNECTED); 527 528 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 529 if (msg_st == NULL) { 530 USER_PANIC("could not allocate reply state"); 531 } 532 533 msg_st->cleanup = NULL; 534 msg_st->send = chan_open_response_tx; 535 msg_st->err = XEON_PHI_ERR_CLIENT_OPEN_REJECT; 536 537 if (client_cb.open) { 538 msg_st->err = client_cb.open(domain, usrdata, msgframe, type); 539 } 540 541 txq_send(msg_st); 542} 543 544struct xeon_phi_rx_vtbl xphi_svc_rx_vtbl = { 545 .domain_init_response = domain_init_response_rx, 546 .domain_register_response = domain_register_response_rx, 547 .domain_lookup_response = domain_lookup_response_rx, 548 .domain_wait_response = domain_wait_response_rx, 549 .spawn_response = spawn_response_rx, 550 .spawn_with_cap_response = spawn_with_cap_response_rx, 551 .kill_response = kill_response_rx, 552 .chan_open_request_response = chan_open_request_response_rx, 553 .chan_open_call = chan_open_call_rx, 554 .dma_register_response = dma_register_response_rx, 555 .dma_memcpy_response = dma_memcpy_response_rx, 556 .get_nodeid_response = get_nodeid_response_rx, 557 .alloc_mem_response = alloc_mem_response_rx, 558}; 559 560/* 561 * ---------------------------------------------------------------------------- 562 * Client Initialization 563 * ---------------------------------------------------------------------------- 564 */ 565 566static errval_t xphi_client_register(struct xeon_phi_client *cl) 567{ 568 errval_t err; 569 570 assert(cl->binding != NULL); 571 572 while (!rpc_start(cl)) { 573 messages_wait_and_handle_next(); 574 } 575 576 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 577 if (msg_st == NULL) { 578 rpc_clear(cl); 579 return LIB_ERR_MALLOC_FAIL; 580 } 581 582 msg_st->cleanup = NULL; 583 msg_st->send = domain_init_call_tx; 584 585 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 586 svc_st->args.domain.domid = disp_get_domain_id(); 587 svc_st->args.domain.core = disp_get_core_id(); 588 589 /// XXX: bug, this fails if disp_name() length == DISP_NAME_LEN 590 svc_st->args.domain.name = disp_name(); 591 592 DEBUG_XPHI("registration {%s} with domid:%x\n", svc_st->args.domain.name, 593 (domainid_t )svc_st->args.domain.domid); 594 595 txq_send(msg_st); 596 597 rpc_wait_done(cl); 598 599 if (err_is_fail(cl->rpc_err)) { 600 cl->state = XPM_SVC_STATE_REGISTER_FAIL; 601 } else { 602 cl->state = XPM_SVC_STATE_REGISTER_OK; 603 } 604 605 err = cl->rpc_err; 606 607 rpc_clear(cl); 608 609 return err; 610} 611 612static void xphi_bind_cb(void *st, 613 errval_t err, 614 struct xeon_phi_binding *b) 615{ 616 struct xeon_phi_client *cl = st; 617 618 DEBUG_XPHI("bound to service: %s\n", err_getstring(err)); 619 620 if (err_is_fail(err)) { 621 cl->err = err; 622 cl->state = XPM_SVC_STATE_BIND_FAIL; 623 return; 624 } 625 626 txq_init(&cl->txq, b, get_default_waitset(), 627 (txq_register_fn_t) b->register_send, sizeof(struct xphi_msg_st)); 628 629 b->rx_vtbl = xphi_svc_rx_vtbl; 630 b->st = cl; 631 632 cl->binding = b; 633 cl->state = XPM_SVC_STATE_BIND_OK; 634} 635 636/* 637 * ---------------------------------------------------------------------------- 638 * Initialization 639 * ---------------------------------------------------------------------------- 640 */ 641 642/** 643 * 644 */ 645static errval_t xphi_client_init(xphi_id_t xid) 646{ 647 errval_t err; 648 649 if (xid >= XEON_PHI_NUM_MAX) { 650 return XEON_PHI_ERR_INVALID_ID; 651 } 652 653 struct xeon_phi_client *cl = xphi_svc[xid]; 654 if (cl == NULL) { 655 cl = calloc(1, sizeof(*cl)); 656 if (cl == NULL) { 657 return LIB_ERR_MALLOC_FAIL; 658 } 659 } else { 660 return cl->err; 661 } 662 663 iref_t svc_iref; 664#ifdef __k1om__ 665 DEBUG_XPHI("looking up service {%s}\n", XEON_PHI_SERVICE_NAME); 666 err = nameservice_blocking_lookup(XEON_PHI_SERVICE_NAME, &svc_iref); 667#else 668 char iface[30]; 669 snprintf(iface, sizeof(iface), "%s.%u", XEON_PHI_SERVICE_NAME, xid); 670 DEBUG_XPHI("looking up service {%s}\n", iface); 671 err = nameservice_blocking_lookup(iface, &svc_iref); 672#endif 673 if (err_is_fail(err)) { 674 free(cl); 675 return err; 676 } 677 678 DEBUG_XPHI("initializing client to xid:%u @ iref:%"PRIxIREF"\n", xid, svc_iref); 679 680 cl->state = XPM_SVC_STATE_BINDING; 681 cl->xid = xid; 682 struct waitset *ws = get_default_waitset(); 683 684 err = xeon_phi_bind(svc_iref, xphi_bind_cb, cl, ws, IDC_BIND_FLAGS_DEFAULT); 685 if (err_is_fail(err)) { 686 return err; 687 } 688 689 while (cl->state == XPM_SVC_STATE_BINDING) { 690 messages_wait_and_handle_next(); 691 } 692 693 if (cl->state == XPM_SVC_STATE_BIND_FAIL) { 694 err = cl->err; 695 free(cl); 696 return err; 697 } 698 699 cl->state = XPM_SVC_STATE_REGISTERING; 700 err = xphi_client_register(cl); 701 if (err_is_fail(err)) { 702 free(cl); 703 return err; 704 } 705 706 if (cl->state == XPM_SVC_STATE_REGISTER_FAIL) { 707 err = cl->err; 708 free(cl); 709 return err; 710 } 711 712 cl->state = XPM_SVC_STATE_CONNECTED; 713 714 xphi_svc[xid] = cl; 715 716#ifdef __k1om__ 717 for (uint32_t i = 0; i < XEON_PHI_NUM_MAX; ++i) { 718 xphi_svc[i] = cl; 719 } 720#endif 721 722 return SYS_ERR_OK; 723} 724 725/* 726 * ============================================================================ 727 * Public interface 728 * ============================================================================ 729 */ 730 731/** 732 * \brief sets the callbacks for incoming messages 733 * 734 * \param cb Xeon Phi callbacks 735 */ 736void xeon_phi_client_set_callbacks(struct xeon_phi_callbacks *cb) 737{ 738 client_cb = *cb; 739} 740 741/** 742 * \brief initializes the Xeon Phi client 743 * 744 * \param xid Xeon Phi ID of the card to initialize 745 */ 746errval_t xeon_phi_client_init(xphi_id_t xid) 747{ 748 assert(xid < XEON_PHI_NUM_MAX); 749 750 if (xphi_svc[xid] == NULL) { 751 return xphi_client_init(xid); 752 } 753 return SYS_ERR_OK; 754} 755 756/** 757 * \brief spawns a new domain on the Xeon Phi or on the host 758 * 759 * \param xid Xeon Phi ID to start the domain 760 * \param core Core to start 761 * \param path Program to spawn 762 * \param argv Program arguments 763 * \param cap Capability to pass 764 * \param flags spawn flags 765 * \param domid returns the domain id of the spawned domain 766 * 767 * \return SYS_ERR_OK on success 768 * errval on failure 769 */ 770errval_t xeon_phi_client_spawn(xphi_id_t xid, 771 coreid_t core, 772 char *path, 773 char *argv[], 774 struct capref cap, 775 uint8_t flags, 776 xphi_dom_id_t *domid) 777{ 778 errval_t err; 779 780 if (xid >= XEON_PHI_NUM_MAX) { 781 return XEON_PHI_ERR_INVALID_ID; 782 } 783 784 err = check_online(xid); 785 if (err_is_fail(err)) { 786 return err; 787 } 788 789 if (xphi_svc[xid] == NULL) { 790 err = xphi_client_init(xid); 791 if (err_is_fail(err)) { 792 return err; 793 } 794 } 795 796 struct xeon_phi_client *cl = xphi_svc[xid]; 797 assert(cl); 798 799 if (!rpc_start(cl)) { 800 return XEON_PHI_ERR_CLIENT_BUSY; 801 } 802 803 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 804 if (msg_st == NULL) { 805 rpc_clear(cl); 806 return LIB_ERR_MALLOC_FAIL; 807 } 808 809 size_t argstrlen = strlen(path) + 1; 810 811 if (argv) { 812 for (int i = 0; argv[i] != NULL; i++) { 813 argstrlen += strlen(argv[i]) + 1; 814 } 815 } 816 817 char cmdline[argstrlen]; 818 size_t argstrpos = strlen(path); 819 strcpy(&cmdline[0], path); 820 cmdline[argstrpos++] = '\0'; 821 822 if (argv) { 823 for (int i = 0; argv[i] != NULL; i++) { 824 strcpy(&cmdline[argstrpos], argv[i]); 825 argstrpos += strlen(argv[i]); 826 cmdline[argstrpos++] = '\0'; 827 } 828 } 829 830 msg_st->cleanup = NULL; 831 832 if (capref_is_null(cap)) { 833 DEBUG_XPHI("spawning %s on core:%u @ xid:%u\n", cmdline, core, xid); 834 msg_st->send = spawn_call_tx; 835 } else { 836 DEBUG_XPHI("spawning %s with cap on core:%u @ xid:%u\n", cmdline, core, xid); 837 msg_st->send = spawn_with_cap_call_tx; 838 } 839 840 cl->rpc_data = 0; 841 842 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 843 svc_st->args.spawn.xid = xid; 844 svc_st->args.spawn.core = core; 845 svc_st->args.spawn.cmdline = cmdline; 846 svc_st->args.spawn.cmdlen = argstrlen; 847 svc_st->args.spawn.flags = flags; 848 svc_st->args.spawn.cap = cap; 849 850 txq_send(msg_st); 851 852 rpc_wait_done(cl); 853 854 if (domid) { 855 *domid = cl->rpc_data; 856 } 857 858 DEBUG_XPHI("spawned %s: domid:%lx %s\n", cmdline, cl->rpc_data, 859 err_getstring(cl->rpc_err)); 860 861 err = cl->rpc_err; 862 863 rpc_clear(cl); 864 865 return err; 866} 867 868/** 869 * \brief sends a kill request to the Xeon Phi 870 * 871 * \param xid Xeon Phi ID 872 * \param domid ID of the domain to kill 873 * 874 * \returns SYS_ERR_OK on success, 875 * XEON_PHI_ERR_CLIENT_DOMAIN_VOID, 876 * errval on error 877 */ 878errval_t xeon_phi_client_kill(xphi_id_t xid, 879 xphi_dom_id_t domid) 880{ 881 errval_t err; 882 883 if (xid >= XEON_PHI_NUM_MAX) { 884 return XEON_PHI_ERR_INVALID_ID; 885 } 886 887 err = check_online(xid); 888 if (err_is_fail(err)) { 889 return err; 890 } 891 892 if (xphi_svc[xid] == NULL) { 893 err = xphi_client_init(xid); 894 if (err_is_fail(err)) { 895 return err; 896 } 897 } 898 899 struct xeon_phi_client *cl = xphi_svc[xid]; 900 901 if (!rpc_start(cl)) { 902 return XEON_PHI_ERR_CLIENT_BUSY; 903 } 904 905 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 906 if (msg_st == NULL) { 907 rpc_clear(cl); 908 return LIB_ERR_MALLOC_FAIL; 909 } 910 911 msg_st->cleanup = NULL; 912 msg_st->send = kill_call_tx; 913 914 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 915 916 DEBUG_XPHI("killing domain:%lx @ xid:%u", domid, xid); 917 918 svc_st->args.kill.xid = xid; 919 svc_st->args.kill.domid = domid; 920 921 txq_send(msg_st); 922 923 rpc_wait_done(cl); 924 925 DEBUG_XPHI("killed %lx: %s\n", domid, err_getstring(cl->rpc_err)); 926 927 err = cl->rpc_err; 928 929 rpc_clear(cl); 930 931 return err; 932} 933 934/** 935 * \brief sends an channel open request to the domain 936 * 937 * \param xid Xeon Phi ID 938 * \param domid Domain ID 939 * \param usrdata Supplied data for the other side 940 * \param iface Interface name of the domain 941 * \param msgframe Message frame 942 * \param chantype Type of the channel 943 * 944 * \returns SYS_ERR_OK on success 945 * XEON_PHI_ERR_CLIENT_OPEN_REJCT if the client rejected 946 * errval on error 947 * 948 * The function expectes to be either the domain or the interface specified. 949 * If both are non-null then the domain ID is taken 950 */ 951errval_t xeon_phi_client_chan_open(xphi_id_t xid, 952 xphi_dom_id_t domid, 953 uint64_t usrdata, 954 struct capref msgframe, 955 xphi_chan_type_t chantype) 956{ 957 errval_t err; 958 assert(domid); 959 assert(!capref_is_null(msgframe)); 960 961 if (xid >= XEON_PHI_NUM_MAX) { 962 return XEON_PHI_ERR_INVALID_ID; 963 } 964 965 err = check_online(xid); 966 if (err_is_fail(err)) { 967 return err; 968 } 969 970 if (xphi_svc[xid] == NULL) { 971 err = xphi_client_init(xid); 972 if (err_is_fail(err)) { 973 return err; 974 } 975 } 976 977 struct xeon_phi_client *cl = xphi_svc[xid]; 978 979 if (!rpc_start(cl)) { 980 return XEON_PHI_ERR_CLIENT_BUSY; 981 } 982 983 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 984 if (msg_st == NULL) { 985 rpc_clear(cl); 986 return LIB_ERR_MALLOC_FAIL; 987 } 988 989 msg_st->cleanup = NULL; 990 991 DEBUG_XPHI("xeon_phi_client_chan_open: domid:%lx, type:%u, @ xid:%u\n", domid, 992 chantype, xid); 993 msg_st->send = chan_open_request_call_tx; 994 995 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 996 997 svc_st->args.open.domid = domid; 998 svc_st->args.open.usrdata = usrdata; 999 svc_st->args.open.xid = xid; 1000 svc_st->args.open.type = chantype; 1001 svc_st->args.open.msgframe = msgframe; 1002 1003 txq_send(msg_st); 1004 1005 rpc_wait_done(cl); 1006 1007 err = cl->rpc_err; 1008 1009 rpc_clear(cl); 1010 1011 return err; 1012} 1013 1014/** 1015 * \brief looks up the domain ID given the information 1016 * 1017 * \param iface Interface name of the domain 1018 * \param retdom returned domain id 1019 * 1020 * \returns SYS_ERR_OK on success, 1021 * XEON_PHI_ERR_CLIENT_DOMAIN_VOID, 1022 * errval on error 1023 */ 1024errval_t xeon_phi_client_domain_lookup(const char *iface, 1025 xphi_dom_id_t *retdom) 1026{ 1027#ifndef __k1om__ 1028 USER_PANIC("xeon_phi_client_domain_wait: not supporte on the host\n"); 1029 return SYS_ERR_OK; 1030#else 1031 errval_t err; 1032 1033 uint8_t xid = disp_xeon_phi_id(); 1034 1035 if (xphi_svc[xid] == NULL) { 1036 err = xphi_client_init(xid); 1037 if (err_is_fail(err)) { 1038 return err; 1039 } 1040 } 1041 1042 struct xeon_phi_client *cl = xphi_svc[xid]; 1043 1044 if (!rpc_start(cl)) { 1045 return XEON_PHI_ERR_CLIENT_BUSY; 1046 } 1047 1048 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 1049 if (msg_st == NULL) { 1050 rpc_clear(cl); 1051 return LIB_ERR_MALLOC_FAIL; 1052 } 1053 1054 msg_st->cleanup = NULL; 1055 1056 DEBUG_XPHI("xeon_phi_client_domain_lookup: iface:%s\n", iface); 1057 1058 msg_st->send = domain_lookup_call_tx; 1059 1060 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 1061 1062 svc_st->args.domain.name = iface; 1063 1064 txq_send(msg_st); 1065 1066 rpc_wait_done(cl); 1067 1068 if (err_is_ok(cl->rpc_err)) { 1069 if (retdom) { 1070 *retdom = cl->rpc_data; 1071 } 1072 } 1073 1074 err = cl->rpc_err; 1075 1076 rpc_clear(cl); 1077 1078 return err; 1079#endif 1080 return SYS_ERR_OK; 1081} 1082 1083/** 1084 * \brief looks up the domain ID given the information and waits 1085 * until the domain registers 1086 * 1087 * \param iface Interface name of the domain 1088 * \param retdom returned domain id 1089 * 1090 * \returns SYS_ERR_OK on success, 1091 * XEON_PHI_ERR_CLIENT_DOMAIN_VOID, 1092 * errval on error 1093 */ 1094errval_t xeon_phi_client_domain_wait(const char *iface, 1095 xphi_dom_id_t *retdom) 1096{ 1097#ifndef __k1om__ 1098 USER_PANIC("xeon_phi_client_domain_wait: not supporte on the host\n"); 1099 return SYS_ERR_OK; 1100#else 1101 errval_t err; 1102 1103 uint8_t xid = disp_xeon_phi_id(); 1104 1105 if (xphi_svc[xid] == NULL) { 1106 err = xphi_client_init(xid); 1107 if (err_is_fail(err)) { 1108 return err; 1109 } 1110 } 1111 1112 static char* format = "%s { domid: _ }"; 1113 int length = snprintf(NULL, 0, format, iface); 1114 1115 char* query = malloc(length + 1); 1116 if (query == NULL) { 1117 return LIB_ERR_MALLOC_FAIL; 1118 } 1119 snprintf(query, length + 1, format, iface); 1120 1121 struct xeon_phi_client *cl = xphi_svc[xid]; 1122 if (!rpc_start(cl)) { 1123 free(query); 1124 return XEON_PHI_ERR_CLIENT_BUSY; 1125 } 1126 1127 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 1128 if (msg_st == NULL) { 1129 rpc_clear(cl); 1130 free(query); 1131 return LIB_ERR_MALLOC_FAIL; 1132 } 1133 1134 msg_st->cleanup = NULL; 1135 1136 DEBUG_XPHI("xeon_phi_client_domain_wait: iface:%s\n", iface); 1137 1138 msg_st->send = domain_wait_call_tx; 1139 1140 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 1141 1142 svc_st->args.domain.name = query; 1143 1144 txq_send(msg_st); 1145 1146 rpc_wait_done(cl); 1147 1148 if (err_is_ok(cl->rpc_err)) { 1149 if (retdom) { 1150 *retdom = cl->rpc_data; 1151 } 1152 } 1153 1154 free(query); 1155 1156 err = cl->rpc_err; 1157 1158 rpc_clear(cl); 1159 1160 return err; 1161#endif 1162} 1163 1164/** 1165 * \brief registers a a domain 1166 * 1167 * \param iface Interface name of the domain 1168 * \param retdom returned domain id 1169 * 1170 * \returns SYS_ERR_OK on success, 1171 * errval on error 1172 */ 1173errval_t xeon_phi_client_domain_register(const char *iface, 1174 xphi_dom_id_t dom) 1175{ 1176#ifndef __k1om__ 1177 USER_PANIC("xeon_phi_client_domain_wait: not supported on the host\n"); 1178 return SYS_ERR_OK; 1179#else 1180 1181 errval_t err; 1182 1183 uint8_t xid = disp_xeon_phi_id(); 1184 1185 if (xphi_svc[xid] == NULL) { 1186 err = xphi_client_init(xid); 1187 if (err_is_fail(err)) { 1188 return err; 1189 } 1190 } 1191 1192 struct xeon_phi_client *cl = xphi_svc[xid]; 1193 while (!rpc_start(cl)) { 1194 return XEON_PHI_ERR_CLIENT_BUSY; 1195 } 1196 1197 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 1198 if (msg_st == NULL) { 1199 rpc_clear(cl); 1200 return LIB_ERR_MALLOC_FAIL; 1201 } 1202 1203 msg_st->cleanup = NULL; 1204 msg_st->send = domain_register_call_tx; 1205 1206 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 1207 1208 svc_st->args.domain.name = iface; 1209 svc_st->args.domain.domid = dom; 1210 1211 DEBUG_XPHI("registration {%s} with domid:%lx\n", svc_st->args.domain.name, 1212 svc_st->args.domain.domid); 1213 1214 txq_send(msg_st); 1215 1216 rpc_wait_done(cl); 1217 1218 if (err_is_fail(cl->rpc_err)) { 1219 cl->state = XPM_SVC_STATE_REGISTER_FAIL; 1220 } else { 1221 cl->state = XPM_SVC_STATE_REGISTER_OK; 1222 } 1223 1224 err = cl->rpc_err; 1225 1226 rpc_clear(cl); 1227 1228 return err; 1229#endif 1230} 1231 1232 1233/** 1234 * @brief obtains the hw model id for the specified xeon phi 1235 * 1236 * @param xid the xeon phi id 1237 * @param path which node to consider 1238 * 1239 * @return node id 1240 */ 1241int32_t xeon_phi_client_get_node_id(xphi_id_t xid, const char *path) 1242{ 1243 errval_t err; 1244 1245 if (xid >= XEON_PHI_NUM_MAX) { 1246 return XEON_PHI_ERR_INVALID_ID; 1247 } 1248 1249 err = check_online(xid); 1250 if (err_is_fail(err)) { 1251 return err; 1252 } 1253 1254 if (xphi_svc[xid] == NULL) { 1255 err = xphi_client_init(xid); 1256 if (err_is_fail(err)) { 1257 return err; 1258 } 1259 } 1260 1261 uint64_t arg; 1262 if (strncmp(path, "dma", 4) == 0) { 1263 /* The DMA engine */ 1264 arg = (1UL << 63) | (1UL<<32); 1265 } else if (strncmp(path, "core:", 4) == 0) { 1266 arg = (1UL << 63) | (1UL<<33) | strtoul(path + 5, NULL, 10);; 1267 } else { 1268 arg = (1UL << 63); 1269 } 1270 1271 1272 struct xeon_phi_client *cl = xphi_svc[xid]; 1273 1274 if (!rpc_start(cl)) { 1275 return XEON_PHI_ERR_CLIENT_BUSY; 1276 } 1277 1278 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 1279 if (msg_st == NULL) { 1280 rpc_clear(cl); 1281 return LIB_ERR_MALLOC_FAIL; 1282 } 1283 1284 msg_st->cleanup = NULL; 1285 1286 DEBUG_XPHI("xeon_phi_client_chan_open: domid:%lx, type:%u, @ xid:%u\n", domid, 1287 chantype, xid); 1288 msg_st->send = get_nodeid_call_tx; 1289 1290 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 1291 1292 svc_st->args.get_nodeid.arg = arg; 1293 1294 txq_send(msg_st); 1295 1296 rpc_wait_done(cl); 1297 1298 err = cl->rpc_err; 1299 int32_t id = (int32_t)cl->rpc_data; 1300 1301 rpc_clear(cl); 1302 1303 if (err_is_fail(err)) { 1304 return -1; 1305 } 1306 return id; 1307 1308} 1309 1310errval_t xeon_phi_client_dma_register(xphi_id_t xid, struct capref mem, uint64_t *devaddr) 1311{ 1312 errval_t err; 1313 1314 if (xid >= XEON_PHI_NUM_MAX) { 1315 return XEON_PHI_ERR_INVALID_ID; 1316 } 1317 1318 err = check_online(xid); 1319 if (err_is_fail(err)) { 1320 return err; 1321 } 1322 1323 if (xphi_svc[xid] == NULL) { 1324 err = xphi_client_init(xid); 1325 if (err_is_fail(err)) { 1326 return err; 1327 } 1328 } 1329 1330 struct xeon_phi_client *cl = xphi_svc[xid]; 1331 1332 if (!rpc_start(cl)) { 1333 return XEON_PHI_ERR_CLIENT_BUSY; 1334 } 1335 1336 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 1337 if (msg_st == NULL) { 1338 rpc_clear(cl); 1339 return LIB_ERR_MALLOC_FAIL; 1340 } 1341 1342 msg_st->cleanup = NULL; 1343 1344 DEBUG_XPHI("xeon_phi_client_chan_open: domid:%lx, type:%u, @ xid:%u\n", domid, 1345 chantype, xid); 1346 msg_st->send = dma_register_call_tx; 1347 1348 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 1349 1350 svc_st->args.dma_register.mem = mem; 1351 1352 txq_send(msg_st); 1353 1354 rpc_wait_done(cl); 1355 1356 err = cl->rpc_err; 1357 *devaddr = cl->rpc_data; 1358 1359 rpc_clear(cl); 1360 1361 return err; 1362 1363} 1364 1365errval_t xeon_phi_client_dma_memcpy(xphi_id_t xid, uint64_t to, uint64_t from, uint64_t size) 1366{ 1367 errval_t err; 1368 1369 if (xid >= XEON_PHI_NUM_MAX) { 1370 return XEON_PHI_ERR_INVALID_ID; 1371 } 1372 1373 err = check_online(xid); 1374 if (err_is_fail(err)) { 1375 return err; 1376 } 1377 1378 if (xphi_svc[xid] == NULL) { 1379 err = xphi_client_init(xid); 1380 if (err_is_fail(err)) { 1381 return err; 1382 } 1383 } 1384 1385 struct xeon_phi_client *cl = xphi_svc[xid]; 1386 1387 if (!rpc_start(cl)) { 1388 return XEON_PHI_ERR_CLIENT_BUSY; 1389 } 1390 1391 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 1392 if (msg_st == NULL) { 1393 rpc_clear(cl); 1394 return LIB_ERR_MALLOC_FAIL; 1395 } 1396 1397 msg_st->cleanup = NULL; 1398 1399 msg_st->send = dma_memcpy_call_tx; 1400 1401 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 1402 1403 svc_st->args.dma_memcpy.from = from; 1404 svc_st->args.dma_memcpy.to = to; 1405 svc_st->args.dma_memcpy.length = size; 1406 1407 txq_send(msg_st); 1408 1409 rpc_wait_done(cl); 1410 1411 err = cl->rpc_err; 1412 1413 rpc_clear(cl); 1414 1415 return err; 1416 1417} 1418 1419 1420errval_t xeon_phi_client_alloc_memory(xphi_id_t xid, struct capref *dst, 1421 size_t bytes) 1422{ 1423 errval_t err; 1424 1425 if (xid >= XEON_PHI_NUM_MAX) { 1426 return XEON_PHI_ERR_INVALID_ID; 1427 } 1428 1429 err = check_online(xid); 1430 if (err_is_fail(err)) { 1431 return err; 1432 } 1433 1434 if (xphi_svc[xid] == NULL) { 1435 err = xphi_client_init(xid); 1436 if (err_is_fail(err)) { 1437 return err; 1438 } 1439 } 1440 1441 struct xeon_phi_client *cl = xphi_svc[xid]; 1442 1443 if (!rpc_start(cl)) { 1444 return XEON_PHI_ERR_CLIENT_BUSY; 1445 } 1446 1447 struct txq_msg_st *msg_st = txq_msg_st_alloc(&cl->txq); 1448 if (msg_st == NULL) { 1449 rpc_clear(cl); 1450 return LIB_ERR_MALLOC_FAIL; 1451 } 1452 1453 msg_st->cleanup = NULL; 1454 1455 DEBUG_XPHI("xeon_phi_client_chan_open: domid:%lx, type:%u, @ xid:%u\n", domid, 1456 chantype, xid); 1457 msg_st->send = alloc_mem_call_tx; 1458 1459 struct xphi_msg_st *svc_st = (struct xphi_msg_st *) msg_st; 1460 1461 svc_st->args.alloc.bytes = bytes; 1462 1463 txq_send(msg_st); 1464 1465 rpc_wait_done(cl); 1466 1467 err = cl->rpc_err; 1468 *dst = cl->rpc_cap; 1469 1470 rpc_clear(cl); 1471 1472 return err; 1473} 1474