Module Name: src Committed By: martin Date: Tue Feb 23 18:50:21 UTC 2021
Modified Files: src/sys/arch/xen/xen [netbsd-9]: xennetback_xenbus.c Log Message: Pull up following revision(s) (requested by jdolecek in ticket #1211): sys/arch/xen/xen/xennetback_xenbus.c: revision 1.92 (via patch) remove support for legacy rx-flip mode for xennet(4)/xvif(4), making rx-copy (first shipped in NetBSD 6.0 in 2012) the only supported mode this is mostly to simplify maintenance and future development rx-flip is not supported by Linux Dom0/DomU, and NetBSD Dom0/DomU defaults to rx-copy for over 8 years now too, so there is little need to keep the support for compatibility besides compatibility there is no other reason to keep rx-flip - page transfer is generally slower than copy due to necessary MMU/TLB manipulation, especially on MP systems To generate a diff of this commit: cvs rdiff -u -r1.75 -r1.75.4.1 src/sys/arch/xen/xen/xennetback_xenbus.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/xen/xen/xennetback_xenbus.c diff -u src/sys/arch/xen/xen/xennetback_xenbus.c:1.75 src/sys/arch/xen/xen/xennetback_xenbus.c:1.75.4.1 --- src/sys/arch/xen/xen/xennetback_xenbus.c:1.75 Sat Mar 9 08:42:25 2019 +++ src/sys/arch/xen/xen/xennetback_xenbus.c Tue Feb 23 18:50:21 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: xennetback_xenbus.c,v 1.75 2019/03/09 08:42:25 maxv Exp $ */ +/* $NetBSD: xennetback_xenbus.c,v 1.75.4.1 2021/02/23 18:50:21 martin Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.75 2019/03/09 08:42:25 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.75.4.1 2021/02/23 18:50:21 martin Exp $"); #include "opt_xen.h" @@ -129,7 +129,6 @@ struct xnetback_instance { void xvifattach(int); static int xennetback_ifioctl(struct ifnet *, u_long, void *); static void xennetback_ifstart(struct ifnet *); -static void xennetback_ifsoftstart_transfer(void *); static void xennetback_ifsoftstart_copy(void *); static void xennetback_ifwatchdog(struct ifnet *); static int xennetback_ifinit(struct ifnet *); @@ -160,35 +159,10 @@ static struct xenbus_backend_driver xvif */ #define NB_XMIT_PAGES_BATCH 64 -/* - * We will transfer a mapped page to the remote domain, and remap another - * page in place immediately. For this we keep a list of pages available. - * When the list is empty, we ask the hypervisor to give us - * NB_XMIT_PAGES_BATCH pages back. - */ -static unsigned long mcl_pages[NB_XMIT_PAGES_BATCH]; /* our physical pages */ -int mcl_pages_alloc; /* current index in mcl_pages */ -static int xennetback_get_mcl_page(paddr_t *); -static void xennetback_get_new_mcl_pages(void); - -/* - * If we can't transfer the mbuf directly, we have to copy it to a page which - * will be transferred to the remote domain. We use a pool_cache for this. - */ -pool_cache_t xmit_pages_cache; - /* arrays used in xennetback_ifstart(), too large to allocate on stack */ /* XXXSMP */ -static mmu_update_t xstart_mmu[NB_XMIT_PAGES_BATCH]; -static multicall_entry_t xstart_mcl[NB_XMIT_PAGES_BATCH + 1]; -static gnttab_transfer_t xstart_gop_transfer[NB_XMIT_PAGES_BATCH]; static gnttab_copy_t xstart_gop_copy[NB_XMIT_PAGES_BATCH]; static struct mbuf *mbufs_sent[NB_XMIT_PAGES_BATCH]; -static struct _pages_pool_free { - vaddr_t va; - paddr_t pa; -} pages_pool_free[NB_XMIT_PAGES_BATCH]; - static inline void xni_pkt_unmap(struct xni_pkt *pkt, vaddr_t pkt_va) @@ -200,31 +174,11 @@ xni_pkt_unmap(struct xni_pkt *pkt, vaddr void xvifattach(int n) { - int i; - struct pglist mlist; - struct vm_page *pg; - XENPRINTF(("xennetback_init\n")); - /* - * steal some non-managed pages to the VM system, to replace - * mbuf cluster or xmit_pages_pool pages given to foreign domains. - */ - if (uvm_pglistalloc(PAGE_SIZE * NB_XMIT_PAGES_BATCH, 0, 0xffffffff, - 0, 0, &mlist, NB_XMIT_PAGES_BATCH, 0) != 0) - panic("xennetback_init: uvm_pglistalloc"); - for (i = 0, pg = mlist.tqh_first; pg != NULL; - pg = pg->pageq.queue.tqe_next, i++) - mcl_pages[i] = xpmap_ptom(VM_PAGE_TO_PHYS(pg)) >> PAGE_SHIFT; - if (i != NB_XMIT_PAGES_BATCH) - panic("xennetback_init: %d mcl pages", i); - mcl_pages_alloc = NB_XMIT_PAGES_BATCH - 1; - /* initialise pools */ pool_init(&xni_pkt_pool, sizeof(struct xni_pkt), 0, 0, 0, "xnbpkt", NULL, IPL_VM); - xmit_pages_cache = pool_cache_init(PAGE_SIZE, 0, 0, 0, "xnbxm", NULL, - IPL_VM, NULL, NULL, NULL); SLIST_INIT(&xnetback_instances); mutex_init(&xnetback_lock, MUTEX_DEFAULT, IPL_NONE); @@ -342,14 +296,6 @@ xennetback_xenbus_create(struct xenbus_d xbusd->xbusd_path, err); goto abort_xbt; } - err = xenbus_printf(xbt, xbusd->xbusd_path, - "feature-rx-flip", "%d", 1); - if (err) { - aprint_error_ifnet(ifp, - "failed to write %s/feature-rx-flip: %d\n", - xbusd->xbusd_path, err); - goto abort_xbt; - } } while ((err = xenbus_transaction_end(xbt, 0)) == EAGAIN); if (err) { aprint_error_ifnet(ifp, @@ -472,21 +418,19 @@ xennetback_connect(struct xnetback_insta } err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, "request-rx-copy", &rx_copy, 10); - if (err == ENOENT) - rx_copy = 0; - else if (err) { + if (err == ENOENT || !rx_copy) { + xenbus_dev_fatal(xbusd, err, + "%s/request-rx-copy not supported by frontend", + xbusd->xbusd_otherend); + return -1; + } else if (err) { xenbus_dev_fatal(xbusd, err, "reading %s/request-rx-copy", xbusd->xbusd_otherend); return -1; } - if (rx_copy) - xneti->xni_softintr = softint_establish(SOFTINT_NET, - xennetback_ifsoftstart_copy, xneti); - else - xneti->xni_softintr = softint_establish(SOFTINT_NET, - xennetback_ifsoftstart_transfer, xneti); - + xneti->xni_softintr = softint_establish(SOFTINT_NET, + xennetback_ifsoftstart_copy, xneti); if (xneti->xni_softintr == NULL) { err = ENOMEM; xenbus_dev_fatal(xbusd, ENOMEM, @@ -662,48 +606,6 @@ xnetif_lookup(domid_t dom , uint32_t han return found; } -/* get a page to replace a mbuf cluster page given to a domain */ -static int -xennetback_get_mcl_page(paddr_t *map) -{ - if (mcl_pages_alloc < 0) { - /* - * we exhausted our allocation. We can't allocate new ones yet - * because the current pages may not have been loaned to - * the remote domain yet. We have to let the caller do this. - */ - return -1; - } - - *map = ((paddr_t)mcl_pages[mcl_pages_alloc]) << PAGE_SHIFT; - mcl_pages_alloc--; - return 0; -} - -static void -xennetback_get_new_mcl_pages(void) -{ - int nb_pages; - struct xen_memory_reservation res; - - /* get some new pages. */ - set_xen_guest_handle(res.extent_start, mcl_pages); - res.nr_extents = NB_XMIT_PAGES_BATCH; - res.extent_order = 0; - res.address_bits = 0; - res.domid = DOMID_SELF; - - nb_pages = HYPERVISOR_memory_op(XENMEM_increase_reservation, &res); - if (nb_pages <= 0) { - printf("xennetback: can't get new mcl pages (%d)\n", nb_pages); - return; - } - if (nb_pages != NB_XMIT_PAGES_BATCH) - printf("xennetback: got only %d new mcl pages\n", nb_pages); - - mcl_pages_alloc = nb_pages - 1; -} - static inline void xennetback_tx_response(struct xnetback_instance *xneti, int id, int status) { @@ -965,255 +867,6 @@ xennetback_ifstart(struct ifnet *ifp) softint_schedule(xneti->xni_softintr); } -static void -xennetback_ifsoftstart_transfer(void *arg) -{ - struct xnetback_instance *xneti = arg; - struct ifnet *ifp = &xneti->xni_if; - struct mbuf *m; - vaddr_t xmit_va; - paddr_t xmit_pa; - paddr_t xmit_ma; - paddr_t newp_ma = 0; /* XXX gcc */ - int i, j, nppitems; - mmu_update_t *mmup; - multicall_entry_t *mclp; - netif_rx_response_t *rxresp; - netif_rx_request_t rxreq; - RING_IDX req_prod, resp_prod; - int do_event = 0; - gnttab_transfer_t *gop; - int id, offset; - - XENPRINTF(("xennetback_ifsoftstart_transfer ")); - int s = splnet(); - if (__predict_false( - (ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)) { - splx(s); - return; - } - - while (!IFQ_IS_EMPTY(&ifp->if_snd)) { - XENPRINTF(("pkt\n")); - req_prod = xneti->xni_rxring.sring->req_prod; - resp_prod = xneti->xni_rxring.rsp_prod_pvt; - xen_rmb(); - - mmup = xstart_mmu; - mclp = xstart_mcl; - gop = xstart_gop_transfer; - for (nppitems = 0, i = 0; !IFQ_IS_EMPTY(&ifp->if_snd);) { - XENPRINTF(("have a packet\n")); - IFQ_POLL(&ifp->if_snd, m); - if (__predict_false(m == NULL)) - panic("xennetback_ifstart: IFQ_POLL"); - if (__predict_false( - req_prod == xneti->xni_rxring.req_cons || - xneti->xni_rxring.req_cons - resp_prod == - NET_RX_RING_SIZE)) { - /* out of ring space */ - XENPRINTF(("xennetback_ifstart: ring full " - "req_prod 0x%x req_cons 0x%x resp_prod " - "0x%x\n", - req_prod, xneti->xni_rxring.req_cons, - resp_prod)); - ifp->if_timer = 1; - break; - } - if (__predict_false(i == NB_XMIT_PAGES_BATCH)) - break; /* we filled the array */ - if (__predict_false( - xennetback_get_mcl_page(&newp_ma) != 0)) - break; /* out of memory */ - if ((m->m_flags & M_EXT_CLUSTER) != 0 && - !M_READONLY(m) && MCLBYTES == PAGE_SIZE) { - /* we can give this page away */ - xmit_pa = m->m_ext.ext_paddr; - xmit_ma = xpmap_ptom(xmit_pa); - xmit_va = (vaddr_t)m->m_ext.ext_buf; - KASSERT(xmit_pa != M_PADDR_INVALID); - KASSERT((xmit_va & PAGE_MASK) == 0); - offset = m->m_data - m->m_ext.ext_buf; - } else { - /* we have to copy the packet */ - xmit_va = (vaddr_t)pool_cache_get_paddr( - xmit_pages_cache, PR_NOWAIT, &xmit_pa); - if (__predict_false(xmit_va == 0)) - break; /* out of memory */ - - KASSERT(xmit_pa != POOL_PADDR_INVALID); - xmit_ma = xpmap_ptom(xmit_pa); - XENPRINTF(("xennetback_get_xmit_page: got va " - "0x%x ma 0x%x\n", (u_int)xmit_va, - (u_int)xmit_ma)); - m_copydata(m, 0, m->m_pkthdr.len, - (char *)xmit_va + LINUX_REQUESTED_OFFSET); - offset = LINUX_REQUESTED_OFFSET; - pages_pool_free[nppitems].va = xmit_va; - pages_pool_free[nppitems].pa = xmit_pa; - nppitems++; - } - /* start filling ring */ - RING_COPY_REQUEST(&xneti->xni_rxring, - xneti->xni_rxring.req_cons, &rxreq); - gop->ref = rxreq.gref; - id = rxreq.id; - xen_rmb(); - xneti->xni_rxring.req_cons++; - rxresp = RING_GET_RESPONSE(&xneti->xni_rxring, - resp_prod); - rxresp->id = id; - rxresp->offset = offset; - rxresp->status = m->m_pkthdr.len; - if ((m->m_pkthdr.csum_flags & - (M_CSUM_TCPv4 | M_CSUM_UDPv4)) != 0) { - rxresp->flags = NETRXF_csum_blank; - } else { - rxresp->flags = 0; - } - /* - * transfers the page containing the packet to the - * remote domain, and map newp in place. - */ - xpmap_ptom_map(xmit_pa, newp_ma); - MULTI_update_va_mapping(mclp, xmit_va, - newp_ma | PTE_P | PTE_W | PTE_A | PTE_D | xpmap_pg_nx, 0); - mclp++; - gop->mfn = xmit_ma >> PAGE_SHIFT; - gop->domid = xneti->xni_domid; - gop++; - - mmup->ptr = newp_ma | MMU_MACHPHYS_UPDATE; - mmup->val = xmit_pa >> PAGE_SHIFT; - mmup++; - - /* done with this packet */ - IFQ_DEQUEUE(&ifp->if_snd, m); - mbufs_sent[i] = m; - resp_prod++; - i++; /* this packet has been queued */ - ifp->if_opackets++; - bpf_mtap(ifp, m, BPF_D_OUT); - } - if (i != 0) { - /* - * We may have allocated buffers which have entries - * outstanding in the page update queue -- make sure - * we flush those first! - */ - int svm = splvm(); - xpq_flush_queue(); - splx(svm); - mclp[-1].args[MULTI_UVMFLAGS_INDEX] = - UVMF_TLB_FLUSH|UVMF_ALL; - mclp->op = __HYPERVISOR_mmu_update; - mclp->args[0] = (unsigned long)xstart_mmu; - mclp->args[1] = i; - mclp->args[2] = 0; - mclp->args[3] = DOMID_SELF; - mclp++; - /* update the MMU */ - if (HYPERVISOR_multicall(xstart_mcl, i + 1) != 0) { - panic("%s: HYPERVISOR_multicall failed", - ifp->if_xname); - } - for (j = 0; j < i + 1; j++) { - if (xstart_mcl[j].result != 0) { - printf("%s: xstart_mcl[%d] " - "failed (%lu)\n", ifp->if_xname, - j, xstart_mcl[j].result); - printf("%s: req_prod %u req_cons " - "%u rsp_prod %u rsp_prod_pvt %u " - "i %u\n", - ifp->if_xname, - xneti->xni_rxring.sring->req_prod, - xneti->xni_rxring.req_cons, - xneti->xni_rxring.sring->rsp_prod, - xneti->xni_rxring.rsp_prod_pvt, - i); - } - } - if (HYPERVISOR_grant_table_op(GNTTABOP_transfer, - xstart_gop_transfer, i) != 0) { - panic("%s: GNTTABOP_transfer failed", - ifp->if_xname); - } - - for (j = 0; j < i; j++) { - if (xstart_gop_transfer[j].status != GNTST_okay) { - printf("%s GNTTABOP_transfer[%d] %d\n", - ifp->if_xname, - j, xstart_gop_transfer[j].status); - printf("%s: req_prod %u req_cons " - "%u rsp_prod %u rsp_prod_pvt %u " - "i %d\n", - ifp->if_xname, - xneti->xni_rxring.sring->req_prod, - xneti->xni_rxring.req_cons, - xneti->xni_rxring.sring->rsp_prod, - xneti->xni_rxring.rsp_prod_pvt, - i); - rxresp = RING_GET_RESPONSE( - &xneti->xni_rxring, - xneti->xni_rxring.rsp_prod_pvt + j); - rxresp->status = NETIF_RSP_ERROR; - } - } - - /* update pointer */ - KASSERT( - xneti->xni_rxring.rsp_prod_pvt + i == resp_prod); - xneti->xni_rxring.rsp_prod_pvt = resp_prod; - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY( - &xneti->xni_rxring, j); - if (j) - do_event = 1; - /* now we can free the mbufs */ - for (j = 0; j < i; j++) { - m_freem(mbufs_sent[j]); - } - for (j = 0; j < nppitems; j++) { - pool_cache_put_paddr(xmit_pages_cache, - (void *)pages_pool_free[j].va, - pages_pool_free[j].pa); - } - } - /* send event */ - if (do_event) { - xen_rmb(); - XENPRINTF(("%s receive event\n", - xneti->xni_if.if_xname)); - hypervisor_notify_via_evtchn(xneti->xni_evtchn); - do_event = 0; - } - /* check if we need to get back some pages */ - if (mcl_pages_alloc < 0) { - xennetback_get_new_mcl_pages(); - if (mcl_pages_alloc < 0) { - /* - * setup the watchdog to try again, because - * xennetback_ifstart() will never be called - * again if queue is full. - */ - printf("xennetback_ifstart: no mcl_pages\n"); - ifp->if_timer = 1; - break; - } - } - /* - * note that we don't use RING_FINAL_CHECK_FOR_REQUESTS() - * here, as the frontend doesn't notify when adding - * requests anyway - */ - if (__predict_false( - !RING_HAS_UNCONSUMED_REQUESTS(&xneti->xni_rxring))) { - /* ring full */ - break; - } - } - splx(s); -} - /* * sighly different from m_dup(); for some reason m_dup() can return * a chain where the data area can cross a page boundary.