Author: kib
Date: Sat May 12 20:49:58 2012
New Revision: 235375
URL: http://svn.freebsd.org/changeset/base/235375

Log:
  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

Modified:
  head/sys/vm/device_pager.c
  head/sys/vm/vm.h
  head/sys/vm/vm_pager.c
  head/sys/vm/vm_pager.h

Modified: head/sys/vm/device_pager.c
==============================================================================
--- head/sys/vm/device_pager.c  Sat May 12 20:49:02 2012        (r235374)
+++ head/sys/vm/device_pager.c  Sat May 12 20:49:58 2012        (r235375)
@@ -61,6 +61,7 @@ static void dev_pager_putpages(vm_object
                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 o
        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_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, v
        }
 
        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);

Modified: head/sys/vm/vm.h
==============================================================================
--- head/sys/vm/vm.h    Sat May 12 20:49:02 2012        (r235374)
+++ head/sys/vm/vm.h    Sat May 12 20:49:58 2012        (r235375)
@@ -83,7 +83,7 @@ typedef u_char vm_prot_t;     /* protection 
 #define        VM_PROT_DEFAULT         VM_PROT_ALL
 
 enum obj_type { OBJT_DEFAULT, OBJT_SWAP, OBJT_VNODE, OBJT_DEVICE, OBJT_PHYS,
-               OBJT_DEAD, OBJT_SG };
+               OBJT_DEAD, OBJT_SG, OBJT_MGTDEVICE };
 typedef u_char objtype_t;
 
 union vm_map_object;

Modified: head/sys/vm/vm_pager.c
==============================================================================
--- head/sys/vm/vm_pager.c      Sat May 12 20:49:02 2012        (r235374)
+++ head/sys/vm/vm_pager.c      Sat May 12 20:49:58 2012        (r235375)
@@ -159,7 +159,8 @@ struct pagerops *pagertab[] = {
        &devicepagerops,        /* OBJT_DEVICE */
        &physpagerops,          /* OBJT_PHYS */
        &deadpagerops,          /* OBJT_DEAD */
-       &sgpagerops             /* OBJT_SG */
+       &sgpagerops,            /* OBJT_SG */
+       &mgtdevicepagerops,     /* OBJT_MGTDEVICE */
 };
 
 static const int npagers = sizeof(pagertab) / sizeof(pagertab[0]);

Modified: head/sys/vm/vm_pager.h
==============================================================================
--- head/sys/vm/vm_pager.h      Sat May 12 20:49:02 2012        (r235374)
+++ head/sys/vm/vm_pager.h      Sat May 12 20:49:58 2012        (r235375)
@@ -71,6 +71,7 @@ extern struct pagerops vnodepagerops;
 extern struct pagerops devicepagerops;
 extern struct pagerops physpagerops;
 extern struct pagerops sgpagerops;
+extern struct pagerops mgtdevicepagerops;
 
 /*
  * get/put return values
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to