Bugfixes Xeon Phi Driver startup - removed check for boot info - added initialization...
[barrelfish] / lib / xeon_phi / xeon_phi_messaging_client.c
1 /*
2  * Copyright (c) 2014 ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 #include <string.h>
11 #include <barrelfish/barrelfish.h>
12 #include <barrelfish/nameservice_client.h>
13
14 #include <xeon_phi/xeon_phi.h>
15
16 #include <xeon_phi/xeon_phi_messaging.h>
17 #include <xeon_phi/xeon_phi_messaging_client.h>
18
19 #include <if/xeon_phi_messaging_defs.h>
20
21 #define DEBUG_XPMC(x...) debug_printf(" XPMC | " x)
22
23 enum xpm_state
24 {
25     XPM_STATE_NSLOOKUP,
26     XPM_STATE_BINDING,
27     XPM_STATE_BIND_OK,
28     XPM_STATE_BIND_FAIL,
29 };
30
31 /* todo: extend this with array of 8 */
32 static iref_t xpm_iref[XEON_PHI_NUM_MAX];
33 struct xeon_phi_messaging_binding *xpm_binding[XEON_PHI_NUM_MAX];
34
35 enum xpm_state conn_state = XPM_STATE_NSLOOKUP;
36
37 /*
38  * --------------------------------------------------------------------------
39  * Handling of OPEN commands
40  */
41 struct xpm_msg_param_open
42 {
43     struct capref frame;
44     struct xeon_phi_messaging_binding *b;
45     uint8_t type;
46     char iface[44];
47 };
48
49 static void xpm_msg_open_tx(void *a)
50 {
51     errval_t err;
52
53     struct xpm_msg_param_open *param = a;
54
55     struct event_closure txcont = MKCONT(free, a);
56
57     size_t length = strlen(param->iface)+1;
58
59     err = xeon_phi_messaging_open_iface__tx(param->b,
60                                       txcont,
61                                       param->frame,
62                                       param->type,
63                                       param->iface,
64                                       length);
65     if (err_is_fail(err)) {
66         if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
67             txcont = MKCONT(xpm_msg_open_tx, a);
68             err = param->b->register_send(param->b,
69                                              get_default_waitset(),
70                                              txcont);
71             if (err_is_fail(err)) {
72                 USER_PANIC_ERR(err, "failed to register send\n");
73             }
74         }
75     }
76 }
77
78 /*
79  * --------------------------------------------------------------------------
80  * Handling of SPAWN commands
81  */
82 struct xpm_msg_param_spawn
83 {
84     struct xeon_phi_messaging_binding *b;
85     coreid_t core;
86     char name[55];
87 };
88
89 static void xpm_msg_spawn_tx(void *a)
90 {
91     errval_t err;
92
93     struct xpm_msg_param_spawn *param = a;
94
95     struct event_closure txcont = MKCONT(free, a);
96
97     size_t length = strlen(param->name)+1;
98
99     err = xeon_phi_messaging_spawn__tx(param->b,
100                                       txcont,
101                                       param->core,
102                                       param->name,
103                                       length);
104     if (err_is_fail(err)) {
105         if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
106             txcont = MKCONT(xpm_msg_spawn_tx, a);
107             err = param->b->register_send(param->b,
108                                              get_default_waitset(),
109                                              txcont);
110             if (err_is_fail(err)) {
111                 USER_PANIC_ERR(err, "failed to register send\n");
112             }
113         }
114     }
115 }
116
117
118 struct xeon_phi_messaging_rx_vtbl xpm_rx_vtbl = {
119     .open = NULL
120 };
121
122 /*
123  * --------------------------------------------------------------------------
124  * Xeon Phi Manager Binding
125  */
126
127 /**
128  * \brief
129  *
130  * \param
131  * \param
132  * \param
133  */
134 static void xpm_bind_cb(void *st,
135                         errval_t err,
136                         struct xeon_phi_messaging_binding *b)
137 {
138
139     if (err_is_fail(err)) {
140         conn_state = XPM_STATE_BIND_FAIL;
141         return;
142     }
143
144     uint8_t xeon_phi_id = (uint8_t)(uintptr_t)st;
145
146     assert(xpm_binding[xeon_phi_id] == 0);
147
148     b->rx_vtbl = xpm_rx_vtbl;
149     b->st = (void *)(uintptr_t)xeon_phi_id;
150
151     xpm_binding[xeon_phi_id] = b;
152
153     DEBUG_XPMC("Binding ok.\n");
154
155     conn_state = XPM_STATE_BIND_OK;
156 }
157
158 /**
159  * \brief
160  */
161 static errval_t xpm_connect(uint8_t xeon_phi_id)
162 {
163     errval_t err;
164
165     if (xpm_binding[xeon_phi_id] != NULL) {
166         return SYS_ERR_OK;
167     }
168
169     char buf[50];
170 #if !defined(__k1om__)
171     snprintf(buf, 50, "%s.%u", XEON_PHI_MESSAGING_NAME, xeon_phi_id);
172 #else
173     snprintf(buf, 50, "%s", XEON_PHI_MESSAGING_NAME);
174 #endif
175
176     DEBUG_XPMC("Nameservice lookup: %s\n", buf);
177     err = nameservice_blocking_lookup(buf, &xpm_iref[xeon_phi_id]);
178     if (err_is_fail(err)) {
179         return err;
180     }
181
182     conn_state = XPM_STATE_BINDING;
183
184     DEBUG_XPMC("binding to iref [%u]... \n", xpm_iref[xeon_phi_id]);
185     err = xeon_phi_messaging_bind(xpm_iref[xeon_phi_id], xpm_bind_cb,
186                                   (void *)(uintptr_t)xeon_phi_id,
187                                   get_default_waitset(),
188                                   IDC_BIND_FLAGS_DEFAULT);
189     if (err_is_fail(err)) {
190         return err;
191     }
192
193     while (conn_state == XPM_STATE_BINDING) {
194         messages_wait_and_handle_next();
195     }
196
197     if (conn_state == XPM_STATE_BIND_FAIL) {
198         return FLOUNDER_ERR_BIND;
199     }
200
201     return SYS_ERR_OK;
202 }
203
204 /*
205  * --------------------------------------------------------------------------
206  * Public Interface
207  */
208
209 /**
210  * \brief sends a OPEN command message over the Xeon Phi channel
211  *
212  * \param iface the name of the iface to talk to
213  * \param frame capability representing the allocated frame
214  * \param type  type of the channel
215  *
216  * \return SYS_ERR_OK on success
217  */
218 errval_t xeon_phi_messaging_open(uint8_t xeon_phi_id,
219                                  char *iface,
220                                  struct capref frame,
221                                  uint8_t type)
222 {
223     errval_t err;
224     if (xpm_binding[xeon_phi_id] == NULL) {
225         err = xpm_connect(xeon_phi_id);
226         if (err_is_fail(err)) {
227             return err;
228         }
229     }
230
231     struct xpm_msg_param_open *param = malloc(sizeof(struct xpm_msg_param_open));
232     if (param == NULL) {
233         return LIB_ERR_MALLOC_FAIL;
234     }
235
236     param->frame = frame;
237     param->type = type;
238     param->b = xpm_binding[xeon_phi_id];
239
240     snprintf(param->iface, sizeof(param->iface), "%s", iface);
241
242     xpm_msg_open_tx(param);
243
244     return SYS_ERR_OK;
245 }
246
247 /**
248  * \brief sends a SPAWN command message over the Xeon Phi channel
249  *        to spawn a new domain on the other side
250  *
251  * \param core  core ID of the core to spawn the program on
252  * \param name  path to the program to spawn
253  *
254  * \returns SYS_ERR_OK on success
255  */
256 errval_t xeon_phi_messaging_spawn(uint8_t xeon_phi_id,
257                                   coreid_t core,
258                                   char *name)
259 {
260     errval_t err;
261     if (xpm_binding[xeon_phi_id] == NULL) {
262         err = xpm_connect(xeon_phi_id);
263         if (err_is_fail(err)) {
264             return err;
265         }
266     }
267
268     struct xpm_msg_param_spawn *param = malloc(sizeof(struct xpm_msg_param_spawn));
269     if (param == NULL) {
270         return LIB_ERR_MALLOC_FAIL;
271     }
272
273     param->b = xpm_binding[xeon_phi_id];
274     param->core = core;
275     snprintf(param->name, sizeof(param->name), "%s", name);
276
277     xpm_msg_spawn_tx(param);
278
279     return SYS_ERR_OK;
280 }
281
282 /**
283  * \brief sends a KILL command over the Xeon Phi channel to terminated
284  *        a previously spawned domain
285  *
286  * \param d the domain ID of the domain to terminate
287  *
288  * \returns SYS_ERR_OK on success
289  */
290 errval_t xeon_phi_messaging_kill(uint8_t xeon_phi_id,
291                                  domainid_t d)
292 {
293     errval_t err;
294     if (xpm_binding[xeon_phi_id] == NULL) {
295         err = xpm_connect(xeon_phi_id);
296         if (err_is_fail(err)) {
297             return err;
298         }
299     }
300
301     return SYS_ERR_OK;
302 }