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

Nathan Whitehorn nwhitehorn at freebsd.org
Sun Nov 2 15:27:27 UTC 2014


There is actually a write-combining memory type on PowerPC. You can set 
it the same way as on x86 (with VM_MEMATTR_WRITE_COMBINING).
-Nathan

On 11/02/14 03:26, Tijl Coosemans wrote:
> 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