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
This commit is contained in:
parent
ecb0bac9ab
commit
b7ac5a8571
@ -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);
|
||||
|
@ -83,7 +83,7 @@ typedef u_char vm_prot_t; /* protection codes */
|
||||
#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;
|
||||
|
@ -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]);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user