socsvn commit: r288612 - soc2015/stefano/ptnetmap/stable/10/usr.sbin/bhyve
stefano at FreeBSD.org
stefano at FreeBSD.org
Tue Jul 21 13:49:46 UTC 2015
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 ***
More information about the svn-soc-all
mailing list