1/*
2 * Copyright (c) 2007-12 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13
14#include <barrelfish/barrelfish.h>
15#include <barrelfish/dispatch.h>
16#include <barrelfish/ump_chan.h>
17
18#include <dma/xeon_phi/xeon_phi_dma.h>
19#include <dma/dma_request.h>
20#include <dma/client/dma_client_device.h>
21#include <dma/dma_manager_client.h>
22
23#include <xeon_phi/xeon_phi.h>
24#include <xeon_phi/xeon_phi_client.h>
25#include <xeon_phi/xeon_phi_domain.h>
26
27uint32_t send_reply = 0x0;
28
29#include "benchmark.h"
30
31uint8_t connected = 0;
32
33static void *local_buf;
34static struct capref local_frame;
35static lpaddr_t local_base;
36static size_t local_frame_sz;
37
38static void *remote_buf;
39static struct capref remote_frame;
40static lpaddr_t remote_base;
41static size_t remote_frame_sz;
42
43static struct ump_chan uc;
44static struct ump_chan uc_rev;
45
46static void *inbuf;
47static void *outbuf;
48
49static void *inbuf_rev;
50static void *outbuf_rev;
51
52static struct bench_bufs bufs;
53static struct bench_bufs bufs_rev;
54
55static xphi_dom_id_t domid;
56
57static void init_buffer_c0(void)
58{
59#ifdef XPHI_BENCH_CHAN_HOST
60    inbuf = local_buf + XPHI_BENCH_MSG_FRAME_SIZE;
61    outbuf = local_buf;
62    inbuf_rev = remote_buf + XPHI_BENCH_MSG_FRAME_SIZE;;
63    outbuf_rev = remote_buf;
64#endif
65
66#ifdef XPHI_BENCH_CHAN_CARD
67    inbuf = remote_buf;
68    outbuf = remote_buf + XPHI_BENCH_MSG_FRAME_SIZE;
69    inbuf_rev = local_buf;
70    outbuf_rev = local_buf + XPHI_BENCH_MSG_FRAME_SIZE;
71#endif
72
73#ifdef XPHI_BENCH_CHAN_DEFAULT
74    inbuf = remote_buf;
75    outbuf = local_buf;
76    inbuf_rev = outbuf + XPHI_BENCH_MSG_FRAME_SIZE;
77    outbuf_rev = inbuf + XPHI_BENCH_MSG_FRAME_SIZE;
78#endif
79
80#ifdef XPHI_BENCH_BUFFER_CARD
81    bufs.buf = remote_buf + 2 * XPHI_BENCH_MSG_FRAME_SIZE;
82    bufs_rev.buf = local_buf + 2 * XPHI_BENCH_MSG_FRAME_SIZE;
83#else
84    bufs.buf = local_buf + 2 * XPHI_BENCH_MSG_FRAME_SIZE;
85    bufs_rev.buf = remote_buf + 2 * XPHI_BENCH_MSG_FRAME_SIZE;
86#endif
87}
88
89static errval_t alloc_local(void)
90{
91    errval_t err;
92
93    size_t frame_size = 0;
94    if (disp_xeon_phi_id() == 0) {
95        frame_size = XPHI_BENCH_FRAME_SIZE_HOST;
96    } else {
97        frame_size = XPHI_BENCH_FRAME_SIZE_CARD;
98    }
99
100    if (!frame_size) {
101        frame_size = 4096;
102    }
103
104    debug_printf("Allocating a frame of size: %lx\n", frame_size);
105
106    size_t alloced_size = 0;
107    err = frame_alloc(&local_frame, frame_size, &alloced_size);
108    assert(err_is_ok(err));
109    assert(alloced_size >= frame_size);
110
111    struct frame_identity id;
112    err = frame_identify(local_frame, &id);
113    assert(err_is_ok(err));
114    local_base = id.base;
115    local_frame_sz = alloced_size;
116
117    err = vspace_map_one_frame(&local_buf, alloced_size, local_frame, NULL, NULL);
118
119    return err;
120}
121
122static errval_t msg_open_cb(xphi_dom_id_t domain,
123                            uint64_t usrdata,
124                            struct capref msgframe,
125                            uint8_t type)
126{
127    errval_t err;
128
129    domid = domain;
130
131    struct frame_identity id;
132    err = frame_identify(msgframe, &id);
133    if (err_is_fail(err)) {
134        USER_PANIC_ERR(err, "could not identify the frame");
135    }
136
137    debug_printf("msg_open_cb | Frame base: %016lx, size=%lx, ud:%lx\n", id.base,
138                 id.bytes, usrdata);
139
140    remote_frame = msgframe;
141
142    remote_base = id.base;
143
144    remote_frame_sz = id.bytes;
145
146    err = vspace_map_one_frame(&remote_buf, remote_frame_sz, msgframe,
147    NULL,
148                               NULL);
149    if (err_is_fail(err)) {
150        USER_PANIC_ERR(err, "Could not map the frame");
151    }
152
153    init_buffer_c0();
154
155    connected = 0x1;
156
157    return SYS_ERR_OK;
158}
159
160static struct xeon_phi_callbacks callbacks = {
161    .open = msg_open_cb
162};
163
164int main(int argc,
165         char **argv)
166{
167    errval_t err;
168
169    debug_printf("Xeon Phi Test started on the card %u.\n", disp_xeon_phi_id());
170
171    debug_printf("Msg Buf Size = %lx, Buf Frame Size = %lx\n",
172    XPHI_BENCH_MSG_FRAME_SIZE,
173                 XPHI_BENCH_BUF_FRAME_SIZE);
174
175    xeon_phi_client_set_callbacks(&callbacks);
176
177    err = xeon_phi_client_init(disp_xeon_phi_id());
178    if (err_is_fail(err)) {
179        USER_PANIC_ERR(err, "could not init the service\n");
180    }
181
182    err = alloc_local();
183    assert(err_is_ok(err));
184
185    if (disp_xeon_phi_id() == 0) {
186        char *iface = xeon_phi_domain_build_iface("xeon_phi_inter", 1, 2);
187        err = xeon_phi_domain_blocking_lookup(iface, &domid);
188        if (err_is_fail(err)) {
189            USER_PANIC_ERR(err, "looking up domain id\n");
190        }
191        debug_printf("sending open message to %s on node 1\n", iface);
192        err = xeon_phi_client_chan_open(1, domid, 0xcafebabe, local_frame, 2);
193        if (err_is_fail(err)) {
194            USER_PANIC_ERR(err, "could not open channel");
195        }
196    }
197
198    while (!connected) {
199        messages_wait_and_handle_next();
200    }
201
202    debug_printf("Initializing UMP channel...\n");
203
204    if (disp_xeon_phi_id() != 0) {
205        err = xeon_phi_client_chan_open(0, domid, 0xdeadbeef, local_frame, 2);
206        if (err_is_fail(err)) {
207            USER_PANIC_ERR(err, "could not open channel");
208        }
209    } else {
210        debug_printf("Other node reply: %s\n", (char *) local_buf);
211    }
212
213    err = ump_chan_init(&uc, inbuf,
214    XPHI_BENCH_MSG_FRAME_SIZE,
215                        outbuf,
216                        XPHI_BENCH_MSG_FRAME_SIZE);
217    err = ump_chan_init(&uc_rev, inbuf_rev,
218    XPHI_BENCH_MSG_FRAME_SIZE,
219                        outbuf_rev,
220                        XPHI_BENCH_MSG_FRAME_SIZE);
221
222    if (err_is_fail(err)) {
223        USER_PANIC_ERR(err, "Could not initialize UMP");
224    }
225
226    if (disp_xeon_phi_id() == 1) {
227#ifndef XPHI_BENCH_THROUGHPUT
228        debug_printf("---------------- normal run -----------------\n");
229        xphi_bench_start_initator_rtt(&bufs, &uc);
230        debug_printf("---------------- reversed run -----------------\n");
231        xphi_bench_start_initator_rtt(&bufs_rev, &uc_rev);
232#else
233#ifdef XPHI_BENCH_SEND_SYNC
234        debug_printf("---------------- normal run -----------------\n");
235        xphi_bench_start_initator_sync(&bufs, &uc);
236        debug_printf("---------------- reversed run -----------------\n");
237        xphi_bench_start_initator_sync(&bufs_rev, &uc_rev);
238#else
239        debug_printf("---------------- normal run -----------------\n");
240        xphi_bench_start_initator_async(&bufs, &uc);
241        debug_printf("---------------- reversed run -----------------\n");
242        xphi_bench_start_initator_async(&bufs_rev, &uc_rev);
243#endif
244#endif
245    } else {
246#ifndef XPHI_BENCH_THROUGHPUT
247        debug_printf("---------------- normal run -----------------\n");
248        xphi_bench_start_echo(&bufs, &uc);
249        debug_printf("---------------- reversed run -----------------\n");
250        xphi_bench_start_echo(&bufs_rev, &uc_rev);
251#else
252        debug_printf("---------------- normal run -----------------\n");
253        xphi_bench_start_processor(&bufs, &uc);
254        debug_printf("---------------- reversed run -----------------\n");
255        xphi_bench_start_processor(&bufs_rev, &uc_rev);
256#endif
257    }
258
259    err = dma_manager_wait_for_driver(DMA_DEV_TYPE_XEON_PHI, disp_xeon_phi_id());
260    if (err_is_fail(err)) {
261        USER_PANIC_ERR(err, "waiting for drive");
262    }
263
264    struct dma_client_info info = {
265        .type = DMA_CLIENT_INFO_TYPE_NAME,
266        .device_type = DMA_DEV_TYPE_XEON_PHI,
267        .args = {
268            .name = XEON_PHI_DMA_SERVICE_NAME
269        }
270    };
271
272    struct dma_client_device *xdev;
273    err = dma_client_device_init(&info, &xdev);
274    if (err_is_fail(err)) {
275        USER_PANIC_ERR(err, "could not initialize client device");
276    }
277
278    struct dma_device *dev = (struct dma_device *) xdev;
279
280    err = dma_register_memory((struct dma_device *) dev, local_frame);
281    if (err_is_fail(err)) {
282        USER_PANIC_ERR(err, "could not register memory");
283    }
284
285    err = dma_register_memory((struct dma_device *) dev, remote_frame);
286    if (err_is_fail(err)) {
287        USER_PANIC_ERR(err, "could not register memory");
288    }
289
290    if (disp_xeon_phi_id() == 1) {
291        debug_printf("+++++++ DMA / MEMCOPY Benchmark ++++++++\n");
292
293        debug_printf("\n");
294        debug_printf("========================================\n");
295        debug_printf("\n");
296        debug_printf("DMA-BENCH: LOCAL -> REMOTE \n");
297        debug_printf("\n");
298        debug_printf("========================================\n");
299        debug_printf("\n");
300        xphi_bench_memcpy(dev, remote_buf + 2 * XPHI_BENCH_MSG_FRAME_SIZE,
301                          local_buf + 2 * XPHI_BENCH_MSG_FRAME_SIZE,
302                          XPHI_BENCH_BUF_FRAME_SIZE / 2,
303                          remote_base + 2 * XPHI_BENCH_MSG_FRAME_SIZE,
304                          local_base + 2 * XPHI_BENCH_MSG_FRAME_SIZE);
305
306        debug_printf("\n");
307        debug_printf("========================================\n");
308        debug_printf("\n");
309        debug_printf("DMA-BENCH: REMOTE -> LOCAL \n");
310        debug_printf("\n");
311        debug_printf("========================================\n");
312        debug_printf("\n");
313        xphi_bench_memcpy(dev, local_buf + 2 * XPHI_BENCH_MSG_FRAME_SIZE,
314                          remote_buf + 2 * XPHI_BENCH_MSG_FRAME_SIZE,
315                          XPHI_BENCH_BUF_FRAME_SIZE / 2,
316                          local_base + 2 * XPHI_BENCH_MSG_FRAME_SIZE,
317                          remote_base + 2 * XPHI_BENCH_MSG_FRAME_SIZE);
318    }
319
320    debug_printf("benchmark done.");
321
322    while (1) {
323        messages_wait_and_handle_next();
324    }
325}
326