From owner-svn-src-all@freebsd.org Thu Jun 2 11:18:03 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 9ED0EB644A4; Thu, 2 Jun 2016 11:18:03 +0000 (UTC) (envelope-from royger@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 78D601AFA; Thu, 2 Jun 2016 11:18:03 +0000 (UTC) (envelope-from royger@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u52BI2fY047386; Thu, 2 Jun 2016 11:18:02 GMT (envelope-from royger@FreeBSD.org) Received: (from royger@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u52BI2q8047385; Thu, 2 Jun 2016 11:18:02 GMT (envelope-from royger@FreeBSD.org) Message-Id: <201606021118.u52BI2q8047385@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: royger set sender to royger@FreeBSD.org using -f From: =?UTF-8?Q?Roger_Pau_Monn=c3=a9?= Date: Thu, 2 Jun 2016 11:18:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r301199 - head/sys/dev/xen/netfront X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 02 Jun 2016 11:18:03 -0000 Author: royger Date: Thu Jun 2 11:18:02 2016 New Revision: 301199 URL: https://svnweb.freebsd.org/changeset/base/301199 Log: xen-netfront: fix two hotplug related issues This patch fixes two issues seen on hot-unplug. The first one is a panic caused by calling ether_ifdetach after freeing the internal netfront queue structures. ether_ifdetach will call xn_qflush, and this needs to be done before freeing the queues. This prevents the following panic: Fatal trap 9: general protection fault while in kernel mode cpuid = 2; apic id = 04 instruction pointer = 0x20:0xffffffff80b1687f stack pointer = 0x28:0xfffffe009239e770 frame pointer = 0x28:0xfffffe009239e780 code segment = base 0x0, limit 0xfffff, type 0x1b = DPL 0, pres 1, long 1, def32 0, gran 1 processor eflags = interrupt enabled, resume, IOPL = 0 current process = 0 (thread taskq) [ thread pid 0 tid 100015 ] Stopped at strlen+0x1f: movq (%rcx),%rax db> bt Tracing pid 0 tid 100015 td 0xfffff800038a6000 strlen() at strlen+0x1f/frame 0xfffffe009239e780 kvprintf() at kvprintf+0xfa0/frame 0xfffffe009239e890 vsnprintf() at vsnprintf+0x31/frame 0xfffffe009239e8b0 kassert_panic() at kassert_panic+0x5a/frame 0xfffffe009239e920 __mtx_lock_flags() at __mtx_lock_flags+0x164/frame 0xfffffe009239e970 xn_qflush() at xn_qflush+0x59/frame 0xfffffe009239e9b0 if_detach() at if_detach+0x17e/frame 0xfffffe009239ea10 netif_free() at netif_free+0x97/frame 0xfffffe009239ea30 netfront_detach() at netfront_detach+0x11/frame 0xfffffe009239ea40 [...] Another panic can be triggered by hot-plugging a NIC: Fatal trap 18: integer divide fault while in kernel mode cpuid = 0; apic id = 00 instruction pointer = 0x20:0xffffffff80902203 stack pointer = 0x28:0xfffffe00508d3660 frame pointer = 0x28:0xfffffe00508d36a0 code segment = base 0x0, limit 0xfffff, type 0x1b = DPL 0, pres 1, long 1, def32 0, gran 1 processor eflags = interrupt enabled, resume, IOPL = 0 current process = 2960 (ifconfig) [ thread pid 2960 tid 100088 ] Stopped at xn_txq_mq_start+0x33: divl %esi,%eax db> bt Tracing pid 2960 tid 100088 td 0xfffff8000850aa00 xn_txq_mq_start() at xn_txq_mq_start+0x33/frame 0xfffffe00508d36a0 ether_output() at ether_output+0x570/frame 0xfffffe00508d3720 arprequest() at arprequest+0x433/frame 0xfffffe00508d3820 arp_ifinit() at arp_ifinit+0x49/frame 0xfffffe00508d3850 xn_ioctl() at xn_ioctl+0x1a2/frame 0xfffffe00508d3890 in_control() at in_control+0x882/frame 0xfffffe00508d3910 ifioctl() at ifioctl+0xda1/frame 0xfffffe00508d39a0 kern_ioctl() at kern_ioctl+0x246/frame 0xfffffe00508d3a00 sys_ioctl() at sys_ioctl+0x171/frame 0xfffffe00508d3ae0 amd64_syscall() at amd64_syscall+0x2db/frame 0xfffffe00508d3bf0 Xfast_syscall() at Xfast_syscall+0xfb/frame 0xfffffe00508d3bf0 --- syscall (54, FreeBSD ELF64, sys_ioctl), rip = 0x8011e185a, rsp = 0x7fffffffe478, rbp = 0x7fffffffe4c0 --- This is caused by marking the driver as active before it's fully initialized, and thus calling xn_txq_mq_start with num_queues set to 0. Reviewed by: Wei Liu Sponsored by: Citrix Systems R&D Differential revision: https://reviews.freebsd.org/D6646 Modified: head/sys/dev/xen/netfront/netfront.c Modified: head/sys/dev/xen/netfront/netfront.c ============================================================================== --- head/sys/dev/xen/netfront/netfront.c Thu Jun 2 11:16:35 2016 (r301198) +++ head/sys/dev/xen/netfront/netfront.c Thu Jun 2 11:18:02 2016 (r301199) @@ -1704,7 +1704,7 @@ xn_ifinit_locked(struct netfront_info *n ifp = np->xn_ifp; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (ifp->if_drv_flags & IFF_DRV_RUNNING || !netfront_carrier_ok(np)) return; xn_stop(np); @@ -2088,6 +2088,8 @@ xn_txq_mq_start(struct ifnet *ifp, struc np = ifp->if_softc; npairs = np->num_queues; + KASSERT(npairs != 0, ("called with 0 available queues")); + /* check if flowid is set */ if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) i = m->m_pkthdr.flowid % npairs; @@ -2202,9 +2204,9 @@ netif_free(struct netfront_info *np) xn_stop(np); XN_UNLOCK(np); netif_disconnect_backend(np); + ether_ifdetach(np->xn_ifp); free(np->rxq, M_DEVBUF); free(np->txq, M_DEVBUF); - ether_ifdetach(np->xn_ifp); if_free(np->xn_ifp); np->xn_ifp = NULL; ifmedia_removeall(&np->sc_media);