All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] grant table map (gntdev) for minios
@ 2008-07-23 17:31 Diego Ongaro
  2008-07-23 18:11 ` Diego Ongaro
  2008-07-24 14:42 ` Diego Ongaro
  0 siblings, 2 replies; 3+ messages in thread
From: Diego Ongaro @ 2008-07-23 17:31 UTC (permalink / raw)
  To: xen-devel

I've implemented a grant map for mini-os to support the xc_gnttab_*()
functions, the equivalent of gntdev in linux. This is useful for my work
in putting xenstored in a stub domain. I think the libxc component is
pretty trivial, but it'd be nice to get a few more sets of eyes on the
new gntmap.c.
Thanks,
Diego

Signed-off-by: Diego Ongaro <diego.ongaro@citrix.com>
---
diff -r 7299346111fb extras/mini-os/gntmap.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/gntmap.c	Wed Jul 23 18:23:12 2008 +0100
@@ -0,0 +1,250 @@
+/*
+ * Manages grant mappings from other domains.
+ *
+ * Diego Ongaro <diego.ongaro@citrix.com>, July 2008
+ *
+ * Files of type FTYPE_GNTMAP contain a gntmap, which is an array of
+ * (host address, grant handle) pairs. Grant handles come from a hypervisor map
+ * operation and are needed for the corresponding unmap.
+ *
+ * This is a rather naive implementation in terms of performance. If we start
+ * using it frequently, there's definitely some low-hanging fruit here.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <os.h>
+#include <xmalloc.h>
+#include <errno.h>
+#include <xen/grant_table.h>
+#include <inttypes.h>
+#include "gntmap.h"
+
+#define DEFAULT_MAX_GRANTS 128
+
+struct gntmap_entry {
+    unsigned long host_addr;
+    grant_handle_t handle;
+};
+
+static inline int
+gntmap_entry_used(struct gntmap_entry *entry)
+{
+    return entry->host_addr != 0;
+}
+
+static struct gntmap_entry*
+gntmap_find_free_entry(struct gntmap *map)
+{
+    int i;
+
+    for (i = 0; i < map->nentries; i++) {
+        if (!gntmap_entry_used(&map->entries[i]))
+            return &map->entries[i];
+    }
+
+#ifdef GNTMAP_DEBUG
+    printk("gntmap_find_free_entry(map=%p): all %d entries full\n",
+           map, map->nentries);
+#endif
+    return NULL;
+}
+
+static struct gntmap_entry*
+gntmap_find_entry(struct gntmap *map, unsigned long addr)
+{
+    int i;
+
+    for (i = 0; i < map->nentries; i++) {
+        if (map->entries[i].host_addr == addr)
+            return &map->entries[i];
+    }
+    return NULL;
+}
+
+int
+gntmap_set_max_grants(struct gntmap *map, int count)
+{
+#ifdef GNTMAP_DEBUG
+    printk("gntmap_set_max_grants(map=%p, count=%d)\n", map, count);
+#endif
+
+    if (map->nentries != 0)
+        return -EBUSY;
+
+    map->entries = xmalloc_array(struct gntmap_entry, count);
+    if (map->entries == NULL)
+        return -ENOMEM;
+
+    memset(map->entries, 0, sizeof(struct gntmap_entry) * count);
+    map->nentries = count;
+    return 0;
+}
+
+static int
+_gntmap_map_grant_ref(struct gntmap_entry *entry, 
+                      unsigned long host_addr,
+                      uint32_t domid,
+                      uint32_t ref,
+                      int writable)
+{
+    struct gnttab_map_grant_ref op;
+    int rc;
+
+    op.ref = (grant_ref_t) ref;
+    op.dom = (domid_t) domid;
+    op.host_addr = (uint64_t) host_addr;
+    op.flags = GNTMAP_host_map;
+    if (!writable)
+        op.flags |= GNTMAP_readonly;
+
+    rc = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
+    if (rc != 0 || op.status != GNTST_okay) {
+        printk("GNTTABOP_map_grant_ref failed: "
+               "returned %d, status %d\n",
+               rc, op.status);
+        return rc != 0 ? rc : op.status;
+    }
+
+    entry->host_addr = host_addr;
+    entry->handle = op.handle;
+    return 0;
+}
+
+static int
+_gntmap_unmap_grant_ref(struct gntmap_entry *entry)
+{
+    struct gnttab_unmap_grant_ref op;
+    int rc;
+
+    op.host_addr    = (uint64_t) entry->host_addr;
+    op.handle       = entry->handle;
+
+    rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
+    if (rc != 0 || op.status != GNTST_okay) {
+        printk("GNTTABOP_unmap_grant_ref failed: "
+               "returned %d, status %d\n",
+               rc, op.status);
+        return rc != 0 ? rc : op.status;
+    }
+
+    entry->host_addr = 0;
+    return 0;
+}
+
+int
+gntmap_munmap(struct gntmap *map, unsigned long start_address, int count)
+{
+    int i, rc;
+    struct gntmap_entry *ent;
+
+#ifdef GNTMAP_DEBUG
+    printk("gntmap_munmap(map=%p, start_address=%lx, count=%d)\n",
+           map, start_address, count);
+#endif
+
+    for (i = 0; i < count; i++) {
+        ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i);
+        if (ent == NULL) {
+            printk("gntmap: tried to munmap unknown page\n");
+            return -EINVAL;
+        }
+
+        rc = _gntmap_unmap_grant_ref(ent);
+        if (rc != 0)
+            return rc;
+    }
+
+    return 0;
+}
+
+void*
+gntmap_map_grant_refs(struct gntmap *map, 
+                      uint32_t count,
+                      uint32_t *domids,
+                      int domids_stride,
+                      uint32_t *refs,
+                      int writable)
+{
+    unsigned long addr;
+    struct gntmap_entry *ent;
+    int i;
+
+#ifdef GNTMAP_DEBUG
+    printk("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", "
+           "domids=%p [%" PRIu32 "...], domids_stride=%d, "
+           "refs=%p [%" PRIu32 "...], writable=%d)\n",
+           map, count, domids, domids[0], domids_stride,
+           refs, refs[0], writable);
+#endif
+
+    (void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS);
+
+    addr = allocate_ondemand((unsigned long) count, 1);
+    if (addr == 0)
+        return NULL;
+
+    for (i = 0; i < count; i++) {
+        ent = gntmap_find_free_entry(map);
+        if (ent == NULL ||
+            _gntmap_map_grant_ref(ent,
+                                  addr + PAGE_SIZE * i,
+                                  domids[i * domids_stride],
+                                  refs[i],
+                                  writable) != 0) {
+
+            (void) gntmap_munmap(map, addr, i);
+            return NULL;
+        }
+    }
+
+    return (void*) addr;
+}
+
+void
+gntmap_init(struct gntmap *map)
+{
+#ifdef GNTMAP_DEBUG
+    printk("gntmap_init(map=%p)\n", map);
+#endif
+    map->nentries = 0;
+    map->entries = NULL;
+}
+
+void
+gntmap_fini(struct gntmap *map)
+{
+    struct gntmap_entry *ent;
+    int i;
+
+#ifdef GNTMAP_DEBUG
+    printk("gntmap_fini(map=%p)\n", map);
+#endif
+
+    for (i = 0; i < map->nentries; i++) {
+        ent = &map->entries[i];
+        if (gntmap_entry_used(ent))
+            (void) _gntmap_unmap_grant_ref(ent);
+    }
+
+    xfree(map->entries);
+    map->entries = NULL;
+    map->nentries = 0;
+}
diff -r 7299346111fb extras/mini-os/include/gntmap.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/gntmap.h	Wed Jul 23 18:23:12 2008 +0100
@@ -0,0 +1,35 @@
+#ifndef __GNTMAP_H__
+#define __GNTMAP_H__
+
+#include <os.h>
+
+/*
+ * Please consider struct gntmap opaque. If instead you choose to disregard
+ * this message, I insist that you keep an eye out for raptors.
+ */
+struct gntmap {
+    int nentries;
+    struct gntmap_entry *entries;
+};
+
+int
+gntmap_set_max_grants(struct gntmap *map, int count);
+
+int
+gntmap_munmap(struct gntmap *map, unsigned long start_address, int count);
+
+void*
+gntmap_map_grant_refs(struct gntmap *map, 
+                      uint32_t count,
+                      uint32_t *domids,
+                      int domids_stride,
+                      uint32_t *refs,
+                      int writable);
+
+void
+gntmap_init(struct gntmap *map);
+
+void
+gntmap_fini(struct gntmap *map);
+
+#endif /* !__GNTMAP_H__ */
diff -r 7299346111fb extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h	Wed Jul 23 16:39:46 2008 +0100
+++ b/extras/mini-os/include/lib.h	Wed Jul 23 18:23:12 2008 +0100
@@ -59,6 +59,7 @@
 #include <stddef.h>
 #include <xen/xen.h>
 #include <xen/event_channel.h>
+#include "gntmap.h"
 
 #ifdef HAVE_LIBC
 #include <stdio.h>
@@ -138,6 +139,7 @@ enum fd_type {
     FTYPE_XENBUS,
     FTYPE_XC,
     FTYPE_EVTCHN,
+    FTYPE_GNTMAP,
     FTYPE_SOCKET,
     FTYPE_TAP,
     FTYPE_BLK,
@@ -168,6 +170,7 @@ extern struct file {
                 int bound;
             } ports[MAX_EVTCHN_PORTS];
 	} evtchn;
+	struct gntmap gntmap;
 	struct {
 	    struct netfront_dev *dev;
 	} tap;
diff -r 7299346111fb extras/mini-os/minios.mk
--- a/extras/mini-os/minios.mk	Wed Jul 23 16:39:46 2008 +0100
+++ b/extras/mini-os/minios.mk	Wed Jul 23 18:23:12 2008 +0100
@@ -21,6 +21,7 @@ DEF_CFLAGS += -g
 #DEF_CFLAGS += -DFS_DEBUG
 #DEF_CFLAGS += -DLIBC_DEBUG
 DEF_CFLAGS += -DGNT_DEBUG
+DEF_CFLAGS += -DGNTMAP_DEBUG
 else
 DEF_CFLAGS += -O3
 endif
diff -r 7299346111fb tools/libxc/xc_minios.c
--- a/tools/libxc/xc_minios.c	Wed Jul 23 16:39:46 2008 +0100
+++ b/tools/libxc/xc_minios.c	Wed Jul 23 18:23:12 2008 +0100
@@ -15,6 +15,7 @@
 #include <os.h>
 #include <mm.h>
 #include <lib.h>
+#include <gntmap.h>
 #include <events.h>
 #include <wait.h>
 #include <sys/mman.h>
@@ -315,6 +316,76 @@ void discard_file_cache(int fd, int flus
     if (flush)
         fsync(fd);
 }
+
+int xc_gnttab_open(void)
+{
+    int xcg_handle;
+    xcg_handle = alloc_fd(FTYPE_GNTMAP);
+    gntmap_init(&files[xcg_handle].gntmap);
+    return xcg_handle;
+}
+
+int xc_gnttab_close(int xcg_handle)
+{
+    gntmap_fini(&files[xcg_handle].gntmap);
+    files[xcg_handle].type = FTYPE_NONE;
+    return 0;
+}
+
+void *xc_gnttab_map_grant_ref(int xcg_handle,
+                              uint32_t domid,
+                              uint32_t ref,
+                              int prot)
+{
+    return gntmap_map_grant_refs(&files[xcg_handle].gntmap,
+                                 1,
+                                 &domid, 0,
+                                 &ref,
+                                 prot & PROT_WRITE);
+}
+
+void *xc_gnttab_map_grant_refs(int xcg_handle,
+                               uint32_t count,
+                               uint32_t *domids,
+                               uint32_t *refs,
+                               int prot)
+{
+    return gntmap_map_grant_refs(&files[xcg_handle].gntmap,
+                                 count,
+                                 domids, 1,
+                                 refs,
+                                 prot & PROT_WRITE);
+}
+
+void *xc_gnttab_map_domain_grant_refs(int xcg_handle,
+                                      uint32_t count,
+                                      uint32_t domid,
+                                      uint32_t *refs,
+                                      int prot)
+{
+    return gntmap_map_grant_refs(&files[xcg_handle].gntmap,
+                                 count,
+                                 &domid, 0,
+                                 refs,
+                                 prot & PROT_WRITE);
+}
+
+int xc_gnttab_munmap(int xcg_handle,
+                     void *start_address,
+                     uint32_t count)
+{
+    return gntmap_munmap(&files[xcg_handle].gntmap,
+                         (unsigned long) start_address,
+                         count);
+}
+
+int xc_gnttab_set_max_grants(int xcg_handle,
+                             uint32_t count)
+{
+    return gntmap_set_max_grants(&files[xcg_handle].gntmap,
+                                 count);
+}
+
 /*
  * Local variables:
  * mode: C

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC] grant table map (gntdev) for minios
  2008-07-23 17:31 [RFC] grant table map (gntdev) for minios Diego Ongaro
@ 2008-07-23 18:11 ` Diego Ongaro
  2008-07-24 14:42 ` Diego Ongaro
  1 sibling, 0 replies; 3+ messages in thread
From: Diego Ongaro @ 2008-07-23 18:11 UTC (permalink / raw)
  To: xen-devel

Diego Ongaro wrote:
> I've implemented a grant map for mini-os to support the xc_gnttab_*()
> functions, the equivalent of gntdev in linux.

Adds a close() case for the new file type.

Signed-off-by: Diego Ongaro <diego.ongaro@citrix.com>
---
diff --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c
+++ b/extras/mini-os/lib/sys.c
@@ -401,6 +401,9 @@ int close(int fd)
 	case FTYPE_EVTCHN:
             xc_evtchn_close(fd);
             return 0;
+	case FTYPE_GNTMAP:
+	    xc_gnttab_close(fd);
+	    return 0;
 	case FTYPE_TAP:
 	    shutdown_netfront(files[fd].tap.dev);
 	    files[fd].type = FTYPE_NONE;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC] grant table map (gntdev) for minios
  2008-07-23 17:31 [RFC] grant table map (gntdev) for minios Diego Ongaro
  2008-07-23 18:11 ` Diego Ongaro
@ 2008-07-24 14:42 ` Diego Ongaro
  1 sibling, 0 replies; 3+ messages in thread
From: Diego Ongaro @ 2008-07-24 14:42 UTC (permalink / raw)
  To: xen-devel

Diego Ongaro wrote:
> I've implemented a grant map for mini-os to support the xc_gnttab_*()
> functions, the equivalent of gntdev in linux.

Bug fixes:
 * Uninitialized dev_bus_addr argument to GNTTABOP_unmap_grant_ref
   results in an angry hypervisor.
 * Set errno in libxc and return -1 on error.
 * op.status is a int16_t, so it should be printed with PRId16.
 * Don't print domids[0] or refs[0] if the ptr is NULL. It's more polite
   to crash later, after the message has been printed.

Signed-off-by: Diego Ongaro <diego.ongaro@citrix.com>
---
diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c
--- a/extras/mini-os/gntmap.c
+++ b/extras/mini-os/gntmap.c
@@ -118,7 +118,7 @@ _gntmap_map_grant_ref(struct gntmap_entr
     rc = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
     if (rc != 0 || op.status != GNTST_okay) {
         printk("GNTTABOP_map_grant_ref failed: "
-               "returned %d, status %d\n",
+               "returned %d, status %" PRId16 "\n",
                rc, op.status);
         return rc != 0 ? rc : op.status;
     }
@@ -135,12 +135,13 @@ _gntmap_unmap_grant_ref(struct gntmap_en
     int rc;
 
     op.host_addr    = (uint64_t) entry->host_addr;
+    op.dev_bus_addr = 0;
     op.handle       = entry->handle;
 
     rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
     if (rc != 0 || op.status != GNTST_okay) {
         printk("GNTTABOP_unmap_grant_ref failed: "
-               "returned %d, status %d\n",
+               "returned %d, status %" PRId16 "\n",
                rc, op.status);
         return rc != 0 ? rc : op.status;
     }
@@ -191,8 +192,9 @@ gntmap_map_grant_refs(struct gntmap *map
     printk("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", "
            "domids=%p [%" PRIu32 "...], domids_stride=%d, "
            "refs=%p [%" PRIu32 "...], writable=%d)\n",
-           map, count, domids, domids[0], domids_stride,
-           refs, refs[0], writable);
+           map, count,
+           domids, domids == NULL ? 0 : domids[0], domids_stride,
+           refs, refs == NULL ? 0 : refs[0], writable);
 #endif
 
     (void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS);
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -383,16 +383,28 @@ int xc_gnttab_munmap(int xcg_handle,
                      void *start_address,
                      uint32_t count)
 {
-    return gntmap_munmap(&files[xcg_handle].gntmap,
-                         (unsigned long) start_address,
-                         count);
+    int ret;
+    ret = gntmap_munmap(&files[xcg_handle].gntmap,
+                        (unsigned long) start_address,
+                        count);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
 }
 
 int xc_gnttab_set_max_grants(int xcg_handle,
                              uint32_t count)
 {
-    return gntmap_set_max_grants(&files[xcg_handle].gntmap,
-                                 count);
+    int ret;
+    ret = gntmap_set_max_grants(&files[xcg_handle].gntmap,
+                                count);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
 }
 
 /*

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-07-24 14:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-23 17:31 [RFC] grant table map (gntdev) for minios Diego Ongaro
2008-07-23 18:11 ` Diego Ongaro
2008-07-24 14:42 ` Diego Ongaro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.