Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Jul 2015 13:49:43 GMT
From:      stefano@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r288612 - soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve
Message-ID:  <201507211349.t6LDnhDl014426@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: stefano
Date: Tue Jul 21 13:49:42 2015
New Revision: 288612
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=288612

Log:
  add ptnetmap backend and ptnetmap_memdev

Added:
  soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_ptnetmap_memdev.c
  soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_virtio_ptnetmap.h
  soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/ptnetmap.h
Modified:
  soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/Makefile
  soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/net_backends.c
  soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/net_backends.h
  soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_virtio_net.c

Modified: soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/Makefile
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/Makefile	Tue Jul 21 13:42:23 2015	(r288611)
+++ soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/Makefile	Tue Jul 21 13:49:42 2015	(r288612)
@@ -27,6 +27,7 @@
 	pci_irq.c		\
 	pci_lpc.c		\
 	pci_passthru.c		\
+	pci_ptnetmap_memdev.c	\
 	pci_virtio_block.c	\
 	pci_virtio_net.c	\
 	pci_virtio_rnd.c	\

Modified: soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/net_backends.c
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/net_backends.c	Tue Jul 21 13:42:23 2015	(r288611)
+++ soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/net_backends.c	Tue Jul 21 13:49:42 2015	(r288612)
@@ -109,6 +109,8 @@
 	 */
 	uint64_t (*set_features)(struct net_backend *be, uint64_t features);
 
+	struct ptnetmap_state * (*get_ptnetmap)(struct net_backend *be);
+
 	struct pci_vtnet_softc *sc;
 	int fd;
 	void *priv;	/* Pointer to backend-specific data. */
@@ -164,6 +166,12 @@
 	return -1; /* never called, i believe */
 }
 
+static struct ptnetmap_state *
+netbe_null_get_ptnetmap(struct net_backend *be)
+{
+	return NULL;
+}
+
 static struct net_backend null_backend = {
 	.name = "null",
 	.init = netbe_null_init,
@@ -172,6 +180,7 @@
 	.recv = netbe_null_recv,
 	.get_features = netbe_null_get_features,
 	.set_features = netbe_null_set_features,
+	.get_ptnetmap = netbe_null_get_ptnetmap,
 };
 
 DATA_SET(net_backend_set, null_backend);
@@ -697,6 +706,265 @@
 
 
 /*
+ * The ptnetmap backend
+ */
+#include <stddef.h>
+#include "net/netmap.h"
+#include "dev/netmap/netmap_virt.h"
+#include "ptnetmap.h"
+
+struct ptnbe_priv {
+	struct netmap_priv up;
+	struct ptnetmap_state ptns;
+	int created;			/* ptnetmap kthreads created */
+	unsigned long features;		/* ptnetmap features */
+	unsigned long acked_features;	/* ptnetmap acked features */
+};
+
+
+
+/* The virtio-net features supported by ptnetmap. */
+#define VIRTIO_NET_F_PTNETMAP  0x2000000 /* ptnetmap available */
+
+#define PTNETMAP_FEATURES VIRTIO_NET_F_PTNETMAP
+
+static uint64_t
+ptnbe_get_features(struct net_backend *be)
+{
+	return PTNETMAP_FEATURES;
+}
+
+static uint64_t
+ptnbe_set_features(struct net_backend *be, uint64_t features)
+{
+	if (features & PTNETMAP_FEATURES) {
+		WPRINTF(("ptnbe_set_features\n"));
+	}
+
+	return 0;
+}
+
+#define PTNETMAP_NAME_HDR	2
+
+static void ptnbe_init_ptnetmap(struct net_backend *be);
+
+static int
+ptnbe_init(struct net_backend *be, const char *devname,
+			net_backend_cb_t cb, void *param)
+{
+	const char *ndname = "/dev/netmap";
+	struct ptnbe_priv *priv = NULL;
+	struct netmap_priv *npriv;
+	struct nmreq req;
+	char tname[40];
+
+	priv = calloc(1, sizeof(struct ptnbe_priv));
+	if (priv == NULL) {
+		WPRINTF(("Unable alloc netmap private data\n"));
+		return -1;
+	}
+	WPRINTF(("ptnbe_init(): devname '%s'\n", devname));
+
+	npriv = &priv->up;
+	strncpy(npriv->ifname, devname + PTNETMAP_NAME_HDR, sizeof(npriv->ifname));
+	npriv->ifname[sizeof(npriv->ifname) - 1] = '\0';
+
+	memset(&req, 0, sizeof(req));
+	req.nr_flags |= NR_PASSTHROUGH_HOST;
+
+	npriv->nmd = nm_open(npriv->ifname, &req, NETMAP_NO_TX_POLL, NULL);
+	if (npriv->nmd == NULL) {
+		WPRINTF(("Unable to nm_open(): device '%s', "
+				"interface '%s', errno (%s)\n",
+				ndname, devname, strerror(errno)));
+		goto err_open;
+	}
+#if 0
+	/* check parent (nm_desc with the same allocator already mapped) */
+	parent_nmd = netmap_find_parent(nmd);
+	/* mmap or inherit from parent */
+	if (nm_mmap(nmd, parent_nmd)) {
+	        error_report("failed to mmap %s: %s", netmap_opts->ifname, strerror(errno));
+	        nm_close(nmd);
+	        return -1;
+	}
+#endif
+
+
+	npriv->tx = NETMAP_TXRING(npriv->nmd->nifp, 0);
+	npriv->rx = NETMAP_RXRING(npriv->nmd->nifp, 0);
+
+	npriv->cb = cb;
+	npriv->cb_param = param;
+
+	be->fd = npriv->nmd->fd;
+	be->priv = priv;
+
+	ptnbe_init_ptnetmap(be);
+
+	return 0;
+
+err_open:
+	free(priv);
+
+	return -1;
+}
+
+static void
+ptnbe_cleanup(struct net_backend *be)
+{
+	struct ptnbe_priv *priv = be->priv;
+
+	if (priv) {
+		nm_close(priv->up.nmd);
+	}
+	be->fd = -1;
+}
+
+struct ptnetmap_state *
+ptnbe_get_ptnetmap(struct net_backend *be)
+{
+	struct ptnbe_priv *priv = be->priv;
+
+	return &priv->ptns;
+}
+
+static void
+ptnbe_init_ptnetmap(struct net_backend *be)
+{
+	struct ptnbe_priv *priv = be->priv;
+
+	ptn_memdev_attach(priv->up.nmd->mem, priv->up.nmd->memsize, priv->up.nmd->req.nr_arg2);
+
+	priv->ptns.ptn_be = be;
+	priv->created = 0;
+	priv->features = NET_PTN_FEATURES_BASE;
+	priv->acked_features = 0;
+}
+
+/* return the subset of requested features that we support */
+uint32_t
+ptnetmap_get_features(struct ptnetmap_state *ptns, uint32_t features)
+{
+	struct ptnbe_priv *priv = ptns->ptn_be->priv;
+
+	return priv->features & features;
+}
+
+/* store the agreed upon features */
+void
+ptnetmap_ack_features(struct ptnetmap_state *ptns, uint32_t features)
+{
+	struct ptnbe_priv *priv = ptns->ptn_be->priv;
+
+	priv->acked_features |= features;
+}
+
+int
+ptnetmap_get_mem(struct ptnetmap_state *ptns)
+{
+	struct netmap_priv *npriv = ptns->ptn_be->priv;
+
+	if (npriv->nmd == NULL)
+		return EINVAL;
+
+	ptns->offset = npriv->nmd->req.nr_offset;
+	ptns->num_tx_rings = npriv->nmd->req.nr_tx_rings;
+	ptns->num_rx_rings = npriv->nmd->req.nr_rx_rings;
+	ptns->num_tx_slots = npriv->nmd->req.nr_tx_slots;
+	ptns->num_rx_slots = npriv->nmd->req.nr_rx_slots;
+
+	return 0;
+}
+
+int
+ptnetmap_get_hostmemid(struct ptnetmap_state *ptns)
+{
+	struct netmap_priv *npriv = ptns->ptn_be->priv;
+
+	if (npriv->nmd == NULL)
+		return EINVAL;
+
+	return npriv->nmd->req.nr_arg2;
+}
+
+int
+ptnetmap_create(struct ptnetmap_state *ptns, struct ptnetmap_cfg *conf)
+{
+	struct ptnbe_priv *priv = ptns->ptn_be->priv;
+	struct nmreq req;
+	int err;
+
+	if (!(priv->acked_features & NET_PTN_FEATURES_BASE)) {
+		printf("ptnetmap features not acked\n");
+		return EFAULT;
+	}
+
+	if (priv->created)
+		return 0;
+
+	/* TODO: ioctl to start kthreads */
+#if 1
+	memset(&req, 0, sizeof(req));
+	strncpy(req.nr_name, priv->up.ifname, sizeof(req.nr_name));
+	req.nr_version = NETMAP_API;
+	ptnetmap_write_cfg(&req, conf);
+	req.nr_cmd = NETMAP_PT_HOST_CREATE;
+	err = ioctl(priv->up.nmd->fd, NIOCREGIF, &req);
+	if (err) {
+		printf("Unable to execute NETMAP_PT_HOST_CREATE on %s: %s\n",
+				priv->up.ifname, strerror(errno));
+	} else
+		priv->created = 1;
+#endif
+
+
+ 	return err;
+}
+
+int
+ptnetmap_delete(struct ptnetmap_state *ptns)
+{
+	struct ptnbe_priv *priv = ptns->ptn_be->priv;
+	struct nmreq req;
+	int err;
+
+	if (!(priv->acked_features & NET_PTN_FEATURES_BASE)) {
+		printf("ptnetmap features not acked\n");
+		return EFAULT;
+	}
+
+	if (!priv->created)
+		return 0;
+
+	/* TODO: ioctl to stop kthreads */
+	memset(&req, 0, sizeof(req));
+	strncpy(req.nr_name, priv->up.ifname, sizeof(req.nr_name));
+	req.nr_version = NETMAP_API;
+	req.nr_cmd = NETMAP_PT_HOST_DELETE;
+	err = ioctl(priv->up.nmd->fd, NIOCREGIF, &req);
+	if (err) {
+		printf("Unable to execute NETMAP_PT_HOST_DELETE on %s: %s\n",
+				priv->up.ifname, strerror(errno));
+	}
+	priv->created = 0;
+
+	return 0;
+}
+
+static struct net_backend ptnbe_backend = {
+	.name = "ptnetmap|ptvale",
+	.init = ptnbe_init,
+	.cleanup = ptnbe_cleanup,
+	.get_features = ptnbe_get_features,
+	.set_features = ptnbe_set_features,
+	.get_ptnetmap = ptnbe_get_ptnetmap,
+};
+
+DATA_SET(net_backend_set, ptnbe_backend);
+
+
+/*
  * make sure a backend is properly initialized
  */
 static void
@@ -734,6 +1002,11 @@
 			be, be->name);
 		be->set_features = netbe_null_set_features;
 	}
+	if (be->get_ptnetmap == NULL) {
+		/*fprintf(stderr, "missing set_features for %p %s\n",
+			be, be->name);*/
+		be->get_ptnetmap = netbe_null_get_ptnetmap;
+	}
 }
 
 /*
@@ -848,3 +1121,11 @@
 		return -1;
 	return be->recv(be, iov, iovcnt, more);
 }
+
+struct ptnetmap_state *
+netbe_get_ptnetmap(struct net_backend *be)
+{
+	if (be == NULL)
+		return NULL;
+	return be->get_ptnetmap(be);
+}

Modified: soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/net_backends.h
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/net_backends.h	Tue Jul 21 13:42:23 2015	(r288611)
+++ soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/net_backends.h	Tue Jul 21 13:49:42 2015	(r288612)
@@ -33,6 +33,8 @@
 
 typedef void (*net_backend_cb_t)(int, enum ev_type, void *param);
 
+struct ptnetmap_state;
+
 /* Interface between virtio-net and the network backend. */
 struct net_backend;
 
@@ -45,5 +47,6 @@
                         int iovcnt, int len, int more);
 int	netbe_recv(struct net_backend *be, struct iovec *iov,
 		    int iovcnt, int *more);
+struct ptnetmap_state *netbe_get_ptnetmap(struct net_backend *be);
 
 #endif /* __NET_BACKENDS_H__ */

Added: soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_ptnetmap_memdev.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_ptnetmap_memdev.c	Tue Jul 21 13:49:42 2015	(r288612)
@@ -0,0 +1,324 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+//#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+//#include <string.h>
+//#include <strings.h>
+//#include <unistd.h>
+//#include <assert.h>
+
+#include <machine/vmm.h>
+#include <vmmapi.h>
+#include "bhyverun.h"
+#include "pci_emul.h"
+#include "ptnetmap.h"
+
+
+/* ptnetmap memdev PCI-ID and PCI-BARS XXX-ste: remove*/
+#define PTN_MEMDEV_NAME                 "ptnetmap-memdev"
+#define PTNETMAP_PCI_VENDOR_ID          0x3333  /* XXX-ste: set vendor_id */
+#define PTNETMAP_PCI_DEVICE_ID          0x0001
+#define PTNETMAP_IO_PCI_BAR             0
+#define PTNETMAP_MEM_PCI_BAR            1
+
+/* ptnetmap memdev register */
+/* 32 bit r/o */
+#define PTNETMAP_IO_PCI_FEATURES        0
+/* 32 bit r/o */
+#define PTNETMAP_IO_PCI_MEMSIZE         4
+/* 16 bit r/o */
+#define PTNETMAP_IO_PCI_HOSTID          8
+#define PTNEMTAP_IO_SIZE                10
+
+struct ptn_memdev_softc {
+	struct pci_devinst *pi;		/* PCI device instance */
+
+	void *mem_ptr;			/* netmap shared memory */
+	uint64_t mem_size;		/* netmap shared memory size */
+	uint16_t mem_id;		/* netmap memory allocator ID */
+
+	TAILQ_ENTRY(ptn_memdev_softc) next;
+};
+static TAILQ_HEAD(, ptn_memdev_softc) ptn_memdevs = TAILQ_HEAD_INITIALIZER(ptn_memdevs);
+
+/*
+ * find ptn_memdev through mem_id
+ */
+static struct ptn_memdev_softc *
+ptn_memdev_find_memid(uint16_t mem_id)
+{
+	struct ptn_memdev_softc *sc;
+
+	TAILQ_FOREACH(sc, &ptn_memdevs, next) {
+		if (sc->mem_ptr != NULL && mem_id == sc->mem_id) {
+			return sc;
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * find ptn_memdev that has not memory
+ */
+static struct ptn_memdev_softc *
+ptn_memdev_find_empty_mem()
+{
+	struct ptn_memdev_softc *sc;
+
+	TAILQ_FOREACH(sc, &ptn_memdevs, next) {
+		if (sc->mem_ptr == NULL) {
+			return sc;
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * find ptn_memdev that has not PCI device istance
+ */
+static struct ptn_memdev_softc *
+ptn_memdev_find_empty_pi()
+{
+	struct ptn_memdev_softc *sc;
+
+	TAILQ_FOREACH(sc, &ptn_memdevs, next) {
+		if (sc->pi == NULL) {
+			return sc;
+		}
+	}
+
+	return NULL;
+}
+
+static struct ptn_memdev_softc *
+ptn_memdev_create()
+{
+	struct ptn_memdev_softc *sc;
+
+	sc = calloc(1, sizeof(struct ptn_memdev_softc));
+
+	if (sc != NULL) {
+		TAILQ_INSERT_TAIL(&ptn_memdevs, sc, next);
+	}
+
+	return sc;
+}
+
+static void
+ptn_memdev_delete(struct ptn_memdev_softc *sc)
+{
+	TAILQ_REMOVE(&ptn_memdevs, sc, next);
+
+	free(sc);
+}
+
+static uint64_t
+ptn_pci_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ 		int baridx, uint64_t offset, int size)
+{
+	struct ptn_memdev_softc *sc = pi->pi_arg;
+	uint64_t ret = 0;
+
+	if (sc == NULL)
+		return 0;
+
+	if (baridx == PTNETMAP_MEM_PCI_BAR) {
+		printf("ptnetmap_memdev: MEM read\n");
+		printf("ptnentmap_memdev: mem_read - offset: %lx size: %d ret: %lx\n", offset, size, ret);
+		return 0; /* XXX */
+	}
+
+	/* XXX probably should do something better than just assert() */
+	assert(baridx == PTNETMAP_IO_PCI_BAR);
+
+	switch (offset) {
+	case PTNETMAP_IO_PCI_MEMSIZE:
+		ret = sc->mem_size;
+		break;
+	case PTNETMAP_IO_PCI_HOSTID:
+		ret = sc->mem_id;
+		break;
+	default:
+		printf("ptnentmap_memdev: read io reg unexpected\n");
+		break;
+	}
+
+	printf("ptnentmap_memdev: io_read - offset: %lx size: %d ret: %llu\n", offset, size,(unsigned long long)ret);
+
+	return ret;
+}
+
+static void
+ptn_pci_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+  		int baridx, uint64_t offset, int size, uint64_t value)
+{
+	struct ptn_memdev_softc *sc = pi->pi_arg;
+
+	if (sc == NULL)
+		return;
+
+	if (baridx == PTNETMAP_MEM_PCI_BAR) {
+		printf("ptnetmap_memdev: MEM write\n");
+		return; /* XXX */
+	}
+
+	/* XXX probably should do something better than just assert() */
+	assert(baridx == PTNETMAP_IO_PCI_BAR);
+
+	switch (offset) {
+
+	default:
+		printf("ptnentmap_memdev: write io reg unexpected\n");
+		break;
+	}
+
+
+	printf("ptnentmap_memdev: io_write - offset: %lx size: %d val: %lx\n", offset, size, value);
+}
+
+static int
+ptn_memdev_configure(struct ptn_memdev_softc *sc)
+{
+	int ret;
+
+	printf("ptnetmap_memdev: configuring\n");
+
+	if (sc->pi == NULL || sc->mem_ptr == NULL)
+		return 0;
+
+
+	/* init iobar */
+	ret = pci_emul_alloc_bar(sc->pi, PTNETMAP_IO_PCI_BAR, PCIBAR_IO, PTNEMTAP_IO_SIZE);
+	if (ret) {
+		printf("ptnetmap_memdev: iobar allocation error %d\n", ret);
+		return ret;
+	}
+
+
+	/* init membar */
+	/* XXX MEM64 has MEM_PREFETCH */
+	ret = pci_emul_alloc_bar(sc->pi, PTNETMAP_MEM_PCI_BAR, PCIBAR_MEM32, sc->mem_size);
+	if (ret) {
+		printf("ptnetmap_memdev: membar allocation error %d\n", ret);
+		return ret;
+	}
+
+	printf("ptnetmap_memdev: pci_addr: %llx, mem_size: %llu, mem_ptr: %p\n",
+			(unsigned long long) sc->pi->pi_bar[PTNETMAP_MEM_PCI_BAR].addr,
+			(unsigned long long) sc->mem_size, sc->mem_ptr);
+
+	ret = vm_map_user_buf(sc->pi->pi_vmctx, sc->pi->pi_bar[PTNETMAP_MEM_PCI_BAR].addr,
+			sc->mem_size, sc->mem_ptr);
+	if (ret) {
+		printf("ptnetmap_memdev: membar map error %d\n", ret);
+		return ret;
+	}
+
+	printf("ptnetmap_memdev: configured\n");
+
+	return 0;
+}
+
+static int
+ptn_memdev_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+	struct ptn_memdev_softc *sc;
+	uint64_t size;
+	int ret;
+
+	printf("ptnetmap_memdev: loading\n");
+
+	sc = ptn_memdev_find_empty_pi();
+	if (sc == NULL) {
+		sc = ptn_memdev_create();
+		if (sc == NULL) {
+			printf("ptnetmap_memdev: calloc error\n");
+			return (ENOMEM);
+		}
+	}
+
+	/* link our softc in pi */
+	pi->pi_arg = sc;
+	sc->pi = pi;
+
+	/* initialize config space */
+	pci_set_cfgdata16(pi, PCIR_VENDOR, PTNETMAP_PCI_VENDOR_ID);
+	pci_set_cfgdata16(pi, PCIR_DEVICE, PTNETMAP_PCI_DEVICE_ID);
+	pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK);
+	pci_set_cfgdata16(pi, PCIR_SUBDEV_0, 1); /* XXX-ste remove? */
+	pci_set_cfgdata16(pi, PCIR_SUBVEND_0, PTNETMAP_PCI_VENDOR_ID); /* XXX-ste remove? */
+
+	ret = ptn_memdev_configure(sc);
+	if (ret) {
+		printf("ptnetmap_memdev: configure error\n");
+		goto err;
+	}
+
+	printf("ptnetmap_memdev: loaded\n");
+
+ 	return (0);
+err:
+	ptn_memdev_delete(sc);
+	pi->pi_arg = NULL;
+	return ret;
+}
+
+int
+ptn_memdev_attach(void *mem_ptr, uint32_t mem_size, uint16_t mem_id)
+{
+	struct ptn_memdev_softc *sc;
+	int ret;
+	printf("ptnetmap_memdev: attaching\n");
+
+	/* if a device with the same mem_id is already attached, we are done */
+	if (ptn_memdev_find_memid(mem_id)) {
+		printf("ptnetmap_memdev: already attched\n");
+		return 0;
+	}
+
+	sc = ptn_memdev_find_empty_mem();
+	if (sc == NULL) {
+		sc = ptn_memdev_create();
+		if (sc == NULL) {
+			printf("ptnetmap_memdev: calloc error\n");
+			return (ENOMEM);
+		}
+	}
+
+	sc->mem_ptr = mem_ptr;
+	sc->mem_size = mem_size;
+	sc->mem_id = mem_id;
+
+	printf("ptnetmap_memdev_attach: mem_id: %u, mem_size: %lu, mem_ptr: %p\n", mem_id,
+			(unsigned long) mem_size, mem_ptr);
+
+	/* TODO: configure device BARs */
+	ret = ptn_memdev_configure(sc);
+	if (ret) {
+		printf("ptnetmap_memdev: configure error\n");
+		goto err;
+	}
+
+	printf("ptnetmap_memdev: attached\n");
+
+	return 0;
+err:
+	ptn_memdev_delete(sc);
+	sc->pi->pi_arg = NULL;
+	return ret;
+}
+
+
+struct pci_devemu pci_de_ptnetmap = {
+	.pe_emu = 	PTN_MEMDEV_NAME,
+	.pe_init =	ptn_memdev_init,
+	.pe_barwrite =	ptn_pci_write,
+	.pe_barread =	ptn_pci_read
+};
+PCI_EMUL_SET(pci_de_ptnetmap);

Modified: soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_virtio_net.c
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_virtio_net.c	Tue Jul 21 13:42:23 2015	(r288611)
+++ soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_virtio_net.c	Tue Jul 21 13:49:42 2015	(r288612)
@@ -93,6 +93,7 @@
 struct virtio_net_config {
 	uint8_t  mac[6];
 	uint16_t status;
+	uint16_t max_virtqueue_pairs;
 } __packed;
 
 /*
@@ -124,6 +125,25 @@
 #define DPRINTF(params) if (pci_vtnet_debug) printf params
 #define WPRINTF(params) printf params
 
+
+#define BHYVE_VIRTIO_PTNETMAP
+#ifdef BHYVE_VIRTIO_PTNETMAP
+#include <stddef.h>
+#include <net/if.h>
+#include "net/netmap.h"
+#include "dev/netmap/netmap_virt.h"
+
+struct pci_vtnet_ptnetmap {
+	struct paravirt_csb *csb;	/* Communication Status Block. */
+	uint32_t features;		/* ptnetmap features */
+	int up;				/* ptnetmap up/down */
+	struct ptnetmap_state *state;	/* ptnetmap state (shared with backend) */
+	struct ptnetmap_cfg cfg;	/* ptnetmap configuration */
+
+	/* ptnetmap register */
+	uint8_t reg[PTNEMTAP_VIRTIO_IO_SIZE];
+};
+#endif
 /*
  * Per-device softc
  */
@@ -149,8 +169,15 @@
 	pthread_mutex_t	tx_mtx;
 	pthread_cond_t	tx_cond;
 	int		tx_in_progress;
+#ifdef BHYVE_VIRTIO_PTNETMAP
+	struct pci_vtnet_ptnetmap ptn;
+#endif
 };
 
+#ifdef BHYVE_VIRTIO_PTNETMAP
+#include "pci_virtio_ptnetmap.h"
+#endif
+
 static void pci_vtnet_reset(void *);
 /* static void pci_vtnet_notify(void *, struct vqueue_info *); */
 static int pci_vtnet_cfgread(void *, int, int, uint32_t *);
@@ -555,6 +582,9 @@
 			WPRINTF(("net backend initialization failed\n"));
 		} else {
 			vc->vc_hv_caps |= netbe_get_features(sc->vsc_be);
+#ifdef BHYVE_VIRTIO_PTNETMAP
+			pci_vtnet_ptnetmap_init(sc, vc);
+#endif /* BHYVE_VIRTIO_PTNETMAP */
 		}
 		free(devname);
 	}
@@ -633,6 +663,10 @@
 		 */
 		ptr = &sc->vsc_config.mac[offset];
 		memcpy(ptr, &value, size);
+#ifdef BHYVE_VIRTIO_PTNETMAP
+	} else if (offset >= PTNETMAP_VIRTIO_IO_BASE) {
+		pci_vtnet_ptnetmap_write(sc, offset, size, value);
+#endif
 	} else {
 		/* silently ignore other writes */
 		DPRINTF(("vtnet: write to readonly reg %d\n\r", offset));
@@ -647,6 +681,12 @@
 	struct pci_vtnet_softc *sc = vsc;
 	void *ptr;
 
+#ifdef BHYVE_VIRTIO_PTNETMAP
+	if (offset >= PTNETMAP_VIRTIO_IO_BASE) {
+		pci_vtnet_ptnetmap_read(sc, offset, size, retval);
+		return (0);
+	}
+#endif
 	ptr = (uint8_t *)&sc->vsc_config + offset;
 	memcpy(retval, ptr, size);
 	return (0);

Added: soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_virtio_ptnetmap.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve/pci_virtio_ptnetmap.h	Tue Jul 21 13:49:42 2015	(r288612)
@@ -0,0 +1,255 @@
+#ifndef __PCI_VIRTIO_PTNETMAP_H__
+#define __PCI_VIRTIO_PTNETMAP_H__
+
+/* XXX-ste: move in other file and split in .c .h? */
+#ifdef BHYVE_VIRTIO_PTNETMAP
+
+/* ptnetmap virtio register BASE */
+#define PTNETMAP_VIRTIO_IO_BASE         sizeof(struct virtio_net_config)
+#include "ptnetmap.h"
+
+static void
+ptnetmap_configure_csb(struct vmctx *ctx, struct paravirt_csb** csb, uint32_t csbbal,
+		uint32_t csbbah)
+{
+	uint64_t len = 4096;
+	uint64_t base = ((uint64_t)csbbah << 32) | csbbal;
+
+	/*
+	 * We require that writes to the CSB address registers
+	 * are in the order CSBBAH , CSBBAL so on the second one
+	 * we have a valid 64-bit memory address.
+	 * Any previous region is unmapped, and handlers terminated.
+	 * The CSB is then remapped if the new pointer is != 0
+	 */
+	if (*csb) {
+		/* TODO: unmap */
+		*csb = NULL;
+	}
+	if (base) {
+		*csb = paddr_guest2host(ctx, base, len);
+	}
+
+}
+
+static void
+pci_vtnet_ptnetmap_init(struct pci_vtnet_softc *sc, struct virtio_consts *vc)
+{
+	sc->ptn.up = 0;
+
+	sc->ptn.state = netbe_get_ptnetmap(sc->vsc_be);
+	if (sc->ptn.state == NULL) {
+		printf("ptnetmap not supported by backend\n");
+		sc->ptn.features = 0;
+		return;
+	}
+
+	sc->ptn.features = ptnetmap_get_features(sc->ptn.state, NET_PTN_FEATURES_BASE);
+
+	/* backend require ptnetmap support? */
+	if (!(sc->ptn.features & NET_PTN_FEATURES_BASE)) {
+		printf("ptnetmap not supported/required\n");
+		sc->ptn.state = NULL;
+		sc->ptn.features = 0;
+		return;
+	}
+
+	/* extend cfgsize. virtio creates PCIBAR for us */
+	vc->vc_cfgsize += PTNEMTAP_VIRTIO_IO_SIZE;
+
+	printf("ptnetmap-virtio init END\n");
+}
+
+static int
+pci_vtnet_ptnetmap_get_mem(struct pci_vtnet_softc *sc)
+{
+	struct ptnetmap_state *ptns = sc->ptn.state;
+	struct paravirt_csb *csb = sc->ptn.csb;
+	int ret;
+
+	ret = ptnetmap_get_mem(ptns);
+	if (ret)
+	 	return ret;
+
+	if (csb == NULL) {
+	 	printf("ERROR ptnetmap: csb not initialized\n");
+	 	return ret;
+	}
+	csb->nifp_offset = ptns->offset;
+	csb->num_tx_rings = ptns->num_tx_rings;
+	csb->num_rx_rings = ptns->num_rx_rings;
+	csb->num_tx_slots = ptns->num_tx_slots;
+	csb->num_rx_slots = ptns->num_rx_slots;
+	printf("txr %u rxr %u txd %u rxd %u nifp_offset %u\n",
+	 	        csb->num_tx_rings,
+	 	        csb->num_rx_rings,
+	 	        csb->num_tx_slots,
+	 	        csb->num_rx_slots,
+	 	        csb->nifp_offset);
+
+	return ret;
+}
+
+static int
+pci_vtnet_ptnetmap_up(struct pci_vtnet_softc *sc)
+{
+	struct ptnetmap_state *ptns = sc->ptn.state;
+	struct paravirt_csb *csb = sc->ptn.csb;
+	int ret;
+
+	if (sc->ptn.up) {
+		printf("ERROR ptnetmap: already UP\n");
+		return -1;
+	}
+
+	if (csb == NULL) {
+		printf("ERROR ptnetmap: CSB undefined\n");
+		return -1;
+	}
+
+	/* TODO-ste: add support for multiqueue */
+
+	/* TODO: Stop processing guest/host IO notifications in qemu.
+	 * Start processing them in ptnetmap.
+	 */
+
+
+	/* Configure the RX ring */
+	sc->ptn.cfg.rx_ring.ioeventfd = -1;
+	sc->ptn.cfg.rx_ring.irqfd = -1;
+
+	/* Configure the TX ring */
+	sc->ptn.cfg.tx_ring.ioeventfd = -1;
+	sc->ptn.cfg.tx_ring.irqfd = -1;
+
+	/* TODO: push fake-elem in the tx/rx queue to enable interrupts */
+
+	/* Initialize CSB */
+	sc->ptn.cfg.csb = sc->ptn.csb;
+	sc->ptn.csb->host_need_txkick = 1;
+	sc->ptn.csb->guest_need_txkick = 0;
+	sc->ptn.csb->guest_need_rxkick = 1;
+	sc->ptn.csb->host_need_rxkick = 1;
+
+	sc->ptn.cfg.features = PTNETMAP_CFG_FEAT_CSB | PTNETMAP_CFG_FEAT_EVENTFD;
+
+	/* Configure the net backend. */
+	ret = ptnetmap_create(sc->ptn.state, &sc->ptn.cfg);
+	if (ret)
+		goto err_ptn_create;
+
+	sc->ptn.up = 1;
+
+	return (0);
+
+err_ptn_create:
+	return (ret);
+}
+
+static int
+pci_vtnet_ptnetmap_down(struct pci_vtnet_softc *sc)
+{
+	int ret;
+
+	if (!sc->ptn.state || !sc->ptn.up) {
+		return (0);
+	}
+
+	sc->ptn.up = 0;
+	/*
+	 * TODO: Start processing guest/host IO notifications in qemu.
+	 */
+
+	return (ptnetmap_delete(sc->ptn.state));
+}
+
+static int
+pci_vtnet_ptnetmap_write(struct pci_vtnet_softc *sc, int offset, int size, uint32_t value)
+{
+	uint32_t *val, ret;
+
+	if (sc->ptn.state == NULL) {
+		printf("ERROR ptnetmap: not supported by backend\n");
+		return -1;
+	}
+
+	offset -= PTNETMAP_VIRTIO_IO_BASE;
+	memcpy(&sc->ptn.reg[offset], &value, size);
+
+	switch (offset) {
+		case PTNETMAP_VIRTIO_IO_PTFEAT:
+			val = (uint32_t *)(sc->ptn.reg + offset);
+			ret = (sc->ptn.features &= *val);
+			ptnetmap_ack_features(sc->ptn.state, sc->ptn.features);
+			printf("ptnetmap acked features: %x\n", sc->ptn.features);
+
+			sc->ptn.reg[PTNETMAP_VIRTIO_IO_PTFEAT] = ret;
+			break;
+		case PTNETMAP_VIRTIO_IO_PTCTL:
+			val = (uint32_t *)(sc->ptn.reg + offset);
+
+			ret = EINVAL;
+			switch(*val) {
+				case NET_PARAVIRT_PTCTL_CONFIG:
+					ret = pci_vtnet_ptnetmap_get_mem(sc);
+					break;
+				case NET_PARAVIRT_PTCTL_REGIF:
+					ret = pci_vtnet_ptnetmap_up(sc);
+					break;
+				case NET_PARAVIRT_PTCTL_UNREGIF:
+					ret = pci_vtnet_ptnetmap_down(sc);
+					break;
+				case NET_PARAVIRT_PTCTL_HOSTMEMID:
+					ret = ptnetmap_get_hostmemid(sc->ptn.state);
+					break;
+				case NET_PARAVIRT_PTCTL_IFNEW:
+				case NET_PARAVIRT_PTCTL_IFDELETE:
+				case NET_PARAVIRT_PTCTL_FINALIZE:
+				case NET_PARAVIRT_PTCTL_DEREF:
+					ret = 0;
+					break;
+			}
+			printf("PTSTS - ret %d\n", ret);
+			sc->ptn.reg[PTNETMAP_VIRTIO_IO_PTSTS] = ret;
+			break;
+		case PTNETMAP_VIRTIO_IO_CSBBAH:
+			break;
+		case PTNETMAP_VIRTIO_IO_CSBBAL:
+			ptnetmap_configure_csb(sc->vsc_vs.vs_pi->pi_vmctx, &sc->ptn.csb, *((uint32_t *)(sc->ptn.reg + PTNETMAP_VIRTIO_IO_CSBBAL)),
+					*((uint32_t *)(sc->ptn.reg + PTNETMAP_VIRTIO_IO_CSBBAH)));
+			break;
+		default:
+			break;
+	}
+
+	printf("ptnentmap_vtnet: io_write - offset: %d size: %d val: %u\n", offset, size, value);
+
+	return (0);
+}
+
+static int
+pci_vtnet_ptnetmap_read(struct pci_vtnet_softc *sc, int offset, int size, uint32_t *value)
+{
+	if (sc->ptn.state == NULL) {
+		printf("ERROR ptnetmap: not supported by backend\n");

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



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