# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1216905267 -3600
# Node ID 379dd201c36c294fbf41897619cbdd7d1823be38
# Parent 707569df20e1680b803e58b2e4a4ee6d5a98824e
minios: grant table map (gntdev) for minios
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.
Signed-off-by: Diego Ongaro <diego.ongaro@xxxxxxxxxx>
---
extras/mini-os/gntmap.c | 250 ++++++++++++++++++++++++++++++++++++++++
extras/mini-os/include/gntmap.h | 35 +++++
extras/mini-os/include/lib.h | 3
extras/mini-os/lib/sys.c | 3
extras/mini-os/minios.mk | 1
tools/libxc/xc_minios.c | 71 +++++++++++
6 files changed, 363 insertions(+)
diff -r 707569df20e1 -r 379dd201c36c extras/mini-os/gntmap.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/gntmap.c Thu Jul 24 14:14:27 2008 +0100
@@ -0,0 +1,250 @@
+/*
+ * Manages grant mappings from other domains.
+ *
+ * Diego Ongaro <diego.ongaro@xxxxxxxxxx>, 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 707569df20e1 -r 379dd201c36c extras/mini-os/include/gntmap.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/gntmap.h Thu Jul 24 14:14:27 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 707569df20e1 -r 379dd201c36c extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h Thu Jul 24 14:12:46 2008 +0100
+++ b/extras/mini-os/include/lib.h Thu Jul 24 14:14:27 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 707569df20e1 -r 379dd201c36c extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c Thu Jul 24 14:12:46 2008 +0100
+++ b/extras/mini-os/lib/sys.c Thu Jul 24 14:14:27 2008 +0100
@@ -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;
diff -r 707569df20e1 -r 379dd201c36c extras/mini-os/minios.mk
--- a/extras/mini-os/minios.mk Thu Jul 24 14:12:46 2008 +0100
+++ b/extras/mini-os/minios.mk Thu Jul 24 14:14:27 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 707569df20e1 -r 379dd201c36c tools/libxc/xc_minios.c
--- a/tools/libxc/xc_minios.c Thu Jul 24 14:12:46 2008 +0100
+++ b/tools/libxc/xc_minios.c Thu Jul 24 14:14:27 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>
@@ -324,6 +325,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
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|