Subject: Re: port-xen/30153: Panic in domU when running a pkgsrc bulk build
To: None <port-xen-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: netbsd-bugs
Date: 05/26/2005 14:03:01
The following reply was made to PR port-xen/30153; it has been noted by GNATS.

From: Manuel Bouyer <bouyer@antioche.lip6.fr>
To: gnats-bugs@NetBSD.org
Cc: port-xen-maintainer@NetBSD.org, gnats-admin@NetBSD.org,
	netbsd-bugs@NetBSD.org
Subject: Re: port-xen/30153: Panic in domU when running a pkgsrc bulk build
Date: Thu, 26 May 2005 16:02:01 +0200

 --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--