2013-09-26 17:14:40 +02:00

214 lines
5.2 KiB
Plaintext

$NetBSD: patch-bb,v 1.1.1.1 2011/04/06 09:10:27 cegger Exp $
--- libxc/xc_netbsd.c.orig 2011-03-29 17:09:58.000000000 +0000
+++ libxc/xc_netbsd.c
@@ -21,6 +21,7 @@
#include "xc_private.h"
#include <xen/sys/evtchn.h>
+#include <xen/sys/gntdev.h>
#include <unistd.h>
#include <fcntl.h>
@@ -351,7 +352,189 @@ void discard_file_cache(xc_interface *xc
errno = saved_errno;
}
-static struct xc_osdep_ops *netbsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
+#define DEVXEN "/dev/xen/"
+
+static xc_osdep_handle
+netbsd_gnttab_open(xc_gnttab *xcg)
+{
+ int fd;
+
+ fd = open(DEVXEN "gntdev", O_RDWR);
+ if (fd == -1)
+ return XC_OSDEP_OPEN_ERROR;
+
+ return (xc_osdep_handle)fd;
+}
+
+static int
+netbsd_gnttab_close(xc_gnttab *xcg, xc_osdep_handle h)
+{
+ int fd = (int)h;
+ return close(fd);
+}
+
+static void *
+netbsd_gnttab_map_grant_ref(xc_gnttab *xch, xc_osdep_handle h,
+ uint32_t domid, uint32_t ref, int prot)
+{
+ int fd = (int)h;
+ struct ioctl_gntdev_map_grant_ref map;
+ void *addr;
+
+ map.count = 1;
+ map.refs[0].domid = domid;
+ map.refs[0].ref = ref;
+
+ if ( ioctl(fd, IOCTL_GNTDEV_MAP_GRANT_REF, &map) ) {
+ PERROR("netbsd_gnttab_map_grant_ref: ioctl MAP_GRANT_REF failed");
+ return NULL;
+ }
+
+mmap_again:
+ addr = mmap(NULL, XC_PAGE_SIZE, prot, MAP_SHARED, fd, map.index);
+ if ( addr == MAP_FAILED )
+ {
+ int saved_errno = errno;
+ struct ioctl_gntdev_unmap_grant_ref unmap_grant;
+
+ if ( saved_errno == EAGAIN )
+ {
+ usleep(1000);
+ goto mmap_again;
+ }
+ /* Unmap the driver slots used to store the grant information. */
+ PERROR("netbsd_gnttab_map_grant_ref: mmap failed");
+ unmap_grant.index = map.index;
+ unmap_grant.count = 1;
+ ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant);
+ errno = saved_errno;
+ return NULL;
+ }
+
+ return addr;
+}
+
+static void *
+do_gnttab_map_grant_refs(xc_gnttab *xch, xc_osdep_handle h,
+ uint32_t count, uint32_t *domids, int domids_stride,
+ uint32_t *refs, int prot)
+{
+ int fd = (int)h;
+ struct ioctl_gntdev_map_grant_ref *map;
+ void *addr = NULL;
+ int i;
+
+ map = malloc(sizeof(*map) +
+ (count - 1) * sizeof(struct ioctl_gntdev_map_grant_ref));
+ if ( map == NULL )
+ return NULL;
+
+ for ( i = 0; i < count; i++ )
+ {
+ map->refs[i].domid = domids[i * domids_stride];
+ map->refs[i].ref = refs[i];
+ }
+
+ map->count = count;
+
+ if ( ioctl(fd, IOCTL_GNTDEV_MAP_GRANT_REF, map) ) {
+ PERROR("xc_gnttab_map_grant_refs: ioctl MAP_GRANT_REF failed");
+ goto out;
+ }
+
+ addr = mmap(NULL, XC_PAGE_SIZE * count, prot, MAP_SHARED, fd,
+ map->index);
+ if ( addr == MAP_FAILED )
+ {
+ int saved_errno = errno;
+ struct ioctl_gntdev_unmap_grant_ref unmap_grant;
+
+ /* Unmap the driver slots used to store the grant information. */
+ PERROR("xc_gnttab_map_grant_refs: mmap failed");
+ unmap_grant.index = map->index;
+ unmap_grant.count = count;
+ ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant);
+ errno = saved_errno;
+ addr = NULL;
+ }
+
+ out:
+ free(map);
+
+ return addr;
+}
+
+static void *
+netbsd_gnttab_map_grant_refs(xc_gnttab *xcg, xc_osdep_handle h,
+ uint32_t count, uint32_t *domids, uint32_t *refs, int prot)
+{
+ return do_gnttab_map_grant_refs(xcg, h, count, domids, 1, refs, prot);
+}
+
+static void *
+netbsd_gnttab_map_domain_grant_refs(xc_gnttab *xcg, xc_osdep_handle h,
+ uint32_t count, uint32_t domid, uint32_t *refs, int prot)
+{
+ return do_gnttab_map_grant_refs(xcg, h, count, &domid, 0, refs, prot);
+}
+
+static int
+netbsd_gnttab_munmap(xc_gnttab *xcg, xc_osdep_handle h,
+ void *start_address, uint32_t count)
+{
+ int fd = (int)h;
+ struct ioctl_gntdev_get_offset_for_vaddr get_offset;
+ struct ioctl_gntdev_unmap_grant_ref unmap_grant;
+ int rc;
+
+ if ( start_address == NULL )
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* First, it is necessary to get the offset which was initially used to
+ * mmap() the pages.
+ */
+ get_offset.vaddr = (unsigned long)start_address;
+ rc = ioctl(fd, IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR, &get_offset);
+ if ( rc )
+ return rc;
+
+ if ( get_offset.count != count )
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Next, unmap the memory. */
+ rc = munmap(start_address, count * getpagesize());
+ if ( rc )
+ return rc;
+
+ /* Finally, unmap the driver slots used to store the grant information. */
+ unmap_grant.index = get_offset.offset;
+ unmap_grant.count = count;
+ rc = ioctl(fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant);
+ if ( rc )
+ return rc;
+ return 0;
+}
+
+static struct xc_osdep_ops netbsd_gnttab_ops = {
+ .open = &netbsd_gnttab_open,
+ .close = &netbsd_gnttab_close,
+
+ .u.gnttab = {
+ .map_grant_ref = &netbsd_gnttab_map_grant_ref,
+ .map_grant_refs = &netbsd_gnttab_map_grant_refs,
+ .map_domain_grant_refs = &netbsd_gnttab_map_domain_grant_refs,
+ .munmap = &netbsd_gnttab_munmap,
+ },
+};
+
+static struct xc_osdep_ops *
+netbsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
{
switch ( type )
{
@@ -360,8 +543,7 @@ static struct xc_osdep_ops *netbsd_osdep
case XC_OSDEP_EVTCHN:
return &netbsd_evtchn_ops;
case XC_OSDEP_GNTTAB:
- ERROR("GNTTAB interface not supported on this platform");
- return NULL;
+ return &netbsd_gnttab_ops;
default:
return NULL;
}