xeon phi: adding more debug printfs to the driver
[barrelfish] / usr / drivers / xeon_phi / interphi.c
1 /**
2  * \file
3  * \brief Boot module for the Xeon Phi
4  *
5  * Loads the co processor OS onto the card and boots it
6  */
7
8 /*
9  * Copyright (c) 2014 ETH Zurich.
10  * All rights reserved.
11  *
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.
15  */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <barrelfish/barrelfish.h>
20 #include <barrelfish/nameservice_client.h>
21 #include <barrelfish/spawn_client.h>
22
23 #include <flounder/flounder_txqueue.h>
24
25 #include <if/interphi_defs.h>
26
27 #include <xeon_phi/xeon_phi.h>
28 #include <xeon_phi/xeon_phi_domain.h>
29
30 #include "xeon_phi_internal.h"
31 #include "interphi.h"
32 #include "smpt.h"
33 #include "domain.h"
34 #include "service.h"
35 #include "xphi_service.h"
36 #include "sysmem_caps.h"
37
38 /**
39  * represents the information for the messaging channel between the host and
40  * the card.
41  */
42 struct msg_info
43 {
44     struct capref frame;
45     struct interphi_frameinfo fi;
46     struct interphi_binding *binding;
47     struct tx_queue queue;
48     errval_t rpc_err;
49     uint64_t rpc_data;
50     uint8_t is_client;
51     uint8_t wait_reply;
52 };
53
54 /*
55  *
56  */
57 struct interphi_msg_st
58 {
59     struct txq_msg_st common;
60     /* union of arguments */
61     union
62     {
63         struct
64         {
65             uint8_t core;
66             char *cmdline;
67             size_t cmdlen;
68             uint8_t flags;
69             uint64_t cap_base;
70             uint8_t cap_size_bits;
71         } spawn_call;
72         struct
73         {
74             uint64_t domainid;
75         } spawn_reply;
76         struct
77         {
78             uint64_t domainid;
79         } kill;
80         struct
81         {
82             uint64_t base;
83             uint64_t offset;
84             uint8_t bits;
85             uint8_t xid;
86             uint8_t is_client;
87         } bootstrap;
88         struct
89         {
90             lpaddr_t msgbase;
91             uint8_t msgbits;
92             char *iface;
93             xphi_dom_id_t source;
94             uint64_t usrdata;
95             xphi_dom_id_t target;
96             xphi_chan_type_t type;
97         } open;
98         struct
99         {
100             char *name;
101             xphi_dom_id_t domid;
102             uintptr_t state;
103         } domain;
104     } args;
105 };
106
107 /*
108  * ---------------------------------------------------------------------------
109  * RPC management
110  * ---------------------------------------------------------------------------
111  */
112
113 /**
114  * \brief starts a new RPC to the inter Xeon Phi connection
115  *
116  * \param mi    Xeon Phi message info
117  *
118  * \returns 1 if the RPC transaction could be started
119  *          0 if there was already a transaction in process
120  */
121 static inline uint8_t rpc_start(struct msg_info *mi)
122 {
123     if (!mi->wait_reply) {
124         mi->wait_reply = 0x1;
125         return 1;
126     }
127     return 0;
128 }
129
130 /**
131  * \brief waits until the started transaction is finished
132  *
133  * \param mi    Xeon Phi message info
134  */
135 static inline void rpc_wait_done(struct msg_info *mi)
136 {
137
138     while (mi->wait_reply) {
139 #ifndef __k1om__
140         errval_t err;
141         uint32_t data = 0x0;
142         uint32_t serial_recv = 0xF;
143         while (serial_recv--) {
144             data |= xeon_phi_serial_handle_recv();
145         }
146
147         err = event_dispatch_non_block(get_default_waitset());
148         switch (err_no(err)) {
149             case SYS_ERR_OK:
150             break;
151             case LIB_ERR_NO_EVENT:
152             if (!data) {
153                 thread_yield();
154             }
155             break;
156             default:
157             USER_PANIC_ERR(err, "in event dispatch\n");
158             break;
159         }
160
161 #else
162         messages_wait_and_handle_next();
163 #endif
164     }
165 }
166
167 /**
168  * \brief signals the completion of the RPC
169  *
170  * \param mi    Xeon Phi message info
171  */
172 static inline void rpc_done(struct msg_info *mi)
173 {
174     mi->wait_reply = 0x0;
175 }
176
177 static struct txq_msg_st *rpc_preamble(struct msg_info *mi)
178 {
179     assert(mi);
180
181     if (mi->binding == NULL) {
182         assert(!"NYI");
183     }
184
185     if (!rpc_start(mi)) {
186         XINTER_DEBUG("waiting until previous rpc is finished\n");
187         rpc_wait_done(mi);
188         rpc_start(mi);
189     }
190
191     mi->rpc_err = SYS_ERR_OK;
192     mi->rpc_data = 0x0;
193
194     struct txq_msg_st *msg_st = txq_msg_st_alloc(&mi->queue);
195     if (msg_st == NULL) {
196         rpc_done(mi);
197     }
198
199     msg_st->cleanup = NULL;
200
201     return msg_st;
202 }
203
204 /*
205  * ----------------------------------------------------------------------------
206  * Helper functions
207  * ----------------------------------------------------------------------------
208  */
209 static errval_t spawn_cmdline_extract_argv(char *cmdline,
210                                            size_t cmdlen,
211                                            char *argv[],
212                                            uint8_t argcmax)
213 {
214        int i = 0;
215        size_t pos = 0;
216        while (pos < cmdlen && i < argcmax) {
217            argv[i++] = &cmdline[pos];
218            char *end = memchr(&cmdline[pos], '\0', cmdlen - pos);
219            if (end == NULL) {
220                return SPAWN_ERR_GET_CMDLINE_ARGS;
221
222            }
223            pos = end - cmdline + 1;
224        }
225        assert(i <= argcmax);
226        argv[i] = NULL;
227
228     return SYS_ERR_OK;
229 }
230
231 /*
232  * ----------------------------------------------------------------------------
233  * Message Send Handlers
234  * ----------------------------------------------------------------------------
235  */
236
237 #ifdef __k1om__
238
239 static errval_t domain_wait_call_tx(struct txq_msg_st *msg_st)
240 {
241     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
242
243     size_t length = strlen(st->args.domain.name) + 1;
244
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);
248 }
249
250 #else
251
252 static errval_t domain_wait_response_tx(struct txq_msg_st *msg_st)
253 {
254     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
255
256     return interphi_domain_wait_response__tx(msg_st->queue->binding,
257                     TXQCONT(msg_st),
258                     st->args.domain.domid,
259                     st->args.domain.state,
260                     msg_st->err);
261 }
262 #endif
263
264 #ifdef __k1om__
265
266 static errval_t domain_lookup_call_tx(struct txq_msg_st *msg_st)
267 {
268     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
269
270     size_t length = strlen(st->args.domain.name) + 1;
271
272     return interphi_domain_lookup_call__tx(msg_st->queue->binding,
273                                            TXQCONT(msg_st), st->args.domain.name,
274                                            length);
275 }
276
277 #else
278
279 static errval_t domain_lookup_response_tx(struct txq_msg_st *msg_st)
280 {
281     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
282
283     return interphi_domain_lookup_response__tx(msg_st->queue->binding,
284                     TXQCONT(msg_st),
285                     st->args.domain.domid, msg_st->err);
286 }
287
288 #endif
289
290 #ifdef __k1om__
291
292 static errval_t domain_register_call_tx(struct txq_msg_st *msg_st)
293 {
294     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
295
296     size_t length = strlen(st->args.domain.name) + 1;
297
298     return interphi_domain_register_call__tx(msg_st->queue->binding,
299                                              TXQCONT(msg_st),
300                                              st->args.domain.name, length,
301                                              st->args.domain.domid);
302 }
303
304 #else
305
306 static errval_t domain_register_response_tx(struct txq_msg_st *msg_st)
307 {
308     return interphi_domain_register_response__tx(msg_st->queue->binding,
309                     TXQCONT(msg_st), SYS_ERR_OK);
310 }
311
312 #endif
313
314 static errval_t spawn_response_tx(struct txq_msg_st *msg_st)
315 {
316     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
317
318     return interphi_spawn_response__tx(msg_st->queue->binding, TXQCONT(msg_st),
319                                        st->args.spawn_reply.domainid, msg_st->err);
320 }
321
322 static errval_t spawn_call_tx(struct txq_msg_st *msg_st)
323 {
324     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
325
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);
331 }
332
333 static errval_t spawn_with_cap_response_tx(struct txq_msg_st *msg_st)
334 {
335     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
336
337     return interphi_spawn_with_cap_response__tx(msg_st->queue->binding,
338                                                 TXQCONT(msg_st),
339                                                 st->args.spawn_reply.domainid,
340                                                 msg_st->err);
341 }
342
343 static errval_t spawn_with_cap_call_tx(struct txq_msg_st *msg_st)
344 {
345     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
346
347     return interphi_spawn_with_cap_call__tx(msg_st->queue->binding,
348                                             TXQCONT(msg_st),
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);
355 }
356
357 static errval_t kill_response_tx(struct txq_msg_st *msg_st)
358 {
359     return interphi_kill_response__tx(msg_st->queue->binding, TXQCONT(msg_st),
360                                       msg_st->err);
361 }
362
363 static errval_t kill_call_tx(struct txq_msg_st *msg_st)
364 {
365     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
366
367     return interphi_kill_call__tx(msg_st->queue->binding, TXQCONT(msg_st),
368                                   st->args.kill.domainid);
369 }
370
371 static errval_t bootstrap_response_tx(struct txq_msg_st *msg_st)
372 {
373     return interphi_bootstrap_response__tx(msg_st->queue->binding,
374                                            TXQCONT(msg_st), msg_st->err);
375 }
376
377 static errval_t bootstrap_call_tx(struct txq_msg_st *msg_st)
378 {
379     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
380
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);
387 }
388
389 static errval_t chan_open_call_tx(struct txq_msg_st *msg_st)
390 {
391     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
392
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);
398 }
399
400 static errval_t chan_open_response_tx(struct txq_msg_st *msg_st)
401 {
402     return interphi_chan_open_response__tx(msg_st->queue->binding,
403                                            TXQCONT(msg_st), msg_st->err);
404 }
405
406 /*
407  * ----------------------------------------------------------------------------
408  * Message Callbacks
409  * ----------------------------------------------------------------------------
410  */
411
412 static void domain_wait_call_rx(struct interphi_binding *_binding,
413                                 char *name,
414                                 size_t length,
415                                 uintptr_t state)
416 {
417 #ifdef __k1om__
418     USER_PANIC("domain_wait_call_rx: not supported on the Xeon Phi\n");
419 #else
420     XINTER_DEBUG("domain_wait_call_rx: {%s}\n", name);
421
422     struct xnode *local_node = _binding->st;
423
424     struct xeon_phi *phi = local_node->local;
425     assert(phi);
426
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");
430     }
431
432     msg_st->send = domain_wait_response_tx;
433     msg_st->cleanup = NULL;
434
435     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
436
437     st->args.domain.state = state;
438
439     msg_st->err = domain_wait(name, local_node, (void *)state, &st->args.domain.domid);
440     switch(err_no(msg_st->err)) {
441         case SYS_ERR_OK:
442             /* there was a record, reply */
443             txq_send(msg_st);
444             break;
445         case OCT_ERR_NO_RECORD:
446             /* trigger installed */
447             txq_msg_st_free(msg_st);
448             break;
449         default:
450             /* error condition */
451             txq_send(msg_st);
452         break;
453     }
454     free(name);
455 #endif
456 }
457
458 static void domain_wait_response_rx(struct interphi_binding *_binding,
459                                     xphi_dom_id_t domain,
460                                     uintptr_t state,
461                                     errval_t msgerr)
462 {
463 #ifdef __k1om__
464     XINTER_DEBUG("domain_wait_response_rx: domid:%lx, st:%p,  %s\n", domain,
465                  (void * )state, err_getstring(msgerr));
466
467     struct xphi_svc_st *st = (struct xphi_svc_st *) state;
468
469     xeon_phi_service_domain_wait_response(st, msgerr, domain);
470 #else
471     USER_PANIC("domain_wait_call_rx: not supported on the host\n");
472 #endif
473 }
474
475 static void domain_lookup_call_rx(struct interphi_binding *_binding,
476                                   char *name,
477                                   size_t length)
478 {
479 #ifdef __k1om__
480     USER_PANIC("domain_lookup_call_rx: not supported on the Xeon Phi\n");
481 #else
482     XINTER_DEBUG("domain_lookup_call_rx: {%s}\n", name);
483
484     struct xnode *local_node = _binding->st;
485
486     struct xeon_phi *phi = local_node->local;
487     assert(phi);
488
489     struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
490     if (msg_st == NULL) {
491         USER_PANIC("ran out of reply state resources\n");
492     }
493
494     msg_st->send = domain_lookup_response_tx;
495     msg_st->cleanup = NULL;
496
497     struct interphi_msg_st *st = (struct interphi_msg_st *)msg_st;
498
499     msg_st->err = domain_lookup(name, &st->args.domain.domid);
500
501     free(name);
502
503     txq_send(msg_st);
504 #endif
505 }
506
507 static void domain_lookup_response_rx(struct interphi_binding *_binding,
508                                       xphi_dom_id_t domain,
509                                       errval_t msgerr)
510 {
511 #ifdef __k1om__
512     XINTER_DEBUG("domain_lookup_response_rx: %lx, %s\n", domain,
513                  err_getstring(msgerr));
514
515     struct xnode *local_node = _binding->st;
516
517     local_node->msg->rpc_err = msgerr;
518     rpc_done(local_node->msg);
519 #else
520     USER_PANIC("domain_lookup_response_rx: not supported on the host\n");
521 #endif
522 }
523
524 static void domain_register_call_rx(struct interphi_binding *_binding,
525                                     char *name,
526                                     size_t length,
527                                     xphi_dom_id_t domid)
528 {
529 #ifdef __k1om__
530     /* register calls on the K1OM are not valid */
531     USER_PANIC("domain_register_call_rx: not supported on the Xeon Phi\n");
532 #else
533     XINTER_DEBUG("domain_register_call_rx: {%s} @ domid:%lx\n", name, domid);
534
535     struct xnode *local_node = _binding->st;
536
537     struct xeon_phi *phi = local_node->local;
538     assert(phi);
539
540     struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
541     if (msg_st == NULL) {
542         USER_PANIC("ran out of reply state resources\n");
543     }
544
545     msg_st->err = SYS_ERR_OK;
546     msg_st->send = domain_register_response_tx;
547     msg_st->cleanup = NULL;
548
549     msg_st->err = domain_register(name, domid);
550
551     free(name);
552
553     txq_send(msg_st);
554 #endif
555 }
556
557 static void domain_register_response_rx(struct interphi_binding *_binding,
558                                         errval_t msgerr)
559 {
560 #ifdef __k1om__
561     XINTER_DEBUG("domain_register_response_rx:%s\n", err_getstring(msgerr));
562
563     struct xnode *local_node = _binding->st;
564
565     local_node->msg->rpc_err = msgerr;
566     rpc_done(local_node->msg);
567 #else
568     USER_PANIC("domain_register_response_rx: not supported on the host\n");
569 #endif
570 }
571
572 static void spawn_call_rx(struct interphi_binding *_binding,
573                           uint8_t core,
574                           char *cmdline,
575                           size_t length,
576                           uint8_t flags)
577 {
578     XINTER_DEBUG("spawn_call_rx: {%s} of length %lu, @ core:%u\n", cmdline,
579                  length, core);
580
581     struct xnode *local_node = _binding->st;
582
583     struct xeon_phi *phi = local_node->local;
584     assert(phi);
585
586     struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
587     if (msg_st == NULL) {
588         USER_PANIC("ran out of reply state resources\n");
589     }
590
591     msg_st->send = spawn_response_tx;
592     msg_st->cleanup = NULL;
593
594     char *argv[MAX_CMDLINE_ARGS+1];
595     msg_st->err = spawn_cmdline_extract_argv(cmdline, length, argv, MAX_CMDLINE_ARGS);
596     if (err_is_fail(msg_st->err)) {
597         txq_send(msg_st);
598         return;
599     }
600     argv[MAX_CMDLINE_ARGS] = NULL;
601
602     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
603
604     domainid_t domid;
605
606     /*
607      * TODO: check if we have that core present...
608      */
609
610     msg_st->err = spawn_program(core, cmdline, argv, NULL, flags, &domid);
611     if (err_is_ok(msg_st->err)) {
612 #ifdef __k1om__
613         uint8_t is_host = 0x0;
614 #else
615         uint8_t is_host = 0x1;
616 #endif
617         st->args.spawn_reply.domainid = xeon_phi_domain_build_id(phi->id, core,
618                                                                  is_host, domid);
619     }
620
621     free(cmdline);
622
623     txq_send(msg_st);
624 }
625
626 static void spawn_response_rx(struct interphi_binding *_binding,
627                               uint64_t domainid,
628                               interphi_errval_t msgerr)
629 {
630     XINTER_DEBUG("spawn_response_rx: %lu, %s\n", domainid, err_getstring(msgerr));
631
632     struct xnode *local_node = _binding->st;
633
634     local_node->msg->rpc_err = msgerr;
635     local_node->msg->rpc_data = domainid;
636     rpc_done(local_node->msg);
637 }
638
639 static void spawn_with_cap_call_rx(struct interphi_binding *_binding,
640                                    uint8_t core,
641                                    char *cmdline,
642                                    size_t length,
643                                    uint8_t flags,
644                                    uint64_t cap_base,
645                                    uint8_t cap_size_bits)
646 {
647     XINTER_DEBUG("spawn_with_cap_call_rx: {%s} of length %lu @ core:%u\n", cmdline,
648                  length, core);
649
650     struct xnode *local_node = _binding->st;
651
652     struct xeon_phi *phi = local_node->local;
653     assert(phi);
654
655     struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
656     if (msg_st == NULL) {
657         USER_PANIC("ran out of reply state resources\n");
658     }
659
660     msg_st->send = spawn_with_cap_response_tx;
661     msg_st->cleanup = NULL;
662
663     char *argv[MAX_CMDLINE_ARGS+1];
664     msg_st->err = spawn_cmdline_extract_argv(cmdline, length, argv, MAX_CMDLINE_ARGS);
665     if (err_is_fail(msg_st->err)) {
666         txq_send(msg_st);
667         return;
668     }
669     argv[MAX_CMDLINE_ARGS] = NULL;
670
671     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
672
673     struct capref cap;
674     msg_st->err = sysmem_cap_request(cap_base, cap_size_bits, &cap);
675     if (err_is_fail(msg_st->err)) {
676         txq_send(msg_st);
677         return;
678     }
679
680     domainid_t domid;
681     msg_st->err = spawn_program_with_caps(core, cmdline, argv, NULL, NULL_CAP,
682                                           cap, flags, &domid);
683     if (err_is_ok(msg_st->err)) {
684 #ifdef __k1om__
685         st->args.spawn_reply.domainid = xeon_phi_domain_build_id(
686                         disp_xeon_phi_id(), core, 0, domid);
687 #else
688         st->args.spawn_reply.domainid = xeon_phi_domain_build_id(
689                         XEON_PHI_DOMAIN_HOST, core, 1, domid);
690 #endif
691     }
692
693     free(cmdline);
694
695     txq_send(msg_st);
696 }
697
698 static void spawn_with_cap_response_rx(struct interphi_binding *_binding,
699                                        uint64_t domainid,
700                                        interphi_errval_t msgerr)
701 {
702     XINTER_DEBUG("spawn_with_cap_response_rx: %lu, %s\n", domainid,
703                  err_getstring(msgerr));
704
705     struct xnode *local_node = _binding->st;
706
707     local_node->msg->rpc_err = msgerr;
708     local_node->msg->rpc_data = domainid;
709     rpc_done(local_node->msg);
710 }
711
712 static void kill_call_rx(struct interphi_binding *_binding,
713                          uint64_t domainid)
714 {
715     XINTER_DEBUG("kill_call_rx: %lu,\n", domainid);
716
717     struct xnode *local_node = _binding->st;
718
719     struct xeon_phi *phi = local_node->local;
720     assert(phi);
721
722     struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
723     if (msg_st == NULL) {
724         USER_PANIC("ran out of reply state resources\n");
725     }
726
727     msg_st->err = SYS_ERR_OK;
728     msg_st->send = kill_response_tx;
729     msg_st->cleanup = NULL;
730
731     msg_st->err = spawn_kill(domainid);
732
733     txq_send(msg_st);
734 }
735
736 static void kill_response_rx(struct interphi_binding *_binding,
737                              interphi_errval_t msgerr)
738 {
739     XINTER_DEBUG("kill_response_rx: %s\n", err_getstring(msgerr));
740
741     struct xnode *local_node = _binding->st;
742
743     local_node->msg->rpc_err = msgerr;
744
745     rpc_done(local_node->msg);
746 }
747
748 static void bootstrap_call_rx(struct interphi_binding *_binding,
749                               uint64_t base,
750                               uint64_t offset,
751                               uint8_t bits,
752                               uint8_t xid,
753                               uint8_t is_client)
754 {
755     XINTER_DEBUG("bootstrap_call_rx: {%016lx, %02x} of:%016lx, xid:%u, c:%u\n",
756                  base, bits, offset, xid, is_client);
757
758     struct xnode *local_node = _binding->st;
759
760     struct xeon_phi *phi = local_node->local;
761     assert(phi);
762
763     struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
764     if (msg_st == NULL) {
765         USER_PANIC("ran out of reply state resources\n");
766     }
767
768     msg_st->err = SYS_ERR_OK;
769     msg_st->send = bootstrap_response_tx;
770     msg_st->cleanup = NULL;
771
772     struct xnode *node = &phi->topology[xid];
773     if (node->msg) {
774         XINTER_DEBUG("already established a connection to xid:%u\n", xid);
775         txq_send(msg_st);
776     }
777
778     struct capref msg_frame;
779     msg_st->err = sysmem_cap_request(base, bits, &msg_frame);
780     if (err_is_fail(msg_st->err)) {
781         txq_send(msg_st);
782         return;
783     }
784
785     smpt_set_coprocessor_offset(phi, xid, offset);
786
787     msg_st->err = interphi_init_xphi(xid, phi, msg_frame, is_client);
788
789     txq_send(msg_st);
790 }
791
792 static void bootstrap_response_rx(struct interphi_binding *_binding,
793                                   interphi_errval_t msgerr)
794 {
795     XINTER_DEBUG("bootstrap_response_rx: %s\n", err_getstring(msgerr));
796
797     struct xnode *local_node = _binding->st;
798
799     local_node->msg->rpc_err = msgerr;
800
801     rpc_done(local_node->msg);
802 }
803
804 static void chan_open_call_rx(struct interphi_binding *_binding,
805                               uint64_t source_did,
806                               uint64_t target_did,
807                               uint64_t usrdata,
808                               uint64_t msgbase,
809                               uint8_t msgbits,
810                               uint8_t type)
811 {
812     XINTER_DEBUG("chan_open_call_rx: %lx -> %lx\n", source_did, target_did);
813
814     struct xnode *local_node = _binding->st;
815
816     struct xeon_phi *phi = local_node->local;
817     assert(phi);
818
819     struct txq_msg_st *msg_st = txq_msg_st_alloc(&local_node->msg->queue);
820     if (msg_st == NULL) {
821         USER_PANIC("ran out of reply state resources\n");
822     }
823
824     msg_st->send = chan_open_response_tx;
825     msg_st->cleanup = NULL;
826
827     struct capref msgcap;
828
829     lpaddr_t offset = smpt_get_coprocessor_address(phi, local_node->id);
830
831     msgbase += offset;
832
833     msg_st->err = sysmem_cap_request(msgbase, msgbits, &msgcap);
834     if (err_is_fail(msg_st->err)) {
835         txq_send(msg_st);
836         return;
837     }
838
839     msg_st->err = xeon_phi_service_open_channel(msgcap, type, target_did,
840                                                 source_did, usrdata);
841     if (err_is_fail(msg_st->err)) {
842         sysmem_cap_return(msgcap);
843     }
844     txq_send(msg_st);
845 }
846
847 static void chan_open_response_rx(struct interphi_binding *_binding,
848                                   errval_t msgerr)
849 {
850     XINTER_DEBUG("chan_open_did_response_rx: %s\n", err_getstring(msgerr));
851
852     struct xnode *local_node = _binding->st;
853
854     local_node->msg->rpc_err = msgerr;
855
856     rpc_done(local_node->msg);
857 }
858
859 struct interphi_rx_vtbl rx_vtbl = {
860     .domain_lookup_call = domain_lookup_call_rx,
861     .domain_lookup_response = domain_lookup_response_rx,
862     .domain_wait_call = domain_wait_call_rx,
863     .domain_wait_response = domain_wait_response_rx,
864     .domain_register_call = domain_register_call_rx,
865     .domain_register_response = domain_register_response_rx,
866     .chan_open_call = chan_open_call_rx,
867     .chan_open_response = chan_open_response_rx,
868     .spawn_call = spawn_call_rx,
869     .spawn_response = spawn_response_rx,
870     .spawn_with_cap_call = spawn_with_cap_call_rx,
871     .spawn_with_cap_response = spawn_with_cap_response_rx,
872     .kill_call = kill_call_rx,
873     .kill_response = kill_response_rx,
874     .bootstrap_call = bootstrap_call_rx,
875     .bootstrap_response = bootstrap_response_rx
876 };
877
878 /*
879  * ----------------------------------------------------------------------------
880  * Flounder Connect / Accept Callbacks
881  * ----------------------------------------------------------------------------
882  */
883
884 static void interphi_bind_cb(void *st,
885                              errval_t err,
886                              struct interphi_binding *_binding)
887 {
888     XINTER_DEBUG("interphi_bind_cb: driver bound %p  %s\n", _binding,
889                  err_getstring(err));
890
891     assert(_binding);
892
893     struct xnode *node = st;
894
895     _binding->rx_vtbl = rx_vtbl;
896     _binding->st = st;
897
898     node->msg->binding = _binding;
899
900     txq_init(&node->msg->queue, _binding, _binding->waitset,
901              (txq_register_fn_t) _binding->register_send,
902              sizeof(struct interphi_msg_st));
903
904     node->state = XNODE_STATE_READY;
905 }
906
907 static void interphi_connect_cb(void *st,
908                                 errval_t err,
909                                 struct interphi_binding *_binding)
910 {
911     XINTER_DEBUG("interphi_connect_cb: client driver connected %p\n", _binding);
912
913     struct xnode *node = st;
914
915     _binding->rx_vtbl = rx_vtbl;
916     _binding->st = st;
917
918     node->msg->binding = _binding;
919
920     txq_init(&node->msg->queue, _binding, _binding->waitset,
921              (txq_register_fn_t) _binding->register_send,
922              sizeof(struct interphi_msg_st));
923
924     node->state = XNODE_STATE_READY;
925 }
926
927 /**
928  * \brief waits for the client driver to connect
929  *
930  * \param phi Xeon Phi
931  *
932  * \return SYS_ERR_OK when then client driver successfully connected
933  */
934 errval_t interphi_wait_for_client(struct xeon_phi *phi)
935 {
936 #ifndef __k1om__
937     errval_t err;
938
939     XINTER_DEBUG("interphi_wait_for_client\n");
940
941     struct xnode *node = &phi->topology[phi->id];
942
943     while (node->state == XNODE_STATE_WAIT_CONNECTION) {
944         uint32_t data = 0x0;
945         uint32_t serial_recv = 0xF;
946         while (serial_recv--) {
947             data |= xeon_phi_serial_handle_recv();
948         }
949
950         err = event_dispatch_non_block(get_default_waitset());
951         switch (err_no(err)) {
952             case SYS_ERR_OK:
953             break;
954             case LIB_ERR_NO_EVENT:
955             if (!data) {
956                 thread_yield();
957             }
958             break;
959             default:
960             return err;
961             break;
962         }
963     }
964 #endif
965     return SYS_ERR_OK;
966
967 }
968
969 /*
970  * ----------------------------------------------------------------------------
971  * Initialization
972  * ----------------------------------------------------------------------------
973  */
974
975 /**
976  * \brief initializes the messaging boostrap infrastructure between the
977  *        two Xeon Phi cards
978  *
979  * \param phi the xeon phi to initialize the basic messaging bootstrap
980  *
981  * \return SYS_ERR_OK on success
982  *         errval on failure
983  */
984 errval_t interphi_init_xphi(uint8_t xphi,
985                             struct xeon_phi *phi,
986                             struct capref frame,
987                             uint8_t is_client)
988 {
989     errval_t err;
990
991     XINTER_DEBUG("initializing intra Xeon Phi [%u <-> %u] client=%u\n", phi->id,
992                  xphi, is_client);
993
994     assert(xphi < XEON_PHI_NUM_MAX);
995     assert(xphi != phi->id);
996
997     assert(phi->topology[xphi].msg == NULL);
998
999     struct msg_info *mi = calloc(1, sizeof(struct msg_info));
1000     if (mi == NULL) {
1001         return LIB_ERR_MALLOC_FAIL;
1002     }
1003
1004     size_t frame_size;
1005
1006     if (capref_is_null(frame)) {
1007         err = frame_alloc(&mi->frame, XEON_PHI_INTERPHI_FRAME_SIZE, &frame_size);
1008         if (err_is_fail(err)) {
1009             return err;
1010         }
1011     } else {
1012         mi->frame = frame;
1013     }
1014
1015     struct frame_identity id;
1016     err = invoke_frame_identify(mi->frame, &id);
1017     if (err_is_fail(err)) {
1018         cap_destroy(mi->frame);
1019         free(mi);
1020         return err;
1021     }
1022
1023     mi->is_client = is_client;
1024
1025     frame_size = (1UL << id.bits);
1026
1027 #ifdef __k1om__
1028     /*
1029      * XXX: the host does not need to do this
1030      */
1031     void *addr;
1032     err = vspace_map_one_frame(&addr, frame_size, mi->frame, NULL, NULL);
1033     if (err_is_fail(err)) {
1034         cap_destroy(mi->frame);
1035         free(mi);
1036         return err;
1037     }
1038
1039     XINTER_DEBUG("Messaging frame mapped: [%016lx -> %016lx, size = %lx ]\n",
1040                  id.base, (uintptr_t )addr, frame_size);
1041
1042     mi->fi.outbufsize = (frame_size >> 1);
1043     mi->fi.inbufsize = (frame_size >> 1);
1044
1045     struct waitset *ws = get_default_waitset();
1046
1047     struct xnode *node = &phi->topology[xphi];
1048
1049     node->msg = mi;
1050     node->local = phi;
1051     node->state = XNODE_STATE_WAIT_CONNECTION;
1052
1053     if (mi->is_client) {
1054         mi->fi.inbuf = ((uint8_t*) addr) + mi->fi.inbufsize;
1055         mi->fi.outbuf = addr;
1056         mi->fi.sendbase = id.base;
1057
1058         XINTER_DEBUG("client mode: connecting to server. %s\n", __FUNCTION__);
1059
1060         err = interphi_connect(&mi->fi, interphi_bind_cb, node,
1061                                ws, IDC_EXPORT_FLAGS_DEFAULT);
1062     } else {
1063         mi->fi.inbuf = addr;
1064         mi->fi.outbuf = ((uint8_t*) addr) + mi->fi.outbufsize;
1065         mi->fi.sendbase = id.base + mi->fi.outbufsize;
1066
1067         XINTER_DEBUG("server mode: accepting connections. %s\n", __FUNCTION__);
1068
1069         err = interphi_accept(&mi->fi, node, interphi_connect_cb,
1070                               ws, IDC_EXPORT_FLAGS_DEFAULT);
1071     }
1072     if (err_is_fail(err)) {
1073         vspace_unmap(addr);
1074         cap_destroy(mi->frame);
1075         free(mi);
1076         return err;
1077     }
1078
1079     if (mi->is_client) {
1080         XINTER_DEBUG("Waiting for connect callback...\n");
1081         while(node->state == XNODE_STATE_WAIT_CONNECTION) {
1082             messages_wait_and_handle_next();
1083         }
1084         XINTER_DEBUG("connected to pier.\n");
1085     }
1086
1087     phi->connected++;
1088
1089 #else
1090     struct xnode *node = &phi->topology[xphi];
1091     lpaddr_t offset = ((node->apt_base >> 32) - ((node->apt_base >> 34)<<2))<<32;
1092     err = interphi_bootstrap(phi, id.base, id.bits, offset, xphi, mi->is_client);
1093     if (err_is_fail(err)) {
1094         free(mi);
1095         return err;
1096     }
1097
1098     XINTER_DEBUG("Local bootstrap succeeded. Sending to other node.\n");
1099
1100     err = service_bootstrap(phi, xphi, mi->frame);
1101     if (err_is_fail(err)) {
1102         XINTER_DEBUG("Could not initialize messaging\n");
1103         return err;
1104     }
1105 #endif
1106
1107     return SYS_ERR_OK;
1108 }
1109
1110 /**
1111  * \brief initializes the communication between the host and the card Xeon Phi
1112  *        drivers using a bootstraped flounder channel
1113  *
1114  * \param phi   Xeon Phi to initialize
1115  *
1116  * \return SYS_ERR_OK on success
1117  *         errval on failure
1118  */
1119 errval_t interphi_init(struct xeon_phi *phi,
1120                        struct capref frame)
1121 {
1122     errval_t err;
1123
1124     assert(phi->msg == NULL);
1125
1126     struct msg_info *mi = calloc(1, sizeof(struct msg_info));
1127     if (mi == NULL) {
1128         return LIB_ERR_MALLOC_FAIL;
1129     }
1130
1131     size_t frame_size;
1132
1133     if (capref_is_null(frame)) {
1134         err = frame_alloc(&mi->frame, XEON_PHI_INTERPHI_FRAME_SIZE, &frame_size);
1135         if (err_is_fail(err)) {
1136             return err;
1137         }
1138     } else {
1139         mi->frame = frame;
1140     }
1141
1142     struct frame_identity id;
1143     err = invoke_frame_identify(mi->frame, &id);
1144     if (err_is_fail(err)) {
1145         cap_destroy(mi->frame);
1146         free(mi);
1147         return err;
1148     }
1149
1150     frame_size = (1UL << id.bits);
1151
1152     void *addr;
1153     err = vspace_map_one_frame(&addr, frame_size, mi->frame, NULL, NULL);
1154     if (err_is_fail(err)) {
1155         cap_destroy(mi->frame);
1156         free(mi);
1157         return err;
1158     }
1159
1160     XINTER_DEBUG("Messaging frame mapped: [%016lx->%016lx, size = %lx]\n",
1161                  id.base, (uintptr_t )addr, frame_size);
1162
1163     mi->is_client = phi->is_client;
1164
1165     mi->fi.outbufsize = (frame_size >> 1);
1166     mi->fi.inbufsize = (frame_size >> 1);
1167
1168     struct waitset *ws = get_default_waitset();
1169
1170     phi->msg = mi;
1171
1172     phi->topology[phi->id].msg = mi;
1173     phi->topology[phi->id].local = phi;
1174     phi->topology[phi->id].state = XNODE_STATE_WAIT_CONNECTION;
1175
1176     if (phi->is_client) {
1177         mi->fi.inbuf = ((uint8_t*) addr) + mi->fi.inbufsize;
1178         mi->fi.outbuf = addr;
1179         mi->fi.sendbase = id.base;
1180
1181         XINTER_DEBUG("client mode: connecting to server. %s\n", __FUNCTION__);
1182
1183         err = interphi_connect(&mi->fi, interphi_bind_cb, &phi->topology[phi->id],
1184                                ws, IDC_EXPORT_FLAGS_DEFAULT);
1185     } else {
1186         mi->fi.inbuf = addr;
1187         mi->fi.outbuf = ((uint8_t*) addr) + mi->fi.outbufsize;
1188         mi->fi.sendbase = id.base + mi->fi.outbufsize;
1189
1190         XINTER_DEBUG("server mode: accepting connections. %s\n", __FUNCTION__);
1191
1192         err = interphi_accept(&mi->fi, &phi->topology[phi->id],
1193                               interphi_connect_cb, ws, IDC_EXPORT_FLAGS_DEFAULT);
1194     }
1195     if (err_is_fail(err)) {
1196         vspace_unmap(addr);
1197         cap_destroy(mi->frame);
1198         free(mi);
1199         return err;
1200     }
1201
1202
1203
1204     phi->connected = 1;
1205
1206     if (!phi->is_client) {
1207         struct xeon_phi_boot_params *bp;
1208         bp = (struct xeon_phi_boot_params *) (phi->apt.vbase + phi->os_offset);
1209         bp->msg_base = id.base;
1210         bp->msg_size_bits = id.bits;
1211     }
1212
1213     return SYS_ERR_OK;
1214 }
1215
1216 /*
1217  * ----------------------------------------------------------------------------
1218  * Message Sending
1219  * ----------------------------------------------------------------------------
1220  */
1221
1222 /**
1223  * \brief sends a bootstrap request to the Xeon Phi client driver
1224  *
1225  * \param phi        Xeon Phi
1226  * \param frame_base base address of the messaging frame
1227  * \param frame_bits size of the messaging frame in bits
1228  * \param offset     offset into the SMPT
1229  * \param xid        ID of the other Xeon Phi
1230  * \param is_client  flag indicating if this is the client of the connection
1231  *
1232  * \returns SYS_ERR_OK on success
1233  *          errval on faiure
1234  */
1235 errval_t interphi_bootstrap(struct xeon_phi *phi,
1236                             lpaddr_t frame_base,
1237                             uint8_t frame_bits,
1238                             lpaddr_t offset,
1239                             uint8_t xid,
1240                             uint8_t is_client)
1241 {
1242 #ifdef __k1om__
1243     USER_PANIC("This function should not be called on the Xeon Phi\n");
1244 #endif
1245
1246     XINTER_DEBUG("sending bootstrap to card. [%u] client:%u\n", xid, is_client);
1247
1248     struct msg_info *mi = phi->msg;
1249
1250     struct txq_msg_st *msg_st = rpc_preamble(mi);
1251     if (msg_st == NULL) {
1252         return LIB_ERR_MALLOC_FAIL;
1253     }
1254
1255     msg_st->send = bootstrap_call_tx;
1256
1257     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1258
1259     svc_st->args.bootstrap.xid = xid;
1260     svc_st->args.bootstrap.offset = offset;
1261     svc_st->args.bootstrap.is_client = is_client;
1262     svc_st->args.bootstrap.base = frame_base;
1263     svc_st->args.bootstrap.bits = frame_bits;
1264
1265     txq_send(msg_st);
1266
1267     rpc_wait_done(phi->msg);
1268
1269     return phi->msg->rpc_err;
1270 }
1271
1272 /**
1273  * \brief sends a spawn request to the Xeon Phi driver
1274  *
1275  * \param node      Xeon Phi Node
1276  * \param core      which core to spawn the domain on
1277  * \param cmdline   Commandline of the domain to spawn (marshalled)
1278  * \param cmdlen    length of the command line
1279  * \param domain    Domain identifier returned
1280  *
1281  * \returns SYS_ERR_OK on success
1282  *          errval on faiure
1283  */
1284 errval_t interphi_spawn(struct xnode *node,
1285                         uint8_t core,
1286                         char *cmdline,
1287                         size_t cmdlen,
1288                         uint8_t flags,
1289                         uint64_t *domain)
1290 {
1291     XINTER_DEBUG("spawning %s on core %u\n", cmdline, core);
1292     struct msg_info *mi = node->msg;
1293
1294     struct txq_msg_st *msg_st = rpc_preamble(mi);
1295     if (msg_st == NULL) {
1296         return LIB_ERR_MALLOC_FAIL;
1297     }
1298
1299     msg_st->send = spawn_call_tx;
1300
1301     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1302
1303     svc_st->args.spawn_call.cmdline = cmdline;
1304     svc_st->args.spawn_call.cmdlen = cmdlen;
1305     svc_st->args.spawn_call.core = core;
1306     svc_st->args.spawn_call.flags = flags;
1307
1308     txq_send(msg_st);
1309
1310     rpc_wait_done(node->msg);
1311
1312     if (err_is_ok(node->msg->rpc_err)) {
1313         if (domain) {
1314             *domain = node->msg->rpc_data;
1315         }
1316     }
1317
1318     return node->msg->rpc_err;
1319 }
1320
1321 /**
1322  * \brief sends a spawn request to the Xeon Phi driver
1323  *
1324  * \param node      Xeon Phi Node
1325  * \param core      which core to spawn the domain on
1326  * \param cmdline   Commandline of the domain to spawn (marshalled args)
1327  * \param cmdlen    length of the cmd line
1328  * \param cap       Cap to hand over to the domain at boot
1329  * \param domain    Domain identifier returned
1330  *
1331  * \returns SYS_ERR_OK on success
1332  *          errval on faiure
1333  */
1334 errval_t interphi_spawn_with_cap(struct xnode *node,
1335                                  uint8_t core,
1336                                  char *cmdline,
1337                                  size_t cmdlen,
1338                                  uint8_t flags,
1339                                  struct capref cap,
1340                                  uint64_t *domain)
1341 {
1342     errval_t err;
1343     struct msg_info *mi = node->msg;
1344
1345     XINTER_DEBUG("spawning %s with cap on core %u\n", cmdline, core);
1346
1347     struct frame_identity id;
1348     err = invoke_frame_identify(cap, &id);
1349     if (err_is_fail(err)) {
1350         return err;
1351     }
1352
1353     struct txq_msg_st *msg_st = rpc_preamble(mi);
1354     if (msg_st == NULL) {
1355         return LIB_ERR_MALLOC_FAIL;
1356     }
1357
1358     msg_st->send = spawn_with_cap_call_tx;
1359
1360     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1361
1362     svc_st->args.spawn_call.cmdline = cmdline;
1363     svc_st->args.spawn_call.cmdlen = cmdlen;
1364     svc_st->args.spawn_call.core = core;
1365     svc_st->args.spawn_call.flags = flags;
1366     svc_st->args.spawn_call.cap_size_bits = id.bits;
1367     svc_st->args.spawn_call.cap_base = id.base;
1368
1369     txq_send(msg_st);
1370
1371     rpc_wait_done(node->msg);
1372
1373     if (err_is_ok(node->msg->rpc_err)) {
1374         if (domain) {
1375             *domain = node->msg->rpc_data;
1376         }
1377     }
1378
1379     return node->msg->rpc_err;
1380 }
1381
1382 /**
1383  * \brief sends a kill request for a domain
1384  *
1385  * \param node      Target Xeon Phi node
1386  * \param domain    Domain identifier
1387  *
1388  * \returns SYS_ERR_OK on success
1389  *          errval on failure
1390  */
1391 errval_t interphi_kill(struct xnode *node,
1392                        xphi_dom_id_t domain)
1393 {
1394     XINTER_DEBUG("sending kill signal for domain:%lu\n", domain);
1395
1396     struct msg_info *mi = node->msg;
1397
1398     struct txq_msg_st *msg_st = rpc_preamble(mi);
1399     if (msg_st == NULL) {
1400         return LIB_ERR_MALLOC_FAIL;
1401     }
1402
1403     msg_st->send = kill_call_tx;
1404
1405     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1406
1407     svc_st->args.kill.domainid = domain;
1408
1409     txq_send(msg_st);
1410
1411     rpc_wait_done(mi);
1412
1413     return mi->rpc_err;
1414 }
1415
1416 /**
1417  * \brief sends a channel open messages to another Xeon Phi driver
1418  *
1419  * \param node      Xeon Phi Node to send the message to
1420  * \param target    target domain id
1421  * \param source    source domain id
1422  * \param usedata   usr specified data
1423  * \param msgframe  capability of the messaging frame
1424  * \param type      Channel type
1425  *
1426  * \returns SYS_ERR_OK on success
1427  */
1428 errval_t interphi_chan_open(struct xnode *node,
1429                             xphi_dom_id_t target,
1430                             xphi_dom_id_t source,
1431                             uint64_t usrdata,
1432                             struct capref msgframe,
1433                             xphi_chan_type_t type)
1434 {
1435     errval_t err;
1436
1437     XINTER_DEBUG("sending channel open to domain {%lx}\n", target);
1438
1439     struct msg_info *mi = node->msg;
1440
1441     struct frame_identity id;
1442     err = invoke_frame_identify(msgframe, &id);
1443     if (err_is_fail(err)) {
1444         return err;
1445     }
1446
1447     struct txq_msg_st *msg_st = rpc_preamble(mi);
1448     if (msg_st == NULL) {
1449         return LIB_ERR_MALLOC_FAIL;
1450     }
1451
1452     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1453
1454     svc_st->args.open.msgbase = id.base;
1455     svc_st->args.open.msgbits = id.bits;
1456     svc_st->args.open.source = source;
1457     svc_st->args.open.usrdata = usrdata;
1458     svc_st->args.open.type = type;
1459
1460     if (target) {
1461         msg_st->send = chan_open_call_tx;
1462         svc_st->args.open.target = target;
1463     } else {
1464         rpc_done(node->msg);
1465         txq_msg_st_free(msg_st);
1466         return -1;
1467     }
1468
1469     txq_send(msg_st);
1470
1471     rpc_wait_done(mi);
1472
1473     return mi->rpc_err;
1474 }
1475
1476 /**
1477  * \brief registers a ready domain with the Xeon Phi Domain Service
1478  *
1479  * \param node  Xeon Phi Node to send the message to
1480  * \param name  Name to register
1481  * \param domid Xeon Phi Domain ID
1482  *
1483  * \returns SYS_ERR_OK on success
1484  *          errval on error
1485  */
1486 errval_t interphi_domain_register(struct xnode *node,
1487                                   char *name,
1488                                   xphi_dom_id_t domid)
1489 {
1490 #ifdef __k1om__
1491     XINTER_DEBUG("domain register {%s} with domainid:%lx @ xnode:%u\n", name,
1492                  domid, node->id);
1493
1494     assert(node->msg);
1495
1496     struct msg_info *mi = node->msg;
1497
1498     struct txq_msg_st *msg_st = rpc_preamble(mi);
1499     if (msg_st == NULL) {
1500         return LIB_ERR_MALLOC_FAIL;
1501     }
1502     msg_st->send = domain_register_call_tx;
1503
1504     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1505
1506     svc_st->args.domain.domid = domid;
1507     svc_st->args.domain.name = name;
1508
1509     txq_send(msg_st);
1510
1511     rpc_wait_done(mi);
1512
1513     return mi->rpc_err;
1514 #else
1515     USER_PANIC("interphi_domain_lookup: not supporte on host.\n");
1516
1517     return SYS_ERR_OK;
1518 #endif
1519 }
1520
1521 /**
1522  * \brief checks if a domain is running and returns its domain id if it is.
1523  *
1524  * \param node  Xeon Phi Node to send the message to
1525  * \param name  Name of the Domain
1526  * \param domid returned Xeon Phi Domain ID
1527  *
1528  * \returns SYS_ERR_OK on success
1529  *          errval on error
1530  */
1531 errval_t interphi_domain_lookup(struct xnode *node,
1532                                 char *name,
1533                                 xphi_dom_id_t *retdomid)
1534 {
1535 #ifdef __k1om__
1536     XINTER_DEBUG("domain lookup {%s} @ xnode:%u\n", name, node->id);
1537
1538     struct msg_info *mi = node->msg;
1539
1540     struct txq_msg_st *msg_st = rpc_preamble(mi);
1541     if (msg_st == NULL) {
1542         return LIB_ERR_MALLOC_FAIL;
1543     }
1544
1545     msg_st->send = domain_lookup_call_tx;
1546
1547     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1548
1549     svc_st->args.domain.name = name;
1550
1551     txq_send(msg_st);
1552
1553     rpc_wait_done(mi);
1554
1555     return mi->rpc_err;
1556 #else
1557     USER_PANIC("interphi_domain_lookup: not supporte on host.\n");
1558
1559     return SYS_ERR_OK;
1560 #endif
1561 }
1562
1563 /**
1564  * \brief checks if a domain is running and installs a trigger to reply
1565  *
1566  * \param node  Xeon Phi Node to send the message to
1567  * \param name  Name of the Domain
1568  * \param state user state
1569  *
1570  * \returns SYS_ERR_OK on success
1571  *          errval on error
1572  */
1573 errval_t interphi_domain_wait(struct xnode *node,
1574                               char *name,
1575                               void *state)
1576 {
1577 #ifdef __k1om__
1578     XINTER_DEBUG("domain wait {%s} @ xnode:%u\n", name, node->id);
1579
1580     assert(node->msg);
1581
1582     struct msg_info *mi = node->msg;
1583     if (mi->binding == NULL) {
1584         assert(!"NYI");
1585     }
1586
1587     struct txq_msg_st *msg_st = txq_msg_st_alloc(&mi->queue);
1588     if (msg_st == NULL) {
1589         rpc_done(node->msg);
1590         return LIB_ERR_MALLOC_FAIL;
1591     }
1592
1593     msg_st->send = domain_wait_call_tx;
1594     msg_st->cleanup = NULL;
1595
1596     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1597
1598     svc_st->args.domain.name = name;
1599     svc_st->args.domain.state = (uintptr_t) state;
1600
1601     txq_send(msg_st);
1602 #else
1603     USER_PANIC("interphi_domain_wait: not supporte on host\n");
1604 #endif
1605     return SYS_ERR_OK;
1606 }
1607
1608 /**
1609  * \brief sends a reply when the Octopus trigger fired
1610  *
1611  * \param node  Xeon Phi Node
1612  * \param domid Xeon Phi Domain ID
1613  * \param err   Outcome of the reply
1614  * \param state State pointer supplied by the card.
1615  *
1616  * \returns SYS_ERR_OK on success
1617  */
1618 errval_t interphi_domain_wait_reply(struct xnode *node,
1619                                     errval_t err,
1620                                     void *state,
1621                                     xphi_dom_id_t domid)
1622 {
1623 #ifndef __k1om__
1624     XINTER_DEBUG("domain interphi_domain_wait_reply domid:%lx @ xnode:%u, st:%p\n",
1625                     domid, node->id, state);
1626
1627     struct msg_info *mi = node->msg;
1628     if (mi->binding == NULL) {
1629         assert(!"NYI");
1630     }
1631
1632     struct txq_msg_st *msg_st = txq_msg_st_alloc(&mi->queue);
1633     if (msg_st == NULL) {
1634         rpc_done(node->msg);
1635         return LIB_ERR_MALLOC_FAIL;
1636     }
1637
1638     msg_st->send = domain_wait_response_tx;
1639     msg_st->cleanup = NULL;
1640     msg_st->err = err;
1641
1642     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1643
1644     svc_st->args.domain.domid = domid;
1645     svc_st->args.domain.state = (uintptr_t)state;
1646
1647     txq_send(msg_st);
1648
1649 #else
1650     USER_PANIC("interphi_domain_wait_reply: Not supported on Xeon Phi\n");
1651 #endif
1652     return SYS_ERR_OK;
1653 }