diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2012-05-12 20:49:58 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2012-05-12 20:49:58 +0000 |
commit | b7ac5a85714c218faaf9e0803f0ba03015647cc1 (patch) | |
tree | bc20093a4c12f2f5f1f0c7cde134a59736672853 /sys/vm/device_pager.c | |
parent | ecb0bac9ab371a397376630dd87e71c6bc40feb7 (diff) | |
download | src-b7ac5a85714c218faaf9e0803f0ba03015647cc1.tar.gz src-b7ac5a85714c218faaf9e0803f0ba03015647cc1.zip |
Add new pager type, OBJT_MGTDEVICE. It provides the device pager
which carries fictitous managed pages. In particular, the consumers of
the new object type can remove all mappings of the device page with
pmap_remove_all().
The range of physical addresses used for fake page allocation shall be
registered with vm_phys_fictitious_reg_range() interface to allow the
PHYS_TO_VM_PAGE() to work in pmap.
Most likely, only i386 and amd64 pmaps can handle fictitious managed
pages right now.
Sponsored by: The FreeBSD Foundation
Reviewed by: alc
MFC after: 1 month
Notes
Notes:
svn path=/head/; revision=235375
Diffstat (limited to 'sys/vm/device_pager.c')
-rw-r--r-- | sys/vm/device_pager.c | 54 |
1 files changed, 46 insertions, 8 deletions
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c index 899369c44429..b3c795082e90 100644 --- a/sys/vm/device_pager.c +++ b/sys/vm/device_pager.c @@ -61,6 +61,7 @@ static void dev_pager_putpages(vm_object_t, vm_page_t *, int, boolean_t, int *); static boolean_t dev_pager_haspage(vm_object_t, vm_pindex_t, int *, int *); +static void dev_pager_free_page(vm_object_t object, vm_page_t m); /* list of device pager objects */ static struct pagerlst dev_pager_object_list; @@ -76,6 +77,14 @@ struct pagerops devicepagerops = { .pgo_haspage = dev_pager_haspage, }; +struct pagerops mgtdevicepagerops = { + .pgo_alloc = dev_pager_alloc, + .pgo_dealloc = dev_pager_dealloc, + .pgo_getpages = dev_pager_getpages, + .pgo_putpages = dev_pager_putpages, + .pgo_haspage = dev_pager_haspage, +}; + static int old_dev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff, struct ucred *cred, u_short *color); static void old_dev_pager_dtor(void *handle); @@ -115,7 +124,7 @@ cdev_pager_allocate(void *handle, enum obj_type tp, struct cdev_pager_ops *ops, vm_pindex_t pindex; u_short color; - if (tp != OBJT_DEVICE) + if (tp != OBJT_DEVICE && tp != OBJT_MGTDEVICE) return (NULL); /* @@ -196,6 +205,24 @@ cdev_pager_free_page(vm_object_t object, vm_page_t m) { VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); + if (object->type == OBJT_MGTDEVICE) { + KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("unmanaged %p", m)); + pmap_remove_all(m); + vm_page_lock(m); + vm_page_remove(m); + vm_page_unlock(m); + } else if (object->type == OBJT_DEVICE) + dev_pager_free_page(object, m); +} + +static void +dev_pager_free_page(vm_object_t object, vm_page_t m) +{ + + VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); + KASSERT((object->type == OBJT_DEVICE && + (m->oflags & VPO_UNMANAGED) != 0), + ("Managed device or page obj %p m %p", object, m)); TAILQ_REMOVE(&object->un_pager.devp.devp_pglist, m, pageq); vm_page_putfake(m); } @@ -213,11 +240,15 @@ dev_pager_dealloc(object) TAILQ_REMOVE(&dev_pager_object_list, object, pager_object_list); mtx_unlock(&dev_pager_mtx); VM_OBJECT_LOCK(object); - /* - * Free up our fake pages. - */ - while ((m = TAILQ_FIRST(&object->un_pager.devp.devp_pglist)) != NULL) - cdev_pager_free_page(object, m); + + if (object->type == OBJT_DEVICE) { + /* + * Free up our fake pages. + */ + while ((m = TAILQ_FIRST(&object->un_pager.devp.devp_pglist)) + != NULL) + dev_pager_free_page(object, m); + } } static int @@ -240,8 +271,15 @@ dev_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int reqpage) } if (error == VM_PAGER_OK) { - TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist, - ma[reqpage], pageq); + KASSERT((object->type == OBJT_DEVICE && + (ma[reqpage]->oflags & VPO_UNMANAGED) != 0) || + (object->type == OBJT_MGTDEVICE && + (ma[reqpage]->oflags & VPO_UNMANAGED) == 0), + ("Wrong page type %p %p", ma[reqpage], object)); + if (object->type == OBJT_DEVICE) { + TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist, + ma[reqpage], pageq); + } } return (error); |