Kernel crash on Asus A7N8X-X

John Baldwin jhb at freebsd.org
Thu Mar 6 13:44:13 UTC 2008


On Thursday 06 March 2008 08:31:26 am John Baldwin wrote:
> On Tuesday 04 March 2008 05:59:59 pm Frédéric PRACA wrote:
> > Hello dear hackers,
> > I own a Asus A7N8X-X motherboard (NForce2 chipset) with a Radeon 9600
> > video card. After upgrading from 6.3 to 7.0, I launched xorg which
> > crashed the kernel. After looking in the kernel core dump, I found that
> > the
> > agp_nvidia_flush_tlb function of /usr/src/sys/pci/agp_nvidia.c crashed on
> > the line 377. The loop fails from the beginning (when i==0). I commented
> > out the two last loops and it seems to work now but as I didn't
> > understand what is this code for, I'd like to have some explanation about
> > it and want to know if someone got the same problem.
>
> The Linux AGP driver has the same code.  It appears to be forcing a read of
> the TLB registers to force prior writes to clear the TLB entries to flush
> perhaps?  I'm not sure why you are getting a panic.  What kind of fault did
> you get?  (The original kernel panic messages would be needed.)

Actually, it looks like you have a 64MB aperture and with either a 32MB or 
64MB aperture this loop runs off the end of the GATT (GATT has 16384 entries 
* 4 bytes == 64k == 16 pages on x86) so if it dies before it starts the next 
loop that might explain it.  The patch below makes it walk the full GATT 
reading the first word from each page to force a flush w/o walking off the 
end of the GATT.

Actually, this is what appears to have happened:

(gdb) set $start = 0xd4d05000  (ag_virtual)
(gdb) set $fva = 3570491392    (eva in trap_pfault() frame)
(gdb) p ($fva - $start) / 4
$2 = 17408

That's well over your current ag_entries of 16384.  Try this patch (note 
Linux's in-kernel agp driver has the same bug):

Index: agp_nvidia.c
===================================================================
RCS file: /host/cvs/usr/cvs/src/sys/dev/agp/agp_nvidia.c,v
retrieving revision 1.13
diff -u -r1.13 agp_nvidia.c
--- agp_nvidia.c	12 Nov 2007 21:51:37 -0000	1.13
+++ agp_nvidia.c	6 Mar 2008 13:37:43 -0000
@@ -347,7 +347,7 @@
 	struct agp_nvidia_softc *sc;
 	u_int32_t wbc_reg, temp;
 	volatile u_int32_t *ag_virtual;
-	int i;
+	int i, pages;
 
 	sc = (struct agp_nvidia_softc *)device_get_softc(dev);
 
@@ -373,9 +373,10 @@
 	ag_virtual = (volatile u_int32_t *)sc->gatt->ag_virtual;
 
 	/* Flush TLB entries. */
-	for(i = 0; i < 32 + 1; i++)
+	pages = sc->gatt->ag_entries * sizeof(u_int32_t) / PAGE_SIZE;
+	for(i = 0; i < pages; i++)
 		temp = ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
-	for(i = 0; i < 32 + 1; i++)
+	for(i = 0; i < pages; i++)
 		temp = ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
 
 	return (0);

-- 
John Baldwin


More information about the freebsd-hackers mailing list