xref: /freebsd/sys/compat/linuxkpi/common/src/linux_page.c (revision d749076e80a2f2627fea5dfd3d328cc4fb767ec9)
1 /*-
2  * Copyright (c) 2010 Isilon Systems, Inc.
3  * Copyright (c) 2016 Matthew Macy (mmacy@mattmacy.io)
4  * Copyright (c) 2017 Mellanox Technologies, Ltd.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/malloc.h>
32 #include <sys/kernel.h>
33 #include <sys/sysctl.h>
34 #include <sys/lock.h>
35 #include <sys/mutex.h>
36 #include <sys/rwlock.h>
37 #include <sys/proc.h>
38 #include <sys/sched.h>
39 #include <sys/memrange.h>
40 
41 #include <machine/bus.h>
42 
43 #include <vm/vm.h>
44 #include <vm/pmap.h>
45 #include <vm/vm_param.h>
46 #include <vm/vm_kern.h>
47 #include <vm/vm_object.h>
48 #include <vm/vm_map.h>
49 #include <vm/vm_page.h>
50 #include <vm/vm_pageout.h>
51 #include <vm/vm_pager.h>
52 #include <vm/vm_radix.h>
53 #include <vm/vm_reserv.h>
54 #include <vm/vm_extern.h>
55 
56 #include <vm/uma.h>
57 #include <vm/uma_int.h>
58 
59 #include <linux/gfp.h>
60 #include <linux/mm.h>
61 #include <linux/preempt.h>
62 #include <linux/fs.h>
63 #include <linux/shmem_fs.h>
64 #include <linux/kernel.h>
65 #include <linux/idr.h>
66 #include <linux/io.h>
67 #include <linux/io-mapping.h>
68 #include <linux/device.h>
69 
70 #ifdef __i386__
71 DEFINE_IDR(mtrr_idr);
72 static MALLOC_DEFINE(M_LKMTRR, "idr", "Linux MTRR compat");
73 extern int pat_works;
74 #endif
75 
76 void
si_meminfo(struct sysinfo * si)77 si_meminfo(struct sysinfo *si)
78 {
79 	si->totalram = physmem;
80 	si->freeram = vm_free_count();
81 	si->totalhigh = 0;
82 	si->freehigh = 0;
83 	si->mem_unit = PAGE_SIZE;
84 }
85 
86 void *
linux_page_address(const struct page * page)87 linux_page_address(const struct page *page)
88 {
89 
90 	if (page->object != kernel_object) {
91 		return (PMAP_HAS_DMAP ? PHYS_TO_DMAP(page_to_phys(page)) :
92 		    NULL);
93 	}
94 	return ((void *)(uintptr_t)(VM_MIN_KERNEL_ADDRESS +
95 	    IDX_TO_OFF(page->pindex)));
96 }
97 
98 struct page *
linux_alloc_pages(gfp_t flags,unsigned int order)99 linux_alloc_pages(gfp_t flags, unsigned int order)
100 {
101 	struct page *page;
102 
103 	if (PMAP_HAS_DMAP) {
104 		unsigned long npages = 1UL << order;
105 		int req = VM_ALLOC_WIRED;
106 
107 		if ((flags & M_ZERO) != 0)
108 			req |= VM_ALLOC_ZERO;
109 
110 		if (order == 0 && (flags & GFP_DMA32) == 0) {
111 			page = vm_page_alloc_noobj(req);
112 			if (page == NULL)
113 				return (NULL);
114 		} else {
115 			vm_paddr_t pmax = (flags & GFP_DMA32) ?
116 			    BUS_SPACE_MAXADDR_32BIT : BUS_SPACE_MAXADDR;
117 
118 			if ((flags & __GFP_NORETRY) != 0)
119 				req |= VM_ALLOC_NORECLAIM;
120 
121 		retry:
122 			if ((flags & __GFP_THISNODE) != 0) {
123 				int curdomain = PCPU_GET(domain);
124 				page = vm_page_alloc_noobj_contig_domain(
125 				    curdomain, req, npages, 0, pmax,
126 				    PAGE_SIZE, 0, VM_MEMATTR_DEFAULT);
127 			} else {
128 				page = vm_page_alloc_noobj_contig(
129 				    req, npages, 0, pmax,
130 				    PAGE_SIZE, 0, VM_MEMATTR_DEFAULT);
131 			}
132 
133 			if (page == NULL) {
134 				if ((flags & (M_WAITOK | __GFP_NORETRY | __GFP_THISNODE)) ==
135 				    M_WAITOK) {
136 					int err = vm_page_reclaim_contig(req,
137 					    npages, 0, pmax, PAGE_SIZE, 0);
138 					if (err == ENOMEM)
139 						vm_wait(NULL);
140 					else if (err != 0)
141 						return (NULL);
142 					flags &= ~M_WAITOK;
143 					goto retry;
144 				}
145 				return (NULL);
146 			}
147 		}
148 	} else {
149 		vm_offset_t vaddr;
150 
151 		vaddr = linux_alloc_kmem(flags, order);
152 		if (vaddr == 0)
153 			return (NULL);
154 
155 		page = virt_to_page((void *)vaddr);
156 
157 		KASSERT(vaddr == (vm_offset_t)page_address(page),
158 		    ("Page address mismatch"));
159 	}
160 
161 	return (page);
162 }
163 
164 static void
_linux_free_kmem(vm_offset_t addr,unsigned int order)165 _linux_free_kmem(vm_offset_t addr, unsigned int order)
166 {
167 	size_t size = ((size_t)PAGE_SIZE) << order;
168 
169 	kmem_free((void *)addr, size);
170 }
171 
172 void
linux_free_pages(struct page * page,unsigned int order)173 linux_free_pages(struct page *page, unsigned int order)
174 {
175 	if (PMAP_HAS_DMAP) {
176 		unsigned long npages = 1UL << order;
177 		unsigned long x;
178 
179 		for (x = 0; x != npages; x++) {
180 			vm_page_t pgo = page + x;
181 
182 			/*
183 			 * The "free page" function is used in several
184 			 * contexts.
185 			 *
186 			 * Some pages are allocated by `linux_alloc_pages()`
187 			 * above, but not all of them are. For instance in the
188 			 * DRM drivers, some pages come from
189 			 * `shmem_read_mapping_page_gfp()`.
190 			 *
191 			 * That's why we need to check if the page is managed
192 			 * or not here.
193 			 */
194 			if ((pgo->oflags & VPO_UNMANAGED) == 0) {
195 				vm_page_unwire(pgo, PQ_ACTIVE);
196 			} else {
197 				if (vm_page_unwire_noq(pgo))
198 					vm_page_free(pgo);
199 			}
200 		}
201 	} else {
202 		vm_offset_t vaddr;
203 
204 		vaddr = (vm_offset_t)page_address(page);
205 
206 		_linux_free_kmem(vaddr, order);
207 	}
208 }
209 
210 void
linux_release_pages(release_pages_arg arg,int nr)211 linux_release_pages(release_pages_arg arg, int nr)
212 {
213 	int i;
214 
215 	CTASSERT(offsetof(struct folio, page) == 0);
216 
217 	for (i = 0; i < nr; i++)
218 		__free_page(arg.pages[i]);
219 }
220 
221 vm_offset_t
linux_alloc_kmem(gfp_t flags,unsigned int order)222 linux_alloc_kmem(gfp_t flags, unsigned int order)
223 {
224 	size_t size = ((size_t)PAGE_SIZE) << order;
225 	void *addr;
226 
227 	addr = kmem_alloc_contig(size, flags & GFP_NATIVE_MASK, 0,
228 	    ((flags & GFP_DMA32) == 0) ? -1UL : BUS_SPACE_MAXADDR_32BIT,
229 	    PAGE_SIZE, 0, VM_MEMATTR_DEFAULT);
230 
231 	return ((vm_offset_t)addr);
232 }
233 
234 void
linux_free_kmem(vm_offset_t addr,unsigned int order)235 linux_free_kmem(vm_offset_t addr, unsigned int order)
236 {
237 	KASSERT((addr & ~PAGE_MASK) == 0,
238 	    ("%s: addr %p is not page aligned", __func__, (void *)addr));
239 
240 	if (addr >= VM_MIN_KERNEL_ADDRESS && addr < VM_MAX_KERNEL_ADDRESS) {
241 		_linux_free_kmem(addr, order);
242 	} else {
243 		vm_page_t page;
244 
245 		page = DMAP_TO_VM_PAGE(addr);
246 		linux_free_pages(page, order);
247 	}
248 }
249 
250 static int
linux_get_user_pages_internal(vm_map_t map,unsigned long start,int nr_pages,int write,struct page ** pages)251 linux_get_user_pages_internal(vm_map_t map, unsigned long start, int nr_pages,
252     int write, struct page **pages)
253 {
254 	vm_prot_t prot;
255 	size_t len;
256 	int count;
257 
258 	prot = write ? (VM_PROT_READ | VM_PROT_WRITE) : VM_PROT_READ;
259 	len = ptoa((vm_offset_t)nr_pages);
260 	count = vm_fault_quick_hold_pages(map, start, len, prot, pages, nr_pages);
261 	return (count == -1 ? -EFAULT : nr_pages);
262 }
263 
264 int
__get_user_pages_fast(unsigned long start,int nr_pages,int write,struct page ** pages)265 __get_user_pages_fast(unsigned long start, int nr_pages, int write,
266     struct page **pages)
267 {
268 	vm_map_t map;
269 	vm_page_t *mp;
270 	vm_offset_t va;
271 	vm_offset_t end;
272 	vm_prot_t prot;
273 	int count;
274 
275 	if (nr_pages == 0 || in_interrupt())
276 		return (0);
277 
278 	MPASS(pages != NULL);
279 	map = &curthread->td_proc->p_vmspace->vm_map;
280 	end = start + ptoa((vm_offset_t)nr_pages);
281 	if (!vm_map_range_valid(map, start, end))
282 		return (-EINVAL);
283 	prot = write ? (VM_PROT_READ | VM_PROT_WRITE) : VM_PROT_READ;
284 	for (count = 0, mp = pages, va = start; va < end;
285 	    mp++, va += PAGE_SIZE, count++) {
286 		*mp = pmap_extract_and_hold(map->pmap, va, prot);
287 		if (*mp == NULL)
288 			break;
289 
290 		if ((prot & VM_PROT_WRITE) != 0 &&
291 		    (*mp)->dirty != VM_PAGE_BITS_ALL) {
292 			/*
293 			 * Explicitly dirty the physical page.  Otherwise, the
294 			 * caller's changes may go unnoticed because they are
295 			 * performed through an unmanaged mapping or by a DMA
296 			 * operation.
297 			 *
298 			 * The object lock is not held here.
299 			 * See vm_page_clear_dirty_mask().
300 			 */
301 			vm_page_dirty(*mp);
302 		}
303 	}
304 	return (count);
305 }
306 
307 long
get_user_pages_remote(struct task_struct * task,struct mm_struct * mm,unsigned long start,unsigned long nr_pages,unsigned int gup_flags,struct page ** pages,struct vm_area_struct ** vmas)308 get_user_pages_remote(struct task_struct *task, struct mm_struct *mm,
309     unsigned long start, unsigned long nr_pages, unsigned int gup_flags,
310     struct page **pages, struct vm_area_struct **vmas)
311 {
312 	vm_map_t map;
313 
314 	map = &task->task_thread->td_proc->p_vmspace->vm_map;
315 	return (linux_get_user_pages_internal(map, start, nr_pages,
316 	    !!(gup_flags & FOLL_WRITE), pages));
317 }
318 
319 long
lkpi_get_user_pages(unsigned long start,unsigned long nr_pages,unsigned int gup_flags,struct page ** pages)320 lkpi_get_user_pages(unsigned long start, unsigned long nr_pages,
321     unsigned int gup_flags, struct page **pages)
322 {
323 	vm_map_t map;
324 
325 	map = &curthread->td_proc->p_vmspace->vm_map;
326 	return (linux_get_user_pages_internal(map, start, nr_pages,
327 	    !!(gup_flags & FOLL_WRITE), pages));
328 }
329 
330 /*
331  * Hash of vmmap addresses.  This is infrequently accessed and does not
332  * need to be particularly large.  This is done because we must store the
333  * caller's idea of the map size to properly unmap.
334  */
335 struct vmmap {
336 	LIST_ENTRY(vmmap)	vm_next;
337 	void			*vm_addr;
338 	unsigned long		vm_size;
339 };
340 
341 struct vmmaphd {
342 	struct vmmap *lh_first;
343 };
344 #define VMMAP_HASH_SIZE 64
345 #define VMMAP_HASH_MASK (VMMAP_HASH_SIZE - 1)
346 #define VM_HASH(addr)   ((uintptr_t)(addr) >> PAGE_SHIFT) & VMMAP_HASH_MASK
347 static struct vmmaphd vmmaphead[VMMAP_HASH_SIZE];
348 static struct mtx vmmaplock;
349 
350 int
is_vmalloc_addr(const void * addr)351 is_vmalloc_addr(const void *addr)
352 {
353 	struct vmmap *vmmap;
354 
355 	mtx_lock(&vmmaplock);
356 	LIST_FOREACH(vmmap, &vmmaphead[VM_HASH(addr)], vm_next)
357 		if (addr == vmmap->vm_addr)
358 			break;
359 	mtx_unlock(&vmmaplock);
360 	if (vmmap != NULL)
361 		return (1);
362 
363 	return (vtoslab((vm_offset_t)addr & ~UMA_SLAB_MASK) != NULL);
364 }
365 
366 static void
vmmap_add(void * addr,unsigned long size)367 vmmap_add(void *addr, unsigned long size)
368 {
369 	struct vmmap *vmmap;
370 
371 	vmmap = kmalloc(sizeof(*vmmap), GFP_KERNEL);
372 	mtx_lock(&vmmaplock);
373 	vmmap->vm_size = size;
374 	vmmap->vm_addr = addr;
375 	LIST_INSERT_HEAD(&vmmaphead[VM_HASH(addr)], vmmap, vm_next);
376 	mtx_unlock(&vmmaplock);
377 }
378 
379 static struct vmmap *
vmmap_remove(void * addr)380 vmmap_remove(void *addr)
381 {
382 	struct vmmap *vmmap;
383 
384 	mtx_lock(&vmmaplock);
385 	LIST_FOREACH(vmmap, &vmmaphead[VM_HASH(addr)], vm_next)
386 		if (vmmap->vm_addr == addr)
387 			break;
388 	if (vmmap)
389 		LIST_REMOVE(vmmap, vm_next);
390 	mtx_unlock(&vmmaplock);
391 
392 	return (vmmap);
393 }
394 
395 #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) || defined(__aarch64__) || defined(__riscv)
396 void *
_ioremap_attr(vm_paddr_t phys_addr,unsigned long size,int attr)397 _ioremap_attr(vm_paddr_t phys_addr, unsigned long size, int attr)
398 {
399 	void *addr;
400 
401 	addr = pmap_mapdev_attr(phys_addr, size, attr);
402 	if (addr == NULL)
403 		return (NULL);
404 	vmmap_add(addr, size);
405 
406 	return (addr);
407 }
408 #endif
409 
410 void
iounmap(void * addr)411 iounmap(void *addr)
412 {
413 	struct vmmap *vmmap;
414 
415 	vmmap = vmmap_remove(addr);
416 	if (vmmap == NULL)
417 		return;
418 #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) || defined(__aarch64__) || defined(__riscv)
419 	pmap_unmapdev(addr, vmmap->vm_size);
420 #endif
421 	kfree(vmmap);
422 }
423 
424 static void
lkpi_devm_memremap_unmap(struct device * dev,void * p)425 lkpi_devm_memremap_unmap(struct device *dev, void *p)
426 {
427 	void **dr = p;
428 
429 	memunmap(*dr);
430 }
431 
432 void *
linuxkpi_devm_memremap(struct device * dev,resource_size_t offset,size_t size,unsigned long flags)433 linuxkpi_devm_memremap(struct device *dev, resource_size_t offset, size_t size,
434     unsigned long flags)
435 {
436 	void **dr, *addr;
437 
438 	dr = devres_alloc(lkpi_devm_memremap_unmap, sizeof(*dr), GFP_KERNEL);
439 	if (dr == NULL)
440 		return (ERR_PTR(-ENOMEM));
441 	addr = memremap(offset, size, flags);
442 	if (addr != NULL) {
443 		*dr = addr;
444 		devres_add(dev, dr);
445 	} else {
446 		addr = ERR_PTR(-ENXIO);
447 		devres_free(dr);
448 	}
449 
450 	return (addr);
451 }
452 
453 void *
vmap(struct page ** pages,unsigned int count,unsigned long flags,int prot)454 vmap(struct page **pages, unsigned int count, unsigned long flags, int prot)
455 {
456 	void *off;
457 	size_t size;
458 
459 	size = count * PAGE_SIZE;
460 	off = kva_alloc(size);
461 	if (off == NULL)
462 		return (NULL);
463 	vmmap_add(off, size);
464 	pmap_qenter(off, pages, count);
465 
466 	return (off);
467 }
468 
469 #define	VMAP_MAX_CHUNK_SIZE (65536U / sizeof(struct vm_page)) /* KMEM_ZMAX */
470 
471 void *
linuxkpi_vmap_pfn(unsigned long * pfns,unsigned int count,int prot)472 linuxkpi_vmap_pfn(unsigned long *pfns, unsigned int count, int prot)
473 {
474 	vm_page_t m, *ma, fma;
475 	void *off;
476 	char *coff;
477 	vm_paddr_t pa;
478 	vm_memattr_t attr;
479 	size_t size;
480 	unsigned int i, c, chunk;
481 
482 	size = ptoa(count);
483 	off = kva_alloc(size);
484 	if (off == NULL)
485 		return (NULL);
486 	vmmap_add(off, size);
487 
488 	chunk = MIN(count, VMAP_MAX_CHUNK_SIZE);
489 	attr = pgprot2cachemode(prot);
490 	ma = malloc(chunk * sizeof(vm_page_t), M_TEMP, M_WAITOK | M_ZERO);
491 	fma = NULL;
492 	c = 0;
493 	coff = off;
494 	for (i = 0; i < count; i++) {
495 		pa = IDX_TO_OFF(pfns[i]);
496 		m = PHYS_TO_VM_PAGE(pa);
497 		if (m == NULL) {
498 			if (fma == NULL)
499 				fma = malloc(chunk * sizeof(struct vm_page),
500 				    M_TEMP, M_WAITOK | M_ZERO);
501 			m = fma + c;
502 			vm_page_initfake(m, pa, attr);
503 		} else {
504 			pmap_page_set_memattr(m, attr);
505 		}
506 		ma[c] = m;
507 		c++;
508 		if (c == chunk || i == count - 1) {
509 			pmap_qenter(coff, ma, c);
510 			if (i == count - 1)
511 				break;
512 			coff += ptoa(c);
513 			c = 0;
514 			memset(ma, 0, chunk * sizeof(vm_page_t));
515 			if (fma != NULL)
516 				memset(fma, 0, chunk * sizeof(struct vm_page));
517 		}
518 	}
519 	free(fma, M_TEMP);
520 	free(ma, M_TEMP);
521 
522 	return (off);
523 }
524 
525 void
vunmap(void * addr)526 vunmap(void *addr)
527 {
528 	struct vmmap *vmmap;
529 
530 	vmmap = vmmap_remove(addr);
531 	if (vmmap == NULL)
532 		return;
533 	pmap_qremove(addr, vmmap->vm_size / PAGE_SIZE);
534 	kva_free(addr, vmmap->vm_size);
535 	kfree(vmmap);
536 }
537 
538 vm_fault_t
lkpi_vmf_insert_pfn_prot_locked(struct vm_area_struct * vma,unsigned long addr,unsigned long pfn,pgprot_t prot)539 lkpi_vmf_insert_pfn_prot_locked(struct vm_area_struct *vma, unsigned long addr,
540     unsigned long pfn, pgprot_t prot)
541 {
542 	struct pctrie_iter pages;
543 	vm_object_t vm_obj = vma->vm_obj;
544 	vm_object_t tmp_obj;
545 	vm_page_t page;
546 	vm_pindex_t pindex;
547 
548 	if (addr < vma->vm_start || addr >= vma->vm_end)
549 		return (VM_FAULT_SIGBUS);
550 
551 	VM_OBJECT_ASSERT_WLOCKED(vm_obj);
552 	vm_page_iter_init(&pages, vm_obj);
553 	pindex = OFF_TO_IDX(addr - vma->vm_start);
554 	if (vma->vm_pfn_count == 0)
555 		vma->vm_pfn_first = pindex;
556 	MPASS(pindex < OFF_TO_IDX(vma->vm_end));
557 
558 retry:
559 	page = vm_page_grab_iter(vm_obj, pindex, VM_ALLOC_NOCREAT, &pages);
560 	if (page == NULL) {
561 		page = PHYS_TO_VM_PAGE(IDX_TO_OFF(pfn));
562 		if (page == NULL)
563 			return (VM_FAULT_SIGBUS);
564 		if (!vm_page_busy_acquire(page, VM_ALLOC_WAITFAIL)) {
565 			pctrie_iter_reset(&pages);
566 			goto retry;
567 		}
568 		if (page->object != NULL) {
569 			tmp_obj = page->object;
570 			vm_page_xunbusy(page);
571 			VM_OBJECT_WUNLOCK(vm_obj);
572 			VM_OBJECT_WLOCK(tmp_obj);
573 			if (page->object == tmp_obj &&
574 			    vm_page_busy_acquire(page, VM_ALLOC_WAITFAIL)) {
575 				KASSERT(page->object == tmp_obj,
576 				    ("page has changed identity"));
577 				KASSERT((page->oflags & VPO_UNMANAGED) == 0,
578 				    ("page does not belong to shmem"));
579 				vm_pager_page_unswapped(page);
580 				if (pmap_page_is_mapped(page)) {
581 					vm_page_xunbusy(page);
582 					VM_OBJECT_WUNLOCK(tmp_obj);
583 					printf("%s: page rename failed: page "
584 					    "is mapped\n", __func__);
585 					VM_OBJECT_WLOCK(vm_obj);
586 					return (VM_FAULT_NOPAGE);
587 				}
588 				vm_page_remove(page);
589 			}
590 			VM_OBJECT_WUNLOCK(tmp_obj);
591 			pctrie_iter_reset(&pages);
592 			VM_OBJECT_WLOCK(vm_obj);
593 			goto retry;
594 		}
595 		if (vm_page_iter_insert(page, vm_obj, pindex, &pages) != 0) {
596 			vm_page_xunbusy(page);
597 			return (VM_FAULT_OOM);
598 		}
599 		vm_page_valid(page);
600 	}
601 	pmap_page_set_memattr(page, pgprot2cachemode(prot));
602 	vma->vm_pfn_count++;
603 
604 	return (VM_FAULT_NOPAGE);
605 }
606 
607 int
lkpi_remap_pfn_range(struct vm_area_struct * vma,unsigned long start_addr,unsigned long start_pfn,unsigned long size,pgprot_t prot)608 lkpi_remap_pfn_range(struct vm_area_struct *vma, unsigned long start_addr,
609     unsigned long start_pfn, unsigned long size, pgprot_t prot)
610 {
611 	vm_object_t vm_obj;
612 	unsigned long addr, pfn;
613 	int err = 0;
614 
615 	vm_obj = vma->vm_obj;
616 
617 	VM_OBJECT_WLOCK(vm_obj);
618 	for (addr = start_addr, pfn = start_pfn;
619 	    addr < start_addr + size;
620 	    addr += PAGE_SIZE) {
621 		vm_fault_t ret;
622 retry:
623 		ret = lkpi_vmf_insert_pfn_prot_locked(vma, addr, pfn, prot);
624 
625 		if ((ret & VM_FAULT_OOM) != 0) {
626 			VM_OBJECT_WUNLOCK(vm_obj);
627 			vm_wait(NULL);
628 			VM_OBJECT_WLOCK(vm_obj);
629 			goto retry;
630 		}
631 
632 		if ((ret & VM_FAULT_ERROR) != 0) {
633 			err = -EFAULT;
634 			break;
635 		}
636 
637 		pfn++;
638 	}
639 	VM_OBJECT_WUNLOCK(vm_obj);
640 
641 	if (unlikely(err)) {
642 		zap_vma_ptes(vma, start_addr,
643 		    (pfn - start_pfn) << PAGE_SHIFT);
644 		return (err);
645 	}
646 
647 	return (0);
648 }
649 
650 int
lkpi_io_mapping_map_user(struct io_mapping * iomap,struct vm_area_struct * vma,unsigned long addr,unsigned long pfn,unsigned long size)651 lkpi_io_mapping_map_user(struct io_mapping *iomap,
652     struct vm_area_struct *vma, unsigned long addr,
653     unsigned long pfn, unsigned long size)
654 {
655 	pgprot_t prot;
656 	int ret;
657 
658 	prot = cachemode2protval(iomap->attr);
659 	ret = lkpi_remap_pfn_range(vma, addr, pfn, size, prot);
660 
661 	return (ret);
662 }
663 
664 /*
665  * Although FreeBSD version of unmap_mapping_range has semantics and types of
666  * parameters compatible with Linux version, the values passed in are different
667  * @obj should match to vm_private_data field of vm_area_struct returned by
668  *      mmap file operation handler, see linux_file_mmap_single() sources
669  * @holelen should match to size of area to be munmapped.
670  */
671 void
lkpi_unmap_mapping_range(void * obj,loff_t const holebegin __unused,loff_t const holelen __unused,int even_cows __unused)672 lkpi_unmap_mapping_range(void *obj, loff_t const holebegin __unused,
673     loff_t const holelen __unused, int even_cows __unused)
674 {
675 	vm_object_t devobj;
676 
677 	devobj = cdev_pager_lookup(obj);
678 	if (devobj != NULL) {
679 		cdev_mgtdev_pager_free_pages(devobj);
680 		vm_object_deallocate(devobj);
681 	}
682 }
683 
684 int
lkpi_arch_phys_wc_add(unsigned long base,unsigned long size)685 lkpi_arch_phys_wc_add(unsigned long base, unsigned long size)
686 {
687 #ifdef __i386__
688 	struct mem_range_desc *mrdesc;
689 	int error, id, act;
690 
691 	/* If PAT is available, do nothing */
692 	if (pat_works)
693 		return (0);
694 
695 	mrdesc = malloc(sizeof(*mrdesc), M_LKMTRR, M_WAITOK);
696 	mrdesc->mr_base = base;
697 	mrdesc->mr_len = size;
698 	mrdesc->mr_flags = MDF_WRITECOMBINE;
699 	strlcpy(mrdesc->mr_owner, "drm", sizeof(mrdesc->mr_owner));
700 	act = MEMRANGE_SET_UPDATE;
701 	error = mem_range_attr_set(mrdesc, &act);
702 	if (error == 0) {
703 		error = idr_get_new(&mtrr_idr, mrdesc, &id);
704 		MPASS(idr_find(&mtrr_idr, id) == mrdesc);
705 		if (error != 0) {
706 			act = MEMRANGE_SET_REMOVE;
707 			mem_range_attr_set(mrdesc, &act);
708 		}
709 	}
710 	if (error != 0) {
711 		free(mrdesc, M_LKMTRR);
712 		pr_warn(
713 		    "Failed to add WC MTRR for [%p-%p]: %d; "
714 		    "performance may suffer\n",
715 		    (void *)base, (void *)(base + size - 1), error);
716 	} else
717 		pr_warn("Successfully added WC MTRR for [%p-%p]\n",
718 		    (void *)base, (void *)(base + size - 1));
719 
720 	return (error != 0 ? -error : id + __MTRR_ID_BASE);
721 #else
722 	return (0);
723 #endif
724 }
725 
726 void
lkpi_arch_phys_wc_del(int reg)727 lkpi_arch_phys_wc_del(int reg)
728 {
729 #ifdef __i386__
730 	struct mem_range_desc *mrdesc;
731 	int act;
732 
733 	/* Check if arch_phys_wc_add() failed. */
734 	if (reg < __MTRR_ID_BASE)
735 		return;
736 
737 	mrdesc = idr_find(&mtrr_idr, reg - __MTRR_ID_BASE);
738 	MPASS(mrdesc != NULL);
739 	idr_remove(&mtrr_idr, reg - __MTRR_ID_BASE);
740 	act = MEMRANGE_SET_REMOVE;
741 	mem_range_attr_set(mrdesc, &act);
742 	free(mrdesc, M_LKMTRR);
743 #endif
744 }
745 
746 int
lkpi_set_pages_attr(struct page * page,int numpages,vm_memattr_t ma)747 lkpi_set_pages_attr(struct page *page, int numpages, vm_memattr_t ma)
748 {
749 	while (numpages-- > 0) {
750 		/*
751 		 * pmap_page_set_memattr() would only update the DMAP mapping
752 		 * if it's a normal page, leaving the kernel map untouched.
753 		 */
754 		MPASS(page->object != kernel_object);
755 
756 		/*
757 		 * pmap_page_set_memattr() sets page->md.pat_mode, which is
758 		 * crucial for future userspace mappings.
759 		 */
760 		pmap_page_set_memattr(page, ma);
761 		page++;
762 	}
763 
764 	return (0);
765 }
766 
767 /*
768  * This is a highly simplified version of the Linux page_frag_cache.
769  * We only support up-to 1 single page as fragment size and we will
770  * always return a full page.  This may be wasteful on small objects
771  * but the only known consumer (mt76) is either asking for a half-page
772  * or a full page.  If this was to become a problem we can implement
773  * a more elaborate version.
774  */
775 void *
linuxkpi_page_frag_alloc(struct page_frag_cache * pfc,size_t fragsz,gfp_t gfp)776 linuxkpi_page_frag_alloc(struct page_frag_cache *pfc,
777     size_t fragsz, gfp_t gfp)
778 {
779 	struct page *pages;
780 
781 	if (fragsz == 0)
782 		return (NULL);
783 
784 	KASSERT(fragsz <= PAGE_SIZE, ("%s: fragsz %zu > PAGE_SIZE not yet "
785 	    "supported", __func__, fragsz));
786 
787 	pages = alloc_pages(gfp, flsl(howmany(fragsz, PAGE_SIZE) - 1));
788 	if (pages == NULL)
789 		return (NULL);
790 	pfc->va = linux_page_address(pages);
791 
792 	/* Passed in as "count" to __page_frag_cache_drain(). Unused by us. */
793 	pfc->pagecnt_bias = 0;
794 
795 	return (pfc->va);
796 }
797 
798 void
linuxkpi_page_frag_free(void * addr)799 linuxkpi_page_frag_free(void *addr)
800 {
801 	struct page *page;
802 
803 	page = virt_to_page(addr);
804 	linux_free_pages(page, 0);
805 }
806 
807 void
linuxkpi__page_frag_cache_drain(struct page * page,size_t count __unused)808 linuxkpi__page_frag_cache_drain(struct page *page, size_t count __unused)
809 {
810 
811 	linux_free_pages(page, 0);
812 }
813 
814 static void
lkpi_page_init(void * arg)815 lkpi_page_init(void *arg)
816 {
817 	int i;
818 
819 	mtx_init(&vmmaplock, "IO Map lock", NULL, MTX_DEF);
820 	for (i = 0; i < VMMAP_HASH_SIZE; i++)
821 		LIST_INIT(&vmmaphead[i]);
822 }
823 SYSINIT(lkpi_page, SI_SUB_DRIVERS, SI_ORDER_SECOND, lkpi_page_init, NULL);
824 
825 static void
lkpi_page_uninit(void * arg)826 lkpi_page_uninit(void *arg)
827 {
828 	mtx_destroy(&vmmaplock);
829 }
830 SYSUNINIT(lkpi_page, SI_SUB_DRIVERS, SI_ORDER_SECOND, lkpi_page_uninit, NULL);
831