1acaa9ee9SHemant Agrawal /* SPDX-License-Identifier: BSD-3-Clause 2acaa9ee9SHemant Agrawal * Copyright(c) 2010-2014 Intel Corporation 3acaa9ee9SHemant Agrawal */ 4acaa9ee9SHemant Agrawal 5acaa9ee9SHemant Agrawal #include <sys/cdefs.h> 6acaa9ee9SHemant Agrawal __FBSDID("$FreeBSD$"); 7acaa9ee9SHemant Agrawal 8acaa9ee9SHemant Agrawal #include <sys/param.h> 9acaa9ee9SHemant Agrawal #include <sys/bio.h> 10acaa9ee9SHemant Agrawal #include <sys/bus.h> 11acaa9ee9SHemant Agrawal #include <sys/conf.h> 12acaa9ee9SHemant Agrawal #include <sys/kernel.h> 13acaa9ee9SHemant Agrawal #include <sys/malloc.h> 14acaa9ee9SHemant Agrawal #include <sys/module.h> 15acaa9ee9SHemant Agrawal #include <sys/proc.h> 161c7191e7SBruce Richardson #include <sys/lock.h> 17acaa9ee9SHemant Agrawal #include <sys/rwlock.h> 181c7191e7SBruce Richardson #include <sys/mutex.h> 19acaa9ee9SHemant Agrawal #include <sys/systm.h> 20acaa9ee9SHemant Agrawal #include <sys/sysctl.h> 21acaa9ee9SHemant Agrawal #include <sys/vmmeter.h> 221c7191e7SBruce Richardson #include <sys/eventhandler.h> 23acaa9ee9SHemant Agrawal 24acaa9ee9SHemant Agrawal #include <machine/bus.h> 25acaa9ee9SHemant Agrawal 26acaa9ee9SHemant Agrawal #include <vm/vm.h> 27acaa9ee9SHemant Agrawal #include <vm/pmap.h> 28acaa9ee9SHemant Agrawal #include <vm/vm_param.h> 29acaa9ee9SHemant Agrawal #include <vm/vm_object.h> 30acaa9ee9SHemant Agrawal #include <vm/vm_page.h> 31acaa9ee9SHemant Agrawal #include <vm/vm_pager.h> 32acaa9ee9SHemant Agrawal #include <vm/vm_phys.h> 33acaa9ee9SHemant Agrawal 34acaa9ee9SHemant Agrawal struct contigmem_buffer { 35acaa9ee9SHemant Agrawal void *addr; 36acaa9ee9SHemant Agrawal int refcnt; 37acaa9ee9SHemant Agrawal struct mtx mtx; 38acaa9ee9SHemant Agrawal }; 39acaa9ee9SHemant Agrawal 40acaa9ee9SHemant Agrawal struct contigmem_vm_handle { 41acaa9ee9SHemant Agrawal int buffer_index; 42acaa9ee9SHemant Agrawal }; 43acaa9ee9SHemant Agrawal 44acaa9ee9SHemant Agrawal static int contigmem_load(void); 45acaa9ee9SHemant Agrawal static int contigmem_unload(void); 46acaa9ee9SHemant Agrawal static int contigmem_physaddr(SYSCTL_HANDLER_ARGS); 47acaa9ee9SHemant Agrawal 48acaa9ee9SHemant Agrawal static d_mmap_single_t contigmem_mmap_single; 49acaa9ee9SHemant Agrawal static d_open_t contigmem_open; 50acaa9ee9SHemant Agrawal static d_close_t contigmem_close; 51acaa9ee9SHemant Agrawal 52acaa9ee9SHemant Agrawal static int contigmem_num_buffers = RTE_CONTIGMEM_DEFAULT_NUM_BUFS; 53acaa9ee9SHemant Agrawal static int64_t contigmem_buffer_size = RTE_CONTIGMEM_DEFAULT_BUF_SIZE; 54*cbe57f35SDmitry Kozlyuk static bool contigmem_coredump_enable; 55acaa9ee9SHemant Agrawal 56acaa9ee9SHemant Agrawal static eventhandler_tag contigmem_eh_tag; 57acaa9ee9SHemant Agrawal static struct contigmem_buffer contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; 58acaa9ee9SHemant Agrawal static struct cdev *contigmem_cdev = NULL; 59acaa9ee9SHemant Agrawal static int contigmem_refcnt; 60acaa9ee9SHemant Agrawal 61acaa9ee9SHemant Agrawal TUNABLE_INT("hw.contigmem.num_buffers", &contigmem_num_buffers); 62acaa9ee9SHemant Agrawal TUNABLE_QUAD("hw.contigmem.buffer_size", &contigmem_buffer_size); 63*cbe57f35SDmitry Kozlyuk TUNABLE_BOOL("hw.contigmem.coredump_enable", &contigmem_coredump_enable); 64acaa9ee9SHemant Agrawal 65acaa9ee9SHemant Agrawal static SYSCTL_NODE(_hw, OID_AUTO, contigmem, CTLFLAG_RD, 0, "contigmem"); 66acaa9ee9SHemant Agrawal 67acaa9ee9SHemant Agrawal SYSCTL_INT(_hw_contigmem, OID_AUTO, num_buffers, CTLFLAG_RD, 68acaa9ee9SHemant Agrawal &contigmem_num_buffers, 0, "Number of contigmem buffers allocated"); 69acaa9ee9SHemant Agrawal SYSCTL_QUAD(_hw_contigmem, OID_AUTO, buffer_size, CTLFLAG_RD, 70acaa9ee9SHemant Agrawal &contigmem_buffer_size, 0, "Size of each contiguous buffer"); 71acaa9ee9SHemant Agrawal SYSCTL_INT(_hw_contigmem, OID_AUTO, num_references, CTLFLAG_RD, 72acaa9ee9SHemant Agrawal &contigmem_refcnt, 0, "Number of references to contigmem"); 73*cbe57f35SDmitry Kozlyuk SYSCTL_BOOL(_hw_contigmem, OID_AUTO, coredump_enable, CTLFLAG_RD, 74*cbe57f35SDmitry Kozlyuk &contigmem_coredump_enable, 0, "Include mapped buffers in core dump"); 75acaa9ee9SHemant Agrawal 76acaa9ee9SHemant Agrawal static SYSCTL_NODE(_hw_contigmem, OID_AUTO, physaddr, CTLFLAG_RD, 0, 77acaa9ee9SHemant Agrawal "physaddr"); 78acaa9ee9SHemant Agrawal 79acaa9ee9SHemant Agrawal MALLOC_DEFINE(M_CONTIGMEM, "contigmem", "contigmem(4) allocations"); 80acaa9ee9SHemant Agrawal 81acaa9ee9SHemant Agrawal static int contigmem_modevent(module_t mod, int type, void *arg) 82acaa9ee9SHemant Agrawal { 83acaa9ee9SHemant Agrawal int error = 0; 84acaa9ee9SHemant Agrawal 85acaa9ee9SHemant Agrawal switch (type) { 86acaa9ee9SHemant Agrawal case MOD_LOAD: 87acaa9ee9SHemant Agrawal error = contigmem_load(); 88acaa9ee9SHemant Agrawal break; 89acaa9ee9SHemant Agrawal case MOD_UNLOAD: 90acaa9ee9SHemant Agrawal error = contigmem_unload(); 91acaa9ee9SHemant Agrawal break; 92acaa9ee9SHemant Agrawal default: 93acaa9ee9SHemant Agrawal break; 94acaa9ee9SHemant Agrawal } 95acaa9ee9SHemant Agrawal 96acaa9ee9SHemant Agrawal return error; 97acaa9ee9SHemant Agrawal } 98acaa9ee9SHemant Agrawal 99acaa9ee9SHemant Agrawal moduledata_t contigmem_mod = { 100acaa9ee9SHemant Agrawal "contigmem", 101acaa9ee9SHemant Agrawal (modeventhand_t)contigmem_modevent, 102acaa9ee9SHemant Agrawal 0 103acaa9ee9SHemant Agrawal }; 104acaa9ee9SHemant Agrawal 105acaa9ee9SHemant Agrawal DECLARE_MODULE(contigmem, contigmem_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); 106acaa9ee9SHemant Agrawal MODULE_VERSION(contigmem, 1); 107acaa9ee9SHemant Agrawal 108acaa9ee9SHemant Agrawal static struct cdevsw contigmem_ops = { 109acaa9ee9SHemant Agrawal .d_name = "contigmem", 110acaa9ee9SHemant Agrawal .d_version = D_VERSION, 111acaa9ee9SHemant Agrawal .d_flags = D_TRACKCLOSE, 112acaa9ee9SHemant Agrawal .d_mmap_single = contigmem_mmap_single, 113acaa9ee9SHemant Agrawal .d_open = contigmem_open, 114acaa9ee9SHemant Agrawal .d_close = contigmem_close, 115acaa9ee9SHemant Agrawal }; 116acaa9ee9SHemant Agrawal 117acaa9ee9SHemant Agrawal static int 11812b7ef3cSBruce Richardson contigmem_load(void) 119acaa9ee9SHemant Agrawal { 120acaa9ee9SHemant Agrawal char index_string[8], description[32]; 121acaa9ee9SHemant Agrawal int i, error = 0; 122acaa9ee9SHemant Agrawal void *addr; 123acaa9ee9SHemant Agrawal 124acaa9ee9SHemant Agrawal if (contigmem_num_buffers > RTE_CONTIGMEM_MAX_NUM_BUFS) { 125acaa9ee9SHemant Agrawal printf("%d buffers requested is greater than %d allowed\n", 126acaa9ee9SHemant Agrawal contigmem_num_buffers, RTE_CONTIGMEM_MAX_NUM_BUFS); 127acaa9ee9SHemant Agrawal error = EINVAL; 128acaa9ee9SHemant Agrawal goto error; 129acaa9ee9SHemant Agrawal } 130acaa9ee9SHemant Agrawal 131acaa9ee9SHemant Agrawal if (contigmem_buffer_size < PAGE_SIZE || 132acaa9ee9SHemant Agrawal (contigmem_buffer_size & (contigmem_buffer_size - 1)) != 0) { 133acaa9ee9SHemant Agrawal printf("buffer size 0x%lx is not greater than PAGE_SIZE and " 134acaa9ee9SHemant Agrawal "power of two\n", contigmem_buffer_size); 135acaa9ee9SHemant Agrawal error = EINVAL; 136acaa9ee9SHemant Agrawal goto error; 137acaa9ee9SHemant Agrawal } 138acaa9ee9SHemant Agrawal 139acaa9ee9SHemant Agrawal for (i = 0; i < contigmem_num_buffers; i++) { 140acaa9ee9SHemant Agrawal addr = contigmalloc(contigmem_buffer_size, M_CONTIGMEM, M_ZERO, 141acaa9ee9SHemant Agrawal 0, BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); 142acaa9ee9SHemant Agrawal if (addr == NULL) { 143acaa9ee9SHemant Agrawal printf("contigmalloc failed for buffer %d\n", i); 144acaa9ee9SHemant Agrawal error = ENOMEM; 145acaa9ee9SHemant Agrawal goto error; 146acaa9ee9SHemant Agrawal } 147acaa9ee9SHemant Agrawal 148acaa9ee9SHemant Agrawal printf("%2u: virt=%p phys=%p\n", i, addr, 149acaa9ee9SHemant Agrawal (void *)pmap_kextract((vm_offset_t)addr)); 150acaa9ee9SHemant Agrawal 151acaa9ee9SHemant Agrawal mtx_init(&contigmem_buffers[i].mtx, "contigmem", NULL, MTX_DEF); 152acaa9ee9SHemant Agrawal contigmem_buffers[i].addr = addr; 153acaa9ee9SHemant Agrawal contigmem_buffers[i].refcnt = 0; 154acaa9ee9SHemant Agrawal 155acaa9ee9SHemant Agrawal snprintf(index_string, sizeof(index_string), "%d", i); 156acaa9ee9SHemant Agrawal snprintf(description, sizeof(description), 157acaa9ee9SHemant Agrawal "phys addr for buffer %d", i); 158acaa9ee9SHemant Agrawal SYSCTL_ADD_PROC(NULL, 159acaa9ee9SHemant Agrawal &SYSCTL_NODE_CHILDREN(_hw_contigmem, physaddr), OID_AUTO, 160acaa9ee9SHemant Agrawal index_string, CTLTYPE_U64 | CTLFLAG_RD, 161acaa9ee9SHemant Agrawal (void *)(uintptr_t)i, 0, contigmem_physaddr, "LU", 162acaa9ee9SHemant Agrawal description); 163acaa9ee9SHemant Agrawal } 164acaa9ee9SHemant Agrawal 165acaa9ee9SHemant Agrawal contigmem_cdev = make_dev_credf(0, &contigmem_ops, 0, NULL, UID_ROOT, 166acaa9ee9SHemant Agrawal GID_WHEEL, 0600, "contigmem"); 167acaa9ee9SHemant Agrawal 168acaa9ee9SHemant Agrawal return 0; 169acaa9ee9SHemant Agrawal 170acaa9ee9SHemant Agrawal error: 171acaa9ee9SHemant Agrawal for (i = 0; i < contigmem_num_buffers; i++) { 1723df95133SJim Harris if (contigmem_buffers[i].addr != NULL) { 173acaa9ee9SHemant Agrawal contigfree(contigmem_buffers[i].addr, 174acaa9ee9SHemant Agrawal contigmem_buffer_size, M_CONTIGMEM); 1753df95133SJim Harris contigmem_buffers[i].addr = NULL; 1763df95133SJim Harris } 177acaa9ee9SHemant Agrawal if (mtx_initialized(&contigmem_buffers[i].mtx)) 178acaa9ee9SHemant Agrawal mtx_destroy(&contigmem_buffers[i].mtx); 179acaa9ee9SHemant Agrawal } 180acaa9ee9SHemant Agrawal 181acaa9ee9SHemant Agrawal return error; 182acaa9ee9SHemant Agrawal } 183acaa9ee9SHemant Agrawal 184acaa9ee9SHemant Agrawal static int 18512b7ef3cSBruce Richardson contigmem_unload(void) 186acaa9ee9SHemant Agrawal { 187acaa9ee9SHemant Agrawal int i; 188acaa9ee9SHemant Agrawal 189acaa9ee9SHemant Agrawal if (contigmem_refcnt > 0) 190acaa9ee9SHemant Agrawal return EBUSY; 191acaa9ee9SHemant Agrawal 192acaa9ee9SHemant Agrawal if (contigmem_cdev != NULL) 193acaa9ee9SHemant Agrawal destroy_dev(contigmem_cdev); 194acaa9ee9SHemant Agrawal 195acaa9ee9SHemant Agrawal if (contigmem_eh_tag != NULL) 196acaa9ee9SHemant Agrawal EVENTHANDLER_DEREGISTER(process_exit, contigmem_eh_tag); 197acaa9ee9SHemant Agrawal 198acaa9ee9SHemant Agrawal for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) { 199acaa9ee9SHemant Agrawal if (contigmem_buffers[i].addr != NULL) 200acaa9ee9SHemant Agrawal contigfree(contigmem_buffers[i].addr, 201acaa9ee9SHemant Agrawal contigmem_buffer_size, M_CONTIGMEM); 202acaa9ee9SHemant Agrawal if (mtx_initialized(&contigmem_buffers[i].mtx)) 203acaa9ee9SHemant Agrawal mtx_destroy(&contigmem_buffers[i].mtx); 204acaa9ee9SHemant Agrawal } 205acaa9ee9SHemant Agrawal 206acaa9ee9SHemant Agrawal return 0; 207acaa9ee9SHemant Agrawal } 208acaa9ee9SHemant Agrawal 209acaa9ee9SHemant Agrawal static int 210acaa9ee9SHemant Agrawal contigmem_physaddr(SYSCTL_HANDLER_ARGS) 211acaa9ee9SHemant Agrawal { 212acaa9ee9SHemant Agrawal uint64_t physaddr; 213acaa9ee9SHemant Agrawal int index = (int)(uintptr_t)arg1; 214acaa9ee9SHemant Agrawal 215acaa9ee9SHemant Agrawal physaddr = (uint64_t)vtophys(contigmem_buffers[index].addr); 216acaa9ee9SHemant Agrawal return sysctl_handle_64(oidp, &physaddr, 0, req); 217acaa9ee9SHemant Agrawal } 218acaa9ee9SHemant Agrawal 219acaa9ee9SHemant Agrawal static int 220acaa9ee9SHemant Agrawal contigmem_open(struct cdev *cdev, int fflags, int devtype, 221acaa9ee9SHemant Agrawal struct thread *td) 222acaa9ee9SHemant Agrawal { 223acaa9ee9SHemant Agrawal 224acaa9ee9SHemant Agrawal atomic_add_int(&contigmem_refcnt, 1); 225acaa9ee9SHemant Agrawal 226acaa9ee9SHemant Agrawal return 0; 227acaa9ee9SHemant Agrawal } 228acaa9ee9SHemant Agrawal 229acaa9ee9SHemant Agrawal static int 230acaa9ee9SHemant Agrawal contigmem_close(struct cdev *cdev, int fflags, int devtype, 231acaa9ee9SHemant Agrawal struct thread *td) 232acaa9ee9SHemant Agrawal { 233acaa9ee9SHemant Agrawal 234acaa9ee9SHemant Agrawal atomic_subtract_int(&contigmem_refcnt, 1); 235acaa9ee9SHemant Agrawal 236acaa9ee9SHemant Agrawal return 0; 237acaa9ee9SHemant Agrawal } 238acaa9ee9SHemant Agrawal 239acaa9ee9SHemant Agrawal static int 240acaa9ee9SHemant Agrawal contigmem_cdev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, 241acaa9ee9SHemant Agrawal vm_ooffset_t foff, struct ucred *cred, u_short *color) 242acaa9ee9SHemant Agrawal { 243acaa9ee9SHemant Agrawal struct contigmem_vm_handle *vmh = handle; 244acaa9ee9SHemant Agrawal struct contigmem_buffer *buf; 245acaa9ee9SHemant Agrawal 246acaa9ee9SHemant Agrawal buf = &contigmem_buffers[vmh->buffer_index]; 247acaa9ee9SHemant Agrawal 248acaa9ee9SHemant Agrawal atomic_add_int(&contigmem_refcnt, 1); 249acaa9ee9SHemant Agrawal 250acaa9ee9SHemant Agrawal mtx_lock(&buf->mtx); 251acaa9ee9SHemant Agrawal if (buf->refcnt == 0) 252acaa9ee9SHemant Agrawal memset(buf->addr, 0, contigmem_buffer_size); 253acaa9ee9SHemant Agrawal buf->refcnt++; 254acaa9ee9SHemant Agrawal mtx_unlock(&buf->mtx); 255acaa9ee9SHemant Agrawal 256acaa9ee9SHemant Agrawal return 0; 257acaa9ee9SHemant Agrawal } 258acaa9ee9SHemant Agrawal 259acaa9ee9SHemant Agrawal static void 260acaa9ee9SHemant Agrawal contigmem_cdev_pager_dtor(void *handle) 261acaa9ee9SHemant Agrawal { 262acaa9ee9SHemant Agrawal struct contigmem_vm_handle *vmh = handle; 263acaa9ee9SHemant Agrawal struct contigmem_buffer *buf; 264acaa9ee9SHemant Agrawal 265acaa9ee9SHemant Agrawal buf = &contigmem_buffers[vmh->buffer_index]; 266acaa9ee9SHemant Agrawal 267acaa9ee9SHemant Agrawal mtx_lock(&buf->mtx); 268acaa9ee9SHemant Agrawal buf->refcnt--; 269acaa9ee9SHemant Agrawal mtx_unlock(&buf->mtx); 270acaa9ee9SHemant Agrawal 271acaa9ee9SHemant Agrawal free(vmh, M_CONTIGMEM); 272acaa9ee9SHemant Agrawal 273acaa9ee9SHemant Agrawal atomic_subtract_int(&contigmem_refcnt, 1); 274acaa9ee9SHemant Agrawal } 275acaa9ee9SHemant Agrawal 276acaa9ee9SHemant Agrawal static int 277acaa9ee9SHemant Agrawal contigmem_cdev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot, 278acaa9ee9SHemant Agrawal vm_page_t *mres) 279acaa9ee9SHemant Agrawal { 280acaa9ee9SHemant Agrawal vm_paddr_t paddr; 281acaa9ee9SHemant Agrawal vm_page_t m_paddr, page; 282acaa9ee9SHemant Agrawal vm_memattr_t memattr, memattr1; 283acaa9ee9SHemant Agrawal 284acaa9ee9SHemant Agrawal memattr = object->memattr; 285acaa9ee9SHemant Agrawal 286acaa9ee9SHemant Agrawal VM_OBJECT_WUNLOCK(object); 287acaa9ee9SHemant Agrawal 288acaa9ee9SHemant Agrawal paddr = offset; 289acaa9ee9SHemant Agrawal 290acaa9ee9SHemant Agrawal m_paddr = vm_phys_paddr_to_vm_page(paddr); 291acaa9ee9SHemant Agrawal if (m_paddr != NULL) { 292acaa9ee9SHemant Agrawal memattr1 = pmap_page_get_memattr(m_paddr); 293acaa9ee9SHemant Agrawal if (memattr1 != memattr) 294acaa9ee9SHemant Agrawal memattr = memattr1; 295acaa9ee9SHemant Agrawal } 296acaa9ee9SHemant Agrawal 297acaa9ee9SHemant Agrawal if (((*mres)->flags & PG_FICTITIOUS) != 0) { 298acaa9ee9SHemant Agrawal /* 299acaa9ee9SHemant Agrawal * If the passed in result page is a fake page, update it with 300acaa9ee9SHemant Agrawal * the new physical address. 301acaa9ee9SHemant Agrawal */ 302acaa9ee9SHemant Agrawal page = *mres; 303acaa9ee9SHemant Agrawal VM_OBJECT_WLOCK(object); 304acaa9ee9SHemant Agrawal vm_page_updatefake(page, paddr, memattr); 305acaa9ee9SHemant Agrawal } else { 306acaa9ee9SHemant Agrawal /* 307acaa9ee9SHemant Agrawal * Replace the passed in reqpage page with our own fake page and 308acaa9ee9SHemant Agrawal * free up the original page. 309acaa9ee9SHemant Agrawal */ 310acaa9ee9SHemant Agrawal page = vm_page_getfake(paddr, memattr); 311acaa9ee9SHemant Agrawal VM_OBJECT_WLOCK(object); 31203bff90cSBruce Richardson #if __FreeBSD__ >= 13 31303bff90cSBruce Richardson vm_page_replace(page, object, (*mres)->pindex, *mres); 31403bff90cSBruce Richardson #else 31503bff90cSBruce Richardson vm_page_t mret = vm_page_replace(page, object, (*mres)->pindex); 316acaa9ee9SHemant Agrawal KASSERT(mret == *mres, 317acaa9ee9SHemant Agrawal ("invalid page replacement, old=%p, ret=%p", *mres, mret)); 318acaa9ee9SHemant Agrawal vm_page_lock(mret); 319acaa9ee9SHemant Agrawal vm_page_free(mret); 320acaa9ee9SHemant Agrawal vm_page_unlock(mret); 32103bff90cSBruce Richardson #endif 322acaa9ee9SHemant Agrawal *mres = page; 323acaa9ee9SHemant Agrawal } 324acaa9ee9SHemant Agrawal 325acaa9ee9SHemant Agrawal page->valid = VM_PAGE_BITS_ALL; 326acaa9ee9SHemant Agrawal 327acaa9ee9SHemant Agrawal return VM_PAGER_OK; 328acaa9ee9SHemant Agrawal } 329acaa9ee9SHemant Agrawal 330acaa9ee9SHemant Agrawal static struct cdev_pager_ops contigmem_cdev_pager_ops = { 331acaa9ee9SHemant Agrawal .cdev_pg_ctor = contigmem_cdev_pager_ctor, 332acaa9ee9SHemant Agrawal .cdev_pg_dtor = contigmem_cdev_pager_dtor, 333acaa9ee9SHemant Agrawal .cdev_pg_fault = contigmem_cdev_pager_fault, 334acaa9ee9SHemant Agrawal }; 335acaa9ee9SHemant Agrawal 336acaa9ee9SHemant Agrawal static int 337acaa9ee9SHemant Agrawal contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, 338acaa9ee9SHemant Agrawal struct vm_object **obj, int nprot) 339acaa9ee9SHemant Agrawal { 340acaa9ee9SHemant Agrawal struct contigmem_vm_handle *vmh; 341acaa9ee9SHemant Agrawal uint64_t buffer_index; 342acaa9ee9SHemant Agrawal 343acaa9ee9SHemant Agrawal /* 344acaa9ee9SHemant Agrawal * The buffer index is encoded in the offset. Divide the offset by 345acaa9ee9SHemant Agrawal * PAGE_SIZE to get the index of the buffer requested by the user 346acaa9ee9SHemant Agrawal * app. 347acaa9ee9SHemant Agrawal */ 348acaa9ee9SHemant Agrawal buffer_index = *offset / PAGE_SIZE; 349acaa9ee9SHemant Agrawal if (buffer_index >= contigmem_num_buffers) 350acaa9ee9SHemant Agrawal return EINVAL; 351acaa9ee9SHemant Agrawal 352acaa9ee9SHemant Agrawal if (size > contigmem_buffer_size) 353acaa9ee9SHemant Agrawal return EINVAL; 354acaa9ee9SHemant Agrawal 355acaa9ee9SHemant Agrawal vmh = malloc(sizeof(*vmh), M_CONTIGMEM, M_NOWAIT | M_ZERO); 356acaa9ee9SHemant Agrawal if (vmh == NULL) 357acaa9ee9SHemant Agrawal return ENOMEM; 358acaa9ee9SHemant Agrawal vmh->buffer_index = buffer_index; 359acaa9ee9SHemant Agrawal 360acaa9ee9SHemant Agrawal *offset = (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index].addr); 361acaa9ee9SHemant Agrawal *obj = cdev_pager_allocate(vmh, OBJT_DEVICE, &contigmem_cdev_pager_ops, 362acaa9ee9SHemant Agrawal size, nprot, *offset, curthread->td_ucred); 363acaa9ee9SHemant Agrawal 364*cbe57f35SDmitry Kozlyuk /* Mappings backed by OBJ_FICTITIOUS are excluded from core dump. */ 365*cbe57f35SDmitry Kozlyuk if (contigmem_coredump_enable) 366*cbe57f35SDmitry Kozlyuk (*obj)->flags &= ~OBJ_FICTITIOUS; 367*cbe57f35SDmitry Kozlyuk 368acaa9ee9SHemant Agrawal return 0; 369acaa9ee9SHemant Agrawal } 370