3 * \brief Boot module for the Xeon Phi
5 * Loads the co processor OS onto the card and boots it
9 * Copyright (c) 2014 ETH Zurich.
10 * All rights reserved.
12 * This file is distributed under the terms in the attached LICENSE file.
13 * If you do not find this file, copies can be found by writing to:
14 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
19 #include <barrelfish/barrelfish.h>
20 #include <barrelfish/nameservice_client.h>
21 #include <barrelfish/spawn_client.h>
23 #include <flounder/flounder_txqueue.h>
25 #include <if/interphi_defs.h>
27 #include <xeon_phi/xeon_phi.h>
28 #include <xeon_phi/xeon_phi_domain.h>
30 #include "xeon_phi_internal.h"
35 #include "xphi_service.h"
36 #include "sysmem_caps.h"
39 * represents the information for the messaging channel between the host and
45 struct interphi_frameinfo fi;
46 struct interphi_binding *binding;
47 struct tx_queue queue;
57 struct interphi_msg_st
59 struct txq_msg_st common;
60 /* union of arguments */
70 uint8_t cap_size_bits;
96 xphi_chan_type_t type;
108 * ---------------------------------------------------------------------------
110 * ---------------------------------------------------------------------------
114 * \brief starts a new RPC to the inter Xeon Phi connection
116 * \param mi Xeon Phi message info
118 * \returns 1 if the RPC transaction could be started
119 * 0 if there was already a transaction in process
121 static inline uint8_t rpc_start(struct msg_info *mi)
123 if (!mi->wait_reply) {
124 mi->wait_reply = 0x1;
131 * \brief waits until the started transaction is finished
133 * \param mi Xeon Phi message info
135 static inline void rpc_wait_done(struct msg_info *mi)
138 while (mi->wait_reply) {
142 uint32_t serial_recv = 0xF;
143 while (serial_recv--) {
144 data |= xeon_phi_serial_handle_recv();
147 err = event_dispatch_non_block(get_default_waitset());
148 switch (err_no(err)) {
151 case LIB_ERR_NO_EVENT:
157 USER_PANIC_ERR(err, "in event dispatch\n");
162 messages_wait_and_handle_next();
168 * \brief signals the completion of the RPC
170 * \param mi Xeon Phi message info
172 static inline void rpc_done(struct msg_info *mi)
174 mi->wait_reply = 0x0;
177 static struct txq_msg_st *rpc_preamble(struct msg_info *mi)
181 if (mi->binding == NULL) {
185 if (!rpc_start(mi)) {
186 XINTER_DEBUG("waiting until previous rpc is finished\n");
191 mi->rpc_err = SYS_ERR_OK;
194 struct txq_msg_st *msg_st = txq_msg_st_alloc(&mi->queue);
195 if (msg_st == NULL) {
199 msg_st->cleanup = NULL;
205 * ----------------------------------------------------------------------------
207 * ----------------------------------------------------------------------------
209 static errval_t spawn_cmdline_extract_argv(char *cmdline,
216 while (pos < cmdlen && i < argcmax) {
217 argv[i++] = &cmdline[pos];
218 char *end = memchr(&cmdline[pos], '\0', cmdlen - pos);
220 return SPAWN_ERR_GET_CMDLINE_ARGS;
223 pos = end - cmdline + 1;
225 assert(i <= argcmax);
232 * ----------------------------------------------------------------------------
233 * Message Send Handlers
234 * ----------------------------------------------------------------------------
239 static errval_t domain_wait_call_tx(struct txq_msg_st *msg_st)
241 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
243 size_t length = strlen(st->args.domain.name) + 1;
245 return interphi_domain_wait_call__tx(msg_st->queue->binding, TXQCONT(msg_st),
246 st->args.domain.name, length,
247 st->args.domain.state);
252 static errval_t domain_wait_response_tx(struct txq_msg_st *msg_st)
254 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
256 return interphi_domain_wait_response__tx(msg_st->queue->binding,
258 st->args.domain.domid,
259 st->args.domain.state,
266 static errval_t domain_lookup_call_tx(struct txq_msg_st *msg_st)
268 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
270 size_t length = strlen(st->args.domain.name) + 1;
272 return interphi_domain_lookup_call__tx(msg_st->queue->binding,
273 TXQCONT(msg_st), st->args.domain.name,
279 static errval_t domain_lookup_response_tx(struct txq_msg_st *msg_st)
281 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
283 return interphi_domain_lookup_response__tx(msg_st->queue->binding,
285 st->args.domain.domid, msg_st->err);
292 static errval_t domain_register_call_tx(struct txq_msg_st *msg_st)
294 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
296 size_t length = strlen(st->args.domain.name) + 1;
298 return interphi_domain_register_call__tx(msg_st->queue->binding,
300 st->args.domain.name, length,
301 st->args.domain.domid);
306 static errval_t domain_register_response_tx(struct txq_msg_st *msg_st)
308 return interphi_domain_register_response__tx(msg_st->queue->binding,
309 TXQCONT(msg_st), SYS_ERR_OK);
314 static errval_t spawn_response_tx(struct txq_msg_st *msg_st)
316 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
318 return interphi_spawn_response__tx(msg_st->queue->binding, TXQCONT(msg_st),
319 st->args.spawn_reply.domainid, msg_st->err);
322 static errval_t spawn_call_tx(struct txq_msg_st *msg_st)
324 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
326 return interphi_spawn_call__tx(msg_st->queue->binding, TXQCONT(msg_st),
327 st->args.spawn_call.core,
328 st->args.spawn_call.cmdline,
329 st->args.spawn_call.cmdlen,
330 st->args.spawn_call.flags);
333 static errval_t spawn_with_cap_response_tx(struct txq_msg_st *msg_st)
335 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
337 return interphi_spawn_with_cap_response__tx(msg_st->queue->binding,
339 st->args.spawn_reply.domainid,
343 static errval_t spawn_with_cap_call_tx(struct txq_msg_st *msg_st)
345 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
347 return interphi_spawn_with_cap_call__tx(msg_st->queue->binding,
349 st->args.spawn_call.core,
350 st->args.spawn_call.cmdline,
351 st->args.spawn_call.cmdlen,
352 st->args.spawn_call.flags,
353 st->args.spawn_call.cap_base,
354 st->args.spawn_call.cap_size_bits);
357 static errval_t kill_response_tx(struct txq_msg_st *msg_st)
359 return interphi_kill_response__tx(msg_st->queue->binding, TXQCONT(msg_st),
363 static errval_t kill_call_tx(struct txq_msg_st *msg_st)
365 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
367 return interphi_kill_call__tx(msg_st->queue->binding, TXQCONT(msg_st),
368 st->args.kill.domainid);
371 static errval_t bootstrap_response_tx(struct txq_msg_st *msg_st)
373 return interphi_bootstrap_response__tx(msg_st->queue->binding,
374 TXQCONT(msg_st), msg_st->err);
377 static errval_t bootstrap_call_tx(struct txq_msg_st *msg_st)
379 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
381 return interphi_bootstrap_call__tx(msg_st->queue->binding, TXQCONT(msg_st),
382 st->args.bootstrap.base,
383 st->args.bootstrap.offset,
384 st->args.bootstrap.bits,
385 st->args.bootstrap.xid,
386 st->args.bootstrap.is_client);
389 static errval_t chan_open_call_tx(struct txq_msg_st *msg_st)
391 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
393 return interphi_chan_open_call__tx(msg_st->queue->binding, TXQCONT(msg_st),
394 st->args.open.source, st->args.open.target,
395 st->args.open.usrdata,
396 st->args.open.msgbase,
397 st->args.open.msgbits, st->args.open.type);
400 static errval_t chan_open_response_tx(struct txq_msg_st *msg_st)
402 return interphi_chan_open_response__tx(msg_st->queue->binding,
403 TXQCONT(msg_st), msg_st->err);
407 * ----------------------------------------------------------------------------
409 * ----------------------------------------------------------------------------
412 static void domain_wait_call_rx(struct interphi_binding *_binding,
418 USER_PANIC("domain_wait_call_rx: not supported on the Xeon Phi\n");
420 XINTER_DEBUG("domain_wait_call_rx: {%s}\n", name);
422 struct xnode *local_node = _binding->st;
424 struct xeon_phi *phi = local_node->local;
427 struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
428 if (msg_st == NULL) {
429 USER_PANIC("ran out of reply state resources\n");
432 msg_st->send = domain_wait_response_tx;
433 msg_st->cleanup = NULL;
435 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
437 st->args.domain.state = state;
439 msg_st->err = domain_wait(name, local_node, (void *)state, &st->args.domain.domid);
440 switch(err_no(msg_st->err)) {
442 /* there was a record, reply */
445 case OCT_ERR_NO_RECORD:
446 /* trigger installed */
447 txq_msg_st_free(msg_st);
450 /* error condition */
457 static void domain_wait_response_rx(struct interphi_binding *_binding,
458 xphi_dom_id_t domain,
463 XINTER_DEBUG("domain_wait_response_rx: domid:%lx, st:%p, %s\n", domain,
464 (void * )state, err_getstring(msgerr));
466 struct xphi_svc_st *st = (struct xphi_svc_st *) state;
468 xeon_phi_service_domain_wait_response(st, msgerr, domain);
470 USER_PANIC("domain_wait_call_rx: not supported on the host\n");
474 static void domain_lookup_call_rx(struct interphi_binding *_binding,
479 USER_PANIC("domain_lookup_call_rx: not supported on the Xeon Phi\n");
481 XINTER_DEBUG("domain_lookup_call_rx: {%s}\n", name);
483 struct xnode *local_node = _binding->st;
485 struct xeon_phi *phi = local_node->local;
488 struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
489 if (msg_st == NULL) {
490 USER_PANIC("ran out of reply state resources\n");
493 msg_st->send = domain_lookup_response_tx;
494 msg_st->cleanup = NULL;
496 struct interphi_msg_st *st = (struct interphi_msg_st *)msg_st;
498 msg_st->err = domain_lookup(name, &st->args.domain.domid);
504 static void domain_lookup_response_rx(struct interphi_binding *_binding,
505 xphi_dom_id_t domain,
509 XINTER_DEBUG("domain_lookup_response_rx: %lx, %s\n", domain,
510 err_getstring(msgerr));
512 struct xnode *local_node = _binding->st;
514 local_node->msg->rpc_err = msgerr;
515 rpc_done(local_node->msg);
517 USER_PANIC("domain_lookup_response_rx: not supported on the host\n");
521 static void domain_register_call_rx(struct interphi_binding *_binding,
527 /* register calls on the K1OM are not valid */
528 USER_PANIC("domain_register_call_rx: not supported on the Xeon Phi\n");
530 XINTER_DEBUG("domain_register_call_rx: {%s} @ domid:%lx\n", name, domid);
532 struct xnode *local_node = _binding->st;
534 struct xeon_phi *phi = local_node->local;
537 struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
538 if (msg_st == NULL) {
539 USER_PANIC("ran out of reply state resources\n");
542 msg_st->err = SYS_ERR_OK;
543 msg_st->send = domain_register_response_tx;
544 msg_st->cleanup = NULL;
546 msg_st->err = domain_register(name, domid);
552 static void domain_register_response_rx(struct interphi_binding *_binding,
556 XINTER_DEBUG("domain_register_response_rx:%s\n", err_getstring(msgerr));
558 struct xnode *local_node = _binding->st;
560 local_node->msg->rpc_err = msgerr;
561 rpc_done(local_node->msg);
563 USER_PANIC("domain_register_response_rx: not supported on the host\n");
567 static void spawn_call_rx(struct interphi_binding *_binding,
573 XINTER_DEBUG("spawn_call_rx: {%s} of length %lu, @ core:%u\n", cmdline,
576 struct xnode *local_node = _binding->st;
578 struct xeon_phi *phi = local_node->local;
581 struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
582 if (msg_st == NULL) {
583 USER_PANIC("ran out of reply state resources\n");
586 msg_st->send = spawn_response_tx;
587 msg_st->cleanup = NULL;
589 char *argv[MAX_CMDLINE_ARGS+1];
590 msg_st->err = spawn_cmdline_extract_argv((CONST_CAST)cmdline, length, argv, MAX_CMDLINE_ARGS);
591 if (err_is_fail(msg_st->err)) {
595 argv[MAX_CMDLINE_ARGS] = NULL;
597 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
602 * TODO: check if we have that core present...
605 msg_st->err = spawn_program(core, cmdline, argv, NULL, flags, &domid);
606 if (err_is_ok(msg_st->err)) {
608 uint8_t is_host = 0x0;
610 uint8_t is_host = 0x1;
612 st->args.spawn_reply.domainid = xeon_phi_domain_build_id(phi->id, core,
618 static void spawn_response_rx(struct interphi_binding *_binding,
620 interphi_errval_t msgerr)
622 XINTER_DEBUG("spawn_response_rx: %lu, %s\n", domainid, err_getstring(msgerr));
624 struct xnode *local_node = _binding->st;
626 local_node->msg->rpc_err = msgerr;
627 local_node->msg->rpc_data = domainid;
628 rpc_done(local_node->msg);
631 static void spawn_with_cap_call_rx(struct interphi_binding *_binding,
637 uint8_t cap_size_bits)
639 XINTER_DEBUG("spawn_with_cap_call_rx: {%s} of length %lu @ core:%u\n", cmdline,
642 struct xnode *local_node = _binding->st;
644 struct xeon_phi *phi = local_node->local;
647 struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
648 if (msg_st == NULL) {
649 USER_PANIC("ran out of reply state resources\n");
652 msg_st->send = spawn_with_cap_response_tx;
653 msg_st->cleanup = NULL;
655 char *argv[MAX_CMDLINE_ARGS+1];
656 msg_st->err = spawn_cmdline_extract_argv((CONST_CAST)cmdline, length, argv, MAX_CMDLINE_ARGS);
657 if (err_is_fail(msg_st->err)) {
661 argv[MAX_CMDLINE_ARGS] = NULL;
663 struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
666 msg_st->err = sysmem_cap_request(cap_base, cap_size_bits, &cap);
667 if (err_is_fail(msg_st->err)) {
673 msg_st->err = spawn_program_with_caps(core, cmdline, argv, NULL, NULL_CAP,
675 if (err_is_ok(msg_st->err)) {
677 st->args.spawn_reply.domainid = xeon_phi_domain_build_id(
678 disp_xeon_phi_id(), core, 0, domid);
680 st->args.spawn_reply.domainid = xeon_phi_domain_build_id(
681 XEON_PHI_DOMAIN_HOST, core, 1, domid);
687 static void spawn_with_cap_response_rx(struct interphi_binding *_binding,
689 interphi_errval_t msgerr)
691 XINTER_DEBUG("spawn_with_cap_response_rx: %lu, %s\n", domainid,
692 err_getstring(msgerr));
694 struct xnode *local_node = _binding->st;
696 local_node->msg->rpc_err = msgerr;
697 local_node->msg->rpc_data = domainid;
698 rpc_done(local_node->msg);
701 static void kill_call_rx(struct interphi_binding *_binding,
704 XINTER_DEBUG("kill_call_rx: %lu,\n", domainid);
706 struct xnode *local_node = _binding->st;
708 struct xeon_phi *phi = local_node->local;
711 struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
712 if (msg_st == NULL) {
713 USER_PANIC("ran out of reply state resources\n");
716 msg_st->err = SYS_ERR_OK;
717 msg_st->send = kill_response_tx;
718 msg_st->cleanup = NULL;
720 msg_st->err = spawn_kill(domainid);
725 static void kill_response_rx(struct interphi_binding *_binding,
726 interphi_errval_t msgerr)
728 XINTER_DEBUG("kill_response_rx: %s\n", err_getstring(msgerr));
730 struct xnode *local_node = _binding->st;
732 local_node->msg->rpc_err = msgerr;
734 rpc_done(local_node->msg);
737 static void bootstrap_call_rx(struct interphi_binding *_binding,
744 XINTER_DEBUG("bootstrap_call_rx: {%016lx, %02x} of:%016lx, xid:%u, c:%u\n",
745 base, bits, offset, xid, is_client);
747 struct xnode *local_node = _binding->st;
749 struct xeon_phi *phi = local_node->local;
752 struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
753 if (msg_st == NULL) {
754 USER_PANIC("ran out of reply state resources\n");
757 msg_st->err = SYS_ERR_OK;
758 msg_st->send = bootstrap_response_tx;
759 msg_st->cleanup = NULL;
761 struct xnode *node = &phi->topology[xid];
763 XINTER_DEBUG("already established a connection to xid:%u\n", xid);
767 struct capref msg_frame;
768 msg_st->err = sysmem_cap_request(base, bits, &msg_frame);
769 if (err_is_fail(msg_st->err)) {
774 smpt_set_coprocessor_offset(phi, xid, offset);
776 msg_st->err = interphi_init_xphi(xid, phi, msg_frame, is_client);
781 static void bootstrap_response_rx(struct interphi_binding *_binding,
782 interphi_errval_t msgerr)
784 XINTER_DEBUG("bootstrap_response_rx: %s\n", err_getstring(msgerr));
786 struct xnode *local_node = _binding->st;
788 local_node->msg->rpc_err = msgerr;
790 rpc_done(local_node->msg);
793 static void chan_open_call_rx(struct interphi_binding *_binding,
801 XINTER_DEBUG("chan_open_call_rx: %lx -> %lx\n", source_did, target_did);
803 struct xnode *local_node = _binding->st;
805 struct xeon_phi *phi = local_node->local;
808 struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
809 if (msg_st == NULL) {
810 USER_PANIC("ran out of reply state resources\n");
813 msg_st->send = chan_open_response_tx;
814 msg_st->cleanup = NULL;
816 struct capref msgcap;
818 lpaddr_t offset = smpt_get_coprocessor_address(phi, local_node->id);
822 msg_st->err = sysmem_cap_request(msgbase, msgbits, &msgcap);
823 if (err_is_fail(msg_st->err)) {
828 msg_st->err = xeon_phi_service_open_channel(msgcap, type, target_did,
829 source_did, usrdata);
830 if (err_is_fail(msg_st->err)) {
831 sysmem_cap_return(msgcap);
836 static void chan_open_response_rx(struct interphi_binding *_binding,
839 XINTER_DEBUG("chan_open_did_response_rx: %s\n", err_getstring(msgerr));
841 struct xnode *local_node = _binding->st;
843 local_node->msg->rpc_err = msgerr;
845 rpc_done(local_node->msg);
848 struct interphi_rx_vtbl rx_vtbl = {
849 .domain_lookup_call = domain_lookup_call_rx,
850 .domain_lookup_response = domain_lookup_response_rx,
851 .domain_wait_call = domain_wait_call_rx,
852 .domain_wait_response = domain_wait_response_rx,
853 .domain_register_call = domain_register_call_rx,
854 .domain_register_response = domain_register_response_rx,
855 .chan_open_call = chan_open_call_rx,
856 .chan_open_response = chan_open_response_rx,
857 .spawn_call = spawn_call_rx,
858 .spawn_response = spawn_response_rx,
859 .spawn_with_cap_call = spawn_with_cap_call_rx,
860 .spawn_with_cap_response = spawn_with_cap_response_rx,
861 .kill_call = kill_call_rx,
862 .kill_response = kill_response_rx,
863 .bootstrap_call = bootstrap_call_rx,
864 .bootstrap_response = bootstrap_response_rx
868 * ----------------------------------------------------------------------------
869 * Flounder Connect / Accept Callbacks
870 * ----------------------------------------------------------------------------
873 static void interphi_bind_cb(void *st,
875 struct interphi_binding *_binding)
877 XINTER_DEBUG("interphi_bind_cb: driver bound %p %s\n", _binding,
882 struct xnode *node = st;
884 _binding->rx_vtbl = rx_vtbl;
887 node->msg->binding = _binding;
889 txq_init(&node->msg->queue, _binding, _binding->waitset,
890 (txq_register_fn_t) _binding->register_send,
891 sizeof(struct interphi_msg_st));
893 node->state = XNODE_STATE_READY;
896 static void interphi_connect_cb(void *st,
898 struct interphi_binding *_binding)
900 XINTER_DEBUG("interphi_connect_cb: client driver connected %p\n", _binding);
902 struct xnode *node = st;
904 _binding->rx_vtbl = rx_vtbl;
907 node->msg->binding = _binding;
909 txq_init(&node->msg->queue, _binding, _binding->waitset,
910 (txq_register_fn_t) _binding->register_send,
911 sizeof(struct interphi_msg_st));
913 node->state = XNODE_STATE_READY;
917 * \brief waits for the client driver to connect
919 * \param phi Xeon Phi
921 * \return SYS_ERR_OK when then client driver successfully connected
923 errval_t interphi_wait_for_client(struct xeon_phi *phi)
928 XINTER_DEBUG("interphi_wait_for_client\n");
930 struct xnode *node = &phi->topology[phi->id];
932 while (node->state == XNODE_STATE_WAIT_CONNECTION) {
934 uint32_t serial_recv = 0xF;
935 while (serial_recv--) {
936 data |= xeon_phi_serial_handle_recv();
939 err = event_dispatch_non_block(get_default_waitset());
940 switch (err_no(err)) {
943 case LIB_ERR_NO_EVENT:
959 * ----------------------------------------------------------------------------
961 * ----------------------------------------------------------------------------
965 * \brief initializes the messaging boostrap infrastructure between the
968 * \param phi the xeon phi to initialize the basic messaging bootstrap
970 * \return SYS_ERR_OK on success
973 errval_t interphi_init_xphi(uint8_t xphi,
974 struct xeon_phi *phi,
980 XINTER_DEBUG("initializing intra Xeon Phi [%u <-> %u] client=%u\n", phi->id,
983 assert(xphi < XEON_PHI_NUM_MAX);
984 assert(xphi != phi->id);
986 assert(phi->topology[xphi].msg == NULL);
988 struct msg_info *mi = calloc(1, sizeof(struct msg_info));
990 return LIB_ERR_MALLOC_FAIL;
995 if (capref_is_null(frame)) {
996 err = frame_alloc(&mi->frame, XEON_PHI_INTERPHI_FRAME_SIZE, &frame_size);
997 if (err_is_fail(err)) {
1004 struct frame_identity id;
1005 err = invoke_frame_identify(mi->frame, &id);
1006 if (err_is_fail(err)) {
1007 cap_destroy(mi->frame);
1012 mi->is_client = is_client;
1014 frame_size = id.bytes;
1018 * XXX: the host does not need to do this
1021 err = vspace_map_one_frame(&addr, frame_size, mi->frame, NULL, NULL);
1022 if (err_is_fail(err)) {
1023 cap_destroy(mi->frame);
1028 XINTER_DEBUG("Messaging frame mapped: [%016lx -> %016lx, size = %lx ]\n",
1029 id.base, (uintptr_t )addr, frame_size);
1031 mi->fi.outbufsize = (frame_size >> 1);
1032 mi->fi.inbufsize = (frame_size >> 1);
1034 struct waitset *ws = get_default_waitset();
1036 struct xnode *node = &phi->topology[xphi];
1040 node->state = XNODE_STATE_WAIT_CONNECTION;
1042 if (mi->is_client) {
1043 mi->fi.inbuf = ((uint8_t*) addr) + mi->fi.inbufsize;
1044 mi->fi.outbuf = addr;
1045 mi->fi.sendbase = id.base;
1047 XINTER_DEBUG("client mode: connecting to server. %s\n", __FUNCTION__);
1049 err = interphi_connect(&mi->fi, interphi_bind_cb, node,
1050 ws, IDC_EXPORT_FLAGS_DEFAULT);
1052 mi->fi.inbuf = addr;
1053 mi->fi.outbuf = ((uint8_t*) addr) + mi->fi.outbufsize;
1054 mi->fi.sendbase = id.base + mi->fi.outbufsize;
1056 XINTER_DEBUG("server mode: accepting connections. %s\n", __FUNCTION__);
1058 err = interphi_accept(&mi->fi, node, interphi_connect_cb,
1059 ws, IDC_EXPORT_FLAGS_DEFAULT);
1061 if (err_is_fail(err)) {
1063 cap_destroy(mi->frame);
1068 if (mi->is_client) {
1069 XINTER_DEBUG("Waiting for connect callback...\n");
1070 while(node->state == XNODE_STATE_WAIT_CONNECTION) {
1071 messages_wait_and_handle_next();
1073 XINTER_DEBUG("connected to pier.\n");
1079 struct xnode *node = &phi->topology[xphi];
1080 lpaddr_t offset = ((node->apt_base >> 32) - ((node->apt_base >> 34)<<2))<<32;
1081 assert((1UL << log2ceil(id.bytes)) == id.bytes);
1082 err = interphi_bootstrap(phi, id.base, log2ceil(id.bytes), offset, xphi, mi->is_client);
1083 if (err_is_fail(err)) {
1088 XINTER_DEBUG("Local bootstrap succeeded. Sending to other node.\n");
1090 err = service_bootstrap(phi, xphi, mi->frame);
1091 if (err_is_fail(err)) {
1092 XINTER_DEBUG("Could not initialize messaging\n");
1101 * \brief initializes the communication between the host and the card Xeon Phi
1102 * drivers using a bootstraped flounder channel
1104 * \param phi Xeon Phi to initialize
1106 * \return SYS_ERR_OK on success
1109 errval_t interphi_init(struct xeon_phi *phi,
1110 struct capref frame)
1114 assert(phi->msg == NULL);
1116 struct msg_info *mi = calloc(1, sizeof(struct msg_info));
1118 return LIB_ERR_MALLOC_FAIL;
1123 if (capref_is_null(frame)) {
1124 err = frame_alloc(&mi->frame, XEON_PHI_INTERPHI_FRAME_SIZE, &frame_size);
1125 if (err_is_fail(err)) {
1132 struct frame_identity id;
1133 err = invoke_frame_identify(mi->frame, &id);
1134 if (err_is_fail(err)) {
1135 cap_destroy(mi->frame);
1140 frame_size = id.bytes;
1143 err = vspace_map_one_frame(&addr, frame_size, mi->frame, NULL, NULL);
1144 if (err_is_fail(err)) {
1145 cap_destroy(mi->frame);
1150 XINTER_DEBUG("Messaging frame mapped: [%016lx->%016lx, size = %lx]\n",
1151 id.base, (uintptr_t )addr, frame_size);
1153 mi->is_client = phi->is_client;
1155 mi->fi.outbufsize = (frame_size >> 1);
1156 mi->fi.inbufsize = (frame_size >> 1);
1158 struct waitset *ws = get_default_waitset();
1162 phi->topology[phi->id].msg = mi;
1163 phi->topology[phi->id].local = phi;
1164 phi->topology[phi->id].state = XNODE_STATE_WAIT_CONNECTION;
1166 if (phi->is_client) {
1167 mi->fi.inbuf = ((uint8_t*) addr) + mi->fi.inbufsize;
1168 mi->fi.outbuf = addr;
1169 mi->fi.sendbase = id.base;
1171 XINTER_DEBUG("client mode: connecting to server. %s\n", __FUNCTION__);
1173 err = interphi_connect(&mi->fi, interphi_bind_cb, &phi->topology[phi->id],
1174 ws, IDC_EXPORT_FLAGS_DEFAULT);
1176 mi->fi.inbuf = addr;
1177 mi->fi.outbuf = ((uint8_t*) addr) + mi->fi.outbufsize;
1178 mi->fi.sendbase = id.base + mi->fi.outbufsize;
1180 XINTER_DEBUG("server mode: accepting connections. %s\n", __FUNCTION__);
1182 err = interphi_accept(&mi->fi, &phi->topology[phi->id],
1183 interphi_connect_cb, ws, IDC_EXPORT_FLAGS_DEFAULT);
1185 if (err_is_fail(err)) {
1187 cap_destroy(mi->frame);
1196 if (!phi->is_client) {
1197 struct xeon_phi_boot_params *bp;
1198 bp = (struct xeon_phi_boot_params *) (phi->apt.vbase + phi->os_offset);
1199 bp->msg_base = id.base;
1200 assert((1UL << log2ceil(id.bytes)) == id.bytes);
1201 bp->msg_size_bits = log2ceil(id.bytes);
1208 * ----------------------------------------------------------------------------
1210 * ----------------------------------------------------------------------------
1214 * \brief sends a bootstrap request to the Xeon Phi client driver
1216 * \param phi Xeon Phi
1217 * \param frame_base base address of the messaging frame
1218 * \param frame_bits size of the messaging frame in bits
1219 * \param offset offset into the SMPT
1220 * \param xid ID of the other Xeon Phi
1221 * \param is_client flag indicating if this is the client of the connection
1223 * \returns SYS_ERR_OK on success
1226 errval_t interphi_bootstrap(struct xeon_phi *phi,
1227 lpaddr_t frame_base,
1234 USER_PANIC("This function should not be called on the Xeon Phi\n");
1237 XINTER_DEBUG("sending bootstrap to card. [%u] client:%u\n", xid, is_client);
1239 struct msg_info *mi = phi->msg;
1241 struct txq_msg_st *msg_st = rpc_preamble(mi);
1242 if (msg_st == NULL) {
1243 return LIB_ERR_MALLOC_FAIL;
1246 msg_st->send = bootstrap_call_tx;
1248 struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1250 svc_st->args.bootstrap.xid = xid;
1251 svc_st->args.bootstrap.offset = offset;
1252 svc_st->args.bootstrap.is_client = is_client;
1253 svc_st->args.bootstrap.base = frame_base;
1254 svc_st->args.bootstrap.bits = frame_bits;
1258 rpc_wait_done(phi->msg);
1260 return phi->msg->rpc_err;
1264 * \brief sends a spawn request to the Xeon Phi driver
1266 * \param node Xeon Phi Node
1267 * \param core which core to spawn the domain on
1268 * \param cmdline Commandline of the domain to spawn (marshalled)
1269 * \param cmdlen length of the command line
1270 * \param domain Domain identifier returned
1272 * \returns SYS_ERR_OK on success
1275 errval_t interphi_spawn(struct xnode *node,
1282 XINTER_DEBUG("spawning %s on core %u\n", cmdline, core);
1283 struct msg_info *mi = node->msg;
1285 struct txq_msg_st *msg_st = rpc_preamble(mi);
1286 if (msg_st == NULL) {
1287 return LIB_ERR_MALLOC_FAIL;
1290 msg_st->send = spawn_call_tx;
1292 struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1294 svc_st->args.spawn_call.cmdline = cmdline;
1295 svc_st->args.spawn_call.cmdlen = cmdlen;
1296 svc_st->args.spawn_call.core = core;
1297 svc_st->args.spawn_call.flags = flags;
1301 rpc_wait_done(node->msg);
1303 if (err_is_ok(node->msg->rpc_err)) {
1305 *domain = node->msg->rpc_data;
1309 return node->msg->rpc_err;
1313 * \brief sends a spawn request to the Xeon Phi driver
1315 * \param node Xeon Phi Node
1316 * \param core which core to spawn the domain on
1317 * \param cmdline Commandline of the domain to spawn (marshalled args)
1318 * \param cmdlen length of the cmd line
1319 * \param cap Cap to hand over to the domain at boot
1320 * \param domain Domain identifier returned
1322 * \returns SYS_ERR_OK on success
1325 errval_t interphi_spawn_with_cap(struct xnode *node,
1334 struct msg_info *mi = node->msg;
1336 XINTER_DEBUG("spawning %s with cap on core %u\n", cmdline, core);
1338 struct frame_identity id;
1339 err = invoke_frame_identify(cap, &id);
1340 if (err_is_fail(err)) {
1344 struct txq_msg_st *msg_st = rpc_preamble(mi);
1345 if (msg_st == NULL) {
1346 return LIB_ERR_MALLOC_FAIL;
1349 msg_st->send = spawn_with_cap_call_tx;
1351 struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1353 svc_st->args.spawn_call.cmdline = cmdline;
1354 svc_st->args.spawn_call.cmdlen = cmdlen;
1355 svc_st->args.spawn_call.core = core;
1356 svc_st->args.spawn_call.flags = flags;
1357 assert((1UL << log2ceil(id.bytes)) == id.bytes);
1358 svc_st->args.spawn_call.cap_size_bits = log2ceil(id.bytes);
1359 svc_st->args.spawn_call.cap_base = id.base;
1363 rpc_wait_done(node->msg);
1365 if (err_is_ok(node->msg->rpc_err)) {
1367 *domain = node->msg->rpc_data;
1371 return node->msg->rpc_err;
1375 * \brief sends a kill request for a domain
1377 * \param node Target Xeon Phi node
1378 * \param domain Domain identifier
1380 * \returns SYS_ERR_OK on success
1383 errval_t interphi_kill(struct xnode *node,
1384 xphi_dom_id_t domain)
1386 XINTER_DEBUG("sending kill signal for domain:%lu\n", domain);
1388 struct msg_info *mi = node->msg;
1390 struct txq_msg_st *msg_st = rpc_preamble(mi);
1391 if (msg_st == NULL) {
1392 return LIB_ERR_MALLOC_FAIL;
1395 msg_st->send = kill_call_tx;
1397 struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1399 svc_st->args.kill.domainid = domain;
1409 * \brief sends a channel open messages to another Xeon Phi driver
1411 * \param node Xeon Phi Node to send the message to
1412 * \param target target domain id
1413 * \param source source domain id
1414 * \param usedata usr specified data
1415 * \param msgframe capability of the messaging frame
1416 * \param type Channel type
1418 * \returns SYS_ERR_OK on success
1420 errval_t interphi_chan_open(struct xnode *node,
1421 xphi_dom_id_t target,
1422 xphi_dom_id_t source,
1424 struct capref msgframe,
1425 xphi_chan_type_t type)
1429 XINTER_DEBUG("sending channel open to domain {%lx}\n", target);
1431 struct msg_info *mi = node->msg;
1433 struct frame_identity id;
1434 err = invoke_frame_identify(msgframe, &id);
1435 if (err_is_fail(err)) {
1439 struct txq_msg_st *msg_st = rpc_preamble(mi);
1440 if (msg_st == NULL) {
1441 return LIB_ERR_MALLOC_FAIL;
1444 struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1446 svc_st->args.open.msgbase = id.base;
1447 assert((1UL << log2ceil(id.bytes)) == id.bytes);
1448 svc_st->args.open.msgbits = log2ceil(id.bytes);
1449 svc_st->args.open.source = source;
1450 svc_st->args.open.usrdata = usrdata;
1451 svc_st->args.open.type = type;
1454 msg_st->send = chan_open_call_tx;
1455 svc_st->args.open.target = target;
1457 rpc_done(node->msg);
1458 txq_msg_st_free(msg_st);
1470 * \brief registers a ready domain with the Xeon Phi Domain Service
1472 * \param node Xeon Phi Node to send the message to
1473 * \param name Name to register
1474 * \param domid Xeon Phi Domain ID
1476 * \returns SYS_ERR_OK on success
1479 errval_t interphi_domain_register(struct xnode *node,
1481 xphi_dom_id_t domid)
1484 XINTER_DEBUG("domain register {%s} with domainid:%lx @ xnode:%u\n", name,
1489 struct msg_info *mi = node->msg;
1491 struct txq_msg_st *msg_st = rpc_preamble(mi);
1492 if (msg_st == NULL) {
1493 return LIB_ERR_MALLOC_FAIL;
1495 msg_st->send = domain_register_call_tx;
1497 struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1499 svc_st->args.domain.domid = domid;
1500 svc_st->args.domain.name = name;
1508 USER_PANIC("interphi_domain_lookup: not supporte on host.\n");
1515 * \brief checks if a domain is running and returns its domain id if it is.
1517 * \param node Xeon Phi Node to send the message to
1518 * \param name Name of the Domain
1519 * \param domid returned Xeon Phi Domain ID
1521 * \returns SYS_ERR_OK on success
1524 errval_t interphi_domain_lookup(struct xnode *node,
1526 xphi_dom_id_t *retdomid)
1529 XINTER_DEBUG("domain lookup {%s} @ xnode:%u\n", name, node->id);
1531 struct msg_info *mi = node->msg;
1533 struct txq_msg_st *msg_st = rpc_preamble(mi);
1534 if (msg_st == NULL) {
1535 return LIB_ERR_MALLOC_FAIL;
1538 msg_st->send = domain_lookup_call_tx;
1540 struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1542 svc_st->args.domain.name = name;
1550 USER_PANIC("interphi_domain_lookup: not supporte on host.\n");
1557 * \brief checks if a domain is running and installs a trigger to reply
1559 * \param node Xeon Phi Node to send the message to
1560 * \param name Name of the Domain
1561 * \param state user state
1563 * \returns SYS_ERR_OK on success
1566 errval_t interphi_domain_wait(struct xnode *node,
1571 XINTER_DEBUG("domain wait {%s} @ xnode:%u\n", name, node->id);
1575 struct msg_info *mi = node->msg;
1576 if (mi->binding == NULL) {
1580 struct txq_msg_st *msg_st = txq_msg_st_alloc(&mi->queue);
1581 if (msg_st == NULL) {
1582 rpc_done(node->msg);
1583 return LIB_ERR_MALLOC_FAIL;
1586 msg_st->send = domain_wait_call_tx;
1587 msg_st->cleanup = NULL;
1589 struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1591 svc_st->args.domain.name = name;
1592 svc_st->args.domain.state = (uintptr_t) state;
1596 USER_PANIC("interphi_domain_wait: not supporte on host\n");
1602 * \brief sends a reply when the Octopus trigger fired
1604 * \param node Xeon Phi Node
1605 * \param domid Xeon Phi Domain ID
1606 * \param err Outcome of the reply
1607 * \param state State pointer supplied by the card.
1609 * \returns SYS_ERR_OK on success
1611 errval_t interphi_domain_wait_reply(struct xnode *node,
1614 xphi_dom_id_t domid)
1617 XINTER_DEBUG("domain interphi_domain_wait_reply domid:%lx @ xnode:%u, st:%p\n",
1618 domid, node->id, state);
1620 struct msg_info *mi = node->msg;
1621 if (mi->binding == NULL) {
1625 struct txq_msg_st *msg_st = txq_msg_st_alloc(&mi->queue);
1626 if (msg_st == NULL) {
1627 rpc_done(node->msg);
1628 return LIB_ERR_MALLOC_FAIL;
1631 msg_st->send = domain_wait_response_tx;
1632 msg_st->cleanup = NULL;
1635 struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1637 svc_st->args.domain.domid = domid;
1638 svc_st->args.domain.state = (uintptr_t)state;
1643 USER_PANIC("interphi_domain_wait_reply: Not supported on Xeon Phi\n");