Index: share/man/man9/Makefile =================================================================== --- share/man/man9/Makefile +++ share/man/man9/Makefile @@ -374,6 +374,7 @@ vhold.9 \ vinvalbuf.9 \ vm_fault_prefault.9 \ + vm_fault_quick_hold_pages.9 \ vm_map.9 \ vm_map_check_protection.9 \ vm_map_delete.9 \ @@ -2316,6 +2317,7 @@ vmem.9 vmem_free.9 \ vmem.9 vmem_xalloc.9 \ vmem.9 vmem_xfree.9 +MLINKS+=vm_fault_quick_hold_pages.9 vm_page_unhold_pages.9 MLINKS+=vm_map_lock.9 vm_map_lock_downgrade.9 \ vm_map_lock.9 vm_map_lock_read.9 \ vm_map_lock.9 vm_map_lock_upgrade.9 \ Index: share/man/man9/vm_fault_quick_hold_pages.9 =================================================================== --- /dev/null +++ share/man/man9/vm_fault_quick_hold_pages.9 @@ -0,0 +1,200 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD +.\" +.\" Copyright (c) 2021 The FreeBSD Foundation +.\" +.\" This manual page was written by Ka Ho Ng under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd November 8, 2021 +.Dt VM_FAULT_QUICK_HOLD_PAGES 9 +.Os +.Sh NAME +.Nm vm_fault_quick_hold_pages , +.Nm vm_page_unhold_pages +.Nd "hold pages mapped by a range of virtual addresses" +.Sh SYNOPSIS +.In sys/param.h +.In vm/vm.h +.In vm/vm_extern.h +.Ft int +.Fo vm_fault_quick_hold_pages +.Fa "vm_map_t map" +.Fa "vm_offset_t addr" +.Fa "vm_size_t len" +.Fa "vm_prot_t prot" +.Fa "vm_page_t *ma" +.Fa "int max_count" +.Fc +.Ft void +.Fo vm_page_unhold_pages +.Fa "vm_page_t *ma" +.Fa "int count" +.Fc +.Sh DESCRIPTION +The +.Fn vm_fault_quick_hold_pages +function holds the pages mapped by the map +.Fa map . +The virtual address range +.Eo [ +.Fa addr , addr + len +.Ec ) +must be within the lower and upper address bounds of the specified map, and must +have valid and managed mappings in the specified map. +All the implied pages must allow the protection specified by the +.Fa prot +argument. +The +.Fa ma +argument points to an array to be updated to +contain the +.Ft vm_page_t +structures of the implied pages if the function returns success, and the +.Fa max_count +argument specifies the number of +.Ft vm_page_t +structures the array can contain. +If any pages in the virtual address range is not resident, the function tries to +fault in the pages and wire them, if page fault handling is not disabled. +Page fault handling in the function is disabled if +.Dv VM_PROT_QUICK_NOFAULT +is set in the +.Fa prot +argument, or if the calling thread is blocked from entry into the page fault +handler. +.Pp +The +.Fn vm_page_unhold_pages +function unholds the held pages referenced by the array pointed by the +.Fa ma +argument. +The number of pages to be unheld is specified by the +.Fa count +argument. +.Pp +The +.Fn vm_fault_quick_hold_pages +function is intended to be called in the situations where short-term wiring is +required. +A call to the function simulates the behavior of memory access to the virtual +address range with the specified access rights, and wires and returns pages that +would serve the access, thus the function may need to sleep due to page fault +handling. +Even when page fault handling is disabled, some non-sleepable VM locks, such as +the lock of the physical map associated with the specified map, are still taken +during the call. +Faults and resources used for page-in are accounted for the calling thread +regardless of the map. +There should be no VM, VFS or network locks owned by the caller of the function. +Pages held by the function call stay resident in physical memory, and are +not paged out before a call to the +.Fn vm_page_unhold_pages +function on them. +.Pp +A call to the +.Fn vm_fault_quick_hold_pages +function can fail due to the following reasons: +.Bl -bullet +.It +The specified virtual address range is outside of the valid range in the +specified map. +.It +The specified virtual address range does not allow the access rights listed in +the +.Fa prot +argument. +.It +Some pages in the specified virtual address range are not resident +in the physical memory, and page fault handling is disabled in the function. +.It +Page fault handling fails for the given virtual address range. +.El +.Sh RETURN VALUES +The +.Fn vm_fault_quick_hold_pages +function returns the number of pages mapped by the specified virtual address +range if the operation is successful; +otherwise the value -1 is returned. +.Sh EXAMPLES +Map a user buffer into kernel address space temporarily. +.Bd -literal -offset indent +static int +map_buf_user(struct vmspace *vm, vm_offset_t buf, vm_size_t len, + vm_page_t **pages, int *npages, vm_offset_t *kvap) +{ + int count, n; + vm_page_t *ma; + vm_offset_t kva; + + count = atop(len) + 2; + ma = malloc(sizeof(*pages) * count, M_FOOBAR, M_ZERO | M_WAITOK); + n = vm_fault_quick_hold_pages(&vm->vm_map, (vm_offset_t)buf, len, + VM_PROT_READ | VM_PROT_WRITE, ma, count); + if (n == -1) + goto fail; + if ((kva = kva_alloc(ptoa(n))) == 0) + goto fail; + pmap_qenter(kva, ma, n); + + *pages = ma; + *npages = count; + *kvap = kva; + return (0); +fail: + if (n != -1) + vm_page_unhold_pages(ma, n); + free(ma, M_FOOBAR); + return (1); +} +.Ed +.Sh DIAGNOSTICS +The +.Fn vm_fault_quick_hold_pages +function panics if +.Fa max_count +is smaller than the number of pages mapped by the specified virtual address +range. +.Sh SEE ALSO +.Xr vm_map 9 , +.Xr vm_map_wire 9 +.Sh HISTORY +The +.Fn vm_fault_quick_hold_pages +function was developed by +.An Alan Cox Aq Mt alc@FreeBSD.org +and +.An Konstantin Belousov Aq Mt kib@FreeBSD.org . +.Pp +The +.Fn vm_page_unhold_pages +function was developed by +.An Alan Cox Aq Mt alc@FreeBSD.org . +.Pp +The manual page first appeared in +.Fx 14 . +.Sh AUTHORS +This +manual page was written by +.An Ka Ho Ng Aq Mt khng@FreeBSD.org .