aboutsummaryrefslogtreecommitdiff
path: root/sys/vm/device_pager.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2012-05-12 20:49:58 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2012-05-12 20:49:58 +0000
commitb7ac5a85714c218faaf9e0803f0ba03015647cc1 (patch)
treebc20093a4c12f2f5f1f0c7cde134a59736672853 /sys/vm/device_pager.c
parentecb0bac9ab371a397376630dd87e71c6bc40feb7 (diff)
downloadsrc-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.c54
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);