Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Aug 2016 20:22:21 GMT
From:      vincenzo@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r308107 - in soc2016/vincenzo/current/head: lib/libvmmapi sys/amd64/include sys/amd64/vmm sys/conf sys/dev/netmap sys/modules/netmap sys/modules/vmm sys/net usr.sbin/bhyve
Message-ID:  <201608202022.u7KKMLHU067000@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: vincenzo
Date: Sat Aug 20 20:22:20 2016
New Revision: 308107
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=308107

Log:
  import gsoc2016-ptnet patch

Added:
  soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_usermem.c
  soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_usermem.h
  soc2016/vincenzo/current/head/sys/dev/netmap/if_nfe_netmap.h
  soc2016/vincenzo/current/head/sys/dev/netmap/if_ptnet.c
  soc2016/vincenzo/current/head/sys/dev/netmap/ptnetmap.c
  soc2016/vincenzo/current/head/sys/net/netmap_virt.h
  soc2016/vincenzo/current/head/usr.sbin/bhyve/net_backends.c
  soc2016/vincenzo/current/head/usr.sbin/bhyve/net_backends.h
  soc2016/vincenzo/current/head/usr.sbin/bhyve/net_utils.c
  soc2016/vincenzo/current/head/usr.sbin/bhyve/net_utils.h
  soc2016/vincenzo/current/head/usr.sbin/bhyve/pci_ptnetmap_memdev.c
  soc2016/vincenzo/current/head/usr.sbin/bhyve/pci_ptnetmap_netif.c
Modified:
  soc2016/vincenzo/current/head/lib/libvmmapi/vmmapi.c
  soc2016/vincenzo/current/head/lib/libvmmapi/vmmapi.h
  soc2016/vincenzo/current/head/sys/amd64/include/vmm.h
  soc2016/vincenzo/current/head/sys/amd64/include/vmm_dev.h
  soc2016/vincenzo/current/head/sys/amd64/vmm/vmm.c
  soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_dev.c
  soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_ioport.c
  soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_ioport.h
  soc2016/vincenzo/current/head/sys/conf/files
  soc2016/vincenzo/current/head/sys/dev/netmap/if_ixl_netmap.h
  soc2016/vincenzo/current/head/sys/dev/netmap/if_lem_netmap.h
  soc2016/vincenzo/current/head/sys/dev/netmap/if_vtnet_netmap.h
  soc2016/vincenzo/current/head/sys/dev/netmap/ixgbe_netmap.h
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap.c
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_freebsd.c
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_generic.c
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_kern.h
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_mbq.c
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_mbq.h
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_mem2.c
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_mem2.h
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_monitor.c
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_offloadings.c
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_pipe.c
  soc2016/vincenzo/current/head/sys/dev/netmap/netmap_vale.c
  soc2016/vincenzo/current/head/sys/modules/netmap/Makefile
  soc2016/vincenzo/current/head/sys/modules/vmm/Makefile
  soc2016/vincenzo/current/head/sys/net/netmap.h
  soc2016/vincenzo/current/head/sys/net/netmap_user.h
  soc2016/vincenzo/current/head/usr.sbin/bhyve/Makefile
  soc2016/vincenzo/current/head/usr.sbin/bhyve/pci_virtio_net.c

Modified: soc2016/vincenzo/current/head/lib/libvmmapi/vmmapi.c
==============================================================================
--- soc2016/vincenzo/current/head/lib/libvmmapi/vmmapi.c	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/lib/libvmmapi/vmmapi.c	Sat Aug 20 20:22:20 2016	(r308107)
@@ -883,6 +883,42 @@
 }
 
 int
+vm_get_fd(struct vmctx *ctx)
+{
+	return (ctx->fd);
+}
+
+int
+vm_map_user_buf(struct vmctx *ctx, vm_paddr_t gpa, size_t len, void *host_buf)
+{
+	struct vm_user_buf user_buf;
+
+	bzero(&user_buf, sizeof(user_buf));
+	user_buf.gpa = gpa;
+	user_buf.len = len;
+	user_buf.addr = host_buf;
+
+	return (ioctl(ctx->fd, VM_MAP_USER_BUF, &user_buf));
+}
+
+int
+vm_io_reg_handler(struct vmctx *ctx, uint16_t port, uint16_t in, uint32_t mask_data, uint32_t data,
+     enum vm_io_regh_type type, void *arg)
+{
+	struct vm_io_reg_handler ioregh;
+
+	bzero(&ioregh, sizeof(ioregh));
+	ioregh.port = port;
+	ioregh.in = in;
+	ioregh.mask_data = mask_data;
+	ioregh.data = data;
+	ioregh.type = type;
+	ioregh.arg = arg;
+
+	return (ioctl(ctx->fd, VM_IO_REG_HANDLER, &ioregh));
+}
+
+int
 vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
     uint64_t addr, uint64_t msg, int numvec)
 {

Modified: soc2016/vincenzo/current/head/lib/libvmmapi/vmmapi.h
==============================================================================
--- soc2016/vincenzo/current/head/lib/libvmmapi/vmmapi.h	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/lib/libvmmapi/vmmapi.h	Sat Aug 20 20:22:20 2016	(r308107)
@@ -161,7 +161,10 @@
 
 int	vm_get_intinfo(struct vmctx *ctx, int vcpu, uint64_t *i1, uint64_t *i2);
 int	vm_set_intinfo(struct vmctx *ctx, int vcpu, uint64_t exit_intinfo);
-
+int	vm_get_fd(struct vmctx *ctx);
+int	vm_map_user_buf(struct vmctx *ctx, vm_paddr_t gpa, size_t len, void *host_buf);
+int	vm_io_reg_handler(struct vmctx *ctx, uint16_t port, uint16_t in,
+	    uint32_t mask_data, uint32_t data, enum vm_io_regh_type type, void *arg);
 /*
  * Return a pointer to the statistics buffer. Note that this is not MT-safe.
  */

Modified: soc2016/vincenzo/current/head/sys/amd64/include/vmm.h
==============================================================================
--- soc2016/vincenzo/current/head/sys/amd64/include/vmm.h	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/sys/amd64/include/vmm.h	Sat Aug 20 20:22:20 2016	(r308107)
@@ -183,6 +183,7 @@
 int vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem);
 void vm_free_memseg(struct vm *vm, int ident);
 int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
+int vm_map_usermem(struct vm *vm, vm_paddr_t gpa, size_t len, void *buf, struct thread *td);
 int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len);
 int vm_assign_pptdev(struct vm *vm, int bus, int slot, int func);
 int vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func);
@@ -321,6 +322,7 @@
 struct vatpit *vm_atpit(struct vm *vm);
 struct vpmtmr *vm_pmtmr(struct vm *vm);
 struct vrtc *vm_rtc(struct vm *vm);
+struct ioregh *vm_ioregh(struct vm *vm);
 
 /*
  * Inject exception 'vector' into the guest vcpu. This function returns 0 on
@@ -417,7 +419,13 @@
 	EDGE_TRIGGER,
 	LEVEL_TRIGGER
 };
-	
+
+enum vm_io_regh_type {
+	VM_IO_REGH_DELETE,
+	VM_IO_REGH_KWEVENTS,	/* kernel wait events */
+	VM_IO_REGH_MAX
+};
+
 /*
  * The 'access' field has the format specified in Table 21-2 of the Intel
  * Architecture Manual vol 3b.

Modified: soc2016/vincenzo/current/head/sys/amd64/include/vmm_dev.h
==============================================================================
--- soc2016/vincenzo/current/head/sys/amd64/include/vmm_dev.h	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/sys/amd64/include/vmm_dev.h	Sat Aug 20 20:22:20 2016	(r308107)
@@ -123,6 +123,21 @@
 	size_t		len;
 };
 
+struct vm_user_buf {
+	vm_paddr_t	gpa;
+	void 		*addr;
+	size_t		len;
+};
+
+struct vm_io_reg_handler {
+	uint16_t		port;		/* I/O address */
+	uint16_t		in;		/* 0 out, 1 in */
+	uint32_t		mask_data;	/* 0 means match anything */
+	uint32_t		data;		/* data to match */
+	enum vm_io_regh_type	type;		/* handler type */
+	void			*arg;		/* handler argument */
+};
+
 struct vm_pptdev_msi {
 	int		vcpu;
 	int		bus;
@@ -286,6 +301,10 @@
 	IOCNUM_RTC_WRITE = 101,
 	IOCNUM_RTC_SETTIME = 102,
 	IOCNUM_RTC_GETTIME = 103,
+
+	/* host mmap and IO handler */
+	IOCNUM_MAP_USER_BUF = 104,
+	IOCNUM_IO_REG_HANDLER = 105,
 };
 
 #define	VM_RUN		\
@@ -344,6 +363,10 @@
 	_IOW('v', IOCNUM_UNBIND_PPTDEV, struct vm_pptdev)
 #define	VM_MAP_PPTDEV_MMIO \
 	_IOW('v', IOCNUM_MAP_PPTDEV_MMIO, struct vm_pptdev_mmio)
+#define	VM_MAP_USER_BUF \
+	_IOW('v', IOCNUM_MAP_USER_BUF, struct vm_user_buf)
+#define	VM_IO_REG_HANDLER \
+	_IOW('v', IOCNUM_IO_REG_HANDLER, struct vm_io_reg_handler)
 #define	VM_PPTDEV_MSI \
 	_IOW('v', IOCNUM_PPTDEV_MSI, struct vm_pptdev_msi)
 #define	VM_PPTDEV_MSIX \

Modified: soc2016/vincenzo/current/head/sys/amd64/vmm/vmm.c
==============================================================================
--- soc2016/vincenzo/current/head/sys/amd64/vmm/vmm.c	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/sys/amd64/vmm/vmm.c	Sat Aug 20 20:22:20 2016	(r308107)
@@ -66,6 +66,7 @@
 #include "vmm_ktr.h"
 #include "vmm_host.h"
 #include "vmm_mem.h"
+#include "vmm_usermem.h"
 #include "vmm_util.h"
 #include "vatpic.h"
 #include "vatpit.h"
@@ -148,6 +149,7 @@
 	struct vatpit	*vatpit;		/* (i) virtual atpit */
 	struct vpmtmr	*vpmtmr;		/* (i) virtual ACPI PM timer */
 	struct vrtc	*vrtc;			/* (o) virtual RTC */
+	struct ioregh	*ioregh;		/* () I/O reg handler */
 	volatile cpuset_t active_cpus;		/* (i) active vcpus */
 	int		suspend;		/* (i) stop VM execution */
 	volatile cpuset_t suspended_cpus; 	/* (i) suspended vcpus */
@@ -419,6 +421,7 @@
 	vm->vpmtmr = vpmtmr_init(vm);
 	if (create)
 		vm->vrtc = vrtc_init(vm);
+	vm->ioregh = ioregh_init(vm);
 
 	CPU_ZERO(&vm->active_cpus);
 
@@ -475,11 +478,13 @@
 		vrtc_cleanup(vm->vrtc);
 	else
 		vrtc_reset(vm->vrtc);
+	ioregh_cleanup(vm->ioregh);
 	vpmtmr_cleanup(vm->vpmtmr);
 	vatpit_cleanup(vm->vatpit);
 	vhpet_cleanup(vm->vhpet);
 	vatpic_cleanup(vm->vatpic);
 	vioapic_cleanup(vm->vioapic);
+	vmm_usermem_cleanup(vm->vmspace);
 
 	for (i = 0; i < VM_MAXCPU; i++)
 		vcpu_cleanup(vm, i, destroy);
@@ -553,6 +558,17 @@
 }
 
 int
+vm_map_usermem(struct vm *vm, vm_paddr_t gpa, size_t len, void *buf, struct thread *td)
+{
+	vm_object_t obj;
+
+	if ((obj = vmm_usermem_alloc(vm->vmspace, gpa, len, buf, td)) == NULL)
+		return (ENOMEM);
+
+	return (0);
+}
+
+int
 vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len)
 {
 
@@ -588,6 +604,9 @@
 	if (ppt_is_mmio(vm, gpa))
 		return (true);			/* 'gpa' is pci passthru mmio */
 
+	if (usermem_mapped(vm->vmspace, gpa))
+		return (true);			/* 'gpa' is user-space buffer mapped */
+
 	return (false);
 }
 
@@ -2457,6 +2476,12 @@
 	return (vm->vrtc);
 }
 
+struct ioregh *
+vm_ioregh(struct vm *vm)
+{
+	return (vm->ioregh);
+}
+
 enum vm_reg_name
 vm_segment_name(int seg)
 {

Modified: soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_dev.c
==============================================================================
--- soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_dev.c	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_dev.c	Sat Aug 20 20:22:20 2016	(r308107)
@@ -55,6 +55,7 @@
 #include "vmm_lapic.h"
 #include "vmm_stat.h"
 #include "vmm_mem.h"
+#include "vmm_ioport.h"
 #include "io/ppt.h"
 #include "io/vatpic.h"
 #include "io/vioapic.h"
@@ -300,6 +301,8 @@
 	struct vm_pptdev_mmio *pptmmio;
 	struct vm_pptdev_msi *pptmsi;
 	struct vm_pptdev_msix *pptmsix;
+	struct vm_user_buf *usermem;
+	struct vm_io_reg_handler *ioregh;
 	struct vm_nmi *vmnmi;
 	struct vm_stats *vmstats;
 	struct vm_stat_desc *statdesc;
@@ -358,6 +361,7 @@
 	case VM_UNBIND_PPTDEV:
 	case VM_ALLOC_MEMSEG:
 	case VM_MMAP_MEMSEG:
+	case VM_MAP_USER_BUF:
 	case VM_REINIT:
 		/*
 		 * ioctls that operate on the entire virtual machine must
@@ -433,6 +437,16 @@
 				     pptmmio->func, pptmmio->gpa, pptmmio->len,
 				     pptmmio->hpa);
 		break;
+	case VM_MAP_USER_BUF:
+		usermem = (struct vm_user_buf *)data;
+		error = vm_map_usermem(sc->vm, usermem->gpa, usermem->len,
+					usermem->addr, td);
+		break;
+	case VM_IO_REG_HANDLER:
+		ioregh = (struct vm_io_reg_handler *)data;
+		error = vmm_ioport_reg_handler(sc->vm, ioregh->port, ioregh->in, ioregh->mask_data,
+					ioregh->data, ioregh->type, ioregh->arg);
+		break;
 	case VM_BIND_PPTDEV:
 		pptdev = (struct vm_pptdev *)data;
 		error = vm_assign_pptdev(sc->vm, pptdev->bus, pptdev->slot,

Modified: soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_ioport.c
==============================================================================
--- soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_ioport.c	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_ioport.c	Sat Aug 20 20:22:20 2016	(r308107)
@@ -97,31 +97,274 @@
 }
 #endif	/* KTR */
 
+#ifdef VMM_IOPORT_REG_HANDLER
+#include <sys/kernel.h>
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+static MALLOC_DEFINE(M_IOREGH, "ioregh", "bhyve ioport reg handlers");
+
+#define IOPORT_MAX_REG_HANDLER	16
+
+/*
+ * ioport_reg_handler functions allows us to to catch VM write/read
+ * on specific I/O address and send notification.
+ *
+ * When the VM writes or reads a specific value on I/O address, if the address
+ * and the value matches with the info stored durign the handler registration,
+ * then we send a notification (we can have multiple type of notification,
+ * but for now is implemented only the VM_IO_REGH_KWEVENTS handler.
+ */
+
+typedef int (*ioport_reg_handler_func_t)(struct vm *vm,
+		struct ioport_reg_handler *regh, uint32_t *val);
+
+struct ioport_reg_handler {
+	uint16_t port;				/* I/O address */
+	uint16_t in;				/* 0 out, 1 in */
+	uint32_t mask_data;			/* 0 means match anything */
+	uint32_t data;				/* data to match */
+	ioport_reg_handler_func_t handler;	/* handler pointer */
+	void *handler_arg;			/* handler argument */
+};
+
+struct ioregh {
+	struct sx lock;
+	/* TODO: use hash table */
+	struct ioport_reg_handler handlers[IOPORT_MAX_REG_HANDLER];
+};
+
+/* ----- I/O reg handlers ----- */
+
+/*
+ * VM_IO_REGH_KWEVENTS handler
+ *
+ * wakeup() on specified address that uniquely identifies the event
+ *
+ */
+static int
+vmm_ioport_reg_wakeup(struct vm *vm, struct ioport_reg_handler *regh, uint32_t *val)
+{
+	wakeup(regh->handler_arg);
+	return (0);
+}
+
+/*
+ * TODO:
+ * - VM_IO_REGH_CONDSIGNAL:	pthread_cond_signal
+ * - VM_IO_REGH_WRITEFD:	write on fd
+ * - VM_IO_REGH_IOCTL:		ioctl on fd
+ */
+
+/* call with ioregh->lock held */
+static struct ioport_reg_handler *
+vmm_ioport_find_handler(struct ioregh *ioregh, uint16_t port, uint16_t in,
+		uint32_t mask_data, uint32_t data)
+{
+	struct ioport_reg_handler *regh;
+	uint32_t mask;
+	int i;
+
+	regh = ioregh->handlers;
+	for (i = 0; i < IOPORT_MAX_REG_HANDLER; i++) {
+		if (regh[i].handler != NULL) {
+			mask = regh[i].mask_data & mask_data;
+			if ((regh[i].port == port) && (regh[i].in == in)
+				&& ((mask & regh[i].data) == (mask & data))) {
+				return &regh[i];
+			}
+		}
+	}
+
+	return (NULL);
+}
+
+/* call with ioregh->lock held */
+static struct ioport_reg_handler *
+vmm_ioport_empty_handler(struct ioregh *ioregh)
+{
+	struct ioport_reg_handler *regh;
+	int i;
+
+	regh = ioregh->handlers;
+	for (i = 0; i < IOPORT_MAX_REG_HANDLER; i++) {
+		if (regh[i].handler == NULL) {
+			return &regh[i];
+		}
+	}
+
+	return (NULL);
+}
+
+
+static int
+vmm_ioport_add_handler(struct vm *vm, uint16_t port, uint16_t in, uint32_t mask_data,
+	uint32_t data, ioport_reg_handler_func_t handler, void *handler_arg)
+{
+	struct ioport_reg_handler *regh;
+	struct ioregh *ioregh;
+	int ret = 0;
+
+	ioregh = vm_ioregh(vm);
+
+	sx_xlock(&ioregh->lock);
+
+	regh = vmm_ioport_find_handler(ioregh, port, in, mask_data, data);
+	if (regh != NULL) {
+		printf("%s: handler for port %d in %d mask_data %d data %d \
+				already registered\n",
+				__FUNCTION__, port, in,  mask_data, data);
+		ret = EEXIST;
+		goto err;
+	}
+
+	regh = vmm_ioport_empty_handler(ioregh);
+	if (regh == NULL) {
+		printf("%s: empty reg_handler slot not found\n", __FUNCTION__);
+		ret = ENOMEM;
+		goto err;
+	}
+
+	regh->port = port;
+	regh->in = in;
+	regh->mask_data = mask_data;
+	regh->data = data;
+	regh->handler = handler;
+	regh->handler_arg = handler_arg;
+
+err:
+	sx_xunlock(&ioregh->lock);
+	return (ret);
+}
+
+static int
+vmm_ioport_del_handler(struct vm *vm, uint16_t port, uint16_t in,
+	uint32_t mask_data, uint32_t data)
+{
+	struct ioport_reg_handler *regh;
+	struct ioregh *ioregh;
+	int ret = 0;
+
+	ioregh = vm_ioregh(vm);
+
+	sx_xlock(&ioregh->lock);
+
+	regh = vmm_ioport_find_handler(ioregh, port, in, mask_data, data);
+
+	if (regh == NULL) {
+		ret = EINVAL;
+		goto err;
+	}
+
+	bzero(regh, sizeof(struct ioport_reg_handler));
+err:
+	sx_xunlock(&ioregh->lock);
+	return (ret);
+}
+
+/*
+ * register or delete a new I/O event handler.
+ */
+int
+vmm_ioport_reg_handler(struct vm *vm, uint16_t port, uint16_t in,
+	uint32_t mask_data, uint32_t data, enum vm_io_regh_type type, void *arg)
+{
+	int ret = 0;
+
+	switch (type) {
+	case VM_IO_REGH_DELETE:
+		ret = vmm_ioport_del_handler(vm, port, in, mask_data, data);
+		break;
+	case VM_IO_REGH_KWEVENTS:
+		ret = vmm_ioport_add_handler(vm, port, in, mask_data, data,
+				vmm_ioport_reg_wakeup, arg);
+		break;
+	default:
+		printf("%s: unknown reg_handler type\n", __FUNCTION__);
+		ret = EINVAL;
+		break;
+	}
+
+	return (ret);
+}
+
+/*
+ * Invoke an handler, if the data matches.
+ */
+static int
+invoke_reg_handler(struct vm *vm, int vcpuid, struct vm_exit *vmexit,
+		   uint32_t *val, int *error)
+{
+	struct ioport_reg_handler *regh;
+	struct ioregh *ioregh;
+	uint32_t mask_data;
+
+	mask_data = vie_size2mask(vmexit->u.inout.bytes);
+	ioregh = vm_ioregh(vm);
+
+	sx_slock(&ioregh->lock);
+	regh = vmm_ioport_find_handler(ioregh, vmexit->u.inout.port,
+			vmexit->u.inout.in, mask_data, vmexit->u.inout.eax);
+	if (regh != NULL) {
+		*error = (*(regh->handler))(vm, regh, val);
+	}
+	sx_sunlock(&ioregh->lock);
+	return (regh != NULL);
+}
+
+struct ioregh *
+ioregh_init(struct vm *vm)
+{
+	struct ioregh *ioregh;
+
+	ioregh = malloc(sizeof(struct ioregh), M_IOREGH, M_WAITOK | M_ZERO);
+	sx_init(&ioregh->lock, "ioregh lock");
+
+	return (ioregh);
+}
+
+void
+ioregh_cleanup(struct ioregh *ioregh)
+{
+	sx_destroy(&ioregh->lock);
+	free(ioregh, M_IOREGH);
+}
+#else /* !VMM_IOPORT_REG_HANDLER */
+#define invoke_reg_handler(_1, _2, _3, _4, _5) (0)
+#endif /* VMM_IOPORT_REG_HANDLER */
+
 static int
 emulate_inout_port(struct vm *vm, int vcpuid, struct vm_exit *vmexit,
     bool *retu)
 {
 	ioport_handler_func_t handler;
 	uint32_t mask, val;
-	int error;
+	int regh = 0, error = 0;
 
 	/*
 	 * If there is no handler for the I/O port then punt to userspace.
 	 */
-	if (vmexit->u.inout.port >= MAX_IOPORTS ||
-	    (handler = ioport_handler[vmexit->u.inout.port]) == NULL) {
+	if ((vmexit->u.inout.port >= MAX_IOPORTS ||
+	    (handler = ioport_handler[vmexit->u.inout.port]) == NULL) &&
+	    (regh = invoke_reg_handler(vm, vcpuid, vmexit, &val, &error)) == 0) {
 		*retu = true;
 		return (0);
 	}
 
-	mask = vie_size2mask(vmexit->u.inout.bytes);
+	if (!regh) {
+		mask = vie_size2mask(vmexit->u.inout.bytes);
+
+		if (!vmexit->u.inout.in) {
+			val = vmexit->u.inout.eax & mask;
+		}
 
-	if (!vmexit->u.inout.in) {
-		val = vmexit->u.inout.eax & mask;
+		error = (*handler)(vm, vcpuid, vmexit->u.inout.in,
+			vmexit->u.inout.port, vmexit->u.inout.bytes, &val);
 	}
 
-	error = (*handler)(vm, vcpuid, vmexit->u.inout.in,
-	    vmexit->u.inout.port, vmexit->u.inout.bytes, &val);
 	if (error) {
 		/*
 		 * The value returned by this function is also the return value

Modified: soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_ioport.h
==============================================================================
--- soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_ioport.h	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_ioport.h	Sat Aug 20 20:22:20 2016	(r308107)
@@ -29,6 +29,22 @@
 #ifndef	_VMM_IOPORT_H_
 #define	_VMM_IOPORT_H_
 
+#define VMM_IOPORT_REG_HANDLER
+#ifdef VMM_IOPORT_REG_HANDLER
+struct ioport_reg_handler;
+struct ioregh;
+
+struct ioregh *ioregh_init(struct vm *vm);
+void ioregh_cleanup(struct ioregh *ioregh);
+
+int vmm_ioport_reg_handler(struct vm *vm, uint16_t port, uint16_t in,
+	uint32_t mask_data, uint32_t data, enum vm_io_regh_type type, void *arg);
+#else /* !VMM_IOPORT_REG_HANDLER */
+#define ioregh_init(_1)	(NULL)
+#define ioregh_cleanup(_1)
+#define vmm_ioport_reg_handler(_1, _2, _3, _4,_5, _6, _7) (EINVAL)
+#endif /* VMM_IOPORT_REG_HANDLER */
+
 typedef int (*ioport_handler_func_t)(struct vm *vm, int vcpuid,
     bool in, int port, int bytes, uint32_t *val);
 

Added: soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_usermem.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_usermem.c	Sat Aug 20 20:22:20 2016	(r308107)
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2015 Stefano Garzarella (stefano.garzarella@gmail.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/sglist.h>
+#include <sys/lock.h>
+#include <sys/rwlock.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
+
+#include <machine/md_var.h>
+
+#include "vmm_mem.h"
+#include "vmm_usermem.h"
+
+/*
+ * usermem functions allow us to map an host userspace buffer (eg. from bhyve)
+ * in the guest VM.
+ *
+ * This feature is used to implement ptnetmap on bhyve, mapping the netmap memory
+ * (returned by the mmap() in the byvhe userspace application) in the guest VM.
+ */
+
+/* TODO: we can create a dynamical list of usermem */
+#define MAX_USERMEMS	64
+
+static struct usermem {
+	struct vmspace   *vmspace;	/* guest address space */
+	vm_paddr_t	gpa;		/* guest physical address */
+	size_t		len;
+} usermems[MAX_USERMEMS];
+
+static int
+vmm_usermem_add(struct vmspace *vmspace, vm_paddr_t gpa, size_t len)
+{
+	int i;
+
+	for (i = 0; i < MAX_USERMEMS; i++) {
+		if (usermems[i].len == 0) {
+			usermems[i].vmspace = vmspace;
+			usermems[i].gpa = gpa;
+			usermems[i].len = len;
+			break;
+		}
+	}
+
+	if (i == MAX_USERMEMS) {
+		printf("vmm_usermem_add: empty usermem slot not found\n");
+		return (ENOMEM);
+	}
+
+	return 0;
+}
+
+static int
+vmm_usermem_del(struct vmspace *vmspace, vm_paddr_t gpa, size_t len)
+{
+	int i;
+
+	for (i = 0; i < MAX_USERMEMS; i++) {
+		if (usermems[i].vmspace == vmspace && usermems[i].gpa == gpa
+				&& usermems[i].len == len) {
+			bzero(&usermems[i], sizeof(struct usermem));
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+boolean_t
+usermem_mapped(struct vmspace *vmspace, vm_paddr_t gpa)
+{
+	int i;
+
+	for (i = 0; i < MAX_USERMEMS; i++) {
+		if (usermems[i].vmspace != vmspace || usermems[i].len == 0)
+			continue;
+		if (gpa >= usermems[i].gpa &&
+				gpa < usermems[i].gpa + usermems[i].len)
+			return (TRUE);
+	}
+	return (FALSE);
+}
+
+vm_object_t
+vmm_usermem_alloc(struct vmspace *vmspace, vm_paddr_t gpa, size_t len,
+	       void *buf, struct thread *td)
+{
+	int error;
+	vm_object_t obj;
+	vm_map_t map;
+	vm_map_entry_t entry;
+	vm_pindex_t index;
+	vm_prot_t prot;
+	boolean_t wired;
+
+	map = &td->td_proc->p_vmspace->vm_map;
+	/* lookup the vm_object that describe user addr */
+	error = vm_map_lookup(&map, (unsigned long)buf, VM_PROT_RW, &entry,
+		&obj, &index, &prot, &wired);
+
+	/* map th vm_object in the vmspace */
+	if (obj != NULL) {
+		error = vm_map_find(&vmspace->vm_map, obj, index, &gpa, len, 0,
+				    VMFS_NO_SPACE, VM_PROT_RW, VM_PROT_RW, 0);
+		if (error != KERN_SUCCESS) {
+			vm_object_deallocate(obj);
+			obj = NULL;
+		}
+	}
+	vm_map_lookup_done(map, entry);
+
+	/* acquire the reference to the vm_object */
+	if (obj != NULL) {
+		vm_object_reference(obj);
+		vmm_usermem_add(vmspace, gpa, len);
+	}
+
+	return (obj);
+}
+
+void
+vmm_usermem_free(struct vmspace *vmspace, vm_paddr_t gpa, size_t len)
+{
+	int ret;
+
+	ret  = vmm_usermem_del(vmspace, gpa, len);
+	if (ret) {
+		//TODO check return value of vm_map_remove ?
+		vm_map_remove(&vmspace->vm_map, gpa, gpa + len);
+		//TODO should we call vm_object_deallocate ?
+	}
+}
+
+void
+vmm_usermem_cleanup(struct vmspace *vmspace)
+{
+	int i;
+
+	for (i = 0; i < MAX_USERMEMS; i++) {
+		if (usermems[i].vmspace == vmspace) {
+			//TODO same as above
+			vm_map_remove(&vmspace->vm_map, usermems[i].gpa,
+				      usermems[i].gpa + usermems[i].len);
+			bzero(&usermems[i], sizeof(struct usermem));
+		}
+	}
+}

Added: soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_usermem.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2016/vincenzo/current/head/sys/amd64/vmm/vmm_usermem.h	Sat Aug 20 20:22:20 2016	(r308107)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 Stefano Garzarella (stefano.garzarella@gmail.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef	_VMM_USERMEM_H_
+#define	_VMM_USERMEM_H_
+
+struct vm;
+
+struct vm_object *vmm_usermem_alloc(struct vmspace *, vm_paddr_t gpa,
+				 size_t len, void *buf, struct thread *td);
+void		vmm_usermem_free(struct vmspace *, vm_paddr_t gpa, size_t len);
+void		vmm_usermem_cleanup(struct vmspace *);
+boolean_t	usermem_mapped(struct vmspace *, vm_paddr_t gpa);
+
+#endif

Modified: soc2016/vincenzo/current/head/sys/conf/files
==============================================================================
--- soc2016/vincenzo/current/head/sys/conf/files	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/sys/conf/files	Sat Aug 20 20:22:20 2016	(r308107)
@@ -2166,6 +2166,7 @@
 dev/ncr/ncr.c			optional ncr pci
 dev/ncv/ncr53c500.c		optional ncv
 dev/ncv/ncr53c500_pccard.c	optional ncv pccard
+dev/netmap/if_ptnet.c		optional netmap
 dev/netmap/netmap.c		optional netmap
 dev/netmap/netmap_freebsd.c	optional netmap
 dev/netmap/netmap_generic.c	optional netmap
@@ -2175,6 +2176,7 @@
 dev/netmap/netmap_offloadings.c	optional netmap
 dev/netmap/netmap_pipe.c	optional netmap
 dev/netmap/netmap_vale.c	optional netmap
+dev/netmap/ptnetmap.c		optional netmap
 # compile-with "${NORMAL_C} -Wconversion -Wextra"
 dev/nfsmb/nfsmb.c		optional nfsmb pci
 dev/nge/if_nge.c		optional nge

Modified: soc2016/vincenzo/current/head/sys/dev/netmap/if_ixl_netmap.h
==============================================================================
--- soc2016/vincenzo/current/head/sys/dev/netmap/if_ixl_netmap.h	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/sys/dev/netmap/if_ixl_netmap.h	Sat Aug 20 20:22:20 2016	(r308107)
@@ -59,7 +59,7 @@
 /*
  * device-specific sysctl variables:
  *
- * ixl_crcstrip: 0: keep CRC in rx frames (default), 1: strip it.
+ * ixl_crcstrip: 0: NIC keeps CRC in rx frames (default), 1: NIC strips it.
  *	During regular operations the CRC is stripped, but on some
  *	hardware reception of frames not multiple of 64 is slower,
  *	so using crcstrip=0 helps in benchmarks.
@@ -74,7 +74,7 @@
 int ixl_rx_miss, ixl_rx_miss_bufs, ixl_crcstrip = 1;
 #if 0
 SYSCTL_INT(_dev_netmap, OID_AUTO, ixl_crcstrip,
-    CTLFLAG_RW, &ixl_crcstrip, 1, "strip CRC on rx frames");
+    CTLFLAG_RW, &ixl_crcstrip, 1, "NIC strips CRC on rx frames");
 #endif
 SYSCTL_INT(_dev_netmap, OID_AUTO, ixl_rx_miss,
     CTLFLAG_RW, &ixl_rx_miss, 0, "potentially missed rx intr");

Modified: soc2016/vincenzo/current/head/sys/dev/netmap/if_lem_netmap.h
==============================================================================
--- soc2016/vincenzo/current/head/sys/dev/netmap/if_lem_netmap.h	Sat Aug 20 19:48:03 2016	(r308106)
+++ soc2016/vincenzo/current/head/sys/dev/netmap/if_lem_netmap.h	Sat Aug 20 20:22:20 2016	(r308107)
@@ -38,6 +38,10 @@
 #include <vm/vm.h>
 #include <vm/pmap.h>    /* vtophys ? */
 #include <dev/netmap/netmap_kern.h>
+#ifdef WITH_PTNETMAP_GUEST
+#include <dev/netmap/netmap_mem2.h>
+#endif
+#include <net/netmap_virt.h>
 
 extern int netmap_adaptive_io;
 
@@ -80,6 +84,20 @@
 	return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1);
 }
 
+static void
+lem_netmap_intr(struct netmap_adapter *na, int onoff)
+{
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+
+	EM_CORE_LOCK(adapter);
+	if (onoff) {
+		lem_enable_intr(adapter);
+	} else {
+		lem_disable_intr(adapter);
+	}
+	EM_CORE_UNLOCK(adapter);
+}
 
 /*
  * Reconcile kernel and user view of the transmit ring.
@@ -470,6 +488,176 @@
 	return netmap_ring_reinit(kring);
 }
 
+#if defined (NIC_PTNETMAP) && defined (WITH_PTNETMAP_GUEST)
+/*
+ * ptnetmap support for: lem (FreeBSD version)
+ *
+ * For details on ptnetmap support please see if_vtnet_netmap.h
+ */
+static uint32_t lem_ptnetmap_ptctl(struct ifnet *, uint32_t);
+
+/* Returns device configuration from the CSB */
+static int
+lem_ptnetmap_config(struct netmap_adapter *na,
+		u_int *txr, u_int *txd, u_int *rxr, u_int *rxd)
+{
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+	struct paravirt_csb *csb = adapter->csb;
+	int ret;
+
+	if (csb == NULL)
+		return EINVAL;
+
+	ret = lem_ptnetmap_ptctl(ifp, PTNETMAP_PTCTL_CONFIG);
+	if (ret)
+		return ret;
+
+	*txr = 1; //*txr = csb->num_tx_rings;
+	*rxr = 1; //*rxr = csb->num_rx_rings;
+	*txd = csb->num_tx_slots;
+	*rxd = csb->num_rx_slots;
+
+	D("txr %u rxr %u txd %u rxd %u",
+			*txr, *rxr, *txd, *rxd);
+
+	return 0;
+}
+
+/* Reconcile host and guest view of the transmit ring. */
+static int
+lem_ptnetmap_txsync(struct netmap_kring *kring, int flags)
+{
+	struct netmap_adapter *na = kring->na;
+	//u_int ring_nr = kring->ring_id;
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+	bool notify;
+
+	notify = netmap_pt_guest_txsync(&adapter->csb->tx_ring, kring, flags);
+	if (notify)
+		E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0);
+
+	return 0;
+}
+
+/* Reconcile host and guest view of the receive ring. */
+static int
+lem_ptnetmap_rxsync(struct netmap_kring *kring, int flags)
+{
+	struct netmap_adapter *na = kring->na;
+	//u_int ring_nr = kring->ring_id;
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+	bool notify;
+
+	notify = netmap_pt_guest_rxsync(&adapter->csb->rx_ring, kring, flags);
+	if (notify)
+		E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), 0);
+
+	return 0;
+}
+
+/* Register/unregister. We are already under netmap lock. */
+static int
+lem_ptnetmap_reg(struct netmap_adapter *na, int onoff)
+{
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+	struct paravirt_csb *csb = adapter->csb;
+	struct netmap_kring *kring;
+	int ret;
+
+	if (onoff) {
+		ret = lem_ptnetmap_ptctl(ifp, PTNETMAP_PTCTL_REGIF);
+		if (ret)
+			return ret;
+
+		na->na_flags |= NAF_NETMAP_ON;
+		adapter->ptnetmap_enabled = 1;
+		/*
+		 * Init ring and kring pointers
+		 * After PARAVIRT_PTCTL_REGIF, the csb contains a snapshot of a
+		 * host kring pointers.
+		 * XXX This initialization is required, because we don't close
+		 * the host port on UNREGIF.
+		 */
+
+		// Init rx ring
+		kring = na->rx_rings;
+		kring->rhead = kring->ring->head = csb->rx_ring.head;
+		kring->rcur = kring->ring->cur = csb->rx_ring.cur;
+		kring->nr_hwcur = csb->rx_ring.hwcur;
+		kring->nr_hwtail = kring->rtail = kring->ring->tail =
+			csb->rx_ring.hwtail;
+
+		// Init tx ring
+		kring = na->tx_rings;
+		kring->rhead = kring->ring->head = csb->tx_ring.head;
+		kring->rcur = kring->ring->cur = csb->tx_ring.cur;
+		kring->nr_hwcur = csb->tx_ring.hwcur;
+		kring->nr_hwtail = kring->rtail = kring->ring->tail =
+			csb->tx_ring.hwtail;
+	} else {
+		na->na_flags &= ~NAF_NETMAP_ON;
+		adapter->ptnetmap_enabled = 0;
+		ret = lem_ptnetmap_ptctl(ifp, PTNETMAP_PTCTL_UNREGIF);
+	}
+
+	return lem_netmap_reg(na, onoff);
+}
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608202022.u7KKMLHU067000>