xref: /dpdk/kernel/freebsd/contigmem/contigmem.c (revision cbe57f351b4e6541eb7b50a5c0d6f7e77b45c9db)
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