agp.ko panic: vm_fault: fault on nofault entry, addr: deadc000

John Baldwin jhb at freebsd.org
Thu Oct 25 12:19:36 PDT 2007


On Saturday 20 October 2007 10:30:31 pm pluknet wrote:
> Hello all.
> 
> I could produce panic while kldunload'ing agp.ko.
> 
> It's on 7.0-CURRENT from Oct 11 (just before RELENG_7), i386, UP,
> Intel 82855GME (855GME GMCH) SVGA controller.
> Some debugging below:
> 
> panic: vm_fault: fault on nofault entry, addr: deadc000
> KDB: enter: panic

This is caused by the agp_i810() driver calling agp_generic_detach() first 
which frees the memory resource for the aperture.  Other AGP drivers do the 
same thing.  I think the proper fix is to split agp_generic_detach() into two 
pieces.  The first part would do a destroy_dev() of the /dev node and the 
various agp_foo_detach() methods would call that first.  The rest 
agp_generic_detach() would be called at the end of the agp_foo_detach() 
methods.

A possible patch (untested) is at 
http://www.FreeBSD.org/~jhb/patches/agp_detach.patch and included below:

Index: agp.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp.c,v
retrieving revision 1.56
diff -u -r1.56 agp.c
--- agp.c	13 Jul 2007 16:28:11 -0000	1.56
+++ agp.c	25 Oct 2007 18:28:04 -0000
@@ -261,16 +261,31 @@
 	return 0;
 }
 
-int
-agp_generic_detach(device_t dev)
+void
+agp_free_cdev(device_t dev)
 {
 	struct agp_softc *sc = device_get_softc(dev);
 
 	destroy_dev(sc->as_devnode);
+}
+
+void
+agp_free_res(device_t dev)
+{
+	struct agp_softc *sc = device_get_softc(dev);
+
 	bus_release_resource(dev, SYS_RES_MEMORY, sc->as_aperture_rid,
 	    sc->as_aperture);
 	mtx_destroy(&sc->as_lock);
 	agp_flush_cache();
+}
+
+int
+agp_generic_detach(device_t dev)
+{
+
+	agp_free_cdev(dev);
+	agp_free_res(dev);
 	return 0;
 }
 
Index: agp_ali.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp_ali.c,v
retrieving revision 1.18
diff -u -r1.18 agp_ali.c
--- agp_ali.c	20 Dec 2005 21:12:26 -0000	1.18
+++ agp_ali.c	25 Oct 2007 18:29:55 -0000
@@ -141,12 +141,9 @@
 agp_ali_detach(device_t dev)
 {
 	struct agp_ali_softc *sc = device_get_softc(dev);
-	int error;
 	u_int32_t attbase;
 
-	error = agp_generic_detach(dev);
-	if (error)
-		return error;
+	agp_free_cdev(dev);
 
 	/* Disable the TLB.. */
 	pci_write_config(dev, AGP_ALI_TLBCTRL, 0x90, 1);
@@ -157,6 +154,7 @@
 	pci_write_config(dev, AGP_ALI_ATTBASE, attbase & 0xfff, 4);
 
 	agp_free_gatt(sc->gatt);
+	agp_free_res(dev);
 	return 0;
 }
 
Index: agp_amd.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp_amd.c,v
retrieving revision 1.23
diff -u -r1.23 agp_amd.c
--- agp_amd.c	20 Dec 2005 21:12:26 -0000	1.23
+++ agp_amd.c	25 Oct 2007 18:30:05 -0000
@@ -277,11 +277,8 @@
 agp_amd_detach(device_t dev)
 {
 	struct agp_amd_softc *sc = device_get_softc(dev);
-	int error;
 
-	error = agp_generic_detach(dev);
-	if (error)
-		return error;
+	agp_free_cdev(dev);
 
 	/* Disable the TLB.. */
 	WRITE2(AGP_AMD751_STATUS,
@@ -297,6 +294,7 @@
 	AGP_SET_APERTURE(dev, sc->initial_aperture);
 
 	agp_amd_free_gatt(sc->gatt);
+	agp_free_res(dev);
 
 	bus_release_resource(dev, SYS_RES_MEMORY,
 			     AGP_AMD751_REGISTERS, sc->regs);
Index: agp_amd64.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp_amd64.c,v
retrieving revision 1.14
diff -u -r1.14 agp_amd64.c
--- agp_amd64.c	9 Oct 2006 20:26:32 -0000	1.14
+++ agp_amd64.c	25 Oct 2007 18:29:48 -0000
@@ -250,10 +250,9 @@
 agp_amd64_detach(device_t dev)
 {
 	struct agp_amd64_softc *sc = device_get_softc(dev);
-	int i, error;
+	int i;
 
-	if ((error = agp_generic_detach(dev)))
-		return (error);
+	agp_free_cdev(dev);
 
 	for (i = 0; i < sc->n_mctrl; i++)
 		pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
@@ -262,6 +261,7 @@
 
 	AGP_SET_APERTURE(dev, sc->initial_aperture);
 	agp_free_gatt(sc->gatt);
+	agp_free_res(dev);
 
 	return (0);
 }
Index: agp_ati.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp_ati.c,v
retrieving revision 1.3
diff -u -r1.3 agp_ati.c
--- agp_ati.c	1 Sep 2006 02:22:17 -0000	1.3
+++ agp_ati.c	25 Oct 2007 18:30:50 -0000
@@ -248,18 +248,15 @@
 agp_ati_detach(device_t dev)
 {
 	struct agp_ati_softc *sc = device_get_softc(dev);
-	int error;
 	u_int32_t apsize_reg, temp;
 
+	agp_free_cdev(dev);
+
 	if (sc->is_rs300)
 		apsize_reg = ATI_RS300_APSIZE;
 	else
 		apsize_reg = ATI_RS100_APSIZE;
 
-	error = agp_generic_detach(dev);
-	if (error)
-		return error;
-
 	/* Clear the GATT base */
 	WRITE4(ATI_GART_BASE, 0);
 
@@ -273,6 +270,7 @@
 	free(sc->ag_virtual, M_AGP);
 
 	bus_release_resource(dev, SYS_RES_MEMORY, ATI_GART_MMADDR, sc->regs);
+	agp_free_res(dev);
 
 	return 0;
 }
Index: agp_i810.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp_i810.c,v
retrieving revision 1.41
diff -u -r1.41 agp_i810.c
--- agp_i810.c	15 Sep 2007 18:16:35 -0000	1.41
+++ agp_i810.c	25 Oct 2007 18:31:48 -0000
@@ -583,11 +583,8 @@
 agp_i810_detach(device_t dev)
 {
 	struct agp_i810_softc *sc = device_get_softc(dev);
-	int error;
 
-	error = agp_generic_detach(dev);
-	if (error)
-		return error;
+	agp_free_cdev(dev);
 
 	/* Clear the GATT base. */
 	if ( sc->chiptype == CHIP_I810 ) {
@@ -608,6 +605,7 @@
 	free(sc->gatt, M_AGP);
 
 	bus_release_resources(dev, sc->sc_res_spec, sc->sc_res);
+	agp_free_res(dev);
 
 	return 0;
 }
Index: agp_intel.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp_intel.c,v
retrieving revision 1.34
diff -u -r1.34 agp_intel.c
--- agp_intel.c	6 Jan 2007 08:31:31 -0000	1.34
+++ agp_intel.c	25 Oct 2007 18:32:13 -0000
@@ -262,13 +262,10 @@
 {
 	struct agp_intel_softc *sc;
 	u_int32_t reg;
-	int error;
 
 	sc = device_get_softc(dev);
 
-	error = agp_generic_detach(dev);
-	if (error)
-		return (error);
+	agp_free_cdev(dev);
 
 	/* Disable aperture accesses. */
 	switch (pci_get_devid(dev)) {
@@ -305,6 +302,7 @@
 	pci_write_config(dev, AGP_INTEL_ATTBASE, 0, 4);
 	AGP_SET_APERTURE(dev, sc->initial_aperture);
 	agp_free_gatt(sc->gatt);
+	agp_free_res(dev);
 
 	return (0);
 }
Index: agp_nvidia.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp_nvidia.c,v
retrieving revision 1.11
diff -u -r1.11 agp_nvidia.c
--- agp_nvidia.c	20 Dec 2005 21:12:26 -0000	1.11
+++ agp_nvidia.c	25 Oct 2007 18:32:37 -0000
@@ -247,12 +247,9 @@
 agp_nvidia_detach (device_t dev)
 {
 	struct agp_nvidia_softc *sc = device_get_softc(dev);
-	int error;
 	u_int32_t temp;
 
-	error = agp_generic_detach(dev);
-	if (error)
-		return (error);
+	agp_free_cdev(dev);
 
 	/* GART Control */
 	temp = pci_read_config(sc->dev, AGP_NVIDIA_0_APSIZE, 4);
@@ -270,6 +267,7 @@
 			 sc->initial_aperture);
 
 	agp_free_gatt(sc->gatt);
+	agp_free_res(dev);
 
 	return (0);
 }
Index: agp_sis.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp_sis.c,v
retrieving revision 1.20
diff -u -r1.20 agp_sis.c
--- agp_sis.c	30 May 2006 18:41:26 -0000	1.20
+++ agp_sis.c	25 Oct 2007 18:32:57 -0000
@@ -173,11 +173,8 @@
 agp_sis_detach(device_t dev)
 {
 	struct agp_sis_softc *sc = device_get_softc(dev);
-	int error;
 
-	error = agp_generic_detach(dev);
-	if (error)
-		return error;
+	agp_free_cdev(dev);
 
 	/* Disable the aperture.. */
 	pci_write_config(dev, AGP_SIS_WINCTRL,
@@ -190,6 +187,7 @@
 	AGP_SET_APERTURE(dev, sc->initial_aperture);
 
 	agp_free_gatt(sc->gatt);
+	agp_free_res(dev);
 	return 0;
 }
 
Index: agp_via.c
===================================================================
RCS file: /usr/cvs/src/sys/pci/agp_via.c,v
retrieving revision 1.24
diff -u -r1.24 agp_via.c
--- agp_via.c	21 Sep 2007 02:10:13 -0000	1.24
+++ agp_via.c	25 Oct 2007 18:33:18 -0000
@@ -240,16 +240,14 @@
 agp_via_detach(device_t dev)
 {
 	struct agp_via_softc *sc = device_get_softc(dev);
-	int error;
 
-	error = agp_generic_detach(dev);
-	if (error)
-		return error;
+	agp_free_cdev(dev);
 
 	pci_write_config(dev, sc->regs[REG_GARTCTRL], 0, 4);
 	pci_write_config(dev, sc->regs[REG_ATTBASE], 0, 4);
 	AGP_SET_APERTURE(dev, sc->initial_aperture);
 	agp_free_gatt(sc->gatt);
+	agp_free_res(dev);
 
 	return 0;
 }
Index: agppriv.h
===================================================================
RCS file: /usr/cvs/src/sys/pci/agppriv.h,v
retrieving revision 1.6
diff -u -r1.6 agppriv.h
--- agppriv.h	13 Jul 2007 16:28:12 -0000	1.6
+++ agppriv.h	25 Oct 2007 18:28:29 -0000
@@ -90,7 +90,9 @@
 u_int8_t		agp_find_caps(device_t dev);
 struct agp_gatt	       *agp_alloc_gatt(device_t dev);
 void			agp_set_aperture_resource(device_t dev, int rid);
+void			agp_free_cdev(device_t dev);
 void		        agp_free_gatt(struct agp_gatt *gatt);
+void			agp_free_res(device_t dev);
 int			agp_generic_attach(device_t dev);
 int			agp_generic_detach(device_t dev);
 int			agp_generic_get_aperture(device_t dev);

-- 
John Baldwin


More information about the freebsd-current mailing list