pkgsrc/sysutils/xentools42/patches/patch-libxc_xc__netbsd.c
spz fcf436606c Apply patches for XSA-128 to XSA-140 from upstream
do a patch refresh in xentools42

rather than split the patches for pass-through.c over 5 files, delete
xentools42/patches/patch-CVE-2015-2756 and assemble all in
xentools42/patches/patch-qemu-xen-traditional_hw_pass-through.c
2015-08-23 16:17:12 +00:00

251 lines
6.9 KiB
C

$NetBSD: patch-libxc_xc__netbsd.c,v 1.2 2015/08/23 16:17:12 spz Exp $
--- libxc/xc_netbsd.c.orig 2014-09-02 06:22:57.000000000 +0000
+++ libxc/xc_netbsd.c
@@ -18,13 +18,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "xc_private.h"
-
-#include <xen/sys/evtchn.h>
-#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
#include <fcntl.h>
#include <malloc.h>
-#include <sys/mman.h>
+#include <unistd.h>
+
+#include <xen/memory.h>
+#include <xen/sys/evtchn.h>
+#include <xen/sys/gntdev.h>
+/* #include <xen/sys/gntalloc.h> */
+#include "xc_private.h"
+#include "xenctrl.h"
+#include "xenctrlosdep.h"
static xc_osdep_handle netbsd_privcmd_open(xc_interface *xch)
{
@@ -390,6 +396,210 @@ void *xc_memalign(xc_interface *xch, siz
return valloc(size);
}
+#if 0
+#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 int netbsd_gnttab_set_max_grants(xc_gnttab *xch, xc_osdep_handle h,
+ uint32_t count)
+{
+ int fd = (int)h, rc;
+ struct ioctl_gntdev_set_max_grants max_grants = { .count = count };
+
+ rc = ioctl(fd, IOCTL_GNTDEV_SET_MAX_GRANTS, &max_grants);
+ if (rc) {
+ /*
+ * Newer (e.g. pv-ops) kernels don't implement this IOCTL,
+ * so ignore the resulting specific failure.
+ */
+ if (errno == ENOTTY)
+ rc = 0;
+ else
+ PERROR("netbsd_gnttab_set_max_grants: ioctl SET_MAX_GRANTS failed");
+ }
+ return rc;
+}
+
+static void *netbsd_gnttab_grant_map(xc_gnttab *xch, xc_osdep_handle h,
+ uint32_t count, int flags, int prot,
+ uint32_t *domids, uint32_t *refs,
+ uint32_t notify_offset,
+ evtchn_port_t notify_port)
+{
+ int fd = (int)h;
+ struct ioctl_gntdev_map_grant_ref *map;
+ unsigned int map_size = ROUNDUP((sizeof(*map) + (count - 1) *
+ sizeof(struct ioctl_gntdev_map_grant_ref)),
+ XC_PAGE_SHIFT);
+ void *addr = NULL;
+ int domids_stride = 1;
+ int i;
+
+ if (flags & XC_GRANT_MAP_SINGLE_DOMAIN)
+ domids_stride = 0;
+
+ if ( map_size <= XC_PAGE_SIZE )
+ map = alloca(sizeof(*map) +
+ (count - 1) * sizeof(struct ioctl_gntdev_map_grant_ref));
+ else
+ {
+ map = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0);
+ if ( map == MAP_FAILED )
+ {
+ PERROR("netbsd_gnttab_grant_map: mmap of map failed");
+ 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("netbsd_gnttab_grant_map: ioctl MAP_GRANT_REF failed");
+ goto out;
+ }
+
+ retry:
+ addr = mmap(NULL, XC_PAGE_SIZE * count, prot, MAP_SHARED, fd,
+ map->index);
+
+ if (addr == MAP_FAILED && errno == EAGAIN)
+ {
+ /*
+ * The grant hypercall can return EAGAIN if the granted page is
+ * swapped out. Since the paging daemon may be in the same domain, the
+ * hypercall cannot block without causing a deadlock.
+ *
+ * Because there are no notificaitons when the page is swapped in, wait
+ * a bit before retrying, and hope that the page will arrive eventually.
+ */
+ usleep(1000);
+ goto retry;
+ }
+
+ if (addr != MAP_FAILED)
+ {
+ int rv = 0;
+ struct ioctl_gntdev_unmap_notify notify;
+ notify.index = map->index;
+ notify.action = 0;
+ if (notify_offset < XC_PAGE_SIZE * count) {
+ notify.index += notify_offset;
+ notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
+ }
+ if (notify_port != -1) {
+ notify.event_channel_port = notify_port;
+ notify.action |= UNMAP_NOTIFY_SEND_EVENT;
+ }
+ if (notify.action)
+ rv = ioctl(fd, IOCTL_GNTDEV_SET_UNMAP_NOTIFY, &notify);
+ if (rv) {
+ PERROR("netbsd_gnttab_grant_map: ioctl SET_UNMAP_NOTIFY failed");
+ munmap(addr, count * XC_PAGE_SIZE);
+ addr = MAP_FAILED;
+ }
+ }
+
+ 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:
+ if ( map_size > XC_PAGE_SIZE )
+ munmap(map, map_size);
+
+ return addr;
+}
+
+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 = {
+ .set_max_grants = netbsd_gnttab_set_max_grants,
+ .grant_map = &netbsd_gnttab_grant_map,
+ .munmap = &netbsd_gnttab_munmap,
+ },
+};
+#endif
+
static struct xc_osdep_ops *netbsd_osdep_init(xc_interface *xch, enum xc_osdep_type type)
{
switch ( type )
@@ -398,6 +608,10 @@ static struct xc_osdep_ops *netbsd_osdep
return &netbsd_privcmd_ops;
case XC_OSDEP_EVTCHN:
return &netbsd_evtchn_ops;
+#if 0
+ case XC_OSDEP_GNTTAB:
+ return &netbsd_gnttab_ops;
+#endif
default:
return NULL;
}