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>