Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Jun 2015 18:54:08 GMT
From:      stefano@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r287497 - soc2015/stefano/ptnetmap/head/sys/dev/netmap
Message-ID:  <201506231854.t5NIs8RV007935@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: stefano
Date: Tue Jun 23 18:54:07 2015
New Revision: 287497
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=287497

Log:
  [ptnetmap] preliminary version of ptnetmap
  
  - add netmap_virt.h (ex paravirt.h)
    contains:
  	- CSB definition (shared memory between host/guest)
  	- ptnetmap functions declaration (host/guest)
  	- ptnetmap-memdev ID, register and routines
  - add ptnetmap.c
    contains ptnetmap implementation - OS independent (FreeBSD/linux)

Added:
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_virt.h
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/ptnetmap.c
Modified:
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/if_lem_netmap.h
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap.c
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_freebsd.c
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_kern.h
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_mem2.c
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_mem2.h
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_monitor.c
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_pipe.c
  soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_vale.c

Modified: soc2015/stefano/ptnetmap/head/sys/dev/netmap/if_lem_netmap.h
==============================================================================
--- soc2015/stefano/ptnetmap/head/sys/dev/netmap/if_lem_netmap.h	Tue Jun 23 18:45:26 2015	(r287496)
+++ soc2015/stefano/ptnetmap/head/sys/dev/netmap/if_lem_netmap.h	Tue Jun 23 18:54:07 2015	(r287497)
@@ -38,6 +38,7 @@
 #include <vm/vm.h>
 #include <vm/pmap.h>    /* vtophys ? */
 #include <dev/netmap/netmap_kern.h>
+#include <dev/netmap/netmap_virt.h>
 
 extern int netmap_adaptive_io;
 
@@ -472,6 +473,256 @@
 	return netmap_ring_reinit(kring);
 }
 
+#if defined (NIC_PTNETMAP) && defined (WITH_PTNETMAP_GUEST)
+static uint32_t lem_netmap_ptctl(struct ifnet *, uint32_t);
+
+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_netmap_ptctl(ifp, NET_PARAVIRT_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;
+}
+
+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;
+	struct paravirt_csb *csb = adapter->csb;
+	bool send_kick = false;
+
+	/* Disable notifications */
+	csb->guest_need_txkick = 0;
+
+	/*
+	 * First part: process new packets to send.
+	 */
+	kring->nr_hwcur = csb->tx_ring.hwcur;
+	ptnetmap_guest_write_kring_csb(&csb->tx_ring, kring->rcur, kring->rhead);
+	if (kring->rhead != kring->nr_hwcur) {
+		send_kick = true;
+	}
+
+	/* Send kick to the host if it needs them */
+	if ((send_kick && ACCESS_ONCE(csb->host_need_txkick)) || (flags & NAF_FORCE_RECLAIM)) {
+		csb->tx_ring.sync_flags = flags;
+		E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0);
+	}
+
+	/*
+	 * Second part: reclaim buffers for completed transmissions.
+	 */
+	if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) {
+		ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots);
+	}
+
+	/*
+	 * Ring full. The user thread will go to sleep and
+	 * we need a notification (interrupt) from the NIC,
+	 * whene there is free space.
+	 */
+	if (kring->rcur == kring->nr_hwtail) {
+		/* Reenable notifications. */
+		csb->guest_need_txkick = 1;
+		/* Double check */
+		ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots);
+		/* If there is new free space, disable notifications */
+		if (kring->rcur != kring->nr_hwtail) {
+			csb->guest_need_txkick = 0;
+		}
+	}
+
+	ND("TX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u",
+			csb->tx_ring.head, csb->tx_ring.cur, csb->tx_ring.hwtail, kring->rhead, kring->rcur);
+
+	return 0;
+}
+
+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;
+	struct paravirt_csb *csb = adapter->csb;
+
+	int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
+	uint32_t h_hwcur = kring->nr_hwcur, h_hwtail = kring->nr_hwtail;
+
+	/* Disable notifications */
+	csb->guest_need_rxkick = 0;
+
+	ptnetmap_guest_read_kring_csb(&csb->rx_ring, &h_hwcur, &h_hwtail, kring->nkr_num_slots);
+
+	/*
+	 * First part: import newly received packets.
+	 */
+	if (netmap_no_pendintr || force_update) {
+		kring->nr_hwtail = h_hwtail;
+		kring->nr_kflags &= ~NKR_PENDINTR;
+	}
+
+	/*
+	 * Second part: skip past packets that userspace has released.
+	 */
+	kring->nr_hwcur = h_hwcur;
+	if (kring->rhead != kring->nr_hwcur) {
+		ptnetmap_guest_write_kring_csb(&csb->rx_ring, kring->rcur, kring->rhead);
+		/* Send kick to the host if it needs them */
+		if (ACCESS_ONCE(csb->host_need_rxkick)) {
+			csb->rx_ring.sync_flags = flags;
+			E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), 0);
+		}
+	}
+
+	/*
+	 * Ring empty. The user thread will go to sleep and
+	 * we need a notification (interrupt) from the NIC,
+	 * whene there are new packets.
+	 */
+	if (kring->rcur == kring->nr_hwtail) {
+		/* Reenable notifications. */
+		csb->guest_need_rxkick = 1;
+		/* Double check */
+		ptnetmap_guest_read_kring_csb(&csb->rx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots);
+		/* If there are new packets, disable notifications */
+		if (kring->rcur != kring->nr_hwtail) {
+			csb->guest_need_rxkick = 0;
+		}
+	}
+
+	ND("RX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u",
+			csb->rx_ring.head, csb->rx_ring.cur, csb->rx_ring.hwtail, kring->rhead, kring->rcur);
+
+	return 0;
+
+
+}
+
+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_netmap_ptctl(ifp, NET_PARAVIRT_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_netmap_ptctl(ifp, NET_PARAVIRT_PTCTL_UNREGIF);
+	}
+
+	return lem_netmap_reg(na, onoff);
+}
+
+
+static int
+lem_ptnetmap_bdg_attach(const char *bdg_name, struct netmap_adapter *na)
+{
+	return EOPNOTSUPP;
+}
+
+static struct paravirt_csb *
+lem_netmap_getcsb(struct ifnet *ifp)
+{
+	struct adapter *adapter = ifp->if_softc;
+
+	return adapter->csb;
+}
+
+static uint32_t
+lem_netmap_ptctl(struct ifnet *ifp, uint32_t val)
+{
+	struct adapter *adapter = ifp->if_softc;
+	uint32_t ret;
+
+	E1000_WRITE_REG(&adapter->hw, E1000_PTCTL, val);
+	ret = E1000_READ_REG(&adapter->hw, E1000_PTSTS);
+	D("PTSTS = %u", ret);
+
+	return ret;
+}
+
+
+
+static uint32_t
+lem_ptnetmap_features(struct adapter *adapter)
+{
+	uint32_t features;
+	/* tell the device the features we support */
+	E1000_WRITE_REG(&adapter->hw, E1000_PTFEAT, NET_PTN_FEATURES_BASE);
+	/* get back the acknowledged features */
+	features = E1000_READ_REG(&adapter->hw, E1000_PTFEAT);
+	device_printf(adapter->dev, "netmap passthrough: %s\n",
+			(features & NET_PTN_FEATURES_BASE) ? "base" :
+			"none");
+	return features;
+}
+
+static struct netmap_pt_guest_ops lem_ptnetmap_ops = {
+	.nm_getcsb = lem_netmap_getcsb,
+	.nm_ptctl = lem_netmap_ptctl,
+};
+#elif defined (NIC_PTNETMAP)
+#warning "if_lem supports ptnetmap but netmap does not support it"
+#warning "(configure netmap with passthrough support)"
+#elif defined (WITH_PTNETMAP_GUEST)
+#warning "netmap supports ptnetmap but e1000 does not support it"
+#warning "(configure if_lem with passthrough support)"
+#endif /* NIC_PTNETMAP && WITH_PTNETMAP_GUEST */
 
 static void
 lem_netmap_attach(struct adapter *adapter)
@@ -488,7 +739,19 @@
 	na.nm_rxsync = lem_netmap_rxsync;
 	na.nm_register = lem_netmap_reg;
 	na.num_tx_rings = na.num_rx_rings = 1;
-	netmap_attach(&na);
+#if defined (NIC_PTNETMAP) && defined (WITH_PTNETMAP_GUEST)
+        /* XXX: check if the device support ptnetmap (now we use PARA_SUBDEV) */
+	if ((adapter->hw.subsystem_device_id == E1000_PARA_SUBDEV) &&
+		(lem_ptnetmap_features(adapter) & NET_PTN_FEATURES_BASE)) {
+		na.nm_config = lem_ptnetmap_config;
+		na.nm_register = lem_ptnetmap_reg;
+		na.nm_txsync = lem_ptnetmap_txsync;
+		na.nm_rxsync = lem_ptnetmap_rxsync;
+		na.nm_bdg_attach = lem_ptnetmap_bdg_attach; /* XXX */
+		netmap_pt_guest_attach(&na, &lem_ptnetmap_ops);
+	} else
+#endif /* NIC_PTNETMAP && defined WITH_PTNETMAP_GUEST */
+		netmap_attach(&na);
 }
 
 /* end of file */

Modified: soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap.c
==============================================================================
--- soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap.c	Tue Jun 23 18:45:26 2015	(r287496)
+++ soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap.c	Tue Jun 23 18:54:07 2015	(r287497)
@@ -1381,6 +1381,11 @@
 	 *  !0    !NULL		impossible
 	 */
 
+	/* try to see if this is a passthrough port */
+	error = netmap_get_pt_host_na(nmr, na, create);
+	if (error || *na != NULL)
+		return error;
+
 	/* try to see if this is a monitor port */
 	error = netmap_get_monitor_na(nmr, na, create);
 	if (error || *na != NULL)
@@ -1442,17 +1447,14 @@
  * hwcur, rhead, rtail and hwtail are reliable
  */
 u_int
-nm_txsync_prologue(struct netmap_kring *kring)
+nm_txsync_prologue(struct netmap_kring *kring, uint32_t head, uint32_t cur, uint32_t *tail)
 {
-	struct netmap_ring *ring = kring->ring;
-	u_int head = ring->head; /* read only once */
-	u_int cur = ring->cur; /* read only once */
 	u_int n = kring->nkr_num_slots;
 
 	ND(5, "%s kcur %d ktail %d head %d cur %d tail %d",
 		kring->name,
 		kring->nr_hwcur, kring->nr_hwtail,
-		ring->head, ring->cur, ring->tail);
+		head, cur, tail ? *tail : 0);
 #if 1 /* kernel sanity checks; but we can trust the kring. */
 	if (kring->nr_hwcur >= n || kring->rhead >= n ||
 	    kring->rtail >= n ||  kring->nr_hwtail >= n)
@@ -1490,10 +1492,10 @@
 				goto error;
 		}
 	}
-	if (ring->tail != kring->rtail) {
+	if (tail && *tail != kring->rtail) {
 		RD(5, "tail overwritten was %d need %d",
-			ring->tail, kring->rtail);
-		ring->tail = kring->rtail;
+			*tail, kring->rtail);
+		*tail = kring->rtail;
 	}
 	kring->rhead = head;
 	kring->rcur = cur;
@@ -1504,7 +1506,7 @@
 		kring->name,
 		kring->nr_hwcur,
 		kring->rcur, kring->nr_hwtail,
-		cur, ring->tail);
+		cur, tail ? *tail : 0);
 	return n;
 }
 
@@ -1521,16 +1523,14 @@
  *
  */
 u_int
-nm_rxsync_prologue(struct netmap_kring *kring)
+nm_rxsync_prologue(struct netmap_kring *kring, uint32_t head, uint32_t cur, uint32_t *tail)
 {
-	struct netmap_ring *ring = kring->ring;
 	uint32_t const n = kring->nkr_num_slots;
-	uint32_t head, cur;
 
 	ND(5,"%s kc %d kt %d h %d c %d t %d",
 		kring->name,
 		kring->nr_hwcur, kring->nr_hwtail,
-		ring->head, ring->cur, ring->tail);
+		head, cur, tail ? *tail : 0);
 	/*
 	 * Before storing the new values, we should check they do not
 	 * move backwards. However:
@@ -1538,8 +1538,8 @@
 	 * - cur could in principle go back, however it does not matter
 	 *   because we are processing a brand new rxsync()
 	 */
-	cur = kring->rcur = ring->cur;	/* read only once */
-	head = kring->rhead = ring->head;	/* read only once */
+	kring->rcur = cur;	/* read only once */
+	kring->rhead = head;	/* read only once */
 #if 1 /* kernel sanity checks */
 	if (kring->nr_hwcur >= n || kring->nr_hwtail >= n)
 		goto error;
@@ -1567,11 +1567,11 @@
 				goto error;
 		}
 	}
-	if (ring->tail != kring->rtail) {
+	if (tail && *tail != kring->rtail) {
 		RD(5, "%s tail overwritten was %d need %d",
 			kring->name,
-			ring->tail, kring->rtail);
-		ring->tail = kring->rtail;
+			*tail, kring->rtail);
+		*tail = kring->rtail;
 	}
 	return head;
 
@@ -1579,7 +1579,7 @@
 	RD(5, "kring error: hwcur %d rcur %d hwtail %d head %d cur %d tail %d",
 		kring->nr_hwcur,
 		kring->rcur, kring->nr_hwtail,
-		kring->rhead, kring->rcur, ring->tail);
+		kring->rhead, kring->rcur, tail ? *tail : 0);
 	return n;
 }
 
@@ -1619,7 +1619,7 @@
 	for (i = 0; i <= lim; i++) {
 		u_int idx = ring->slot[i].buf_idx;
 		u_int len = ring->slot[i].len;
-		if (idx < 2 || idx >= kring->na->na_lut_objtotal) {
+		if (idx < 2 || idx >= kring->na->na_lut.objtotal) {
 			RD(5, "bad index at slot %d idx %d len %d ", i, idx, len);
 			ring->slot[i].buf_idx = 0;
 			ring->slot[i].len = 0;
@@ -1981,10 +1981,11 @@
 		 * and make it use the shared buffers.
 		 */
 		/* cache the allocator info in the na */
-		na->na_lut = netmap_mem_get_lut(na->nm_mem);
-		ND("%p->na_lut == %p", na, na->na_lut);
-		na->na_lut_objtotal = netmap_mem_get_buftotal(na->nm_mem);
-		na->na_lut_objsize = netmap_mem_get_bufsize(na->nm_mem);
+		error = netmap_mem_get_lut(na->nm_mem, &na->na_lut);
+		if (error)
+			goto err_del_if;
+		D("lut %p bufs %u size %u", na->na_lut.lut, na->na_lut.objtotal,
+				na->na_lut.objsize);
 		error = na->nm_register(na, 1); /* mode on */
 		if (error) 
 			goto err_del_if;
@@ -2001,9 +2002,7 @@
 	return 0;
 
 err_del_if:
-	na->na_lut = NULL;
-	na->na_lut_objtotal = 0;
-	na->na_lut_objsize = 0;
+	memset(&na->na_lut, 0, sizeof(na->na_lut));
 	na->active_fds--;
 	netmap_mem_if_delete(na, nifp);
 err_rel_excl:
@@ -2123,6 +2122,9 @@
 				|| i == NETMAP_BDG_DELIF) {
 			error = netmap_bdg_ctl(nmr, NULL);
 			break;
+		} else if (i == NETMAP_PT_HOST_CREATE || i == NETMAP_PT_HOST_DELETE) {
+			error = ptnetmap_ctl(nmr, priv->np_na);
+			break;
 		} else if (i != 0) {
 			D("nr_cmd must be 0 not %d", i);
 			error = EINVAL;
@@ -2216,6 +2218,7 @@
 
 		for (i = qfirst; i < qlast; i++) {
 			struct netmap_kring *kring = krings + i;
+			struct netmap_ring *ring = kring->ring;
 			if (nm_kr_tryget(kring)) {
 				error = EBUSY;
 				goto out;
@@ -2223,24 +2226,26 @@
 			if (cmd == NIOCTXSYNC) {
 				if (netmap_verbose & NM_VERB_TXSYNC)
 					D("pre txsync ring %d cur %d hwcur %d",
-					    i, kring->ring->cur,
+					    i, ring->cur,
 					    kring->nr_hwcur);
-				if (nm_txsync_prologue(kring) >= kring->nkr_num_slots) {
+				if (nm_txsync_prologue(kring, ring->head, ring->cur,
+                                            &ring->tail) >= kring->nkr_num_slots) {
 					netmap_ring_reinit(kring);
 				} else if (kring->nm_sync(kring, NAF_FORCE_RECLAIM) == 0) {
 					nm_txsync_finalize(kring);
 				}
 				if (netmap_verbose & NM_VERB_TXSYNC)
 					D("post txsync ring %d cur %d hwcur %d",
-					    i, kring->ring->cur,
+					    i, ring->cur,
 					    kring->nr_hwcur);
 			} else {
-				if (nm_rxsync_prologue(kring) >= kring->nkr_num_slots) {
+				if (nm_rxsync_prologue(kring, ring->head, ring->cur,
+                                            &ring->tail) >= kring->nkr_num_slots) {
 					netmap_ring_reinit(kring);
 				} else if (kring->nm_sync(kring, NAF_FORCE_READ) == 0) {
 					nm_rxsync_finalize(kring);
 				}
-				microtime(&na->rx_rings[i].ring->ts);
+				microtime(&ring->ts);
 			}
 			nm_kr_put(kring);
 		}
@@ -2314,6 +2319,7 @@
 	struct netmap_priv_d *priv = NULL;
 	struct netmap_adapter *na;
 	struct netmap_kring *kring;
+	struct netmap_ring *ring;
 	u_int i, check_all_tx, check_all_rx, want[NR_TXRX], revents = 0;
 #define want_tx want[NR_TX]
 #define want_rx want[NR_RX]
@@ -2363,7 +2369,6 @@
 	want_tx = events & (POLLOUT | POLLWRNORM);
 	want_rx = events & (POLLIN | POLLRDNORM);
 
-
 	/*
 	 * check_all_{tx|rx} are set if the card has more than one queue AND
 	 * the file descriptor is bound to all of them. If so, we sleep on
@@ -2415,7 +2420,9 @@
 			int found = 0;
 
 			kring = &na->tx_rings[i];
-			if (!want_tx && kring->ring->cur == kring->nr_hwcur)
+			ring = kring->ring;
+
+			if (!want_tx && ring->cur == kring->nr_hwcur)
 				continue;
 			/* only one thread does txsync */
 			if (nm_kr_tryget(kring)) {
@@ -2429,7 +2436,8 @@
 					    priv, i);
 				continue;
 			}
-			if (nm_txsync_prologue(kring) >= kring->nkr_num_slots) {
+			if (nm_txsync_prologue(kring, ring->head, ring->cur,
+                                    &ring->tail) >= kring->nkr_num_slots) {
 				netmap_ring_reinit(kring);
 				revents |= POLLERR;
 			} else {
@@ -2473,6 +2481,7 @@
 			int found = 0;
 
 			kring = &na->rx_rings[i];
+			ring = kring->ring;
 
 			if (nm_kr_tryget(kring)) {
 				if (netmap_verbose)
@@ -2481,7 +2490,8 @@
 				continue;
 			}
 
-			if (nm_rxsync_prologue(kring) >= kring->nkr_num_slots) {
+			if (nm_rxsync_prologue(kring, ring->head, ring->cur,
+                                    &ring->tail) >= kring->nkr_num_slots) {
 				netmap_ring_reinit(kring);
 				revents |= POLLERR;
 			}
@@ -2493,9 +2503,9 @@
 			 * XXX NR_FORWARD should only be read on
 			 * physical or NIC ports
 			 */
-			if (netmap_fwd ||kring->ring->flags & NR_FORWARD) {
+			if (netmap_fwd || ring->flags & NR_FORWARD) {
 				ND(10, "forwarding some buffers up %d to %d",
-				    kring->nr_hwcur, kring->ring->cur);
+				    kring->nr_hwcur, ring->cur);
 				netmap_grab_packets(kring, &q, netmap_fwd);
 			}
 
@@ -2504,8 +2514,8 @@
 			else
 				nm_rxsync_finalize(kring);
 			if (netmap_no_timestamp == 0 ||
-					kring->ring->flags & NR_TIMESTAMP) {
-				microtime(&kring->ring->ts);
+					ring->flags & NR_TIMESTAMP) {
+				microtime(&ring->ts);
 			}
 			found = kring->rcur != kring->rtail;
 			nm_kr_put(kring);
@@ -2518,13 +2528,13 @@
 
 		/* transparent mode XXX only during first pass ? */
 		if (na->na_flags & NAF_HOST_RINGS) {
-			kring = &na->rx_rings[na->num_rx_rings];
+			ring = na->rx_rings[na->num_rx_rings].ring;
 			if (check_all_rx
-			    && (netmap_fwd || kring->ring->flags & NR_FORWARD)) {
+			    && (netmap_fwd || ring->flags & NR_FORWARD)) {
 				/* XXX fix to use kring fields */
-				if (nm_ring_empty(kring->ring))
+				if (nm_ring_empty(ring))
 					send_down = netmap_rxsync_from_host(na, td, dev);
-				if (!nm_ring_empty(kring->ring))
+				if (!nm_ring_empty(ring))
 					revents |= want_rx;
 			}
 		}
@@ -2633,6 +2643,7 @@
 	if (na->nm_mem == NULL)
 		/* use the global allocator */
 		na->nm_mem = &nm_mem;
+	netmap_mem_get(na->nm_mem);
 #ifdef WITH_VALE
 	if (na->nm_bdg_attach == NULL)
 		/* no special nm_bdg_attach callback. On VALE
@@ -2656,8 +2667,8 @@
 		na->nm_krings_delete(na);
 	}
 	netmap_pipe_dealloc(na);
-	if (na->na_flags & NAF_MEM_OWNER)
-		netmap_mem_private_delete(na->nm_mem);
+	if (na->nm_mem)
+		netmap_mem_put(na->nm_mem);
 	bzero(na, sizeof(*na));
 	free(na, M_DEVBUF);
 }
@@ -2695,8 +2706,8 @@
  * kring	N+1	is only used for the selinfo for all queues. // XXX still true ?
  * Return 0 on success, ENOMEM otherwise.
  */
-int
-netmap_attach(struct netmap_adapter *arg)
+static int
+_netmap_attach(struct netmap_adapter *arg, size_t size)
 {
 	struct netmap_hw_adapter *hwna = NULL;
 	// XXX when is arg == NULL ?
@@ -2704,7 +2715,7 @@
 
 	if (arg == NULL || ifp == NULL)
 		goto fail;
-	hwna = malloc(sizeof(*hwna), M_DEVBUF, M_NOWAIT | M_ZERO);
+	hwna = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
 	if (hwna == NULL)
 		goto fail;
 	hwna->up = *arg;
@@ -2753,6 +2764,40 @@
 }
 
 
+int
+netmap_attach(struct netmap_adapter *arg)
+{
+	return _netmap_attach(arg, sizeof(struct netmap_hw_adapter));
+}
+
+
+#ifdef WITH_PTNETMAP_GUEST
+int
+netmap_pt_guest_attach(struct netmap_adapter *arg,
+		struct netmap_pt_guest_ops *pv_ops)
+{
+	struct netmap_pt_guest_adapter *ptna;
+	struct ifnet *ifp = arg ? arg->ifp : NULL;
+	int error;
+
+	/* get allocator */
+	arg->nm_mem = netmap_mem_pt_guest_new(ifp, pv_ops);
+	if (arg->nm_mem == NULL)
+		return ENOMEM;
+	arg->na_flags |= NAF_MEM_OWNER;
+	error = _netmap_attach(arg, sizeof(struct netmap_pt_guest_adapter));
+	if (error)
+		return error;
+
+	/* get the netmap_pt_guest_adapter */
+	ptna = (struct netmap_pt_guest_adapter *) NA(ifp);
+	ptna->pv_ops = pv_ops;
+
+	return 0;
+}
+#endif /* WITH_PTNETMAP_GUEST */
+
+
 void
 NM_DBG(netmap_adapter_get)(struct netmap_adapter *na)
 {

Modified: soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_freebsd.c
==============================================================================
--- soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_freebsd.c	Tue Jun 23 18:45:26 2015	(r287496)
+++ soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_freebsd.c	Tue Jun 23 18:54:07 2015	(r287497)
@@ -62,6 +62,7 @@
 #include <net/netmap.h>
 #include <dev/netmap/netmap_kern.h>
 #include <dev/netmap/netmap_mem2.h>
+#include <dev/netmap/netmap_virt.h>
 
 
 /* ======================== FREEBSD-SPECIFIC ROUTINES ================== */
@@ -447,6 +448,248 @@
 	if_free(ifp);
 }
 
+/* ======================== PTNETMAP SUPPORT ========================== */
+
+#ifdef WITH_PTNETMAP_GUEST
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <machine/bus.h>        /* bus_dmamap_* */
+#include <machine/resource.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+/*
+ * ptnetmap memory device (memdev) for freebsd guest
+ * Used to expose host memory to the guest through PCI-BAR
+ */
+
+/*
+ * ptnetmap memdev private data structure
+ */
+struct ptnetmap_memdev
+{
+	device_t dev;
+	struct resource *pci_io;
+	struct resource *pci_mem;
+	struct netmap_mem_d *nm_mem;
+};
+
+static int	ptn_memdev_probe(device_t);
+static int	ptn_memdev_attach(device_t);
+static int	ptn_memdev_detach(device_t);
+static int	ptn_memdev_shutdown(device_t);
+
+static device_method_t ptn_memdev_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, ptn_memdev_probe),
+	DEVMETHOD(device_attach, ptn_memdev_attach),
+	DEVMETHOD(device_detach, ptn_memdev_detach),
+	DEVMETHOD(device_shutdown, ptn_memdev_shutdown),
+	DEVMETHOD_END
+};
+
+static driver_t ptn_memdev_driver = {
+	PTN_MEMDEV_NAME, ptn_memdev_methods, sizeof(struct ptnetmap_memdev),
+};
+
+devclass_t ptnetmap_devclass;
+DRIVER_MODULE(netmap, pci, ptn_memdev_driver, ptnetmap_devclass, 0, 0);
+
+MODULE_DEPEND(netmap, pci, 1, 1, 1);
+
+/*
+ * I/O port read/write wrappers.
+ */
+#define ptn_ioread8(ptn_dev, reg)		bus_read_1((ptn_dev)->pci_io, (reg))
+#define ptn_ioread16(ptn_dev, reg)		bus_read_2((ptn_dev)->pci_io, (reg))
+#define ptn_ioread32(ptn_dev, reg)		bus_read_4((ptn_dev)->pci_io, (reg))
+#define ptn_iowrite8(ptn_dev, reg, val)		bus_write_1((ptn_dev)->pci_io, (reg), (val))
+#define ptn_iowrite16(ptn_dev, reg, val)	bus_write_2((ptn_dev)->pci_io, (reg), (val))
+#define ptn_iowrite32(ptn_dev, reg, val)	bus_write_4((ptn_dev)->pci_io, (reg), (val))
+
+/*
+ * map host netmap memory through PCI-BAR in the guest OS
+ *
+ * return physical (nm_paddr) and virtual (nm_addr) addresses
+ * of the netmap memory mapped in the guest.
+ */
+int
+netmap_pt_memdev_iomap(struct ptnetmap_memdev *ptn_dev, vm_paddr_t *nm_paddr, void **nm_addr)
+{
+	uint32_t mem_size;
+	int rid;
+
+	D("ptn_memdev_driver iomap");
+
+	rid = PCIR_BAR(PTNETMAP_MEM_PCI_BAR);
+	mem_size = ptn_ioread32(ptn_dev, PTNETMAP_IO_PCI_MEMSIZE);
+
+	/* map memory allocator */
+	ptn_dev->pci_mem = bus_alloc_resource(ptn_dev->dev, SYS_RES_MEMORY,
+			&rid, 0, ~0, mem_size, RF_ACTIVE);
+	if (ptn_dev->pci_mem == NULL) {
+		*nm_paddr = 0;
+		*nm_addr = 0;
+		return ENOMEM;
+	}
+
+	*nm_paddr = rman_get_start(ptn_dev->pci_mem);
+	*nm_addr = rman_get_virtual(ptn_dev->pci_mem);
+
+	D("=== BAR %d start %llx len %llx mem_size %x ===",
+			PTNETMAP_MEM_PCI_BAR,
+			*nm_paddr,
+			rman_get_size(ptn_dev->pci_mem),
+			mem_size);
+	return (0);
+}
+
+/*
+ * unmap PCI-BAR
+ */
+void
+netmap_pt_memdev_iounmap(struct ptnetmap_memdev *ptn_dev)
+{
+	D("ptn_memdev_driver iounmap");
+
+	if (ptn_dev->pci_mem) {
+		bus_release_resource(ptn_dev->dev, SYS_RES_MEMORY,
+			PCIR_BAR(PTNETMAP_MEM_PCI_BAR), ptn_dev->pci_mem);
+		ptn_dev->pci_mem = NULL;
+	}
+}
+
+/*********************************************************************
+ *  Device identification routine
+ *
+ *  ixgbe_probe determines if the driver should be loaded on
+ *  adapter based on PCI vendor/device id of the adapter.
+ *
+ *  return BUS_PROBE_DEFAULT on success, positive on failure
+ *********************************************************************/
+static int
+ptn_memdev_probe(device_t dev)
+{
+	char desc[256];
+
+	if (pci_get_vendor(dev) != PTNETMAP_PCI_VENDOR_ID)
+		return (ENXIO);
+	if (pci_get_device(dev) != PTNETMAP_PCI_DEVICE_ID)
+		return (ENXIO);
+
+	D("ptn_memdev_driver probe");
+	snprintf(desc, sizeof(desc), "%s PCI adapter",
+			PTN_MEMDEV_NAME);
+	device_set_desc_copy(dev, desc);
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+/*********************************************************************
+ *  Device initialization routine
+ *
+ *  The attach entry point is called when the driver is being loaded.
+ *  This routine identifies the type of hardware, allocates all resources
+ *  and initializes the hardware.
+ *
+ *  return 0 on success, positive on failure
+ *********************************************************************/
+static int
+ptn_memdev_attach(device_t dev)
+{
+	struct ptnetmap_memdev *ptn_dev;
+	int rid;
+	uint16_t mem_id;
+
+	D("ptn_memdev_driver attach");
+
+	ptn_dev = device_get_softc(dev);
+	ptn_dev->dev = dev;
+
+	pci_enable_busmaster(dev);
+
+	rid = PCIR_BAR(PTNETMAP_IO_PCI_BAR);
+	ptn_dev->pci_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
+			RF_ACTIVE);
+	if (ptn_dev->pci_io == NULL) {
+	        device_printf(dev, "cannot map I/O space\n");
+	        return (ENXIO);
+	}
+
+	mem_id = ptn_ioread16(ptn_dev, PTNETMAP_IO_PCI_HOSTID);
+
+	/* create guest allocator */
+	ptn_dev->nm_mem = netmap_mem_pt_guest_attach(ptn_dev, mem_id);
+	if (ptn_dev->nm_mem == NULL) {
+		ptn_memdev_detach(dev);
+	        return (ENOMEM);
+	}
+	netmap_mem_get(ptn_dev->nm_mem);
+
+	D("ptn_memdev_driver probe OK - host_id: %d", mem_id);
+
+	return (0);
+}
+
+/*********************************************************************
+ *  Device removal routine
+ *
+ *  The detach entry point is called when the driver is being removed.
+ *  This routine stops the adapter and deallocates all the resources
+ *  that were allocated for driver operation.
+ *
+ *  return 0 on success, positive on failure
+ *********************************************************************/
+static int
+ptn_memdev_detach(device_t dev)
+{
+	struct ptnetmap_memdev *ptn_dev;
+
+	D("ptn_memdev_driver detach");
+	ptn_dev = device_get_softc(dev);
+
+	if (ptn_dev->nm_mem) {
+		netmap_mem_put(ptn_dev->nm_mem);
+		ptn_dev->nm_mem = NULL;
+	}
+	if (ptn_dev->pci_mem) {
+		bus_release_resource(dev, SYS_RES_MEMORY,
+			PCIR_BAR(PTNETMAP_MEM_PCI_BAR), ptn_dev->pci_mem);
+		ptn_dev->pci_mem = NULL;
+	}
+	if (ptn_dev->pci_io) {
+		bus_release_resource(dev, SYS_RES_IOPORT,
+			PCIR_BAR(PTNETMAP_IO_PCI_BAR), ptn_dev->pci_io);
+		ptn_dev->pci_io = NULL;
+	}
+
+	return (0);
+}
+
+/*********************************************************************
+ *
+ *  Shutdown entry point
+ *
+ **********************************************************************/
+static int
+ptn_memdev_shutdown(device_t dev)
+{
+	D("ptn_memdev_driver shutsown");
+	return bus_generic_shutdown(dev);
+}
+
+int
+netmap_pt_memdev_init(void)
+{
+	return 0;
+}
+
+void
+netmap_pt_memdev_uninit(void)
+{
+
+}
+#endif /* WITH_PTNETMAP_GUEST */
+
 /*
  * In order to track whether pages are still mapped, we hook into
  * the standard cdev_pager and intercept the constructor and

Modified: soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_kern.h
==============================================================================
--- soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_kern.h	Tue Jun 23 18:45:26 2015	(r287496)
+++ soc2015/stefano/ptnetmap/head/sys/dev/netmap/netmap_kern.h	Tue Jun 23 18:54:07 2015	(r287497)
@@ -51,6 +51,10 @@
 #if defined(CONFIG_NETMAP_V1000)
 #define WITH_V1000
 #endif
+#if defined(CONFIG_NETMAP_PASSTHROUGH)
+#define WITH_PTNETMAP_HOST
+#define WITH_PTNETMAP_GUEST
+#endif
 
 #else /* not linux */
 
@@ -58,6 +62,8 @@
 #define WITH_PIPES
 #define WITH_MONITOR
 #define WITH_GENERIC
+//#define WITH_PTNETMAP_HOST /* ptnetmap host not supported in FreeBSD */
+#define WITH_PTNETMAP_GUEST
 
 #endif
 
@@ -65,6 +71,8 @@
 
 #define likely(x)	__builtin_expect((long)!!(x), 1L)
 #define unlikely(x)	__builtin_expect((long)!!(x), 0L)
+#define __user				/* XXX: temp */
+#define ACCESS_ONCE(x) (x) 	/* XXX: temp */
 
 #define	NM_LOCK_T	struct mtx	/* low level spinlock, used to protect queues */
 
@@ -298,6 +306,7 @@
 	uint32_t	nr_kflags;	/* private driver flags */
 #define NKR_PENDINTR	0x1		// Pending interrupt.
 #define NKR_EXCLUSIVE	0x2		/* exclusive binding */
+#define NKR_PASSTHROUGH 0x4
 	uint32_t	nkr_num_slots;
 
 	/*
@@ -465,6 +474,11 @@
  */
 
 
+struct netmap_lut {
+	struct lut_entry *lut;
+	uint32_t objtotal;	/* max buffer index */
+	uint32_t objsize;	/* buffer size */
+};
 
 struct netmap_vp_adapter; // forward
 
@@ -494,8 +508,8 @@
 				 * forwarding packets coming from this
 				 * interface
 				 */
-#define NAF_MEM_OWNER	8	/* the adapter is responsible for the
-				 * deallocation of the memory allocator
+#define NAF_MEM_OWNER	8	/* the adapter uses its own memory area
+				 * that cannot be changed
 				 */
 #define NAF_NATIVE_ON   16      /* the adapter is native and the attached
 				 * interface is in netmap mode.
@@ -508,6 +522,7 @@
 				 */
 #define NAF_HOST_RINGS  64	/* the adapter supports the host rings */
 #define NAF_FORCE_NATIVE 128	/* the adapter is always NATIVE */
+#define NAF_PASSTHROUGH_HOST 256/* the adapter supports passthrough in the host */
 #define	NAF_BUSY	(1U<<31) /* the adapter is used internally and
 				  * cannot be registered from userspace
 				  */
@@ -637,13 +652,11 @@
 	 * buffer addresses, and the total number of buffers.
 	 */
  	struct netmap_mem_d *nm_mem;
-	struct lut_entry *na_lut;
-	uint32_t na_lut_objtotal;	/* max buffer index */
-	uint32_t na_lut_objsize;	/* buffer size */
+	struct netmap_lut na_lut;
 
 	/* additional information attached to this adapter

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



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