diff --git a/sys/vm/phys_pager.c b/sys/vm/phys_pager.c index 1fbc87bb95df..19a8b97a3d56 100644 --- a/sys/vm/phys_pager.c +++ b/sys/vm/phys_pager.c @@ -51,6 +51,20 @@ static struct pagerlst phys_pager_object_list; /* protect access to phys_pager_object_list */ static struct mtx phys_pager_mtx; +static int default_phys_pager_getpages(vm_object_t object, vm_page_t *m, + int count, int *rbehind, int *rahead); +static int default_phys_pager_populate(vm_object_t object, vm_pindex_t pidx, + int fault_type, vm_prot_t max_prot, vm_pindex_t *first, vm_pindex_t *last); +static boolean_t default_phys_pager_haspage(vm_object_t object, + vm_pindex_t pindex, int *before, int *after); +struct phys_pager_ops default_phys_pg_ops = { + .phys_pg_getpages = default_phys_pager_getpages, + .phys_pg_populate = default_phys_pager_populate, + .phys_pg_haspage = default_phys_pager_haspage, + .phys_pg_ctor = NULL, + .phys_pg_dtor = NULL, +}; + static void phys_pager_init(void) { @@ -59,12 +73,13 @@ phys_pager_init(void) mtx_init(&phys_pager_mtx, "phys_pager list", NULL, MTX_DEF); } -static vm_object_t -phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, - vm_ooffset_t foff, struct ucred *cred) +vm_object_t +phys_pager_allocate(void *handle, struct phys_pager_ops *ops, void *data, + vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff, struct ucred *cred) { vm_object_t object, object1; vm_pindex_t pindex; + bool init; /* * Offset should be page aligned. @@ -73,6 +88,7 @@ phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, return (NULL); pindex = OFF_TO_IDX(foff + PAGE_MASK + size); + init = true; if (handle != NULL) { mtx_lock(&phys_pager_mtx); @@ -97,11 +113,15 @@ phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, */ if (pindex > object->size) object->size = pindex; + init = false; } else { object = object1; object1 = NULL; object->handle = handle; - vm_object_set_flag(object, OBJ_POPULATE); + object->un_pager.phys.ops = ops; + object->un_pager.phys.data_ptr = data; + if (ops->phys_pg_populate != NULL) + vm_object_set_flag(object, OBJ_POPULATE); TAILQ_INSERT_TAIL(&phys_pager_object_list, object, pager_object_list); } @@ -113,12 +133,25 @@ phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, vm_object_deallocate(object1); } else { object = vm_object_allocate(OBJT_PHYS, pindex); - vm_object_set_flag(object, OBJ_POPULATE); + object->un_pager.phys.ops = ops; + object->un_pager.phys.data_ptr = data; + if (ops->phys_pg_populate != NULL) + vm_object_set_flag(object, OBJ_POPULATE); } + if (init && ops->phys_pg_ctor != NULL) + ops->phys_pg_ctor(object, prot, foff, cred); return (object); } +static vm_object_t +phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, + vm_ooffset_t foff, struct ucred *ucred) +{ + return (phys_pager_allocate(handle, &default_phys_pg_ops, NULL, + size, prot, foff, ucred)); +} + static void phys_pager_dealloc(vm_object_t object) { @@ -130,16 +163,18 @@ phys_pager_dealloc(vm_object_t object) mtx_unlock(&phys_pager_mtx); VM_OBJECT_WLOCK(object); } - object->handle = NULL; object->type = OBJT_DEAD; + if (object->un_pager.phys.ops->phys_pg_dtor != NULL) + object->un_pager.phys.ops->phys_pg_dtor(object); + object->handle = NULL; } /* * Fill as many pages as vm_fault has allocated for us. */ static int -phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind, - int *rahead) +default_phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, + int *rbehind, int *rahead) { int i; @@ -161,6 +196,14 @@ phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind, return (VM_PAGER_OK); } +static int +phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind, + int *rahead) +{ + return (object->un_pager.phys.ops->phys_pg_getpages(object, m, + count, rbehind, rahead)); +} + /* * Implement a pretty aggressive clustered getpages strategy. Hint that * everything in an entire 4MB window should be prefaulted at once. @@ -185,7 +228,7 @@ SYSCTL_INT(_vm, OID_AUTO, phys_pager_cluster, CTLFLAG_RWTUN, #define PHYSALLOC 16 static int -phys_pager_populate(vm_object_t object, vm_pindex_t pidx, +default_phys_pager_populate(vm_object_t object, vm_pindex_t pidx, int fault_type __unused, vm_prot_t max_prot __unused, vm_pindex_t *first, vm_pindex_t *last) { @@ -216,6 +259,14 @@ phys_pager_populate(vm_object_t object, vm_pindex_t pidx, return (VM_PAGER_OK); } +static int +phys_pager_populate(vm_object_t object, vm_pindex_t pidx, int fault_type, + vm_prot_t max_prot, vm_pindex_t *first, vm_pindex_t *last) +{ + return (object->un_pager.phys.ops->phys_pg_populate(object, pidx, + fault_type, max_prot, first, last)); +} + static void phys_pager_putpages(vm_object_t object, vm_page_t *m, int count, boolean_t sync, int *rtvals) @@ -225,7 +276,7 @@ phys_pager_putpages(vm_object_t object, vm_page_t *m, int count, boolean_t sync, } static boolean_t -phys_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, +default_phys_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, int *after) { vm_pindex_t base, end; @@ -239,6 +290,14 @@ phys_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, return (TRUE); } +static boolean_t +phys_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, + int *after) +{ + return (object->un_pager.phys.ops->phys_pg_haspage(object, pindex, + before, after)); +} + struct pagerops physpagerops = { .pgo_init = phys_pager_init, .pgo_alloc = phys_pager_alloc, diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 187ad63e8f55..35ea9cc45fae 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -286,6 +286,7 @@ vm_object_init(void) kernel_object->flags |= OBJ_COLORED; kernel_object->pg_color = (u_short)atop(VM_MIN_KERNEL_ADDRESS); #endif + kernel_object->un_pager.phys.ops = &default_phys_pg_ops; /* * The lock portion of struct vm_object must be type stable due diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index 007e945daa77..3c589bd4b42e 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -173,6 +173,17 @@ struct vm_object { struct pctrie swp_blks; vm_ooffset_t writemappings; } swp; + + /* + * Phys pager + */ + struct { + struct phys_pager_ops *ops; + union { + void *data_ptr; + uintptr_t data_val; + }; + } phys; } un_pager; struct ucred *cred; vm_ooffset_t charge; diff --git a/sys/vm/vm_pager.h b/sys/vm/vm_pager.h index afd6f556c231..a8f92eac59e3 100644 --- a/sys/vm/vm_pager.h +++ b/sys/vm/vm_pager.h @@ -227,5 +227,22 @@ vm_object_t cdev_pager_allocate(void *handle, enum obj_type tp, vm_object_t cdev_pager_lookup(void *handle); void cdev_pager_free_page(vm_object_t object, vm_page_t m); +struct phys_pager_ops { + int (*phys_pg_getpages)(vm_object_t vm_obj, vm_page_t *m, int count, + int *rbehind, int *rahead); + int (*phys_pg_populate)(vm_object_t vm_obj, vm_pindex_t pidx, + int fault_type, vm_prot_t max_prot, vm_pindex_t *first, + vm_pindex_t *last); + boolean_t (*phys_pg_haspage)(vm_object_t obj, vm_pindex_t pindex, + int *before, int *after); + void (*phys_pg_ctor)(vm_object_t vm_obj, vm_prot_t prot, + vm_ooffset_t foff, struct ucred *cred); + void (*phys_pg_dtor)(vm_object_t vm_obj); +}; +extern struct phys_pager_ops default_phys_pg_ops; +vm_object_t phys_pager_allocate(void *handle, struct phys_pager_ops *ops, + void *data, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff, + struct ucred *cred); + #endif /* _KERNEL */ #endif /* _VM_PAGER_ */