1*1cdefd08SHans Petter Selasky /*- 2*1cdefd08SHans Petter Selasky * Copyright (c) 2010 Isilon Systems, Inc. 3*1cdefd08SHans Petter Selasky * Copyright (c) 2016 Matt Macy (mmacy@nextbsd.org) 4*1cdefd08SHans Petter Selasky * Copyright (c) 2017 Mellanox Technologies, Ltd. 5*1cdefd08SHans Petter Selasky * All rights reserved. 6*1cdefd08SHans Petter Selasky * 7*1cdefd08SHans Petter Selasky * Redistribution and use in source and binary forms, with or without 8*1cdefd08SHans Petter Selasky * modification, are permitted provided that the following conditions 9*1cdefd08SHans Petter Selasky * are met: 10*1cdefd08SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 11*1cdefd08SHans Petter Selasky * notice unmodified, this list of conditions, and the following 12*1cdefd08SHans Petter Selasky * disclaimer. 13*1cdefd08SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 14*1cdefd08SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 15*1cdefd08SHans Petter Selasky * documentation and/or other materials provided with the distribution. 16*1cdefd08SHans Petter Selasky * 17*1cdefd08SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18*1cdefd08SHans Petter Selasky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19*1cdefd08SHans Petter Selasky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20*1cdefd08SHans Petter Selasky * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21*1cdefd08SHans Petter Selasky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22*1cdefd08SHans Petter Selasky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23*1cdefd08SHans Petter Selasky * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24*1cdefd08SHans Petter Selasky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25*1cdefd08SHans Petter Selasky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26*1cdefd08SHans Petter Selasky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27*1cdefd08SHans Petter Selasky */ 28*1cdefd08SHans Petter Selasky 29*1cdefd08SHans Petter Selasky #include <sys/cdefs.h> 30*1cdefd08SHans Petter Selasky __FBSDID("$FreeBSD$"); 31*1cdefd08SHans Petter Selasky 32*1cdefd08SHans Petter Selasky #include <sys/param.h> 33*1cdefd08SHans Petter Selasky #include <sys/systm.h> 34*1cdefd08SHans Petter Selasky #include <sys/malloc.h> 35*1cdefd08SHans Petter Selasky #include <sys/kernel.h> 36*1cdefd08SHans Petter Selasky #include <sys/sysctl.h> 37*1cdefd08SHans Petter Selasky #include <sys/lock.h> 38*1cdefd08SHans Petter Selasky #include <sys/mutex.h> 39*1cdefd08SHans Petter Selasky #include <sys/rwlock.h> 40*1cdefd08SHans Petter Selasky #include <sys/proc.h> 41*1cdefd08SHans Petter Selasky #include <sys/sched.h> 42*1cdefd08SHans Petter Selasky 43*1cdefd08SHans Petter Selasky #include <machine/bus.h> 44*1cdefd08SHans Petter Selasky 45*1cdefd08SHans Petter Selasky #include <linux/gfp.h> 46*1cdefd08SHans Petter Selasky 47*1cdefd08SHans Petter Selasky #include <vm/vm.h> 48*1cdefd08SHans Petter Selasky #include <vm/vm_page.h> 49*1cdefd08SHans Petter Selasky #include <vm/vm_pageout.h> 50*1cdefd08SHans Petter Selasky 51*1cdefd08SHans Petter Selasky void * 52*1cdefd08SHans Petter Selasky linux_page_address(struct page *page) 53*1cdefd08SHans Petter Selasky { 54*1cdefd08SHans Petter Selasky #ifdef __amd64__ 55*1cdefd08SHans Petter Selasky return ((void *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(page))); 56*1cdefd08SHans Petter Selasky #else 57*1cdefd08SHans Petter Selasky if (page->object != kmem_object && page->object != kernel_object) 58*1cdefd08SHans Petter Selasky return (NULL); 59*1cdefd08SHans Petter Selasky return ((void *)(uintptr_t)(VM_MIN_KERNEL_ADDRESS + 60*1cdefd08SHans Petter Selasky IDX_TO_OFF(page->pindex))); 61*1cdefd08SHans Petter Selasky #endif 62*1cdefd08SHans Petter Selasky } 63*1cdefd08SHans Petter Selasky 64*1cdefd08SHans Petter Selasky vm_page_t 65*1cdefd08SHans Petter Selasky linux_alloc_pages(gfp_t flags, unsigned int order) 66*1cdefd08SHans Petter Selasky { 67*1cdefd08SHans Petter Selasky #ifdef __amd64__ 68*1cdefd08SHans Petter Selasky unsigned long npages = 1UL << order; 69*1cdefd08SHans Petter Selasky int req = (flags & M_ZERO) ? (VM_ALLOC_ZERO | VM_ALLOC_NOOBJ | 70*1cdefd08SHans Petter Selasky VM_ALLOC_NORMAL) : (VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL); 71*1cdefd08SHans Petter Selasky vm_page_t page; 72*1cdefd08SHans Petter Selasky 73*1cdefd08SHans Petter Selasky if (order == 0 && (flags & GFP_DMA32) == 0) { 74*1cdefd08SHans Petter Selasky page = vm_page_alloc(NULL, 0, req); 75*1cdefd08SHans Petter Selasky if (page == NULL) 76*1cdefd08SHans Petter Selasky return (NULL); 77*1cdefd08SHans Petter Selasky } else { 78*1cdefd08SHans Petter Selasky vm_paddr_t pmax = (flags & GFP_DMA32) ? 79*1cdefd08SHans Petter Selasky BUS_SPACE_MAXADDR_32BIT : BUS_SPACE_MAXADDR; 80*1cdefd08SHans Petter Selasky retry: 81*1cdefd08SHans Petter Selasky page = vm_page_alloc_contig(NULL, 0, req, 82*1cdefd08SHans Petter Selasky npages, 0, pmax, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); 83*1cdefd08SHans Petter Selasky 84*1cdefd08SHans Petter Selasky if (page == NULL) { 85*1cdefd08SHans Petter Selasky if (flags & M_WAITOK) { 86*1cdefd08SHans Petter Selasky if (!vm_page_reclaim_contig(req, 87*1cdefd08SHans Petter Selasky npages, 0, pmax, PAGE_SIZE, 0)) { 88*1cdefd08SHans Petter Selasky VM_WAIT; 89*1cdefd08SHans Petter Selasky } 90*1cdefd08SHans Petter Selasky flags &= ~M_WAITOK; 91*1cdefd08SHans Petter Selasky goto retry; 92*1cdefd08SHans Petter Selasky } 93*1cdefd08SHans Petter Selasky return (NULL); 94*1cdefd08SHans Petter Selasky } 95*1cdefd08SHans Petter Selasky } 96*1cdefd08SHans Petter Selasky if (flags & M_ZERO) { 97*1cdefd08SHans Petter Selasky unsigned long x; 98*1cdefd08SHans Petter Selasky 99*1cdefd08SHans Petter Selasky for (x = 0; x != npages; x++) { 100*1cdefd08SHans Petter Selasky vm_page_t pgo = page + x; 101*1cdefd08SHans Petter Selasky 102*1cdefd08SHans Petter Selasky if ((pgo->flags & PG_ZERO) == 0) 103*1cdefd08SHans Petter Selasky pmap_zero_page(pgo); 104*1cdefd08SHans Petter Selasky } 105*1cdefd08SHans Petter Selasky } 106*1cdefd08SHans Petter Selasky #else 107*1cdefd08SHans Petter Selasky vm_offset_t vaddr; 108*1cdefd08SHans Petter Selasky vm_page_t page; 109*1cdefd08SHans Petter Selasky 110*1cdefd08SHans Petter Selasky vaddr = linux_alloc_kmem(flags, order); 111*1cdefd08SHans Petter Selasky if (vaddr == 0) 112*1cdefd08SHans Petter Selasky return (NULL); 113*1cdefd08SHans Petter Selasky 114*1cdefd08SHans Petter Selasky page = PHYS_TO_VM_PAGE(vtophys((void *)vaddr)); 115*1cdefd08SHans Petter Selasky 116*1cdefd08SHans Petter Selasky KASSERT(vaddr == (vm_offset_t)page_address(page), 117*1cdefd08SHans Petter Selasky ("Page address mismatch")); 118*1cdefd08SHans Petter Selasky #endif 119*1cdefd08SHans Petter Selasky return (page); 120*1cdefd08SHans Petter Selasky } 121*1cdefd08SHans Petter Selasky 122*1cdefd08SHans Petter Selasky void 123*1cdefd08SHans Petter Selasky linux_free_pages(vm_page_t page, unsigned int order) 124*1cdefd08SHans Petter Selasky { 125*1cdefd08SHans Petter Selasky #ifdef __amd64__ 126*1cdefd08SHans Petter Selasky unsigned long npages = 1UL << order; 127*1cdefd08SHans Petter Selasky unsigned long x; 128*1cdefd08SHans Petter Selasky 129*1cdefd08SHans Petter Selasky for (x = 0; x != npages; x++) { 130*1cdefd08SHans Petter Selasky vm_page_t pgo = page + x; 131*1cdefd08SHans Petter Selasky 132*1cdefd08SHans Petter Selasky vm_page_lock(pgo); 133*1cdefd08SHans Petter Selasky vm_page_free(pgo); 134*1cdefd08SHans Petter Selasky vm_page_unlock(pgo); 135*1cdefd08SHans Petter Selasky } 136*1cdefd08SHans Petter Selasky #else 137*1cdefd08SHans Petter Selasky vm_offset_t vaddr; 138*1cdefd08SHans Petter Selasky 139*1cdefd08SHans Petter Selasky vaddr = (vm_offset_t)page_address(page); 140*1cdefd08SHans Petter Selasky 141*1cdefd08SHans Petter Selasky linux_free_kmem(vaddr, order); 142*1cdefd08SHans Petter Selasky #endif 143*1cdefd08SHans Petter Selasky } 144*1cdefd08SHans Petter Selasky 145*1cdefd08SHans Petter Selasky vm_offset_t 146*1cdefd08SHans Petter Selasky linux_alloc_kmem(gfp_t flags, unsigned int order) 147*1cdefd08SHans Petter Selasky { 148*1cdefd08SHans Petter Selasky size_t size = ((size_t)PAGE_SIZE) << order; 149*1cdefd08SHans Petter Selasky vm_offset_t addr; 150*1cdefd08SHans Petter Selasky 151*1cdefd08SHans Petter Selasky if ((flags & GFP_DMA32) == 0) { 152*1cdefd08SHans Petter Selasky addr = kmem_malloc(kmem_arena, size, flags & GFP_NATIVE_MASK); 153*1cdefd08SHans Petter Selasky } else { 154*1cdefd08SHans Petter Selasky addr = kmem_alloc_contig(kmem_arena, size, 155*1cdefd08SHans Petter Selasky flags & GFP_NATIVE_MASK, 0, BUS_SPACE_MAXADDR_32BIT, 156*1cdefd08SHans Petter Selasky PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); 157*1cdefd08SHans Petter Selasky } 158*1cdefd08SHans Petter Selasky return (addr); 159*1cdefd08SHans Petter Selasky } 160*1cdefd08SHans Petter Selasky 161*1cdefd08SHans Petter Selasky void 162*1cdefd08SHans Petter Selasky linux_free_kmem(vm_offset_t addr, unsigned int order) 163*1cdefd08SHans Petter Selasky { 164*1cdefd08SHans Petter Selasky size_t size = ((size_t)PAGE_SIZE) << order; 165*1cdefd08SHans Petter Selasky 166*1cdefd08SHans Petter Selasky kmem_free(kmem_arena, addr, size); 167*1cdefd08SHans Petter Selasky } 168