Subject: Re: port-xen/30153: Panic in domU when running a pkgsrc bulk build
To: None <gnats-bugs@NetBSD.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: netbsd-bugs
Date: 05/26/2005 16:02:01
--zYM0uCDKw75PZbzx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Fri, May 06, 2005 at 11:17:00AM +0000, juan@xtrarom.org wrote:
> 	One domU just crashed when running a pkgsrc bulk build
> 	(60% completed):
> 
> panic: HYPERVISOR_mmu_update failed
> 
> Stopped in pid 27247.1 (gcc) at netbsd:cpu_Debugger+0x4:        leave
> cpu_Debugger(c033a025,caecfa78,cbedceec,6,1) at netbsd:cpu_Debugger+0x4
> panic(c033a940,c04d6cc0,0,0,0) at netbsd:panic+0x12e
> xpq_flush_queue(0,3,22,c08c0900,2) at netbsd:xpq_flush_queue+0x4a
> xennet_rx_push_buffer(c099e000,17,c08c0500,c08c0500,c08c0900) at netbsd:xennet_r
> x_push_buffer+0x9f
> xennet_rx_mbuf_free(c08c0900,caa1a000,42,c099ef80,0) at netbsd:xennet_rx_mbuf_fr
> ee+0x2e
> m_freem(c08c0900,1d0,caa1a022,14,20) at netbsd:m_freem+0x10c
> tcp_input(c08c0900,14,6,ca1be7b0,caecfc94) at netbsd:tcp_input+0x10cf
> ip_input(c08c0900,fffffffc,0,0,c0100b13) at netbsd:ip_input+0x572
> ipintr(fffffffe,20,4,0,caecfd04) at netbsd:ipintr+0xad
> DDB lost frame for netbsd:Xsoftnet+0x4f, trying 0xcaecfcc4
> Xsoftnet() at netbsd:Xsoftnet+0x4f

Hi,
I may have found the cause of this bug. I commited a fix to current, and
attached is a diff against netbsd-3. If you're seeing this panic often enouth,
please let me know if this helps.

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
     NetBSD: 26 ans d'experience feront toujours la difference
--

--zYM0uCDKw75PZbzx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: i386/pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/i386/pmap.c,v
retrieving revision 1.8.2.1
diff -u -r1.8.2.1 pmap.c
--- i386/pmap.c	21 Apr 2005 17:09:06 -0000	1.8.2.1
+++ i386/pmap.c	26 May 2005 13:55:08 -0000
@@ -854,6 +854,7 @@
 pte_atomic_update_ma(pt_entry_t *pte, pt_entry_t *mapte, pt_entry_t npte)
 {
 	pt_entry_t opte;
+	int s = splvm();
 
 	XENPRINTK(("pte_atomic_update_ma pte %p mapte %p npte %08x\n",
 		   pte, mapte, npte));
@@ -879,6 +880,7 @@
 			xpq_queue_pte_update(mapte, npte);
 	}
 	xpq_flush_queue();
+	splx(s);
 
 	return opte;
 }
@@ -1895,6 +1897,7 @@
 {
 	pd_entry_t *pdir = object;
 	paddr_t pdirpa;
+	int s;
 
 	/*
 	 * NOTE: The `pmap_lock' is held when the PDP is allocated.
@@ -1928,8 +1931,10 @@
 	pmap_update(pmap_kernel());
 
 	/* pin page type */
+	s = splvm();
 	xpq_queue_pin_table(xpmap_ptom(pdirpa), XPQ_PIN_L2_TABLE);
 	xpq_flush_queue();
+	splx(s);
 
 	return (0);
 }
@@ -1939,6 +1944,7 @@
 {
 	pd_entry_t *pdir = object;
 	paddr_t pdirpa;
+	int s;
 
 	/* fetch the physical address of the page directory. */
 	pdirpa = PDE_GET(&pdir[PDSLOT_PTE]) & PG_FRAME;
@@ -1946,8 +1952,10 @@
 	XENPRINTF(("pmap_pdp_dtor %p %p\n", pdir, (void *)pdirpa));
 
 	/* unpin page type */
+	s = splvm();
 	xpq_queue_unpin_table(xpmap_ptom(pdirpa));
 	xpq_flush_queue();
+	splx(s);
 	pmap_enter(pmap_kernel(), (vaddr_t)pdir, pdirpa,
 	    VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE);
 #if 0
Index: i386/xen_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/i386/xen_machdep.c,v
retrieving revision 1.6.2.1
diff -u -r1.6.2.1 xen_machdep.c
--- i386/xen_machdep.c	21 Apr 2005 17:09:19 -0000	1.6.2.1
+++ i386/xen_machdep.c	26 May 2005 13:55:08 -0000
@@ -94,6 +94,7 @@
 {
 	vaddr_t va;
 	pt_entry_t *ptp, *maptp;
+	int s;
 
 	for (va = base; va < base + entries * sizeof(union descriptor);
 	     va += PAGE_SIZE) {
@@ -104,10 +105,12 @@
 			      entries, ptp, maptp));
 		PTE_CLEARBITS(ptp, maptp, PG_RW);
 	}
+	s = splvm();
 	PTE_UPDATES_FLUSH();
 
 	xpq_queue_set_ldt(base, entries);
 	xpq_flush_queue();
+	splx(s);
 }
 
 void
@@ -684,12 +687,14 @@
 void
 xpq_flush_cache()
 {
+	int s = splvm();
 
 	XENPRINTK2(("xpq_queue_flush_cache\n"));
 	xpq_queue[xpq_idx].pa.ptr = MMU_EXTENDED_COMMAND;
 	xpq_queue[xpq_idx].pa.val = MMUEXT_FLUSH_CACHE;
 	xpq_increment_idx();
 	xpq_flush_queue();
+	splx(s);
 }
 
 
Index: include/xenfunc.h
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/include/xenfunc.h,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 xenfunc.h
--- include/xenfunc.h	1 May 2005 22:02:12 -0000	1.4.2.1
+++ include/xenfunc.h	26 May 2005 13:55:08 -0000
@@ -53,8 +53,10 @@
 static __inline void 
 invlpg(u_int addr)
 {
+	int s = splvm();
 	xpq_queue_invlpg(addr);
 	xpq_flush_queue();
+	splx(s);
 }  
 
 static __inline void
@@ -92,16 +94,20 @@
 static __inline void
 _lcr3(u_int val, char *file, int line)
 {
+	int s = splvm();
 /* 	__PRINTK(("lcr3 %08x at %s:%d\n", val, file, line)); */
 	xpq_queue_pt_switch(xpmap_ptom(val) & PG_FRAME);
 	xpq_flush_queue();
+	splx(s);
 }
 
 static __inline void
 tlbflush(void)
 {
+	int s = splvm();
 	xpq_queue_tlb_flush();
 	xpq_flush_queue();
+	splx(s);
 }
 
 #define	tlbflushg()	tlbflush()	/* we don't use PGE */
Index: include/xenpmap.h
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/include/xenpmap.h,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 xenpmap.h
--- include/xenpmap.h	21 Apr 2005 17:09:12 -0000	1.4.2.1
+++ include/xenpmap.h	26 May 2005 13:55:09 -0000
@@ -83,87 +83,129 @@
 #define	PDE_GET(_pdp)						\
 	(pmap_valid_entry(*(_pdp)) ? xpmap_mtop(*(_pdp)) : *(_pdp))
 #define PDE_SET(_pdp,_mapdp,_npde) do {				\
+	int s = splvm();					\
 	xpq_queue_pde_update((_mapdp), xpmap_ptom((_npde)));	\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PDE_CLEAR(_pdp,_mapdp) do {				\
+	int s = splvm();					\
 	xpq_queue_pde_update((_mapdp), 0);			\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define	PTE_GET(_ptp)						\
 	(pmap_valid_entry(*(_ptp)) ? xpmap_mtop(*(_ptp)) : *(_ptp))
 #define	PTE_GET_MA(_ptp)					\
 	*(_ptp)
 #define PTE_SET(_ptp,_maptp,_npte) do {				\
+	int s = splvm();					\
 	xpq_queue_pte_update((_maptp), xpmap_ptom((_npte)));	\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_SET_MA(_ptp,_maptp,_npte) do {			\
+	int s = splvm();					\
 	xpq_queue_pte_update((_maptp), (_npte));		\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_SET_MA_UNCHECKED(_ptp,_maptp,_npte) do {		\
+	s = splvm();						\
 	xpq_queue_unchecked_pte_update((_maptp), (_npte));	\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_CLEAR(_ptp,_maptp) do {				\
+	int s = splvm();					\
 	xpq_queue_pte_update((_maptp), 0);			\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_ATOMIC_SET(_ptp,_maptp,_npte,_opte) do {		\
+	int s;							\
 	(_opte) = PTE_GET(_ptp);				\
+	s = splvm();						\
 	xpq_queue_pte_update((_maptp), xpmap_ptom((_npte)));	\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_ATOMIC_SET_MA(_ptp,_maptp,_npte,_opte) do {		\
+	int s;							\
 	(_opte) = *(_ptp);					\
+	s = splvm();						\
 	xpq_queue_pte_update((_maptp), (_npte));		\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_ATOMIC_CLEAR(_ptp,_maptp,_opte) do {		\
+	int s;							\
 	(_opte) = PTE_GET(_ptp);				\
+	s = splvm();						\
 	xpq_queue_pte_update((_maptp), 0);			\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_ATOMIC_CLEAR_MA(_ptp,_maptp,_opte) do {		\
+	int s;							\
 	(_opte) = *(_ptp);					\
+	s = splvm();						\
 	xpq_queue_pte_update((_maptp), 0);			\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PDE_CLEARBITS(_pdp,_mapdp,_bits) do {			\
+	int s = splvm();					\
 	xpq_queue_pte_update((_mapdp), *(_pdp) & ~((_bits) & ~PG_FRAME)); \
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_CLEARBITS(_ptp,_maptp,_bits) do {			\
+	int s = splvm();					\
 	xpq_queue_pte_update((_maptp), *(_ptp) & ~((_bits) & ~PG_FRAME)); \
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PDE_ATOMIC_CLEARBITS(_pdp,_mapdp,_bits) do {		\
+	int s = splvm();					\
 	xpq_queue_pde_update((_mapdp), *(_pdp) & ~((_bits) & ~PG_FRAME)); \
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_ATOMIC_CLEARBITS(_ptp,_maptp,_bits) do {		\
+	int s = splvm();					\
 	xpq_queue_pte_update((_maptp), *(_ptp) & ~((_bits) & ~PG_FRAME)); \
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_SETBITS(_ptp,_maptp,_bits) do {			\
+	int s = splvm();					\
 	xpq_queue_pte_update((_maptp), *(_ptp) | ((_bits) & ~PG_FRAME)); \
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PDE_ATOMIC_SETBITS(_pdp,_mapdp,_bits) do {		\
+	int s = splvm();					\
 	xpq_queue_pde_update((_mapdp), *(_pdp) | ((_bits) & ~PG_FRAME)); \
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PTE_ATOMIC_SETBITS(_ptp,_maptp,_bits) do {		\
+	int s = splvm();					\
 	xpq_queue_pte_update((_maptp), *(_ptp) | ((_bits) & ~PG_FRAME)); \
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define PDE_COPY(_dpdp,_madpdp,_spdp) do {			\
+	int s = splvm();					\
 	xpq_queue_pde_update((_madpdp), *(_spdp));		\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 #define	PTE_UPDATES_FLUSH() do {				\
+	int s = splvm();					\
 	xpq_flush_queue();					\
+	splx(s);						\
 } while (/*CONSTCOND*/0)
 
 #endif
Index: xen/if_xennet.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/if_xennet.c,v
retrieving revision 1.13.2.8
diff -u -r1.13.2.8 if_xennet.c
--- xen/if_xennet.c	28 Apr 2005 10:28:53 -0000	1.13.2.8
+++ xen/if_xennet.c	26 May 2005 13:55:09 -0000
@@ -560,6 +560,7 @@
 {
 	NETIF_RING_IDX ringidx;
 	int nr_pfns;
+	int s;
 
 	ringidx = sc->sc_rx->req_prod;
 	nr_pfns = 0;
@@ -600,7 +601,9 @@
 	 * outstanding in the page update queue -- make sure we flush
 	 * those first!
 	 */
+	s = splvm();
 	xpq_flush_queue();
+	splx(s);
 
 	/* After all PTEs have been zapped we blow away stale TLB entries. */
 	rx_mcl[nr_pfns-1].args[2] = UVMF_FLUSH_TLB;
@@ -837,7 +845,7 @@
 	struct vm_page *pg;
 	int id, nr_pfns;
 	NETIF_RING_IDX ringidx;
-	int s;
+	int snet, svm;
 
 	ringidx = sc->sc_rx->req_prod;
 	if ((ringidx - sc->sc_rx_resp_cons) > (RX_MAX_ENTRIES / 2))
@@ -848,7 +856,7 @@
 	rxpages = uvm_km_valloc_align(kernel_map, RX_ENTRIES * PAGE_SIZE,
 	    PAGE_SIZE);
 
-	s = splnet();
+	snet = splnet();
 	for (va = rxpages; va < rxpages + RX_ENTRIES * PAGE_SIZE;
 	     va += PAGE_SIZE) {
 		pg = uvm_pagealloc(NULL, 0, NULL, 0);
@@ -893,7 +901,7 @@
 	}
 
 	if (nr_pfns == 0) {
-		splx(s);
+		splx(snet);
 		return;
 	}
 
@@ -902,7 +910,9 @@
 	 * outstanding in the page update queue -- make sure we flush
 	 * those first!
 	 */
+	svm = splvm();
 	xpq_flush_queue();
+	splx(svm);
 
 	/* After all PTEs have been zapped we blow away stale TLB entries. */
 	rx_mcl[nr_pfns-1].args[2] = UVMF_FLUSH_TLB;
@@ -925,7 +935,7 @@
 	/* Above is a suitable barrier to ensure backend will see requests. */
 	sc->sc_rx->req_prod = ringidx;
 
-	splx(s);
+	splx(snet);
 
 }
 

--zYM0uCDKw75PZbzx--