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
This commit is contained in:
parent
f105c8be8c
commit
2fa8c8d21e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=196615
@ -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 knote *kn)
|
||||
}
|
||||
|
||||
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 offset, vm_paddr_t *paddr, int nprot)
|
||||
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);
|
||||
|
@ -137,6 +137,8 @@ typedef int d_poll_t(struct cdev *dev, int events, struct thread *td);
|
||||
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
|
||||
|
||||
|
@ -299,6 +299,7 @@ typedef __uint32_t intrmask_t; /* Interrupt mask (spl, xxx_imask...) */
|
||||
|
||||
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)
|
||||
|
@ -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_t size, vm_prot_t prot,
|
||||
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_t size, vm_prot_t prot,
|
||||
*/
|
||||
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, reqpage)
|
||||
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, reqpage)
|
||||
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);
|
||||
|
12
sys/vm/vm.h
12
sys/vm/vm.h
@ -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)
|
||||
@ -114,6 +108,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>.
|
||||
|
Loading…
Reference in New Issue
Block a user