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