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 0x0020 /* make_dev() can return NULL */
#define D_NEEDGIANT0x0040 /* driver want Giant */
#defineD_NEEDMINOR 0x0080 /* driver uses clone_create() */
+#defineD_MMAP2 0x0100 /* 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)