flounder: making const pointers in receiving handlers, using CONST_CAST as a temporar...
[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                                 const 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 #endif
455 }
456
457 static void domain_wait_response_rx(struct interphi_binding *_binding,
458                                     xphi_dom_id_t domain,
459                                     uintptr_t state,
460                                     errval_t msgerr)
461 {
462 #ifdef __k1om__
463     XINTER_DEBUG("domain_wait_response_rx: domid:%lx, st:%p,  %s\n", domain,
464                  (void * )state, err_getstring(msgerr));
465
466     struct xphi_svc_st *st = (struct xphi_svc_st *) state;
467
468     xeon_phi_service_domain_wait_response(st, msgerr, domain);
469 #else
470     USER_PANIC("domain_wait_call_rx: not supported on the host\n");
471 #endif
472 }
473
474 static void domain_lookup_call_rx(struct interphi_binding *_binding,
475                                   const char *name,
476                                   size_t length)
477 {
478 #ifdef __k1om__
479     USER_PANIC("domain_lookup_call_rx: not supported on the Xeon Phi\n");
480 #else
481     XINTER_DEBUG("domain_lookup_call_rx: {%s}\n", name);
482
483     struct xnode *local_node = _binding->st;
484
485     struct xeon_phi *phi = local_node->local;
486     assert(phi);
487
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");
491     }
492
493     msg_st->send = domain_lookup_response_tx;
494     msg_st->cleanup = NULL;
495
496     struct interphi_msg_st *st = (struct interphi_msg_st *)msg_st;
497
498     msg_st->err = domain_lookup(name, &st->args.domain.domid);
499
500     txq_send(msg_st);
501 #endif
502 }
503
504 static void domain_lookup_response_rx(struct interphi_binding *_binding,
505                                       xphi_dom_id_t domain,
506                                       errval_t msgerr)
507 {
508 #ifdef __k1om__
509     XINTER_DEBUG("domain_lookup_response_rx: %lx, %s\n", domain,
510                  err_getstring(msgerr));
511
512     struct xnode *local_node = _binding->st;
513
514     local_node->msg->rpc_err = msgerr;
515     rpc_done(local_node->msg);
516 #else
517     USER_PANIC("domain_lookup_response_rx: not supported on the host\n");
518 #endif
519 }
520
521 static void domain_register_call_rx(struct interphi_binding *_binding,
522                                     const char *name,
523                                     size_t length,
524                                     xphi_dom_id_t domid)
525 {
526 #ifdef __k1om__
527     /* register calls on the K1OM are not valid */
528     USER_PANIC("domain_register_call_rx: not supported on the Xeon Phi\n");
529 #else
530     XINTER_DEBUG("domain_register_call_rx: {%s} @ domid:%lx\n", name, domid);
531
532     struct xnode *local_node = _binding->st;
533
534     struct xeon_phi *phi = local_node->local;
535     assert(phi);
536
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");
540     }
541
542     msg_st->err = SYS_ERR_OK;
543     msg_st->send = domain_register_response_tx;
544     msg_st->cleanup = NULL;
545
546     msg_st->err = domain_register(name, domid);
547
548     txq_send(msg_st);
549 #endif
550 }
551
552 static void domain_register_response_rx(struct interphi_binding *_binding,
553                                         errval_t msgerr)
554 {
555 #ifdef __k1om__
556     XINTER_DEBUG("domain_register_response_rx:%s\n", err_getstring(msgerr));
557
558     struct xnode *local_node = _binding->st;
559
560     local_node->msg->rpc_err = msgerr;
561     rpc_done(local_node->msg);
562 #else
563     USER_PANIC("domain_register_response_rx: not supported on the host\n");
564 #endif
565 }
566
567 static void spawn_call_rx(struct interphi_binding *_binding,
568                           uint8_t core,
569                           const char *cmdline,
570                           size_t length,
571                           uint8_t flags)
572 {
573     XINTER_DEBUG("spawn_call_rx: {%s} of length %lu, @ core:%u\n", cmdline,
574                  length, core);
575
576     struct xnode *local_node = _binding->st;
577
578     struct xeon_phi *phi = local_node->local;
579     assert(phi);
580
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");
584     }
585
586     msg_st->send = spawn_response_tx;
587     msg_st->cleanup = NULL;
588
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)) {
592         txq_send(msg_st);
593         return;
594     }
595     argv[MAX_CMDLINE_ARGS] = NULL;
596
597     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
598
599     domainid_t domid;
600
601     /*
602      * TODO: check if we have that core present...
603      */
604
605     msg_st->err = spawn_program(core, cmdline, argv, NULL, flags, &domid);
606     if (err_is_ok(msg_st->err)) {
607 #ifdef __k1om__
608         uint8_t is_host = 0x0;
609 #else
610         uint8_t is_host = 0x1;
611 #endif
612         st->args.spawn_reply.domainid = xeon_phi_domain_build_id(phi->id, core,
613                                                                  is_host, domid);
614     }
615     txq_send(msg_st);
616 }
617
618 static void spawn_response_rx(struct interphi_binding *_binding,
619                               uint64_t domainid,
620                               interphi_errval_t msgerr)
621 {
622     XINTER_DEBUG("spawn_response_rx: %lu, %s\n", domainid, err_getstring(msgerr));
623
624     struct xnode *local_node = _binding->st;
625
626     local_node->msg->rpc_err = msgerr;
627     local_node->msg->rpc_data = domainid;
628     rpc_done(local_node->msg);
629 }
630
631 static void spawn_with_cap_call_rx(struct interphi_binding *_binding,
632                                    uint8_t core,
633                                    const char *cmdline,
634                                    size_t length,
635                                    uint8_t flags,
636                                    uint64_t cap_base,
637                                    uint8_t cap_size_bits)
638 {
639     XINTER_DEBUG("spawn_with_cap_call_rx: {%s} of length %lu @ core:%u\n", cmdline,
640                  length, core);
641
642     struct xnode *local_node = _binding->st;
643
644     struct xeon_phi *phi = local_node->local;
645     assert(phi);
646
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");
650     }
651
652     msg_st->send = spawn_with_cap_response_tx;
653     msg_st->cleanup = NULL;
654
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)) {
658         txq_send(msg_st);
659         return;
660     }
661     argv[MAX_CMDLINE_ARGS] = NULL;
662
663     struct interphi_msg_st *st = (struct interphi_msg_st *) msg_st;
664
665     struct capref cap;
666     msg_st->err = sysmem_cap_request(cap_base, cap_size_bits, &cap);
667     if (err_is_fail(msg_st->err)) {
668         txq_send(msg_st);
669         return;
670     }
671
672     domainid_t domid;
673     msg_st->err = spawn_program_with_caps(core, cmdline, argv, NULL, NULL_CAP,
674                                           cap, flags, &domid);
675     if (err_is_ok(msg_st->err)) {
676 #ifdef __k1om__
677         st->args.spawn_reply.domainid = xeon_phi_domain_build_id(
678                         disp_xeon_phi_id(), core, 0, domid);
679 #else
680         st->args.spawn_reply.domainid = xeon_phi_domain_build_id(
681                         XEON_PHI_DOMAIN_HOST, core, 1, domid);
682 #endif
683     }
684     txq_send(msg_st);
685 }
686
687 static void spawn_with_cap_response_rx(struct interphi_binding *_binding,
688                                        uint64_t domainid,
689                                        interphi_errval_t msgerr)
690 {
691     XINTER_DEBUG("spawn_with_cap_response_rx: %lu, %s\n", domainid,
692                  err_getstring(msgerr));
693
694     struct xnode *local_node = _binding->st;
695
696     local_node->msg->rpc_err = msgerr;
697     local_node->msg->rpc_data = domainid;
698     rpc_done(local_node->msg);
699 }
700
701 static void kill_call_rx(struct interphi_binding *_binding,
702                          uint64_t domainid)
703 {
704     XINTER_DEBUG("kill_call_rx: %lu,\n", domainid);
705
706     struct xnode *local_node = _binding->st;
707
708     struct xeon_phi *phi = local_node->local;
709     assert(phi);
710
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");
714     }
715
716     msg_st->err = SYS_ERR_OK;
717     msg_st->send = kill_response_tx;
718     msg_st->cleanup = NULL;
719
720     msg_st->err = spawn_kill(domainid);
721
722     txq_send(msg_st);
723 }
724
725 static void kill_response_rx(struct interphi_binding *_binding,
726                              interphi_errval_t msgerr)
727 {
728     XINTER_DEBUG("kill_response_rx: %s\n", err_getstring(msgerr));
729
730     struct xnode *local_node = _binding->st;
731
732     local_node->msg->rpc_err = msgerr;
733
734     rpc_done(local_node->msg);
735 }
736
737 static void bootstrap_call_rx(struct interphi_binding *_binding,
738                               uint64_t base,
739                               uint64_t offset,
740                               uint8_t bits,
741                               uint8_t xid,
742                               uint8_t is_client)
743 {
744     XINTER_DEBUG("bootstrap_call_rx: {%016lx, %02x} of:%016lx, xid:%u, c:%u\n",
745                  base, bits, offset, xid, is_client);
746
747     struct xnode *local_node = _binding->st;
748
749     struct xeon_phi *phi = local_node->local;
750     assert(phi);
751
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");
755     }
756
757     msg_st->err = SYS_ERR_OK;
758     msg_st->send = bootstrap_response_tx;
759     msg_st->cleanup = NULL;
760
761     struct xnode *node = &phi->topology[xid];
762     if (node->msg) {
763         XINTER_DEBUG("already established a connection to xid:%u\n", xid);
764         txq_send(msg_st);
765     }
766
767     struct capref msg_frame;
768     msg_st->err = sysmem_cap_request(base, bits, &msg_frame);
769     if (err_is_fail(msg_st->err)) {
770         txq_send(msg_st);
771         return;
772     }
773
774     smpt_set_coprocessor_offset(phi, xid, offset);
775
776     msg_st->err = interphi_init_xphi(xid, phi, msg_frame, is_client);
777
778     txq_send(msg_st);
779 }
780
781 static void bootstrap_response_rx(struct interphi_binding *_binding,
782                                   interphi_errval_t msgerr)
783 {
784     XINTER_DEBUG("bootstrap_response_rx: %s\n", err_getstring(msgerr));
785
786     struct xnode *local_node = _binding->st;
787
788     local_node->msg->rpc_err = msgerr;
789
790     rpc_done(local_node->msg);
791 }
792
793 static void chan_open_call_rx(struct interphi_binding *_binding,
794                               uint64_t source_did,
795                               uint64_t target_did,
796                               uint64_t usrdata,
797                               uint64_t msgbase,
798                               uint8_t msgbits,
799                               uint8_t type)
800 {
801     XINTER_DEBUG("chan_open_call_rx: %lx -> %lx\n", source_did, target_did);
802
803     struct xnode *local_node = _binding->st;
804
805     struct xeon_phi *phi = local_node->local;
806     assert(phi);
807
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");
811     }
812
813     msg_st->send = chan_open_response_tx;
814     msg_st->cleanup = NULL;
815
816     struct capref msgcap;
817
818     lpaddr_t offset = smpt_get_coprocessor_address(phi, local_node->id);
819
820     msgbase += offset;
821
822     msg_st->err = sysmem_cap_request(msgbase, msgbits, &msgcap);
823     if (err_is_fail(msg_st->err)) {
824         txq_send(msg_st);
825         return;
826     }
827
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);
832     }
833     txq_send(msg_st);
834 }
835
836 static void chan_open_response_rx(struct interphi_binding *_binding,
837                                   errval_t msgerr)
838 {
839     XINTER_DEBUG("chan_open_did_response_rx: %s\n", err_getstring(msgerr));
840
841     struct xnode *local_node = _binding->st;
842
843     local_node->msg->rpc_err = msgerr;
844
845     rpc_done(local_node->msg);
846 }
847
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
865 };
866
867 /*
868  * ----------------------------------------------------------------------------
869  * Flounder Connect / Accept Callbacks
870  * ----------------------------------------------------------------------------
871  */
872
873 static void interphi_bind_cb(void *st,
874                              errval_t err,
875                              struct interphi_binding *_binding)
876 {
877     XINTER_DEBUG("interphi_bind_cb: driver bound %p  %s\n", _binding,
878                  err_getstring(err));
879
880     assert(_binding);
881
882     struct xnode *node = st;
883
884     _binding->rx_vtbl = rx_vtbl;
885     _binding->st = st;
886
887     node->msg->binding = _binding;
888
889     txq_init(&node->msg->queue, _binding, _binding->waitset,
890              (txq_register_fn_t) _binding->register_send,
891              sizeof(struct interphi_msg_st));
892
893     node->state = XNODE_STATE_READY;
894 }
895
896 static void interphi_connect_cb(void *st,
897                                 errval_t err,
898                                 struct interphi_binding *_binding)
899 {
900     XINTER_DEBUG("interphi_connect_cb: client driver connected %p\n", _binding);
901
902     struct xnode *node = st;
903
904     _binding->rx_vtbl = rx_vtbl;
905     _binding->st = st;
906
907     node->msg->binding = _binding;
908
909     txq_init(&node->msg->queue, _binding, _binding->waitset,
910              (txq_register_fn_t) _binding->register_send,
911              sizeof(struct interphi_msg_st));
912
913     node->state = XNODE_STATE_READY;
914 }
915
916 /**
917  * \brief waits for the client driver to connect
918  *
919  * \param phi Xeon Phi
920  *
921  * \return SYS_ERR_OK when then client driver successfully connected
922  */
923 errval_t interphi_wait_for_client(struct xeon_phi *phi)
924 {
925 #ifndef __k1om__
926     errval_t err;
927
928     XINTER_DEBUG("interphi_wait_for_client\n");
929
930     struct xnode *node = &phi->topology[phi->id];
931
932     while (node->state == XNODE_STATE_WAIT_CONNECTION) {
933         uint32_t data = 0x0;
934         uint32_t serial_recv = 0xF;
935         while (serial_recv--) {
936             data |= xeon_phi_serial_handle_recv();
937         }
938
939         err = event_dispatch_non_block(get_default_waitset());
940         switch (err_no(err)) {
941             case SYS_ERR_OK:
942             break;
943             case LIB_ERR_NO_EVENT:
944             if (!data) {
945                 thread_yield();
946             }
947             break;
948             default:
949             return err;
950             break;
951         }
952     }
953 #endif
954     return SYS_ERR_OK;
955
956 }
957
958 /*
959  * ----------------------------------------------------------------------------
960  * Initialization
961  * ----------------------------------------------------------------------------
962  */
963
964 /**
965  * \brief initializes the messaging boostrap infrastructure between the
966  *        two Xeon Phi cards
967  *
968  * \param phi the xeon phi to initialize the basic messaging bootstrap
969  *
970  * \return SYS_ERR_OK on success
971  *         errval on failure
972  */
973 errval_t interphi_init_xphi(uint8_t xphi,
974                             struct xeon_phi *phi,
975                             struct capref frame,
976                             uint8_t is_client)
977 {
978     errval_t err;
979
980     XINTER_DEBUG("initializing intra Xeon Phi [%u <-> %u] client=%u\n", phi->id,
981                  xphi, is_client);
982
983     assert(xphi < XEON_PHI_NUM_MAX);
984     assert(xphi != phi->id);
985
986     assert(phi->topology[xphi].msg == NULL);
987
988     struct msg_info *mi = calloc(1, sizeof(struct msg_info));
989     if (mi == NULL) {
990         return LIB_ERR_MALLOC_FAIL;
991     }
992
993     size_t frame_size;
994
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)) {
998             return err;
999         }
1000     } else {
1001         mi->frame = frame;
1002     }
1003
1004     struct frame_identity id;
1005     err = invoke_frame_identify(mi->frame, &id);
1006     if (err_is_fail(err)) {
1007         cap_destroy(mi->frame);
1008         free(mi);
1009         return err;
1010     }
1011
1012     mi->is_client = is_client;
1013
1014     frame_size = id.bytes;
1015
1016 #ifdef __k1om__
1017     /*
1018      * XXX: the host does not need to do this
1019      */
1020     void *addr;
1021     err = vspace_map_one_frame(&addr, frame_size, mi->frame, NULL, NULL);
1022     if (err_is_fail(err)) {
1023         cap_destroy(mi->frame);
1024         free(mi);
1025         return err;
1026     }
1027
1028     XINTER_DEBUG("Messaging frame mapped: [%016lx -> %016lx, size = %lx ]\n",
1029                  id.base, (uintptr_t )addr, frame_size);
1030
1031     mi->fi.outbufsize = (frame_size >> 1);
1032     mi->fi.inbufsize = (frame_size >> 1);
1033
1034     struct waitset *ws = get_default_waitset();
1035
1036     struct xnode *node = &phi->topology[xphi];
1037
1038     node->msg = mi;
1039     node->local = phi;
1040     node->state = XNODE_STATE_WAIT_CONNECTION;
1041
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;
1046
1047         XINTER_DEBUG("client mode: connecting to server. %s\n", __FUNCTION__);
1048
1049         err = interphi_connect(&mi->fi, interphi_bind_cb, node,
1050                                ws, IDC_EXPORT_FLAGS_DEFAULT);
1051     } else {
1052         mi->fi.inbuf = addr;
1053         mi->fi.outbuf = ((uint8_t*) addr) + mi->fi.outbufsize;
1054         mi->fi.sendbase = id.base + mi->fi.outbufsize;
1055
1056         XINTER_DEBUG("server mode: accepting connections. %s\n", __FUNCTION__);
1057
1058         err = interphi_accept(&mi->fi, node, interphi_connect_cb,
1059                               ws, IDC_EXPORT_FLAGS_DEFAULT);
1060     }
1061     if (err_is_fail(err)) {
1062         vspace_unmap(addr);
1063         cap_destroy(mi->frame);
1064         free(mi);
1065         return err;
1066     }
1067
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();
1072         }
1073         XINTER_DEBUG("connected to pier.\n");
1074     }
1075
1076     phi->connected++;
1077
1078 #else
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)) {
1084         free(mi);
1085         return err;
1086     }
1087
1088     XINTER_DEBUG("Local bootstrap succeeded. Sending to other node.\n");
1089
1090     err = service_bootstrap(phi, xphi, mi->frame);
1091     if (err_is_fail(err)) {
1092         XINTER_DEBUG("Could not initialize messaging\n");
1093         return err;
1094     }
1095 #endif
1096
1097     return SYS_ERR_OK;
1098 }
1099
1100 /**
1101  * \brief initializes the communication between the host and the card Xeon Phi
1102  *        drivers using a bootstraped flounder channel
1103  *
1104  * \param phi   Xeon Phi to initialize
1105  *
1106  * \return SYS_ERR_OK on success
1107  *         errval on failure
1108  */
1109 errval_t interphi_init(struct xeon_phi *phi,
1110                        struct capref frame)
1111 {
1112     errval_t err;
1113
1114     assert(phi->msg == NULL);
1115
1116     struct msg_info *mi = calloc(1, sizeof(struct msg_info));
1117     if (mi == NULL) {
1118         return LIB_ERR_MALLOC_FAIL;
1119     }
1120
1121     size_t frame_size;
1122
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)) {
1126             return err;
1127         }
1128     } else {
1129         mi->frame = frame;
1130     }
1131
1132     struct frame_identity id;
1133     err = invoke_frame_identify(mi->frame, &id);
1134     if (err_is_fail(err)) {
1135         cap_destroy(mi->frame);
1136         free(mi);
1137         return err;
1138     }
1139
1140     frame_size = id.bytes;
1141
1142     void *addr;
1143     err = vspace_map_one_frame(&addr, frame_size, mi->frame, NULL, NULL);
1144     if (err_is_fail(err)) {
1145         cap_destroy(mi->frame);
1146         free(mi);
1147         return err;
1148     }
1149
1150     XINTER_DEBUG("Messaging frame mapped: [%016lx->%016lx, size = %lx]\n",
1151                  id.base, (uintptr_t )addr, frame_size);
1152
1153     mi->is_client = phi->is_client;
1154
1155     mi->fi.outbufsize = (frame_size >> 1);
1156     mi->fi.inbufsize = (frame_size >> 1);
1157
1158     struct waitset *ws = get_default_waitset();
1159
1160     phi->msg = mi;
1161
1162     phi->topology[phi->id].msg = mi;
1163     phi->topology[phi->id].local = phi;
1164     phi->topology[phi->id].state = XNODE_STATE_WAIT_CONNECTION;
1165
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;
1170
1171         XINTER_DEBUG("client mode: connecting to server. %s\n", __FUNCTION__);
1172
1173         err = interphi_connect(&mi->fi, interphi_bind_cb, &phi->topology[phi->id],
1174                                ws, IDC_EXPORT_FLAGS_DEFAULT);
1175     } else {
1176         mi->fi.inbuf = addr;
1177         mi->fi.outbuf = ((uint8_t*) addr) + mi->fi.outbufsize;
1178         mi->fi.sendbase = id.base + mi->fi.outbufsize;
1179
1180         XINTER_DEBUG("server mode: accepting connections. %s\n", __FUNCTION__);
1181
1182         err = interphi_accept(&mi->fi, &phi->topology[phi->id],
1183                               interphi_connect_cb, ws, IDC_EXPORT_FLAGS_DEFAULT);
1184     }
1185     if (err_is_fail(err)) {
1186         vspace_unmap(addr);
1187         cap_destroy(mi->frame);
1188         free(mi);
1189         return err;
1190     }
1191
1192
1193
1194     phi->connected = 1;
1195
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);
1202     }
1203
1204     return SYS_ERR_OK;
1205 }
1206
1207 /*
1208  * ----------------------------------------------------------------------------
1209  * Message Sending
1210  * ----------------------------------------------------------------------------
1211  */
1212
1213 /**
1214  * \brief sends a bootstrap request to the Xeon Phi client driver
1215  *
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
1222  *
1223  * \returns SYS_ERR_OK on success
1224  *          errval on faiure
1225  */
1226 errval_t interphi_bootstrap(struct xeon_phi *phi,
1227                             lpaddr_t frame_base,
1228                             uint8_t frame_bits,
1229                             lpaddr_t offset,
1230                             uint8_t xid,
1231                             uint8_t is_client)
1232 {
1233 #ifdef __k1om__
1234     USER_PANIC("This function should not be called on the Xeon Phi\n");
1235 #endif
1236
1237     XINTER_DEBUG("sending bootstrap to card. [%u] client:%u\n", xid, is_client);
1238
1239     struct msg_info *mi = phi->msg;
1240
1241     struct txq_msg_st *msg_st = rpc_preamble(mi);
1242     if (msg_st == NULL) {
1243         return LIB_ERR_MALLOC_FAIL;
1244     }
1245
1246     msg_st->send = bootstrap_call_tx;
1247
1248     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1249
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;
1255
1256     txq_send(msg_st);
1257
1258     rpc_wait_done(phi->msg);
1259
1260     return phi->msg->rpc_err;
1261 }
1262
1263 /**
1264  * \brief sends a spawn request to the Xeon Phi driver
1265  *
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
1271  *
1272  * \returns SYS_ERR_OK on success
1273  *          errval on faiure
1274  */
1275 errval_t interphi_spawn(struct xnode *node,
1276                         uint8_t core,
1277                         char *cmdline,
1278                         size_t cmdlen,
1279                         uint8_t flags,
1280                         uint64_t *domain)
1281 {
1282     XINTER_DEBUG("spawning %s on core %u\n", cmdline, core);
1283     struct msg_info *mi = node->msg;
1284
1285     struct txq_msg_st *msg_st = rpc_preamble(mi);
1286     if (msg_st == NULL) {
1287         return LIB_ERR_MALLOC_FAIL;
1288     }
1289
1290     msg_st->send = spawn_call_tx;
1291
1292     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1293
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;
1298
1299     txq_send(msg_st);
1300
1301     rpc_wait_done(node->msg);
1302
1303     if (err_is_ok(node->msg->rpc_err)) {
1304         if (domain) {
1305             *domain = node->msg->rpc_data;
1306         }
1307     }
1308
1309     return node->msg->rpc_err;
1310 }
1311
1312 /**
1313  * \brief sends a spawn request to the Xeon Phi driver
1314  *
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
1321  *
1322  * \returns SYS_ERR_OK on success
1323  *          errval on faiure
1324  */
1325 errval_t interphi_spawn_with_cap(struct xnode *node,
1326                                  uint8_t core,
1327                                  char *cmdline,
1328                                  size_t cmdlen,
1329                                  uint8_t flags,
1330                                  struct capref cap,
1331                                  uint64_t *domain)
1332 {
1333     errval_t err;
1334     struct msg_info *mi = node->msg;
1335
1336     XINTER_DEBUG("spawning %s with cap on core %u\n", cmdline, core);
1337
1338     struct frame_identity id;
1339     err = invoke_frame_identify(cap, &id);
1340     if (err_is_fail(err)) {
1341         return err;
1342     }
1343
1344     struct txq_msg_st *msg_st = rpc_preamble(mi);
1345     if (msg_st == NULL) {
1346         return LIB_ERR_MALLOC_FAIL;
1347     }
1348
1349     msg_st->send = spawn_with_cap_call_tx;
1350
1351     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1352
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;
1360
1361     txq_send(msg_st);
1362
1363     rpc_wait_done(node->msg);
1364
1365     if (err_is_ok(node->msg->rpc_err)) {
1366         if (domain) {
1367             *domain = node->msg->rpc_data;
1368         }
1369     }
1370
1371     return node->msg->rpc_err;
1372 }
1373
1374 /**
1375  * \brief sends a kill request for a domain
1376  *
1377  * \param node      Target Xeon Phi node
1378  * \param domain    Domain identifier
1379  *
1380  * \returns SYS_ERR_OK on success
1381  *          errval on failure
1382  */
1383 errval_t interphi_kill(struct xnode *node,
1384                        xphi_dom_id_t domain)
1385 {
1386     XINTER_DEBUG("sending kill signal for domain:%lu\n", domain);
1387
1388     struct msg_info *mi = node->msg;
1389
1390     struct txq_msg_st *msg_st = rpc_preamble(mi);
1391     if (msg_st == NULL) {
1392         return LIB_ERR_MALLOC_FAIL;
1393     }
1394
1395     msg_st->send = kill_call_tx;
1396
1397     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1398
1399     svc_st->args.kill.domainid = domain;
1400
1401     txq_send(msg_st);
1402
1403     rpc_wait_done(mi);
1404
1405     return mi->rpc_err;
1406 }
1407
1408 /**
1409  * \brief sends a channel open messages to another Xeon Phi driver
1410  *
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
1417  *
1418  * \returns SYS_ERR_OK on success
1419  */
1420 errval_t interphi_chan_open(struct xnode *node,
1421                             xphi_dom_id_t target,
1422                             xphi_dom_id_t source,
1423                             uint64_t usrdata,
1424                             struct capref msgframe,
1425                             xphi_chan_type_t type)
1426 {
1427     errval_t err;
1428
1429     XINTER_DEBUG("sending channel open to domain {%lx}\n", target);
1430
1431     struct msg_info *mi = node->msg;
1432
1433     struct frame_identity id;
1434     err = invoke_frame_identify(msgframe, &id);
1435     if (err_is_fail(err)) {
1436         return err;
1437     }
1438
1439     struct txq_msg_st *msg_st = rpc_preamble(mi);
1440     if (msg_st == NULL) {
1441         return LIB_ERR_MALLOC_FAIL;
1442     }
1443
1444     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1445
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;
1452
1453     if (target) {
1454         msg_st->send = chan_open_call_tx;
1455         svc_st->args.open.target = target;
1456     } else {
1457         rpc_done(node->msg);
1458         txq_msg_st_free(msg_st);
1459         return -1;
1460     }
1461
1462     txq_send(msg_st);
1463
1464     rpc_wait_done(mi);
1465
1466     return mi->rpc_err;
1467 }
1468
1469 /**
1470  * \brief registers a ready domain with the Xeon Phi Domain Service
1471  *
1472  * \param node  Xeon Phi Node to send the message to
1473  * \param name  Name to register
1474  * \param domid Xeon Phi Domain ID
1475  *
1476  * \returns SYS_ERR_OK on success
1477  *          errval on error
1478  */
1479 errval_t interphi_domain_register(struct xnode *node,
1480                                   char *name,
1481                                   xphi_dom_id_t domid)
1482 {
1483 #ifdef __k1om__
1484     XINTER_DEBUG("domain register {%s} with domainid:%lx @ xnode:%u\n", name,
1485                  domid, node->id);
1486
1487     assert(node->msg);
1488
1489     struct msg_info *mi = node->msg;
1490
1491     struct txq_msg_st *msg_st = rpc_preamble(mi);
1492     if (msg_st == NULL) {
1493         return LIB_ERR_MALLOC_FAIL;
1494     }
1495     msg_st->send = domain_register_call_tx;
1496
1497     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1498
1499     svc_st->args.domain.domid = domid;
1500     svc_st->args.domain.name = name;
1501
1502     txq_send(msg_st);
1503
1504     rpc_wait_done(mi);
1505
1506     return mi->rpc_err;
1507 #else
1508     USER_PANIC("interphi_domain_lookup: not supporte on host.\n");
1509
1510     return SYS_ERR_OK;
1511 #endif
1512 }
1513
1514 /**
1515  * \brief checks if a domain is running and returns its domain id if it is.
1516  *
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
1520  *
1521  * \returns SYS_ERR_OK on success
1522  *          errval on error
1523  */
1524 errval_t interphi_domain_lookup(struct xnode *node,
1525                                 char *name,
1526                                 xphi_dom_id_t *retdomid)
1527 {
1528 #ifdef __k1om__
1529     XINTER_DEBUG("domain lookup {%s} @ xnode:%u\n", name, node->id);
1530
1531     struct msg_info *mi = node->msg;
1532
1533     struct txq_msg_st *msg_st = rpc_preamble(mi);
1534     if (msg_st == NULL) {
1535         return LIB_ERR_MALLOC_FAIL;
1536     }
1537
1538     msg_st->send = domain_lookup_call_tx;
1539
1540     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1541
1542     svc_st->args.domain.name = name;
1543
1544     txq_send(msg_st);
1545
1546     rpc_wait_done(mi);
1547
1548     return mi->rpc_err;
1549 #else
1550     USER_PANIC("interphi_domain_lookup: not supporte on host.\n");
1551
1552     return SYS_ERR_OK;
1553 #endif
1554 }
1555
1556 /**
1557  * \brief checks if a domain is running and installs a trigger to reply
1558  *
1559  * \param node  Xeon Phi Node to send the message to
1560  * \param name  Name of the Domain
1561  * \param state user state
1562  *
1563  * \returns SYS_ERR_OK on success
1564  *          errval on error
1565  */
1566 errval_t interphi_domain_wait(struct xnode *node,
1567                               char *name,
1568                               void *state)
1569 {
1570 #ifdef __k1om__
1571     XINTER_DEBUG("domain wait {%s} @ xnode:%u\n", name, node->id);
1572
1573     assert(node->msg);
1574
1575     struct msg_info *mi = node->msg;
1576     if (mi->binding == NULL) {
1577         assert(!"NYI");
1578     }
1579
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;
1584     }
1585
1586     msg_st->send = domain_wait_call_tx;
1587     msg_st->cleanup = NULL;
1588
1589     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1590
1591     svc_st->args.domain.name = name;
1592     svc_st->args.domain.state = (uintptr_t) state;
1593
1594     txq_send(msg_st);
1595 #else
1596     USER_PANIC("interphi_domain_wait: not supporte on host\n");
1597 #endif
1598     return SYS_ERR_OK;
1599 }
1600
1601 /**
1602  * \brief sends a reply when the Octopus trigger fired
1603  *
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.
1608  *
1609  * \returns SYS_ERR_OK on success
1610  */
1611 errval_t interphi_domain_wait_reply(struct xnode *node,
1612                                     errval_t err,
1613                                     void *state,
1614                                     xphi_dom_id_t domid)
1615 {
1616 #ifndef __k1om__
1617     XINTER_DEBUG("domain interphi_domain_wait_reply domid:%lx @ xnode:%u, st:%p\n",
1618                     domid, node->id, state);
1619
1620     struct msg_info *mi = node->msg;
1621     if (mi->binding == NULL) {
1622         assert(!"NYI");
1623     }
1624
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;
1629     }
1630
1631     msg_st->send = domain_wait_response_tx;
1632     msg_st->cleanup = NULL;
1633     msg_st->err = err;
1634
1635     struct interphi_msg_st *svc_st = (struct interphi_msg_st *) msg_st;
1636
1637     svc_st->args.domain.domid = domid;
1638     svc_st->args.domain.state = (uintptr_t)state;
1639
1640     txq_send(msg_st);
1641
1642 #else
1643     USER_PANIC("interphi_domain_wait_reply: Not supported on Xeon Phi\n");
1644 #endif
1645     return SYS_ERR_OK;
1646 }