svn commit: r273963 - head/sys/dev/agp

Tijl Coosemans tijl at FreeBSD.org
Sun Nov 2 11:26:40 UTC 2014


Author: tijl
Date: Sun Nov  2 11:26:37 2014
New Revision: 273963
URL: https://svnweb.freebsd.org/changeset/base/273963

Log:
  In agp(4) avoid the need to flush all cpu caches with wbinvd between
  updating the GTT and flushing the AGP TLB by storing the GTT in
  write-combining memory.
  
  On x86 flushing the AGP TLB is done by an I/O operation or a store to a
  MMIO register in uncacheable memory.  Both cases imply that WC buffers are
  flushed so no memory barriers are needed.
  
  On powerpc there is no WC memory type.  It maps to uncacheable memory and
  two stores to uncacheable memory, such as to the GTT and then to an MMIO
  register, are strongly ordered, so no memory barriers are needed either.
  
  MFC after:	1 month

Modified:
  head/sys/dev/agp/agp.c
  head/sys/dev/agp/agp_amd.c
  head/sys/dev/agp/agp_amd64.c
  head/sys/dev/agp/agp_apple.c
  head/sys/dev/agp/agp_ati.c
  head/sys/dev/agp/agp_i810.c
  head/sys/dev/agp/agppriv.h

Modified: head/sys/dev/agp/agp.c
==============================================================================
--- head/sys/dev/agp/agp.c	Sun Nov  2 09:52:22 2014	(r273962)
+++ head/sys/dev/agp/agp.c	Sun Nov  2 11:26:37 2014	(r273963)
@@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pcireg.h>
 
 #include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_param.h>
 #include <vm/vm_object.h>
 #include <vm/vm_page.h>
@@ -84,14 +86,6 @@ static devclass_t agp_devclass;
 
 /* Helper functions for implementing chipset mini drivers. */
 
-void
-agp_flush_cache()
-{
-#if defined(__i386__) || defined(__amd64__)
-	wbinvd();
-#endif
-}
-
 u_int8_t
 agp_find_caps(device_t dev)
 {
@@ -158,17 +152,16 @@ agp_alloc_gatt(device_t dev)
 		return 0;
 
 	gatt->ag_entries = entries;
-	gatt->ag_virtual = contigmalloc(entries * sizeof(u_int32_t), M_AGP, 0,
-					0, ~0, PAGE_SIZE, 0);
+	gatt->ag_virtual = (void *)kmem_alloc_contig(kernel_arena,
+	    entries * sizeof(u_int32_t), M_NOWAIT | M_ZERO, 0, ~0, PAGE_SIZE,
+	    0, VM_MEMATTR_WRITE_COMBINING);
 	if (!gatt->ag_virtual) {
 		if (bootverbose)
 			device_printf(dev, "contiguous allocation failed\n");
 		free(gatt, M_AGP);
 		return 0;
 	}
-	bzero(gatt->ag_virtual, entries * sizeof(u_int32_t));
 	gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
-	agp_flush_cache();
 
 	return gatt;
 }
@@ -176,8 +169,8 @@ agp_alloc_gatt(device_t dev)
 void
 agp_free_gatt(struct agp_gatt *gatt)
 {
-	contigfree(gatt->ag_virtual,
-		   gatt->ag_entries * sizeof(u_int32_t), M_AGP);
+	kmem_free(kernel_arena, (vm_offset_t)gatt->ag_virtual,
+	    gatt->ag_entries * sizeof(u_int32_t));
 	free(gatt, M_AGP);
 }
 
@@ -280,7 +273,6 @@ agp_free_res(device_t dev)
 		bus_release_resource(dev, SYS_RES_MEMORY, sc->as_aperture_rid,
 		    sc->as_aperture);
 	mtx_destroy(&sc->as_lock);
-	agp_flush_cache();
 }
 
 int
@@ -605,12 +597,6 @@ agp_generic_bind_memory(device_t dev, st
 	VM_OBJECT_WUNLOCK(mem->am_obj);
 
 	/*
-	 * Flush the cpu cache since we are providing a new mapping
-	 * for these pages.
-	 */
-	agp_flush_cache();
-
-	/*
 	 * Make sure the chipset gets the new mappings.
 	 */
 	AGP_FLUSH_TLB(dev);
@@ -668,7 +654,6 @@ agp_generic_unbind_memory(device_t dev, 
 	}
 	VM_OBJECT_WUNLOCK(mem->am_obj);
 		
-	agp_flush_cache();
 	AGP_FLUSH_TLB(dev);
 
 	mem->am_offset = 0;
@@ -1040,7 +1025,6 @@ agp_bind_pages(device_t dev, vm_page_t *
 		}
 	}
 
-	agp_flush_cache();
 	AGP_FLUSH_TLB(dev);
 
 	mtx_unlock(&sc->as_lock);
@@ -1063,7 +1047,6 @@ agp_unbind_pages(device_t dev, vm_size_t
 	for (i = 0; i < size; i += AGP_PAGE_SIZE)
 		AGP_UNBIND_PAGE(dev, offset + i);
 
-	agp_flush_cache();
 	AGP_FLUSH_TLB(dev);
 
 	mtx_unlock(&sc->as_lock);

Modified: head/sys/dev/agp/agp_amd.c
==============================================================================
--- head/sys/dev/agp/agp_amd.c	Sun Nov  2 09:52:22 2014	(r273962)
+++ head/sys/dev/agp/agp_amd.c	Sun Nov  2 11:26:37 2014	(r273963)
@@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pcireg.h>
 
 #include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_object.h>
 #include <vm/pmap.h>
 #include <machine/bus.h>
@@ -92,34 +94,35 @@ agp_amd_alloc_gatt(device_t dev)
 
 	/*
 	 * The AMD751 uses a page directory to map a non-contiguous
-	 * gatt so we don't need to use contigmalloc.
-	 * Malloc individual gatt pages and map them into the page
+	 * gatt so we don't need to use kmem_alloc_contig.
+	 * Allocate individual GATT pages and map them into the page
 	 * directory.
 	 */
 	gatt->ag_entries = entries;
-	gatt->ag_virtual = malloc(entries * sizeof(u_int32_t),
-				  M_AGP, M_NOWAIT);
+	gatt->ag_virtual = (void *)kmem_alloc_attr(kernel_arena,
+	    entries * sizeof(u_int32_t), M_NOWAIT | M_ZERO, 0, ~0,
+	    VM_MEMATTR_WRITE_COMBINING);
 	if (!gatt->ag_virtual) {
 		if (bootverbose)
 			device_printf(dev, "allocation failed\n");
 		free(gatt, M_AGP);
 		return 0;
 	}
-	bzero(gatt->ag_virtual, entries * sizeof(u_int32_t));
 
 	/*
 	 * Allocate the page directory.
 	 */
-	gatt->ag_vdir = malloc(AGP_PAGE_SIZE, M_AGP, M_NOWAIT);
+	gatt->ag_vdir = (void *)kmem_alloc_attr(kernel_arena, AGP_PAGE_SIZE,
+	    M_NOWAIT | M_ZERO, 0, ~0, VM_MEMATTR_WRITE_COMBINING);
 	if (!gatt->ag_vdir) {
 		if (bootverbose)
 			device_printf(dev,
 				      "failed to allocate page directory\n");
-		free(gatt->ag_virtual, M_AGP);
+		kmem_free(kernel_arena, (vm_offset_t)gatt->ag_virtual,
+		    entries * sizeof(u_int32_t));
 		free(gatt, M_AGP);
 		return 0;
 	}
-	bzero(gatt->ag_vdir, AGP_PAGE_SIZE);
 
 	gatt->ag_pdir = vtophys((vm_offset_t) gatt->ag_vdir);
 	if(bootverbose)
@@ -158,19 +161,15 @@ agp_amd_alloc_gatt(device_t dev)
 		gatt->ag_vdir[i + pdir_offset] = pa | 1;
 	}
 
-	/*
-	 * Make sure the chipset can see everything.
-	 */
-	agp_flush_cache();
-
 	return gatt;
 }
 
 static void
 agp_amd_free_gatt(struct agp_amd_gatt *gatt)
 {
-	free(gatt->ag_virtual, M_AGP);
-	free(gatt->ag_vdir, M_AGP);
+	kmem_free(kernel_arena, (vm_offset_t)gatt->ag_vdir, AGP_PAGE_SIZE);
+	kmem_free(kernel_arena, (vm_offset_t)gatt->ag_virtual,
+	    gatt->ag_entries * sizeof(u_int32_t));
 	free(gatt, M_AGP);
 }
 

Modified: head/sys/dev/agp/agp_amd64.c
==============================================================================
--- head/sys/dev/agp/agp_amd64.c	Sun Nov  2 09:52:22 2014	(r273962)
+++ head/sys/dev/agp/agp_amd64.c	Sun Nov  2 11:26:37 2014	(r273963)
@@ -241,8 +241,6 @@ agp_amd64_attach(device_t dev)
 		    4);
 	}
 
-	agp_flush_cache();
-
 	return (0);
 }
 

Modified: head/sys/dev/agp/agp_apple.c
==============================================================================
--- head/sys/dev/agp/agp_apple.c	Sun Nov  2 09:52:22 2014	(r273962)
+++ head/sys/dev/agp/agp_apple.c	Sun Nov  2 11:26:37 2014	(r273963)
@@ -224,8 +224,6 @@ agp_apple_bind_page(device_t dev, vm_off
 		return EINVAL;
 
 	sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical;
-	__asm __volatile("dcbst 0,%0; sync" ::
-	    "r"(&sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT]) : "memory");
 	return (0);
 }
 
@@ -238,8 +236,6 @@ agp_apple_unbind_page(device_t dev, vm_o
 		return EINVAL;
 
 	sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
-	__asm __volatile("dcbst 0,%0; sync" ::
-	    "r"(&sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT]) : "memory");
 	return (0);
 }
 

Modified: head/sys/dev/agp/agp_ati.c
==============================================================================
--- head/sys/dev/agp/agp_ati.c	Sun Nov  2 09:52:22 2014	(r273962)
+++ head/sys/dev/agp/agp_ati.c	Sun Nov  2 11:26:37 2014	(r273963)
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pcireg.h>
 
 #include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_object.h>
 #include <vm/pmap.h>
 #include <machine/bus.h>
@@ -129,20 +131,23 @@ agp_ati_alloc_gatt(device_t dev)
 
 	/* Alloc the GATT -- pointers to pages of AGP memory */
 	sc->ag_entries = entries;
-	sc->ag_virtual = malloc(entries * sizeof(u_int32_t), M_AGP,
-	    M_NOWAIT | M_ZERO);
+	sc->ag_virtual = (void *)kmem_alloc_attr(kernel_arena,
+	    entries * sizeof(u_int32_t), M_NOWAIT | M_ZERO, 0, ~0,
+	    VM_MEMATTR_WRITE_COMBINING);
 	if (sc->ag_virtual == NULL) {
 		if (bootverbose)
-			device_printf(dev, "aperture allocation failed\n");
+			device_printf(dev, "GATT allocation failed\n");
 		return ENOMEM;
 	}
 
 	/* Alloc the page directory -- pointers to each page of the GATT */
-	sc->ag_vdir = malloc(AGP_PAGE_SIZE, M_AGP, M_NOWAIT | M_ZERO);
+	sc->ag_vdir = (void *)kmem_alloc_attr(kernel_arena, AGP_PAGE_SIZE,
+	    M_NOWAIT | M_ZERO, 0, ~0, VM_MEMATTR_WRITE_COMBINING);
 	if (sc->ag_vdir == NULL) {
 		if (bootverbose)
 			device_printf(dev, "pagedir allocation failed\n");
-		free(sc->ag_virtual, M_AGP);
+		kmem_free(kernel_arena, (vm_offset_t)sc->ag_virtual,
+		    entries * sizeof(u_int32_t));
 		return ENOMEM;
 	}
 	sc->ag_pdir = vtophys((vm_offset_t)sc->ag_vdir);
@@ -158,11 +163,6 @@ agp_ati_alloc_gatt(device_t dev)
 		sc->ag_vdir[apbase_offset + i] = pa | 1;
 	}
 
-	/*
-	 * Make sure the chipset can see everything.
-	 */
-	agp_flush_cache();
-
 	return 0;
 }
 
@@ -264,8 +264,9 @@ agp_ati_detach(device_t dev)
 	temp = pci_read_config(dev, apsize_reg, 4);
 	pci_write_config(dev, apsize_reg, temp & ~1, 4);
 
-	free(sc->ag_vdir, M_AGP);
-	free(sc->ag_virtual, M_AGP);
+	kmem_free(kernel_arena, (vm_offset_t)sc->ag_vdir, AGP_PAGE_SIZE);
+	kmem_free(kernel_arena, (vm_offset_t)sc->ag_virtual,
+	    sc->ag_entries * sizeof(u_int32_t));
 
 	bus_release_resource(dev, SYS_RES_MEMORY, ATI_GART_MMADDR, sc->regs);
 	agp_free_res(dev);

Modified: head/sys/dev/agp/agp_i810.c
==============================================================================
--- head/sys/dev/agp/agp_i810.c	Sun Nov  2 09:52:22 2014	(r273962)
+++ head/sys/dev/agp/agp_i810.c	Sun Nov  2 11:26:37 2014	(r273963)
@@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/pci/pci_private.h>
 
 #include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_param.h>
 #include <vm/vm_object.h>
 #include <vm/vm_page.h>
@@ -1388,17 +1390,16 @@ agp_i810_install_gatt(device_t dev)
 		sc->dcache_size = 0;
 
 	/* According to the specs the gatt on the i810 must be 64k. */
-	sc->gatt->ag_virtual = contigmalloc(64 * 1024, M_AGP, 0, 0, ~0,
-	    PAGE_SIZE, 0);
+	sc->gatt->ag_virtual = (void *)kmem_alloc_contig(kernel_arena,
+	    64 * 1024, M_NOWAIT | M_ZERO, 0, ~0, PAGE_SIZE,
+	    0, VM_MEMATTR_WRITE_COMBINING);
 	if (sc->gatt->ag_virtual == NULL) {
 		if (bootverbose)
 			device_printf(dev, "contiguous allocation failed\n");
 		return (ENOMEM);
 	}
 
-	bzero(sc->gatt->ag_virtual, sc->gatt->ag_entries * sizeof(u_int32_t));
 	sc->gatt->ag_physical = vtophys((vm_offset_t)sc->gatt->ag_virtual);
-	agp_flush_cache();
 	/* Install the GATT. */
 	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
 	    sc->gatt->ag_physical | 1);
@@ -1497,7 +1498,7 @@ agp_i810_deinstall_gatt(device_t dev)
 
 	sc = device_get_softc(dev);
 	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, 0);
-	contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
+	kmem_free(kernel_arena, (vm_offset_t)sc->gatt->ag_virtual, 64 * 1024);
 }
 
 static void
@@ -2052,7 +2053,6 @@ agp_i810_bind_memory(device_t dev, struc
 			sc->match->driver->install_gtt_pte(dev, (offset + i) >>
 			    AGP_PAGE_SHIFT, mem->am_physical + i, 0);
 		}
-		agp_flush_cache();
 		mem->am_offset = offset;
 		mem->am_is_bound = 1;
 		mtx_unlock(&sc->agp.as_lock);
@@ -2093,7 +2093,6 @@ agp_i810_unbind_memory(device_t dev, str
 			sc->match->driver->install_gtt_pte(dev,
 			    (mem->am_offset + i) >> AGP_PAGE_SHIFT, 0, 0);
 		}
-		agp_flush_cache();
 		mem->am_is_bound = 0;
 		mtx_unlock(&sc->agp.as_lock);
 		return (0);

Modified: head/sys/dev/agp/agppriv.h
==============================================================================
--- head/sys/dev/agp/agppriv.h	Sun Nov  2 09:52:22 2014	(r273962)
+++ head/sys/dev/agp/agppriv.h	Sun Nov  2 11:26:37 2014	(r273963)
@@ -83,7 +83,6 @@ struct agp_gatt {
 	vm_offset_t	ag_physical;
 };
 
-void			agp_flush_cache(void);
 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);


More information about the svn-src-all mailing list