Xeon Phi DMA
authorReto Achermann <acreto@student.ethz.ch>
Thu, 26 Jun 2014 12:44:43 +0000 (14:44 +0200)
committerStefan Kaestle <stefan.kaestle@inf.ethz.ch>
Wed, 20 Aug 2014 21:35:48 +0000 (23:35 +0200)
Missing service functionality for the DMA service
Bugfixes in the DMA implementation
Addition of the DMA service thest utility in the xeon_phi_test domain

13 files changed:
errors/errno.fugu
lib/xeon_phi/xeon_phi_dma_client.c
usr/drivers/xeon_phi/Hakefile
usr/drivers/xeon_phi/dma/dma.c
usr/drivers/xeon_phi/dma/dma.h
usr/drivers/xeon_phi/dma/dma_channel.c
usr/drivers/xeon_phi/dma/dma_channel.h
usr/drivers/xeon_phi/dma/dma_mem.c
usr/drivers/xeon_phi/dma/dma_mem.h
usr/drivers/xeon_phi/dma/dma_service.c
usr/drivers/xeon_phi/dma/dma_service.h
usr/xeon_phi_test/Hakefile
usr/xeon_phi_test/main_card.c

index 31d6b19..6ffdf03 100755 (executable)
@@ -1046,9 +1046,10 @@ errors xeon_phi XEON_PHI_ERR_ {
     failure DMA_BUSY              "All DMA channels are busy",
     failure DMA_IDLE             "All DMA channels are idle",
     failure DMA_MEM_REGISTERED   "The memory has not been registered",
-    failure DMA_RPC_IN_PROGRESS  "There is currently an RPC going on",
     failure DMA_MEM_ALIGN        "The address / bytes has a wrong alignment",
+    failure DMA_MEM_OVERLAP      "The memory addresses overlap",
+    failure DMA_RPC_IN_PROGRESS  "There is currently an RPC going on",
     failure DMA_NO_DESC          "There are not enough DMA descriptors left",
     failure DMA_REQ_SIZE         "The requested transfer size is too big",
-    failure DMA_OUT_OF_RANGE     "The physical address is out of range",
+    failure DMA_MEM_OUT_OF_RANGE "The physical address is out of range",
 };
index e4e42a1..9c4cb46 100644 (file)
@@ -54,6 +54,9 @@ static struct xdma_req *requests_free;
 /// the number of free requests
 static uint32_t requests_free_count;
 
+/// initialization flag
+static uint8_t xphi_dma_intialized = 0x0;
+
 #define DEBUG_XDMA(x...) debug_printf(" [xdma] " x)
 
 enum xpm_state
@@ -178,7 +181,9 @@ static void xdma_bind_cb(void *st,
     uint8_t xphi_id = (uint8_t) (uintptr_t) st;
     xdma_binding[xphi_id] = b;
 
-    DEBUG_XDMA("Binding to xdma service ok.\n");
+    b->st = (void *)(uintptr_t)xphi_id;
+
+    DEBUG_XDMA("Binding to xdma [%u] service ok.\n", xphi_id);
 
     conn_state = XPM_STATE_BIND_OK;
 }
@@ -190,6 +195,13 @@ static errval_t xdma_connect(uint8_t xphi_id)
 {
     errval_t err;
 
+    if (!xphi_dma_intialized) {
+        err = xeon_phi_dma_client_init();
+        if (err_is_fail(err)) {
+            return err;
+        }
+    }
+
     if (xdma_binding[xphi_id] != NULL) {
         return SYS_ERR_OK;
     }
@@ -199,7 +211,7 @@ static errval_t xdma_connect(uint8_t xphi_id)
 
     iref_t svc_iref;
 
-    DEBUG_XDMA("Nameservice lookup: %s\n", buf);
+    DEBUG_XDMA("Connecting to Xeon Phi DMA service. NS lookup: %s\n", buf);
     err = nameservice_blocking_lookup(buf, &svc_iref);
     if (err_is_fail(err)) {
         return err;
@@ -555,6 +567,9 @@ errval_t xeon_phi_dma_client_start(uint8_t xphi_id,
         return XEON_PHI_ERR_DMA_BUSY;
     }
 
+    req->cont = cont;
+    req->xphi_id = xphi_id;
+
     struct xdma_reg_start_st *msg_st = xdma_reg_start_st + xphi_id;
 
     msg_st->bytes = info->size;
@@ -574,6 +589,8 @@ errval_t xeon_phi_dma_client_start(uint8_t xphi_id,
         *id = msg_st->id;
     }
 
+    req->id = msg_st->id;
+
     return msg_st->err;
 }
 
index a6148e0..f38f1ab 100644 (file)
@@ -25,7 +25,9 @@
                                  "sleep.c",
                                  "dma/dma.c",
                                  "dma/dma_channel.c",
-                                 "dma/dma_descriptor_ring.c" ],
+                                 "dma/dma_descriptor_ring.c",
+                                 "dma/dma_mem.c",
+                                 "dma/dma_service.c"  ],
                       addLibraries = libDeps ["skb", 
                                               "pci", 
                                               "spawndomain", 
@@ -55,7 +57,9 @@
                                  "messaging.c",
                                  "dma/dma.c",
                                  "dma/dma_channel.c",
-                                 "dma/dma_descriptor_ring.c" ],                      
+                                 "dma/dma_descriptor_ring.c",
+                                 "dma/dma_mem.c",
+                                 "dma/dma_service.c"    ],                      
                       -- flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
                       flounderDefs = ["xeon_phi_messaging", "xeon_phi_dma"],
                       flounderBindings = ["xeon_phi_messaging", "xeon_phi_dma"],
index 5533036..2285536 100644 (file)
@@ -72,7 +72,7 @@ errval_t dma_init(struct xeon_phi *phi)
 
     phi->dma = info;
 
-    return SYS_ERR_OK;
+    return dma_service_init(phi);
 }
 
 /**
@@ -101,15 +101,53 @@ errval_t dma_poll_channels(struct xeon_phi *phi)
     return ret_err;
 }
 
-errval_t dma_do_memcpy(lpaddr_t dst,
-                       lpaddr_t src,
-                       size_t bytes);
-errval_t dma_do_memcpy(lpaddr_t dst,
-                       lpaddr_t src,
-                       size_t bytes)
+/**
+ * \brief issues a new DMA request
+ *
+ * \param phi   Xeon Phi to execute the request on
+ * \param setup information about the request
+ *
+ * \returns SYS_ERR_OK on success
+ *          XEON_PHI_ERR_DMA_* on failure
+ */
+errval_t dma_do_request(struct xeon_phi *phi,
+                        struct dma_req_setup *setup)
 {
+    errval_t err = SYS_ERR_OK;
 
-    return SYS_ERR_OK;
+    struct xdma_channel *chan = &phi->dma->channels[phi->dma->chan_alloc_next++];
+
+    /*
+     * XXX: choosing the channel in a round robin fashion. One may want to select
+     *      the one which is least busy.
+     */
+
+    if(phi->dma->chan_alloc_next >= XEON_PHI_DMA_CHAN_NUM) {
+        phi->dma->chan_alloc_next = 0;
+    }
+
+    switch(setup->type) {
+        case XDMA_REQ_TYPE_NOP:
+            assert(!"NYI");
+            break;
+        case XDMA_REQ_TYPE_MEMCPY:
+            err = xdma_channel_req_memcpy(chan, setup, setup->info.mem.dma_id);
+            break;
+        case XDMA_REQ_TYPE_STATUS:
+            assert(!"NYI");
+            break;
+        case XDMA_REQ_TYPE_GENERAL:
+            assert(!"NYI");
+            break;
+        case XDMA_REQ_TYPE_KEYNON:
+            assert(!"NYI");
+            break;
+        case XDMA_REQ_TYPE_KEY :
+            assert(!"NYI");
+            break;
+    }
+
+    return err;
 }
 
 #define XDMA_TEST_BUFFER_SIZE (1024*1024)
@@ -144,7 +182,7 @@ errval_t dma_impl_test(struct xeon_phi *phi)
     debug_printf(" DMA-TEST | setup transfer\n");
 
     struct xdma_channel *chan = &phi->dma->channels[0];
-    struct xdma_req_setup setup = {
+    struct dma_req_setup setup = {
         .type = XDMA_REQ_TYPE_MEMCPY
     };
     setup.info.mem.dst = dst;
index 1d67c1d..e67e834 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef XEON_PHI_DMA_H
 #define XEON_PHI_DMA_H
 
+#include <if/xeon_phi_dma_defs.h>
+
 /// the base name of the exported dma service
 #define XEON_PHI_DMA_SERVICE_NAME "xeon_phi_dma_svc"
 
 /// the number of dma descriptors we allocate
 #define XEON_PHI_DMA_DESC_NUM  128
 
-
 /// alignment constraint of the descriptor ring (cache line)
 #define XEON_PHI_DMA_DESC_RING_ALIGN 64
 
+/// flag if we use polling or interrupts
 #define XEON_PHI_DMA_USE_POLLING 1
 
+///
+typedef errval_t (*xdma_done_cb_t)(void *a,
+                               errval_t err,
+                               xeon_phi_dma_id_t id);
+
+enum dma_req_type
+{
+    XDMA_REQ_TYPE_NOP = 0,
+    XDMA_REQ_TYPE_MEMCPY,
+    XDMA_REQ_TYPE_STATUS,
+    XDMA_REQ_TYPE_GENERAL,
+    XDMA_REQ_TYPE_KEYNON,
+    XDMA_REQ_TYPE_KEY
+};
+
+struct dma_req_setup
+{
+    enum dma_req_type type;
+    xdma_done_cb_t cb;
+    void *st;
+    union
+    {
+        struct
+        {
+            lpaddr_t src;
+            lpaddr_t dst;
+            size_t bytes;
+            xeon_phi_dma_id_t *dma_id;
+        } mem;
+        struct
+        {
+
+        } status;
+        struct
+        {
+
+        } general;
+        struct
+        {
+
+        } keynon;
+        struct
+        {
+
+        } key;
+    } info;
+};
 
 /**
  * \brief Initializes the DMA structure for the Xeon Phi
 errval_t dma_init(struct xeon_phi *phi);
 
 /**
+ * \brief issues a new DMA request
+ *
+ * \param phi   Xeon Phi to execute the request on
+ * \param setup information about the request
+ *
+ * \returns SYS_ERR_OK on success
+ *          XEON_PHI_ERR_DMA_* on failure
+ */
+errval_t dma_do_request(struct xeon_phi *phi,
+                        struct dma_req_setup *setup);
+
+/**
  * \brief polls the owned channels for competed transfers
  *
  * \param phi the xeon phi to poll
@@ -69,7 +130,12 @@ errval_t dma_init(struct xeon_phi *phi);
  */
 errval_t dma_poll_channels(struct xeon_phi *phi);
 
-errval_t dma_impl_test(struct xeon_phi *phi);
+errval_t dma_service_init(struct xeon_phi *phi);
 
+errval_t  dma_service_send_done(void *a,
+                           errval_t err,
+                           xeon_phi_dma_id_t id);
+
+errval_t dma_impl_test(struct xeon_phi *phi);
 
 #endif /* XEON_PHI_DMA_H */
index c45de7b..72c6170 100644 (file)
@@ -384,7 +384,7 @@ errval_t xdma_channel_free(struct xdma_channel *chan)
  *
  */
 errval_t xdma_channel_req_memcpy(struct xdma_channel *chan,
-                                 struct xdma_req_setup *setup,
+                                 struct dma_req_setup *setup,
                                  xeon_phi_dma_id_t *id)
 {
     assert(setup->type == XDMA_REQ_TYPE_MEMCPY);
@@ -395,8 +395,8 @@ errval_t xdma_channel_req_memcpy(struct xdma_channel *chan,
     uint32_t num_desc_needed =
                     (setup->info.mem.bytes + XEON_PHI_DMA_REQ_SIZE_MAX - 1) / XEON_PHI_DMA_REQ_SIZE_MAX;
 
-    XDMA_DEBUG("memcpy request: %lu bytes, %u descriptors\n",
-               setup->info.mem.bytes,
+    XDMA_DEBUG("memcpy request channel %u: %lu bytes, %u descriptors\n",
+               chan->chanid, setup->info.mem.bytes,
                num_desc_needed);
 
     if (num_desc_needed > chan->size) {
@@ -436,7 +436,8 @@ errval_t xdma_channel_req_memcpy(struct xdma_channel *chan,
             first = 1;
             head = entry;
             rinfo->head = 1;
-            rinfo->binding = setup->binding;
+            rinfo->st = setup->st;
+            rinfo->cb = setup->cb;
             rinfo->ndesc = num_desc_needed;
         }
 
@@ -527,6 +528,8 @@ errval_t xdma_channel_intr_handler(struct xdma_channel *chan)
  */
 errval_t xdma_channel_poll(struct xdma_channel *chan)
 {
+    errval_t err;
+
     if (!chan->do_poll) {
         return SYS_ERR_OK;
     }
@@ -566,9 +569,16 @@ errval_t xdma_channel_poll(struct xdma_channel *chan)
             XDMA_DEBUG("Request 0x%016lx done. Last entry was [%u]\n",
                        (uint64_t )first->id,
                        entry);
-
             chan->last_processed = (entry + 1) % chan->size;
             assert(chan->last_processed <= chan->tail);
+
+            assert(first->head == 1);
+            if (first->cb) {
+                err = first->cb(first->st, SYS_ERR_OK, first->id);
+                if (err_is_fail(err)) {
+                    return err;
+                }
+            }
         }
 
         entry = (entry + 1) % chan->size;
index 60971e3..39a5b4c 100644 (file)
@@ -20,6 +20,7 @@
 #include "dma_descriptor_ring.h"
 
 
+
 #define XEON_PHI_DMA_REQ_SIZE_MAX  (((1U) * 1024 * 1024) >> 1)
 
 enum xdma_chan_owner {
@@ -35,7 +36,8 @@ enum xdma_chan_state {
 
 struct xdma_req_info
 {
-    struct xeon_phi_dma_binding *binding;
+    xdma_done_cb_t cb;
+    void *st;
     errval_t err;           ///< outcome of the request
     xeon_phi_dma_id_t id;   ///< DMA request ID
     uint16_t ndesc;         ///< the number of descriptors used in the request
@@ -64,45 +66,6 @@ struct xdma_channel
     lpaddr_t dstat_wb;
 };
 
-enum xdma_req_type
-{
-    XDMA_REQ_TYPE_NOP = 0,
-    XDMA_REQ_TYPE_MEMCPY,
-    XDMA_REQ_TYPE_STATUS,
-    XDMA_REQ_TYPE_GENERAL,
-    XDMA_REQ_TYPE_KEYNON,
-    XDMA_REQ_TYPE_KEY
-};
-
-
-struct xdma_req_setup
-{
-    enum xdma_req_type type;
-    struct xeon_phi_dma_binding *binding;
-    union
-    {
-        struct
-        {
-            lpaddr_t src;
-            lpaddr_t dst;
-            size_t   bytes;
-        } mem;
-        struct
-        {
-
-        } status;
-        struct
-        {
-
-        } general;
-        struct {
-
-        }keynon;
-        struct {
-
-        }key;
-    } info;
-};
 
 static inline xeon_phi_dma_id_t xdma_chan_generate_id(struct xdma_channel *chan)
 {
@@ -143,35 +106,35 @@ errval_t xdma_channel_free(struct xdma_channel *chan);
  *
  */
 errval_t xdma_channel_req_memcpy(struct xdma_channel *chan,
-                                 struct xdma_req_setup *setup,
+                                 struct dma_req_setup *setup,
                                  xeon_phi_dma_id_t *id);
 
 /**
  *
  */
 errval_t xdma_channel_req_status(struct xdma_channel *chan,
-                                 struct xdma_req_setup *setup,
+                                 struct dma_req_setup *setup,
                                  xeon_phi_dma_id_t *id);
 
 /**
  *
  */
 errval_t xdma_channel_req_general(struct xdma_channel *chan,
-                                  struct xdma_req_setup *setup,
+                                  struct dma_req_setup *setup,
                                   xeon_phi_dma_id_t *id);
 
 /**
  *
  */
 errval_t xdma_channel_req_keynoncecent(struct xdma_channel *chan,
-                                       struct xdma_req_setup *setup,
+                                       struct dma_req_setup *setup,
                                        xeon_phi_dma_id_t *id);
 
 /**
  *
  */
 errval_t xdma_channel_req_key(struct xdma_channel *chan,
-                              struct xdma_req_setup *setup,
+                              struct dma_req_setup *setup,
                               xeon_phi_dma_id_t *id);
 
 /**
index 826bbd2..9fe0185 100644 (file)
  */
 
 #include <barrelfish/barrelfish.h>
-#include "xeon_phi.h"
+#include <xeon_phi/xeon_phi.h>
 
 #include <if/xeon_phi_dma_defs.h>
 
+#include "xeon_phi.h"
+#include "dma_mem.h"
+
 struct xdma_mem
 {
     struct xeon_phi *phi;
     struct xeon_phi_dma_binding *b;
     struct xdma_mem_entry *head;
+    uint32_t num_entries;
 };
 
 struct xdma_mem_entry
@@ -29,10 +33,38 @@ struct xdma_mem_entry
     struct capref cap;
     lpaddr_t paddr;
     size_t size;
+    enum xdma_mem_type type;
     struct xdma_mem_entry *next;
     struct xdma_mem_entry *prev;
 };
 
+static lpaddr_t xdma_mem_verify_base_address(struct xeon_phi *phi,
+                                             lpaddr_t addr,
+                                             size_t size)
+{
+#ifdef __k1om__
+    if ((addr + size) > (1UL << 40)) {
+        return 0;
+    }
+    return addr;
+#else
+    lpaddr_t apt_lo = phi->apt.pbase;
+    lpaddr_t apt_hi = phi->apt.pbase + phi->apt.length;
+    if ((addr >= apt_lo) && ((addr + size) <= apt_hi)) {
+        /* we are within the GDDR range */
+        return addr - apt_lo;
+    } else if ((addr + size)< XEON_PHI_SYSMEM_SIZE) {
+        /*
+         * Xeon Phi does not support more host memory,
+         * assume host memory starts at 0x0
+         */
+        return addr + XEON_PHI_SYSMEM_BASE;
+    } else {
+        return 0;
+    }
+#endif
+}
+
 /**
  * \brief initializes the memory manager for the range checks
  */
@@ -51,42 +83,246 @@ errval_t xdma_mem_init(struct xeon_phi_dma_binding *binding,
     return SYS_ERR_OK;
 }
 
+static struct xdma_mem_entry* xdma_mem_find_entry(struct xdma_mem *xmem,
+                                                  lpaddr_t addr,
+                                                  size_t size)
+{
+    struct xdma_mem_entry *head = xmem->head;
+
+    if (head == NULL) {
+        return NULL;
+    }
+
+    struct xdma_mem_entry *current = head;
+    while (current) {
+        if (current->paddr > addr) {
+            return NULL;
+        }
+        if (current->paddr <= addr && (current->paddr = current->size)
+                        <= (addr + size)) {
+            return current;
+        }
+        current = current->next;
+    }
+
+    return NULL;
+}
+
+static uint8_t xdma_mem_insert_entry(struct xdma_mem *xmem,
+                                     struct xdma_mem_entry *entry)
+{
+    if (xmem->num_entries == 0) {
+        xmem->head = entry;
+        entry->next = NULL;
+        entry->prev = NULL;
+        xmem->num_entries++;
+        return 0x1;
+    }
+
+    struct xdma_mem_entry *current = xmem->head;
+    while (current) {
+        /*
+         * insert the entry before the current one.
+         */
+        if (entry->paddr < current->paddr) {
+            if (entry->paddr + entry->size > current->paddr) {
+                /*
+                 * XXX: we may want to coalesce the two regions here...
+                 *      returning false for now.
+                 */
+                return 0;
+            }
+            /* do the insert */
+            current->prev = entry;
+            entry->next = current;
+            entry->prev = current->prev;
+            xmem->num_entries++;
+
+            if (current == xmem->head) {
+                xmem->head = entry;
+            }
+            return 0x1;
+        }
+
+        /*
+         * insert the new element at the end
+         */
+        if (current->next == NULL) {
+            current->next = entry;
+            entry->prev = current;
+            entry->next = NULL;
+            xmem->num_entries++;
+            return 0x1;
+        }
+        current = current->next;
+    }
+    assert(!"This should not happen");
+    return 0x0;
+}
+
+static struct xdma_mem_entry *xdma_mem_remove_entry(struct xdma_mem *xmem,
+                                                    lpaddr_t addr,
+                                                    size_t size)
+{
+    struct xdma_mem_entry *entry = xdma_mem_find_entry(xmem, addr, size);
+    if (entry == NULL) {
+        return NULL;
+    }
+    xmem->num_entries--;
+
+    if (xmem->num_entries == 0) {
+        xmem->head = NULL;
+        return entry;
+    }
+
+    if (entry->prev) {
+        entry->prev->next = entry->next;
+    } else {
+        xmem->head = entry->next;
+    }
+
+    if (entry->next) {
+        entry->next->prev = entry->prev;
+    }
+
+    entry->next = NULL;
+    entry->prev = NULL;
+    return entry;
+}
+
 /**
  * \brief registers a new block of memory to be used with the DMA engine
  */
-errval_t xdma_mem_register(struct xdma_mem *mem,
+errval_t xdma_mem_register(struct xeon_phi_dma_binding *binding,
                            struct capref cap)
 {
+    errval_t err;
+
+    struct xdma_mem *xmem = binding->st;
+    assert(xmem);
 
+    struct frame_identity frame_id;
+    err = invoke_frame_identify(cap, &frame_id);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    XDMA_DEBUG("Registring DMA memory range [0x%016lx, 0x%016lx]\n",
+               frame_id.base,
+               frame_id.base + (1UL << frame_id.bits));
+
+    struct xdma_mem_entry *entry = calloc(1, sizeof(struct xdma_mem_entry));
+    if (entry == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    /*
+     * the DMA engine supports only 40bit addresses of the Xeon Phi address space.
+     * thus we need to do a case distinction here and translate the addresses
+     * appropriately
+     */
+    lpaddr_t addr = xdma_mem_verify_base_address(xmem->phi,
+                                                 frame_id.base,
+                                                 1UL << frame_id.bits);
+    if (addr == 0) {
+        XDMA_DEBUG("Memory address out of range or on other Xeon Phi\n");
+        free(entry);
+        return XEON_PHI_ERR_DMA_MEM_OUT_OF_RANGE;
+    }
+    if (addr > XEON_PHI_SYSMEM_BASE) {
+        entry->type = XDMA_MEM_TYPE_HOST;
+    } else {
+        entry->type = XDMA_MEM_TYPE_CARD;
+    }
+    entry->cap = cap;
+    entry->paddr = addr;
+    entry->size = 1UL << frame_id.bits;
+
+    if (!xdma_mem_insert_entry(xmem, entry)) {
+        free(entry);
+        return XEON_PHI_ERR_DMA_MEM_OVERLAP;
+    }
+
+    return SYS_ERR_OK;
 }
 
 /**
  * \brief removes a block of memory from the usable regions
  */
-errval_t xdma_mem_deregister(struct xdma_mem *mem,
+errval_t xdma_mem_deregister(struct xeon_phi_dma_binding *binding,
                              struct capref cap)
 {
+    errval_t err;
+
+    struct xdma_mem *xmem = binding->st;
+    assert(xmem);
+
+    struct frame_identity frame_id;
+    err = invoke_frame_identify(cap, &frame_id);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    XDMA_DEBUG("De-registring DMA memory range [0x%016lx, 0x%016lx]\n",
+               frame_id.base,
+               frame_id.base + (1UL << frame_id.bits));
+
+    assert(!"NYI");
+
+    /*
+     * the DMA engine supports only 40bit addresses of the Xeon Phi address space.
+     * thus we need to do a case distinction here and translate the addresses
+     * appropriately
+     */
+    lpaddr_t addr = xdma_mem_verify_base_address(xmem->phi,
+                                                 frame_id.base,
+                                                 1UL << frame_id.bits);
 
+    struct xdma_mem_entry *entry = xdma_mem_remove_entry(xmem,
+                                                         addr,
+                                                         (1UL << frame_id.bits));
+
+    if (entry == NULL) {
+        return XEON_PHI_ERR_DMA_MEM_REGISTERED;
+    }
+
+    return SYS_ERR_OK;
 }
 
 /**
- * \brief verifies that a certain memory range is within the previously
- *        registered memory range
+ * \brief verifies the memory range and translates into the DMA usable format
+ *
+ * \param binding the Xeon Phi DMA binding the request originated
+ * \param size    size of the requested range
+ * \param addr    base address of the range
+ *
+ * \returns DMA address if the address has previously been registered
+ *          0 otherwise
  */
-errval_t xdma_mem_verify(struct xdma_mem *mem,
+lpaddr_t xdma_mem_verify(struct xeon_phi_dma_binding *binding,
                          lpaddr_t addr,
                          size_t size)
 {
+    struct xdma_mem *xmem = binding->st;
+    assert(xmem);
 
-}
+    XDMA_DEBUG("Verify DMA memory range [0x%016lx, 0x%016lx]\n", addr, addr + size);
 
-/**
- * \brief verifies the memory range and translates into the DMA usable format
- */
-lpaddr_t xdma_mem_translate(struct xdma_mem *mem,
-                            lpaddr_t addr,
-                            size_t size)
-{
+    lpaddr_t dma_addr = xdma_mem_verify_base_address(xmem->phi, addr, size);
+    if (dma_addr == 0) {
+        return 0;
+    }
 
+    struct xdma_mem_entry *entry = xdma_mem_find_entry(xmem, dma_addr, size);
+    if (entry) {
+        return dma_addr;
+    } else {
+        return 0;
+    }
 }
 
+
+struct xeon_phi *xdma_mem_get_phi(struct xeon_phi_dma_binding *binding)
+{
+    return ((struct xdma_mem *)binding->st)->phi;
+}
index 33f750b..9a7601c 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef XEON_PHI_DMA_MEM_H
 #define XEON_PHI_DMA_MEM_H
 
+#define XEON_PHI_DMA_MEM_HOST_MAX (512UL * 1024 * 1024 * 1024)
+
 struct xdma_mem;
 
 enum xdma_mem_type
@@ -23,7 +25,6 @@ enum xdma_mem_type
     XDMA_MEM_TYPE_CARD
 };
 
-
 /**
  * \brief initializes the memory manager for the range checks
  */
@@ -33,24 +34,29 @@ errval_t xdma_mem_init(struct xeon_phi_dma_binding *binding,
 /**
  * \brief registers a new block of memory to be used with the DMA engine
  */
-errval_t xdma_mem_register(struct xdma_mem *mem,
+errval_t xdma_mem_register(struct xeon_phi_dma_binding *binding,
                            struct capref cap);
 
-
 /**
  * \brief removes a block of memory from the usable regions
  */
-errval_t xdma_mem_deregister(struct xdma_mem *mem,
+errval_t xdma_mem_deregister(struct xeon_phi_dma_binding *binding,
                              struct capref cap);
 
-
 /**
- * \brief verifies that a certain memory range is within the previously
- *        registered memory range
+ * \brief verifies the memory range and translates into the DMA usable format
+ *
+ * \param binding the Xeon Phi DMA binding the request originated
+ * \param size    size of the requested range
+ * \param addr    base address of the range
+ *
+ * \returns DMA address if the address has previously been registered
+ *          0 otherwise
  */
-errval_t xdma_mem_verify(struct xdma_mem *mem,
+lpaddr_t xdma_mem_verify(struct xeon_phi_dma_binding *binding,
                          lpaddr_t addr,
-                         size_t   size);
+                         size_t size);
 
+struct xeon_phi *xdma_mem_get_phi(struct xeon_phi_dma_binding *binding);
 
 #endif /* XEON_PHI_DMA_DESC_RING_H */
index 8e5b4d9..321afc2 100644 (file)
@@ -15,6 +15,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <barrelfish/barrelfish.h>
+#include <barrelfish/nameservice_client.h>
 
 #include <if/xeon_phi_dma_defs.h>
 
@@ -78,7 +79,18 @@ static void dma_register_response_tx(void *a)
 static void dma_register_call_rx(struct xeon_phi_dma_binding *_binding,
                                  struct capref memory)
 {
+    errval_t err;
+
+    XDMA_DEBUG("dma_register_call_rx\n");
 
+    err = xdma_mem_register(_binding, memory);
+
+    struct dma_reg_resp_st *st = malloc(sizeof(struct dma_reg_resp_st));
+    assert(st);
+    st->b = _binding;
+    st->err = err;
+
+    dma_register_response_tx(st);
 }
 
 /*
@@ -115,7 +127,18 @@ static void dma_deregister_response_tx(void *a)
 static void dma_deregister_call_rx(struct xeon_phi_dma_binding *_binding,
                                    struct capref memory)
 {
+    errval_t err;
+
+    XDMA_DEBUG("dma_register_call_rx\n");
 
+    err = xdma_mem_deregister(_binding, memory);
+
+    struct dma_dereg_resp_st *st = malloc(sizeof(struct dma_dereg_resp_st));
+    assert(st);
+    st->b = _binding;
+    st->err = err;
+
+    dma_deregister_response_tx(st);
 }
 
 /*
@@ -154,7 +177,38 @@ static void dma_exec_call_rx(struct xeon_phi_dma_binding *_binding,
                              uint64_t dst,
                              uint64_t length)
 {
+    XDMA_DEBUG("dma_exec_call_rx\n");
+
+    struct dma_exec_resp_st *st = malloc(sizeof(struct dma_exec_resp_st));
+    assert(st);
+    st->b = _binding;
 
+    lpaddr_t dma_src = xdma_mem_verify(_binding, src, length);
+    lpaddr_t dma_dst = xdma_mem_verify(_binding, dst, length);
+    if (!dma_src || !dma_dst) {
+        st->err = XEON_PHI_ERR_DMA_MEM_REGISTERED;
+        st->id = 0;
+    }
+
+    struct dma_req_setup setup = {
+        .type = XDMA_REQ_TYPE_MEMCPY,
+        .st = _binding,
+        .cb = dma_service_send_done,
+        .info = {
+            .mem = {
+                .src = src,
+                .dst = dst,
+                .bytes = length,
+                .dma_id = &st->id
+            }
+        }
+    };
+
+    struct xeon_phi *phi = xdma_mem_get_phi(_binding);
+
+    st->err = dma_do_request(phi, &setup);
+
+    dma_exec_response_tx(st);
 }
 
 /*
@@ -192,6 +246,14 @@ static void dma_stop_call_rx(struct xeon_phi_dma_binding *_binding,
                              xeon_phi_dma_id_t id)
 {
 
+    XDMA_DEBUG("dma_stop_call_rx: NOT YET IMPLEMENTED!!!!\n");
+
+    struct dma_stop_resp_st *st = malloc(sizeof(struct dma_stop_resp_st));
+    assert(st);
+    st->b = _binding;
+    st->err = SYS_ERR_OK;
+
+    dma_stop_response_tx(st);
 }
 
 struct xeon_phi_dma_rx_vtbl dma_rx_vtbl = {
@@ -210,12 +272,16 @@ struct xeon_phi_dma_rx_vtbl dma_rx_vtbl = {
 static errval_t svc_connect_cb(void *st,
                                struct xeon_phi_dma_binding *b)
 {
-    XPHI_MSG_DBG("New connection request\n");
+    errval_t err;
+
+    XDMA_DEBUG("New connection request\n");
     b->rx_vtbl = dma_rx_vtbl;
 
-    /*
-     * TODO: set the state
-     */
+    struct xeon_phi *phi = st;
+    err = xdma_mem_init(b, phi);
+    if (err_is_fail(err)) {
+        return err;
+    }
 
     return SYS_ERR_OK;
 }
@@ -237,23 +303,23 @@ static void svc_export_cb(void *st,
     svc_state = XPM_SVC_STATE_EXPORT_OK;
 }
 
-errval_t dma_service_init(uint8_t xeon_phi_id)
+errval_t dma_service_init(struct xeon_phi *phi)
 {
     errval_t err;
 
 #ifdef __k1om__
-    assert(xeon_phi_id == 0);
+    assert(phi->id == 0);
 #endif
 
     XDMA_DEBUG("Initializing DMA service\n");
 
     struct waitset *ws = get_default_waitset();
 
-    err = xeon_phi_messaging_export(NULL,
-                                    svc_export_cb,
-                                    svc_connect_cb,
-                                    ws,
-                                    IDC_EXPORT_FLAGS_DEFAULT);
+    err = xeon_phi_dma_export(phi,
+                              svc_export_cb,
+                              svc_connect_cb,
+                              ws,
+                              IDC_EXPORT_FLAGS_DEFAULT);
     if (err_is_fail(err)) {
         return err;
     }
@@ -270,7 +336,7 @@ errval_t dma_service_init(uint8_t xeon_phi_id)
     svc_state = XPM_SVC_STATE_NS_REGISTERING;
 
     char buf[50];
-    snprintf(buf, 50, "%s.%u", XEON_PHI_DMA_SERVICE_NAME, xeon_phi_id);
+    snprintf(buf, 50, "%s.%u", XEON_PHI_DMA_SERVICE_NAME, phi->id);
 
     XDMA_DEBUG("Registering iref [%u] with name [%s]\n", dma_iref, buf);
     err = nameservice_register(buf, dma_iref);
@@ -305,7 +371,7 @@ static void dma_done_tx(void *a)
 
     struct event_closure txcont = MKCONT(free, a);
 
-    err = xeon_phi_dma_stop_response__tx(st->b, txcont, st->id, st->err);
+    err = xeon_phi_dma_done__tx(st->b, txcont, st->id, st->err);
     if (err_is_fail(err)) {
         if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
             txcont = MKCONT(dma_done_tx, a);
@@ -316,22 +382,25 @@ static void dma_done_tx(void *a)
     }
 }
 
-errval_t dma_service_send_done(struct xeon_phi_dma_binding *b,
-                               xeon_phi_dma_id_t id,
-                               errval_t err)
+errval_t dma_service_send_done(void *a,
+                           errval_t err,
+                           xeon_phi_dma_id_t id)
 {
-    XDMA_DEBUG("sending done notification: %lu\n", id);
+    XDMA_DEBUG("sending done notification: %lx\n", (uint64_t ) id);
+
+    struct xeon_phi_dma_binding *b = a;
+    assert(b);
 
-    struct dma_done_st *st = malloc(sizeof(struct dma_done_st));
-    if (st == NULL) {
+    struct dma_done_st *msgst = malloc(sizeof(struct dma_done_st));
+    if (msgst == NULL) {
         return LIB_ERR_MALLOC_FAIL;
     }
 
-    st->b = b;
-    st->id = id;
-    st->err = err;
+    msgst->b = b;
+    msgst->id = id;
+    msgst->err = err;
 
-    dma_done_tx(st);
+    dma_done_tx(msgst);
 
     return SYS_ERR_OK;
 }
index c336136..8635cb0 100644 (file)
@@ -15,7 +15,7 @@
 #define XEON_PHI_DMA_SERVICE_H
 
 
-errval_t dma_service_init(void);
+errval_t dma_service_init(struct xeon_phi *phi);
 
 
 
index 17bcc4c..87bec79 100644 (file)
@@ -20,7 +20,7 @@
   build application { target = "xeon_phi_test",
                         cFiles = [ "main_card.c", "benchmark.c" ],
                         flounderDefs = ["xeon_phi_messaging"],
-                        addLibraries = libDeps [ "xeon_phi_messaging", "xeon_phi_messaging_client", "bench" ],
+                        addLibraries = libDeps [ "xeon_phi_messaging", "xeon_phi_messaging_client", "bench", "xeon_phi_dma_client" ],
                         architectures = ["k1om"]
                     }
 
index 663d174..222452d 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <xeon_phi/xeon_phi_messaging.h>
 #include <xeon_phi/xeon_phi_messaging_client.h>
+#include <xeon_phi/xeon_phi_dma_client.h>
 
 uint32_t send_reply = 0x0;
 
@@ -24,12 +25,62 @@ uint8_t connected = 0;
 
 static void *card_buf;
 
+static struct capref card_frame;
+
+static lpaddr_t card_base;
+
+static size_t card_frame_sz;
+
 static void *host_buf;
 
+static struct capref host_frame;
+
+static lpaddr_t host_base;
+
+static size_t host_frame_sz;
+
 struct bench_bufs bufs;
 
 static struct ump_chan uc;
 
+static void do_dma_test(void)
+{
+    debug_printf("starting DMA test...\n");
+
+    errval_t err;
+
+    err = xeon_phi_dma_client_init();
+    assert(err_is_ok(err));
+
+    err = xeon_phi_dma_client_register(0, card_frame);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "could not register memory");
+    }
+
+    err = xeon_phi_dma_client_register(0, host_frame);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "could not register memory");
+    }
+
+    struct xeon_phi_dma_info info = {
+        .src  = card_base,
+        .dest = card_base + card_frame_sz / 2,
+        .size = card_frame_sz / 2
+    };
+
+    struct xeon_phi_dma_cont cont;
+
+    err = xeon_phi_dma_client_start(0, &info, cont, NULL);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "could not exec the transfer");
+    }
+
+    err = xeon_phi_dma_client_exec(0, &info);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "could not exec the transfer");
+    }
+}
+
 static errval_t msg_open_cb(struct capref msgframe,
                             uint8_t chantype)
 {
@@ -45,6 +96,12 @@ static errval_t msg_open_cb(struct capref msgframe,
                  id.base,
                  1UL << id.bits);
 
+    host_frame = msgframe;
+
+    host_base = id.base;
+
+    host_frame_sz = (1UL << id.bits);
+
     err = vspace_map_one_frame(&host_buf, 1UL << id.bits, msgframe, NULL, NULL);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "Could not map the frame");
@@ -136,13 +193,18 @@ int main(int argc,
 
     debug_printf("Allocating a frame of size: %lx\n", frame_size);
 
-    struct capref frame;
     size_t alloced_size = 0;
-    err = frame_alloc(&frame, frame_size, &alloced_size);
+    err = frame_alloc(&card_frame, frame_size, &alloced_size);
     assert(err_is_ok(err));
     assert(alloced_size >= frame_size);
 
-    err = vspace_map_one_frame(&card_buf, frame_size, frame, NULL, NULL);
+    struct frame_identity id;
+    err = invoke_frame_identify(card_frame, &id);
+    assert(err_is_ok(err));
+    card_base = id.base;
+    card_frame_sz = alloced_size;
+
+    err = vspace_map_one_frame(&card_buf, frame_size, card_frame, NULL, NULL);
     assert(err_is_ok(err));
 
     err = xeon_phi_messaging_service_start(XEON_PHI_MESSAGING_NO_HANDLER);
@@ -157,8 +219,10 @@ int main(int argc,
     char iface[30];
     snprintf(iface, 30, "xeon_phi_test.%u", XPHI_BENCH_CORE_HOST);
 
+    do_dma_test();
+
     debug_printf("sending open message to %s\n", iface);
-    err = xeon_phi_messaging_open(0, iface, frame, XEON_PHI_CHAN_TYPE_UMP);
+    err = xeon_phi_messaging_open(0, iface, card_frame, XEON_PHI_CHAN_TYPE_UMP);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "could not open channel");
     }