Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 28 Aug 2009 14:06:56 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r196615 - in head/sys: kern sys vm
Message-ID:  <200908281406.n7SE6uK6026804@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Fri Aug 28 14:06:55 2009
New Revision: 196615
URL: http://svn.freebsd.org/changeset/base/196615

Log:
  Extend the device pager to support different memory attributes on different
  pages in an object.
  - Add a new variant of d_mmap() currently called d_mmap2() which accepts
    an additional in/out parameter that is the memory attribute to use for
    the requested page.
  - A driver either uses d_mmap() or d_mmap2() for all requests but not both.
    The current implementation uses a flag in the cdevsw (D_MMAP2) to indicate
    that the driver provides a d_mmap2() handler instead of d_mmap().  This
    is done to make the change ABI compatible with existing drivers and
    MFC'able to 7 and 8.
  
  Submitted by:	alc
  MFC after:	1 month

Modified:
  head/sys/kern/kern_conf.c
  head/sys/sys/conf.h
  head/sys/sys/types.h
  head/sys/vm/device_pager.c
  head/sys/vm/vm.h

Modified: head/sys/kern/kern_conf.c
==============================================================================
--- head/sys/kern/kern_conf.c	Fri Aug 28 10:25:26 2009	(r196614)
+++ head/sys/kern/kern_conf.c	Fri Aug 28 14:06:55 2009	(r196615)
@@ -302,7 +302,7 @@ static struct cdevsw dead_cdevsw = {
 #define no_read		(d_read_t *)enodev
 #define no_write	(d_write_t *)enodev
 #define no_ioctl	(d_ioctl_t *)enodev
-#define no_mmap		(d_mmap_t *)enodev
+#define no_mmap		(d_mmap2_t *)enodev
 #define no_kqfilter	(d_kqfilter_t *)enodev
 #define no_mmap_single	(d_mmap_single_t *)enodev
 
@@ -469,7 +469,8 @@ giant_kqfilter(struct cdev *dev, struct 
 }
 
 static int
-giant_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
+giant_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot,
+    vm_memattr_t *memattr)
 {
 	struct cdevsw *dsw;
 	int retval;
@@ -478,7 +479,11 @@ giant_mmap(struct cdev *dev, vm_offset_t
 	if (dsw == NULL)
 		return (ENXIO);
 	mtx_lock(&Giant);
-	retval = dsw->d_gianttrick->d_mmap(dev, offset, paddr, nprot);
+	if (dsw->d_gianttrick->d_flags & D_MMAP2)
+		retval = dsw->d_gianttrick->d_mmap2(dev, offset, paddr, nprot,
+		    memattr);
+	else
+		retval = dsw->d_gianttrick->d_mmap(dev, offset, paddr, nprot);
 	mtx_unlock(&Giant);
 	dev_relthread(dev);
 	return (retval);
@@ -614,6 +619,7 @@ prep_cdevsw(struct cdevsw *devsw)
 		if (devsw->d_gianttrick == NULL) {
 			memcpy(dsw2, devsw, sizeof *dsw2);
 			devsw->d_gianttrick = dsw2;
+			devsw->d_flags |= D_MMAP2;
 			dsw2 = NULL;
 		}
 	}
@@ -634,7 +640,7 @@ prep_cdevsw(struct cdevsw *devsw)
 	FIXUP(d_write,		no_write,	giant_write);
 	FIXUP(d_ioctl,		no_ioctl,	giant_ioctl);
 	FIXUP(d_poll,		no_poll,	giant_poll);
-	FIXUP(d_mmap,		no_mmap,	giant_mmap);
+	FIXUP(d_mmap2,		no_mmap,	giant_mmap);
 	FIXUP(d_strategy,	no_strategy,	giant_strategy);
 	FIXUP(d_kqfilter,	no_kqfilter,	giant_kqfilter);
 	FIXUP(d_mmap_single,	no_mmap_single,	giant_mmap_single);

Modified: head/sys/sys/conf.h
==============================================================================
--- head/sys/sys/conf.h	Fri Aug 28 10:25:26 2009	(r196614)
+++ head/sys/sys/conf.h	Fri Aug 28 14:06:55 2009	(r196615)
@@ -137,6 +137,8 @@ typedef int d_poll_t(struct cdev *dev, i
 typedef int d_kqfilter_t(struct cdev *dev, struct knote *kn);
 typedef int d_mmap_t(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr,
    		     int nprot);
+typedef int d_mmap2_t(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr,
+		     int nprot, vm_memattr_t *memattr);
 typedef int d_mmap_single_t(struct cdev *cdev, vm_ooffset_t *offset,
     vm_size_t size, struct vm_object **object, int nprot);
 typedef void d_purge_t(struct cdev *dev);
@@ -170,6 +172,7 @@ typedef int dumper_t(
 #define D_PSEUDO	0x00200000	/* make_dev() can return NULL */
 #define D_NEEDGIANT	0x00400000	/* driver want Giant */
 #define	D_NEEDMINOR	0x00800000	/* driver uses clone_create() */
+#define	D_MMAP2		0x01000000	/* driver uses d_mmap2() */
 
 /*
  * Version numbers.
@@ -198,7 +201,10 @@ struct cdevsw {
 	d_write_t		*d_write;
 	d_ioctl_t		*d_ioctl;
 	d_poll_t		*d_poll;
-	d_mmap_t		*d_mmap;
+	union {
+		d_mmap_t		*old;
+		d_mmap2_t		*new;
+	} __d_mmap;
 	d_strategy_t		*d_strategy;
 	dumper_t		*d_dump;
 	d_kqfilter_t		*d_kqfilter;
@@ -218,6 +224,8 @@ struct cdevsw {
 		SLIST_ENTRY(cdevsw)	postfree_list;
 	} __d_giant;
 };
+#define	d_mmap			__d_mmap.old
+#define	d_mmap2			__d_mmap.new
 #define	d_gianttrick		__d_giant.gianttrick
 #define	d_postfree_list		__d_giant.postfree_list
 

Modified: head/sys/sys/types.h
==============================================================================
--- head/sys/sys/types.h	Fri Aug 28 10:25:26 2009	(r196614)
+++ head/sys/sys/types.h	Fri Aug 28 14:06:55 2009	(r196615)
@@ -299,6 +299,7 @@ typedef	__uint32_t	intrmask_t;	/* Interr
 
 typedef	__uintfptr_t	uintfptr_t;
 typedef	__uint64_t	uoff_t;
+typedef	char		vm_memattr_t;	/* memory attribute codes */
 typedef	struct vm_page	*vm_page_t;
 
 #define offsetof(type, field) __offsetof(type, field)

Modified: head/sys/vm/device_pager.c
==============================================================================
--- head/sys/vm/device_pager.c	Fri Aug 28 10:25:26 2009	(r196614)
+++ head/sys/vm/device_pager.c	Fri Aug 28 14:06:55 2009	(r196615)
@@ -93,6 +93,17 @@ dev_pager_init()
 	    UMA_ZONE_NOFREE|UMA_ZONE_VM); 
 }
 
+static __inline int
+dev_mmap(struct cdevsw *csw, struct cdev *dev, vm_offset_t offset,
+    vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr)
+{
+
+	if (csw->d_flags & D_MMAP2)
+		return (csw->d_mmap2(dev, offset, paddr, nprot, memattr));
+	else
+		return (csw->d_mmap(dev, offset, paddr, nprot));
+}
+
 /*
  * MPSAFE
  */
@@ -106,6 +117,7 @@ dev_pager_alloc(void *handle, vm_ooffset
 	unsigned int npages;
 	vm_paddr_t paddr;
 	vm_offset_t off;
+	vm_memattr_t dummy;
 	struct cdevsw *csw;
 
 	/*
@@ -133,7 +145,7 @@ dev_pager_alloc(void *handle, vm_ooffset
 	 */
 	npages = OFF_TO_IDX(size);
 	for (off = foff; npages--; off += PAGE_SIZE)
-		if ((*csw->d_mmap)(dev, off, &paddr, (int)prot) != 0) {
+		if (dev_mmap(csw, dev, off, &paddr, (int)prot, &dummy) != 0) {
 			dev_relthread(dev);
 			return (NULL);
 		}
@@ -214,7 +226,6 @@ dev_pager_getpages(object, m, count, req
 	vm_memattr_t memattr;
 	struct cdev *dev;
 	int i, ret;
-	int prot;
 	struct cdevsw *csw;
 	struct thread *td;
 	struct file *fpop;
@@ -228,12 +239,11 @@ dev_pager_getpages(object, m, count, req
 	csw = dev_refthread(dev);
 	if (csw == NULL)
 		panic("dev_pager_getpage: no cdevsw");
-	prot = PROT_READ;	/* XXX should pass in? */
-
 	td = curthread;
 	fpop = td->td_fpop;
 	td->td_fpop = NULL;
-	ret = (*csw->d_mmap)(dev, (vm_offset_t)offset << PAGE_SHIFT, &paddr, prot);
+	ret = dev_mmap(csw, dev, (vm_offset_t)offset << PAGE_SHIFT, &paddr,
+	    PROT_READ, &memattr);
 	KASSERT(ret == 0, ("dev_pager_getpage: map function returns error"));
 	td->td_fpop = fpop;
 	dev_relthread(dev);

Modified: head/sys/vm/vm.h
==============================================================================
--- head/sys/vm/vm.h	Fri Aug 28 10:25:26 2009	(r196614)
+++ head/sys/vm/vm.h	Fri Aug 28 14:06:55 2009	(r196615)
@@ -63,12 +63,6 @@
 
 #include <machine/vm.h>
 
-/*
- * The exact set of memory attributes is machine dependent.  However, every
- * machine is required to define VM_MEMATTR_DEFAULT.
- */
-typedef	char vm_memattr_t;	/* memory attribute codes */
-
 typedef char vm_inherit_t;	/* inheritance codes */
 
 #define	VM_INHERIT_SHARE	((vm_inherit_t) 0)
@@ -115,6 +109,12 @@ typedef struct vm_object *vm_object_t;
 typedef int boolean_t;
 
 /*
+ * The exact set of memory attributes is machine dependent.  However, every
+ * machine is required to define VM_MEMATTR_DEFAULT.
+ */
+typedef	char vm_memattr_t;	/* memory attribute codes */
+
+/*
  * This is defined in <sys/types.h> for the kernel so that vnode_if.h
  * doesn't have to include <vm/vm.h>.
  */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908281406.n7SE6uK6026804>