2005-01-07 02:29:27 +00:00
|
|
|
/*-
|
2017-11-20 19:43:44 +00:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*
|
1994-05-24 10:09:53 +00:00
|
|
|
* Copyright (c) 1988 University of Utah.
|
|
|
|
* Copyright (c) 1991, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* the Systems Programming Group of the University of Utah Computer
|
|
|
|
* Science Department.
|
|
|
|
*
|
|
|
|
* 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.
|
2017-02-28 23:42:47 +00:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1994-05-24 10:09:53 +00:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
|
|
|
*
|
|
|
|
* from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
|
|
|
|
*
|
|
|
|
* @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mapped file (mmap) interface to VM
|
|
|
|
*/
|
|
|
|
|
2003-06-11 23:50:51 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2006-03-26 12:20:54 +00:00
|
|
|
#include "opt_hwpmc_hooks.h"
|
2015-03-21 17:56:55 +00:00
|
|
|
#include "opt_vm.h"
|
1996-12-22 23:17:09 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
2014-03-16 10:55:57 +00:00
|
|
|
#include <sys/capsicum.h>
|
2011-08-11 12:30:23 +00:00
|
|
|
#include <sys/kernel.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/lock.h>
|
2001-05-19 01:28:09 +00:00
|
|
|
#include <sys/mutex.h>
|
1995-11-12 06:43:28 +00:00
|
|
|
#include <sys/sysproto.h>
|
2019-07-02 19:07:17 +00:00
|
|
|
#include <sys/elf.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/filedesc.h>
|
2006-11-06 13:42:10 +00:00
|
|
|
#include <sys/priv.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/proc.h>
|
2013-09-19 18:53:42 +00:00
|
|
|
#include <sys/procctl.h>
|
2011-04-05 20:23:59 +00:00
|
|
|
#include <sys/racct.h>
|
2002-06-26 00:29:28 +00:00
|
|
|
#include <sys/resource.h>
|
|
|
|
#include <sys/resourcevar.h>
|
2013-03-09 02:32:23 +00:00
|
|
|
#include <sys/rwlock.h>
|
2012-12-18 07:35:01 +00:00
|
|
|
#include <sys/sysctl.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/vnode.h>
|
1997-03-23 03:37:54 +00:00
|
|
|
#include <sys/fcntl.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/file.h>
|
|
|
|
#include <sys/mman.h>
|
2004-03-18 20:58:51 +00:00
|
|
|
#include <sys/mount.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/conf.h>
|
1998-05-19 07:13:21 +00:00
|
|
|
#include <sys/stat.h>
|
2013-09-19 18:53:42 +00:00
|
|
|
#include <sys/syscallsubr.h>
|
2009-09-20 12:40:56 +00:00
|
|
|
#include <sys/sysent.h>
|
1995-12-07 12:48:31 +00:00
|
|
|
#include <sys/vmmeter.h>
|
2019-02-09 03:51:51 +00:00
|
|
|
#if defined(__amd64__) || defined(__i386__) /* for i386_read_exec */
|
|
|
|
#include <machine/md_var.h>
|
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2016-07-10 08:04:02 +00:00
|
|
|
#include <security/audit/audit.h>
|
2006-10-22 11:52:19 +00:00
|
|
|
#include <security/mac/mac_framework.h>
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <vm/vm.h>
|
1995-12-07 12:48:31 +00:00
|
|
|
#include <vm/vm_param.h>
|
|
|
|
#include <vm/pmap.h>
|
|
|
|
#include <vm/vm_map.h>
|
|
|
|
#include <vm/vm_object.h>
|
1999-01-21 08:29:12 +00:00
|
|
|
#include <vm/vm_page.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <vm/vm_pager.h>
|
1995-03-16 18:17:34 +00:00
|
|
|
#include <vm/vm_pageout.h>
|
1995-12-07 12:48:31 +00:00
|
|
|
#include <vm/vm_extern.h>
|
1996-05-19 07:36:50 +00:00
|
|
|
#include <vm/vm_page.h>
|
2012-02-23 21:07:16 +00:00
|
|
|
#include <vm/vnode_pager.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2006-03-26 12:20:54 +00:00
|
|
|
#ifdef HWPMC_HOOKS
|
|
|
|
#include <sys/pmckern.h>
|
|
|
|
#endif
|
|
|
|
|
2012-12-18 07:35:01 +00:00
|
|
|
int old_mlock = 0;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RWTUN, &old_mlock, 0,
|
2012-12-18 07:35:01 +00:00
|
|
|
"Do not apply RLIMIT_MEMLOCK on mlockall");
|
2019-01-07 22:10:48 +00:00
|
|
|
static int mincore_mapped = 1;
|
|
|
|
SYSCTL_INT(_vm, OID_AUTO, mincore_mapped, CTLFLAG_RWTUN, &mincore_mapped, 0,
|
|
|
|
"mincore reports mappings, not residency");
|
2019-06-20 18:24:16 +00:00
|
|
|
static int imply_prot_max = 0;
|
|
|
|
SYSCTL_INT(_vm, OID_AUTO, imply_prot_max, CTLFLAG_RWTUN, &imply_prot_max, 0,
|
2020-06-04 01:49:29 +00:00
|
|
|
"Imply maximum page protections in mmap() when none are specified");
|
2012-12-18 07:35:01 +00:00
|
|
|
|
2013-09-09 18:11:59 +00:00
|
|
|
#ifdef MAP_32BIT
|
|
|
|
#define MAP_32BIT_MAX_ADDR ((vm_offset_t)1 << 31)
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
2020-09-02 18:16:43 +00:00
|
|
|
_Static_assert(MAXPAGESIZES <= 4, "MINCORE_SUPER too narrow");
|
|
|
|
|
2013-09-09 18:11:59 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct sbrk_args {
|
|
|
|
int incr;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2017-02-13 00:40:55 +00:00
|
|
|
sys_sbrk(struct thread *td, struct sbrk_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
/* Not yet implemented */
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sstk_args {
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
int incr;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2017-02-13 00:40:55 +00:00
|
|
|
sys_sstk(struct thread *td, struct sstk_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
/* Not yet implemented */
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
2004-06-11 11:16:26 +00:00
|
|
|
#if defined(COMPAT_43)
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2018-12-04 16:48:47 +00:00
|
|
|
ogetpagesize(struct thread *td, struct ogetpagesize_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2017-02-13 00:40:55 +00:00
|
|
|
|
2001-09-12 08:38:13 +00:00
|
|
|
td->td_retval[0] = PAGE_SIZE;
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2004-06-11 11:16:26 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2003-12-08 02:45:45 +00:00
|
|
|
/*
|
1997-08-30 18:50:06 +00:00
|
|
|
* Memory Map (mmap) system call. Note that the file offset
|
|
|
|
* and address are allowed to be NOT page aligned, though if
|
|
|
|
* the MAP_FIXED flag it set, both must have the same remainder
|
|
|
|
* modulo the PAGE_SIZE (POSIX 1003.1b). If the address is not
|
|
|
|
* page-aligned, the actual mapping starts at trunc_page(addr)
|
|
|
|
* and the return value is adjusted up by the page offset.
|
1999-09-21 05:00:48 +00:00
|
|
|
*
|
|
|
|
* Generally speaking, only character devices which are themselves
|
|
|
|
* memory-based, such as a video framebuffer, can be mmap'd. Otherwise
|
|
|
|
* there would be no cache coherency between a descriptor and a VM mapping
|
|
|
|
* both to the same character device.
|
1997-08-30 18:50:06 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mmap_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
size_t len;
|
|
|
|
int prot;
|
|
|
|
int flags;
|
|
|
|
int fd;
|
|
|
|
long pad;
|
|
|
|
off_t pos;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
int
|
2017-02-06 20:57:12 +00:00
|
|
|
sys_mmap(struct thread *td, struct mmap_args *uap)
|
|
|
|
{
|
|
|
|
|
2021-01-23 00:08:59 +00:00
|
|
|
return (kern_mmap(td, &(struct mmap_req){
|
|
|
|
.mr_hint = (uintptr_t)uap->addr,
|
|
|
|
.mr_len = uap->len,
|
|
|
|
.mr_prot = uap->prot,
|
|
|
|
.mr_flags = uap->flags,
|
|
|
|
.mr_fd = uap->fd,
|
|
|
|
.mr_pos = uap->pos,
|
|
|
|
}));
|
2017-02-06 20:57:12 +00:00
|
|
|
}
|
|
|
|
|
2019-07-02 19:07:17 +00:00
|
|
|
int
|
|
|
|
kern_mmap_maxprot(struct proc *p, int prot)
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((p->p_flag2 & P2_PROTMAX_DISABLE) != 0 ||
|
|
|
|
(p->p_fctl0 & NT_FREEBSD_FCTL_PROTMAX_DISABLE) != 0)
|
|
|
|
return (_PROT_ALL);
|
|
|
|
if (((p->p_flag2 & P2_PROTMAX_ENABLE) != 0 || imply_prot_max) &&
|
|
|
|
prot != PROT_NONE)
|
|
|
|
return (prot);
|
|
|
|
return (_PROT_ALL);
|
|
|
|
}
|
|
|
|
|
2017-02-06 20:57:12 +00:00
|
|
|
int
|
2021-01-23 00:08:59 +00:00
|
|
|
kern_mmap(struct thread *td, const struct mmap_req *mrp)
|
2020-01-04 23:39:58 +00:00
|
|
|
{
|
2017-02-13 09:04:38 +00:00
|
|
|
struct vmspace *vms;
|
2004-02-27 22:02:15 +00:00
|
|
|
struct file *fp;
|
2019-07-02 19:01:14 +00:00
|
|
|
struct proc *p;
|
2020-03-04 21:27:12 +00:00
|
|
|
off_t pos;
|
2020-09-09 22:12:51 +00:00
|
|
|
vm_offset_t addr, orig_addr;
|
2020-03-04 21:27:12 +00:00
|
|
|
vm_size_t len, pageoff, size;
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
vm_prot_t cap_maxprot;
|
2020-03-04 21:27:12 +00:00
|
|
|
int align, error, fd, flags, max_prot, prot;
|
2011-08-11 12:30:23 +00:00
|
|
|
cap_rights_t rights;
|
2020-03-04 21:27:12 +00:00
|
|
|
mmap_check_fp_fn check_fp_fn;
|
|
|
|
|
2020-09-09 22:12:51 +00:00
|
|
|
orig_addr = addr = mrp->mr_hint;
|
2020-03-04 21:27:12 +00:00
|
|
|
len = mrp->mr_len;
|
|
|
|
prot = mrp->mr_prot;
|
|
|
|
flags = mrp->mr_flags;
|
|
|
|
fd = mrp->mr_fd;
|
|
|
|
pos = mrp->mr_pos;
|
|
|
|
check_fp_fn = mrp->mr_check_fp_fn;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2019-06-20 18:24:16 +00:00
|
|
|
if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0)
|
|
|
|
return (EINVAL);
|
|
|
|
max_prot = PROT_MAX_EXTRACT(prot);
|
|
|
|
prot = PROT_EXTRACT(prot);
|
|
|
|
if (max_prot != 0 && (max_prot & prot) != prot)
|
2020-02-26 20:03:43 +00:00
|
|
|
return (ENOTSUP);
|
2019-07-02 19:01:14 +00:00
|
|
|
|
|
|
|
p = td->td_proc;
|
|
|
|
|
2019-06-20 18:24:16 +00:00
|
|
|
/*
|
|
|
|
* Always honor PROT_MAX if set. If not, default to all
|
|
|
|
* permissions unless we're implying maximum permissions.
|
|
|
|
*/
|
|
|
|
if (max_prot == 0)
|
2019-07-02 19:07:17 +00:00
|
|
|
max_prot = kern_mmap_maxprot(p, prot);
|
2019-06-20 18:24:16 +00:00
|
|
|
|
2019-07-02 19:01:14 +00:00
|
|
|
vms = p->p_vmspace;
|
2002-01-13 11:58:06 +00:00
|
|
|
fp = NULL;
|
2017-02-06 20:57:12 +00:00
|
|
|
AUDIT_ARG_FD(fd);
|
2009-09-27 14:49:51 +00:00
|
|
|
|
2014-10-18 12:28:51 +00:00
|
|
|
/*
|
|
|
|
* Ignore old flags that used to be defined but did not do anything.
|
|
|
|
*/
|
2014-12-05 15:24:42 +00:00
|
|
|
flags &= ~(MAP_RESERVED0020 | MAP_RESERVED0040);
|
2020-09-01 21:20:45 +00:00
|
|
|
|
2012-08-14 11:47:07 +00:00
|
|
|
/*
|
|
|
|
* Enforce the constraints.
|
|
|
|
* Mapping of length 0 is only allowed for old binaries.
|
|
|
|
* Anonymous mapping shall specify -1 as filedescriptor and
|
|
|
|
* zero position for new code. Be nice to ancient a.out
|
|
|
|
* binaries and correct pos for anonymous mapping, since old
|
|
|
|
* ld.so sometimes issues anonymous map requests with non-zero
|
|
|
|
* pos.
|
|
|
|
*/
|
|
|
|
if (!SV_CURPROC_FLAG(SV_AOUT)) {
|
2019-07-02 19:01:14 +00:00
|
|
|
if ((len == 0 && p->p_osrel >= P_OSREL_MAP_ANON) ||
|
2017-02-06 20:57:12 +00:00
|
|
|
((flags & MAP_ANON) != 0 && (fd != -1 || pos != 0)))
|
2012-08-14 11:47:07 +00:00
|
|
|
return (EINVAL);
|
|
|
|
} else {
|
|
|
|
if ((flags & MAP_ANON) != 0)
|
|
|
|
pos = 0;
|
|
|
|
}
|
1996-03-02 17:14:09 +00:00
|
|
|
|
1999-01-06 23:05:42 +00:00
|
|
|
if (flags & MAP_STACK) {
|
2017-02-06 20:57:12 +00:00
|
|
|
if ((fd != -1) ||
|
1999-01-06 23:05:42 +00:00
|
|
|
((prot & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)))
|
|
|
|
return (EINVAL);
|
|
|
|
flags |= MAP_ANON;
|
|
|
|
pos = 0;
|
1999-01-26 02:49:52 +00:00
|
|
|
}
|
2014-10-18 12:28:51 +00:00
|
|
|
if ((flags & ~(MAP_SHARED | MAP_PRIVATE | MAP_FIXED | MAP_HASSEMAPHORE |
|
|
|
|
MAP_STACK | MAP_NOSYNC | MAP_ANON | MAP_EXCL | MAP_NOCORE |
|
Implement address space guards.
Guard, requested by the MAP_GUARD mmap(2) flag, prevents the reuse of
the allocated address space, but does not allow instantiation of the
pages in the range. It is useful for more explicit support for usual
two-stage reserve then commit allocators, since it prevents accidental
instantiation of the mapping, e.g. by mprotect(2).
Use guards to reimplement stack grow code. Explicitely track stack
grow area with the guard, including the stack guard page. On stack
grow, trivial shift of the guard map entry and stack map entry limits
makes the stack expansion. Move the code to detect stack grow and
call vm_map_growstack(), from vm_fault() into vm_map_lookup().
As result, it is impossible to get random mapping to occur in the
stack grow area, or to overlap the stack guard page.
Enable stack guard page by default.
Reviewed by: alc, markj
Man page update reviewed by: alc, bjk, emaste, markj, pho
Tested by: pho, Qualys
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D11306 (man pages)
2017-06-24 17:01:11 +00:00
|
|
|
MAP_PREFAULT_READ | MAP_GUARD |
|
2014-09-15 17:20:13 +00:00
|
|
|
#ifdef MAP_32BIT
|
|
|
|
MAP_32BIT |
|
|
|
|
#endif
|
|
|
|
MAP_ALIGNMENT_MASK)) != 0)
|
|
|
|
return (EINVAL);
|
2014-06-19 05:00:39 +00:00
|
|
|
if ((flags & (MAP_EXCL | MAP_FIXED)) == MAP_EXCL)
|
|
|
|
return (EINVAL);
|
The vm_mmap_cdev() explicitely converts absence of both MAP_SHARED and
MAP_PRIVATE flags to MAP_SHARED. Apparently, some code in tree, in
particular, libgeom, relied on this behaviour, see r271721. For
regular file types, the absence of the flags is interpreted as
MAP_PRIVATE, and libc nlist used this (fixed in r271723).
Allow the implicit flags for legacy binaries. Bump __FreeBSD_version
to get the ABI note on new binaries to check for in mmap code.
Remove the test for presence of one of the MAP_ANON, MAP_SHARED or
MAP_PRIVATE flags before fget_mmap(). For MAP_ANON, we already verify
that passed fd == -1. For fd != -1, test after fget_mmap() (for newer
binaries) covers the case.
Reported by: bdrewery, pho
Reviewed by: jhb
Sponsored by: The FreeBSD Foundation
2014-09-17 21:04:50 +00:00
|
|
|
if ((flags & (MAP_SHARED | MAP_PRIVATE)) == (MAP_SHARED | MAP_PRIVATE))
|
2014-09-15 17:20:13 +00:00
|
|
|
return (EINVAL);
|
|
|
|
if (prot != PROT_NONE &&
|
|
|
|
(prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) != 0)
|
|
|
|
return (EINVAL);
|
Implement address space guards.
Guard, requested by the MAP_GUARD mmap(2) flag, prevents the reuse of
the allocated address space, but does not allow instantiation of the
pages in the range. It is useful for more explicit support for usual
two-stage reserve then commit allocators, since it prevents accidental
instantiation of the mapping, e.g. by mprotect(2).
Use guards to reimplement stack grow code. Explicitely track stack
grow area with the guard, including the stack guard page. On stack
grow, trivial shift of the guard map entry and stack map entry limits
makes the stack expansion. Move the code to detect stack grow and
call vm_map_growstack(), from vm_fault() into vm_map_lookup().
As result, it is impossible to get random mapping to occur in the
stack grow area, or to overlap the stack guard page.
Enable stack guard page by default.
Reviewed by: alc, markj
Man page update reviewed by: alc, bjk, emaste, markj, pho
Tested by: pho, Qualys
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D11306 (man pages)
2017-06-24 17:01:11 +00:00
|
|
|
if ((flags & MAP_GUARD) != 0 && (prot != PROT_NONE || fd != -1 ||
|
2018-06-01 21:37:42 +00:00
|
|
|
pos != 0 || (flags & ~(MAP_FIXED | MAP_GUARD | MAP_EXCL |
|
2018-06-01 23:50:51 +00:00
|
|
|
#ifdef MAP_32BIT
|
|
|
|
MAP_32BIT |
|
|
|
|
#endif
|
|
|
|
MAP_ALIGNMENT_MASK)) != 0))
|
Implement address space guards.
Guard, requested by the MAP_GUARD mmap(2) flag, prevents the reuse of
the allocated address space, but does not allow instantiation of the
pages in the range. It is useful for more explicit support for usual
two-stage reserve then commit allocators, since it prevents accidental
instantiation of the mapping, e.g. by mprotect(2).
Use guards to reimplement stack grow code. Explicitely track stack
grow area with the guard, including the stack guard page. On stack
grow, trivial shift of the guard map entry and stack map entry limits
makes the stack expansion. Move the code to detect stack grow and
call vm_map_growstack(), from vm_fault() into vm_map_lookup().
As result, it is impossible to get random mapping to occur in the
stack grow area, or to overlap the stack guard page.
Enable stack guard page by default.
Reviewed by: alc, markj
Man page update reviewed by: alc, bjk, emaste, markj, pho
Tested by: pho, Qualys
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D11306 (man pages)
2017-06-24 17:01:11 +00:00
|
|
|
return (EINVAL);
|
1999-01-26 02:49:52 +00:00
|
|
|
|
1996-03-02 17:14:09 +00:00
|
|
|
/*
|
1997-08-30 18:50:06 +00:00
|
|
|
* Align the file position to a page boundary,
|
|
|
|
* and save its page offset component.
|
1996-03-02 17:14:09 +00:00
|
|
|
*/
|
1997-08-30 18:50:06 +00:00
|
|
|
pageoff = (pos & PAGE_MASK);
|
|
|
|
pos -= pageoff;
|
|
|
|
|
2019-06-10 21:26:14 +00:00
|
|
|
/* Compute size from len by rounding (on both ends). */
|
|
|
|
size = len + pageoff; /* low end... */
|
2019-06-10 03:07:10 +00:00
|
|
|
size = round_page(size); /* hi end */
|
2019-06-10 21:26:14 +00:00
|
|
|
/* Check for rounding up to zero. */
|
2019-06-10 22:06:40 +00:00
|
|
|
if (len > size)
|
2019-06-10 21:26:14 +00:00
|
|
|
return (ENOMEM);
|
1996-03-02 17:14:09 +00:00
|
|
|
|
2013-08-16 21:13:55 +00:00
|
|
|
/* Ensure alignment is at least a page and fits in a pointer. */
|
|
|
|
align = flags & MAP_ALIGNMENT_MASK;
|
|
|
|
if (align != 0 && align != MAP_ALIGNED_SUPER &&
|
|
|
|
(align >> MAP_ALIGNMENT_SHIFT >= sizeof(void *) * NBBY ||
|
|
|
|
align >> MAP_ALIGNMENT_SHIFT < PAGE_SHIFT))
|
|
|
|
return (EINVAL);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
* Check for illegal addresses. Watch out for address wrap... Note
|
|
|
|
* that VM_*_ADDRESS are not constants due to casts (argh).
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
|
|
|
if (flags & MAP_FIXED) {
|
1997-08-30 18:50:06 +00:00
|
|
|
/*
|
|
|
|
* The specified address must have the same remainder
|
|
|
|
* as the file offset taken modulo PAGE_SIZE, so it
|
|
|
|
* should be aligned after adjustment by pageoff.
|
|
|
|
*/
|
|
|
|
addr -= pageoff;
|
|
|
|
if (addr & PAGE_MASK)
|
|
|
|
return (EINVAL);
|
2009-09-27 14:49:51 +00:00
|
|
|
|
1997-08-30 18:50:06 +00:00
|
|
|
/* Address range must be all in user VM space. */
|
2020-06-19 03:32:04 +00:00
|
|
|
if (!vm_map_range_valid(&vms->vm_map, addr, addr + size))
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
2013-09-09 18:11:59 +00:00
|
|
|
#ifdef MAP_32BIT
|
|
|
|
if (flags & MAP_32BIT && addr + size > MAP_32BIT_MAX_ADDR)
|
|
|
|
return (EINVAL);
|
|
|
|
} else if (flags & MAP_32BIT) {
|
|
|
|
/*
|
|
|
|
* For MAP_32BIT, override the hint if it is too high and
|
|
|
|
* do not bother moving the mapping past the heap (since
|
|
|
|
* the heap is usually above 2GB).
|
|
|
|
*/
|
|
|
|
if (addr + size > MAP_32BIT_MAX_ADDR)
|
|
|
|
addr = 0;
|
|
|
|
#endif
|
2004-02-04 21:52:57 +00:00
|
|
|
} else {
|
2010-12-04 17:41:58 +00:00
|
|
|
/*
|
|
|
|
* XXX for non-fixed mappings where no hint is provided or
|
|
|
|
* the hint would fall in the potential heap space,
|
|
|
|
* place it after the end of the largest possible heap.
|
|
|
|
*
|
|
|
|
* There should really be a pmap call to determine a reasonable
|
|
|
|
* location.
|
|
|
|
*/
|
2004-02-04 21:52:57 +00:00
|
|
|
if (addr == 0 ||
|
|
|
|
(addr >= round_page((vm_offset_t)vms->vm_taddr) &&
|
|
|
|
addr < round_page((vm_offset_t)vms->vm_daddr +
|
2015-07-02 18:30:12 +00:00
|
|
|
lim_max(td, RLIMIT_DATA))))
|
2004-02-04 21:52:57 +00:00
|
|
|
addr = round_page((vm_offset_t)vms->vm_daddr +
|
2015-07-02 18:30:12 +00:00
|
|
|
lim_max(td, RLIMIT_DATA));
|
2004-02-04 21:52:57 +00:00
|
|
|
}
|
2019-06-10 21:26:14 +00:00
|
|
|
if (len == 0) {
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
/*
|
|
|
|
* Return success without mapping anything for old
|
|
|
|
* binaries that request a page-aligned mapping of
|
|
|
|
* length 0. For modern binaries, this function
|
|
|
|
* returns an error earlier.
|
|
|
|
*/
|
|
|
|
error = 0;
|
Implement address space guards.
Guard, requested by the MAP_GUARD mmap(2) flag, prevents the reuse of
the allocated address space, but does not allow instantiation of the
pages in the range. It is useful for more explicit support for usual
two-stage reserve then commit allocators, since it prevents accidental
instantiation of the mapping, e.g. by mprotect(2).
Use guards to reimplement stack grow code. Explicitely track stack
grow area with the guard, including the stack guard page. On stack
grow, trivial shift of the guard map entry and stack map entry limits
makes the stack expansion. Move the code to detect stack grow and
call vm_map_growstack(), from vm_fault() into vm_map_lookup().
As result, it is impossible to get random mapping to occur in the
stack grow area, or to overlap the stack guard page.
Enable stack guard page by default.
Reviewed by: alc, markj
Man page update reviewed by: alc, bjk, emaste, markj, pho
Tested by: pho, Qualys
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D11306 (man pages)
2017-06-24 17:01:11 +00:00
|
|
|
} else if ((flags & MAP_GUARD) != 0) {
|
|
|
|
error = vm_mmap_object(&vms->vm_map, &addr, size, VM_PROT_NONE,
|
|
|
|
VM_PROT_NONE, flags, NULL, pos, FALSE, td);
|
|
|
|
} else if ((flags & MAP_ANON) != 0) {
|
2004-03-01 02:44:33 +00:00
|
|
|
/*
|
|
|
|
* Mapping blank space is trivial.
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
*
|
|
|
|
* This relies on VM_PROT_* matching PROT_*.
|
2004-03-01 02:44:33 +00:00
|
|
|
*/
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
error = vm_mmap_object(&vms->vm_map, &addr, size, prot,
|
2019-06-20 18:24:16 +00:00
|
|
|
max_prot, flags, NULL, pos, FALSE, td);
|
2004-03-01 02:44:33 +00:00
|
|
|
} else {
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2011-08-11 12:30:23 +00:00
|
|
|
* Mapping file, get fp for validation and don't let the
|
|
|
|
* descriptor disappear on us if we block. Check capability
|
|
|
|
* rights, but also return the maximum rights to be combined
|
|
|
|
* with maxprot later.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2020-02-15 01:29:07 +00:00
|
|
|
cap_rights_init_one(&rights, CAP_MMAP);
|
2011-08-11 12:30:23 +00:00
|
|
|
if (prot & PROT_READ)
|
2020-02-15 01:29:07 +00:00
|
|
|
cap_rights_set_one(&rights, CAP_MMAP_R);
|
2011-08-11 12:30:23 +00:00
|
|
|
if ((flags & MAP_SHARED) != 0) {
|
|
|
|
if (prot & PROT_WRITE)
|
2020-02-15 01:29:07 +00:00
|
|
|
cap_rights_set_one(&rights, CAP_MMAP_W);
|
2011-08-11 12:30:23 +00:00
|
|
|
}
|
|
|
|
if (prot & PROT_EXEC)
|
2020-02-15 01:29:07 +00:00
|
|
|
cap_rights_set_one(&rights, CAP_MMAP_X);
|
2017-02-06 20:57:12 +00:00
|
|
|
error = fget_mmap(td, fd, &rights, &cap_maxprot, &fp);
|
Change the cap_rights_t type from uint64_t to a structure that we can extend
in the future in a backward compatible (API and ABI) way.
The cap_rights_t represents capability rights. We used to use one bit to
represent one right, but we are running out of spare bits. Currently the new
structure provides place for 114 rights (so 50 more than the previous
cap_rights_t), but it is possible to grow the structure to hold at least 285
rights, although we can make it even larger if 285 rights won't be enough.
The structure definition looks like this:
struct cap_rights {
uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
};
The initial CAP_RIGHTS_VERSION is 0.
The top two bits in the first element of the cr_rights[] array contain total
number of elements in the array - 2. This means if those two bits are equal to
0, we have 2 array elements.
The top two bits in all remaining array elements should be 0.
The next five bits in all array elements contain array index. Only one bit is
used and bit position in this five-bits range defines array index. This means
there can be at most five array elements in the future.
To define new right the CAPRIGHT() macro must be used. The macro takes two
arguments - an array index and a bit to set, eg.
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
We still support aliases that combine few rights, but the rights have to belong
to the same array element, eg:
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
There is new API to manage the new cap_rights_t structure:
cap_rights_t *cap_rights_init(cap_rights_t *rights, ...);
void cap_rights_set(cap_rights_t *rights, ...);
void cap_rights_clear(cap_rights_t *rights, ...);
bool cap_rights_is_set(const cap_rights_t *rights, ...);
bool cap_rights_is_valid(const cap_rights_t *rights);
void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
Capability rights to the cap_rights_init(), cap_rights_set(),
cap_rights_clear() and cap_rights_is_set() functions are provided by
separating them with commas, eg:
cap_rights_t rights;
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT);
There is no need to terminate the list of rights, as those functions are
actually macros that take care of the termination, eg:
#define cap_rights_set(rights, ...) \
__cap_rights_set((rights), __VA_ARGS__, 0ULL)
void __cap_rights_set(cap_rights_t *rights, ...);
Thanks to using one bit as an array index we can assert in those functions that
there are no two rights belonging to different array elements provided
together. For example this is illegal and will be detected, because CAP_LOOKUP
belongs to element 0 and CAP_PDKILL to element 1:
cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL);
Providing several rights that belongs to the same array's element this way is
correct, but is not advised. It should only be used for aliases definition.
This commit also breaks compatibility with some existing Capsicum system calls,
but I see no other way to do that. This should be fine as Capsicum is still
experimental and this change is not going to 9.x.
Sponsored by: The FreeBSD Foundation
2013-09-05 00:09:56 +00:00
|
|
|
if (error != 0)
|
2002-01-13 11:58:06 +00:00
|
|
|
goto done;
|
The vm_mmap_cdev() explicitely converts absence of both MAP_SHARED and
MAP_PRIVATE flags to MAP_SHARED. Apparently, some code in tree, in
particular, libgeom, relied on this behaviour, see r271721. For
regular file types, the absence of the flags is interpreted as
MAP_PRIVATE, and libc nlist used this (fixed in r271723).
Allow the implicit flags for legacy binaries. Bump __FreeBSD_version
to get the ABI note on new binaries to check for in mmap code.
Remove the test for presence of one of the MAP_ANON, MAP_SHARED or
MAP_PRIVATE flags before fget_mmap(). For MAP_ANON, we already verify
that passed fd == -1. For fd != -1, test after fget_mmap() (for newer
binaries) covers the case.
Reported by: bdrewery, pho
Reviewed by: jhb
Sponsored by: The FreeBSD Foundation
2014-09-17 21:04:50 +00:00
|
|
|
if ((flags & (MAP_SHARED | MAP_PRIVATE)) == 0 &&
|
2019-07-02 19:01:14 +00:00
|
|
|
p->p_osrel >= P_OSREL_MAP_FSTRICT) {
|
The vm_mmap_cdev() explicitely converts absence of both MAP_SHARED and
MAP_PRIVATE flags to MAP_SHARED. Apparently, some code in tree, in
particular, libgeom, relied on this behaviour, see r271721. For
regular file types, the absence of the flags is interpreted as
MAP_PRIVATE, and libc nlist used this (fixed in r271723).
Allow the implicit flags for legacy binaries. Bump __FreeBSD_version
to get the ABI note on new binaries to check for in mmap code.
Remove the test for presence of one of the MAP_ANON, MAP_SHARED or
MAP_PRIVATE flags before fget_mmap(). For MAP_ANON, we already verify
that passed fd == -1. For fd != -1, test after fget_mmap() (for newer
binaries) covers the case.
Reported by: bdrewery, pho
Reviewed by: jhb
Sponsored by: The FreeBSD Foundation
2014-09-17 21:04:50 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
2020-01-04 23:39:58 +00:00
|
|
|
if (check_fp_fn != NULL) {
|
|
|
|
error = check_fp_fn(fp, prot, max_prot & cap_maxprot,
|
|
|
|
flags);
|
|
|
|
if (error != 0)
|
|
|
|
goto done;
|
|
|
|
}
|
2020-09-09 22:12:51 +00:00
|
|
|
if (fp->f_ops == &shm_ops && shm_largepage(fp->f_data))
|
|
|
|
addr = orig_addr;
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
/* This relies on VM_PROT_* matching PROT_*. */
|
|
|
|
error = fo_mmap(fp, &vms->vm_map, &addr, size, prot,
|
2019-06-20 18:24:16 +00:00
|
|
|
max_prot & cap_maxprot, flags, pos, td);
|
2006-03-26 12:20:54 +00:00
|
|
|
}
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
if (error == 0)
|
2001-09-12 08:38:13 +00:00
|
|
|
td->td_retval[0] = (register_t) (addr + pageoff);
|
2000-11-18 21:01:04 +00:00
|
|
|
done:
|
|
|
|
if (fp)
|
2001-09-12 08:38:13 +00:00
|
|
|
fdrop(fp, td);
|
2002-07-06 22:14:38 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
The lseek(2), mmap(2), truncate(2), ftruncate(2), pread(2), and
pwrite(2) syscalls are wrapped to provide compatibility with pre-7.x
kernels which required padding before the off_t parameter. The
fcntl(2) contains compatibility code to handle kernels before the
struct flock was changed during the 8.x CURRENT development. The
shims were reasonable to allow easier revert to the older kernel at
that time.
Now, two or three major releases later, shims do not serve any
purpose. Such old kernels cannot handle current libc, so revert the
compatibility code.
Make padded syscalls support conditional under the COMPAT6 config
option. For COMPAT32, the syscalls were under COMPAT6 already.
Remove WITHOUT_SYSCALL_COMPAT build option, which only purpose was to
(partially) disable the removed shims.
Reviewed by: jhb, imp (previous versions)
Discussed with: peter
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2015-04-18 21:50:13 +00:00
|
|
|
#if defined(COMPAT_FREEBSD6)
|
2007-07-04 22:57:21 +00:00
|
|
|
int
|
|
|
|
freebsd6_mmap(struct thread *td, struct freebsd6_mmap_args *uap)
|
|
|
|
{
|
2021-01-23 00:08:59 +00:00
|
|
|
return (kern_mmap(td, &(struct mmap_req){
|
|
|
|
.mr_hint = (uintptr_t)uap->addr,
|
|
|
|
.mr_len = uap->len,
|
|
|
|
.mr_prot = uap->prot,
|
|
|
|
.mr_flags = uap->flags,
|
|
|
|
.mr_fd = uap->fd,
|
|
|
|
.mr_pos = uap->pos,
|
|
|
|
}));
|
2007-07-04 22:57:21 +00:00
|
|
|
}
|
The lseek(2), mmap(2), truncate(2), ftruncate(2), pread(2), and
pwrite(2) syscalls are wrapped to provide compatibility with pre-7.x
kernels which required padding before the off_t parameter. The
fcntl(2) contains compatibility code to handle kernels before the
struct flock was changed during the 8.x CURRENT development. The
shims were reasonable to allow easier revert to the older kernel at
that time.
Now, two or three major releases later, shims do not serve any
purpose. Such old kernels cannot handle current libc, so revert the
compatibility code.
Make padded syscalls support conditional under the COMPAT6 config
option. For COMPAT32, the syscalls were under COMPAT6 already.
Remove WITHOUT_SYSCALL_COMPAT build option, which only purpose was to
(partially) disable the removed shims.
Reviewed by: jhb, imp (previous versions)
Discussed with: peter
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2015-04-18 21:50:13 +00:00
|
|
|
#endif
|
2007-07-04 22:57:21 +00:00
|
|
|
|
1994-10-09 01:52:19 +00:00
|
|
|
#ifdef COMPAT_43
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-10-09 01:52:19 +00:00
|
|
|
struct ommap_args {
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
caddr_t addr;
|
|
|
|
int len;
|
|
|
|
int prot;
|
|
|
|
int flags;
|
|
|
|
int fd;
|
|
|
|
long pos;
|
1994-10-09 01:52:19 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-10-09 01:52:19 +00:00
|
|
|
int
|
2017-02-06 20:57:12 +00:00
|
|
|
ommap(struct thread *td, struct ommap_args *uap)
|
1994-10-09 01:52:19 +00:00
|
|
|
{
|
|
|
|
static const char cvtbsdprot[8] = {
|
|
|
|
0,
|
|
|
|
PROT_EXEC,
|
|
|
|
PROT_WRITE,
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
PROT_EXEC | PROT_WRITE,
|
1994-10-09 01:52:19 +00:00
|
|
|
PROT_READ,
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
PROT_EXEC | PROT_READ,
|
|
|
|
PROT_WRITE | PROT_READ,
|
|
|
|
PROT_EXEC | PROT_WRITE | PROT_READ,
|
1994-10-09 01:52:19 +00:00
|
|
|
};
|
2017-02-06 20:57:12 +00:00
|
|
|
int flags, prot;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
1994-10-09 01:52:19 +00:00
|
|
|
#define OMAP_ANON 0x0002
|
|
|
|
#define OMAP_COPY 0x0020
|
|
|
|
#define OMAP_SHARED 0x0010
|
|
|
|
#define OMAP_FIXED 0x0100
|
|
|
|
|
2017-02-06 20:57:12 +00:00
|
|
|
prot = cvtbsdprot[uap->prot & 0x7];
|
2019-02-09 03:56:48 +00:00
|
|
|
#if (defined(COMPAT_FREEBSD32) && defined(__amd64__)) || defined(__i386__)
|
2012-08-14 12:11:48 +00:00
|
|
|
if (i386_read_exec && SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
|
2017-02-06 20:57:12 +00:00
|
|
|
prot != 0)
|
|
|
|
prot |= PROT_EXEC;
|
2012-08-14 12:11:48 +00:00
|
|
|
#endif
|
2017-02-06 20:57:12 +00:00
|
|
|
flags = 0;
|
1994-10-09 01:52:19 +00:00
|
|
|
if (uap->flags & OMAP_ANON)
|
2017-02-06 20:57:12 +00:00
|
|
|
flags |= MAP_ANON;
|
1994-10-09 01:52:19 +00:00
|
|
|
if (uap->flags & OMAP_COPY)
|
2017-02-06 20:57:12 +00:00
|
|
|
flags |= MAP_COPY;
|
1994-10-09 01:52:19 +00:00
|
|
|
if (uap->flags & OMAP_SHARED)
|
2017-02-06 20:57:12 +00:00
|
|
|
flags |= MAP_SHARED;
|
1994-10-09 01:52:19 +00:00
|
|
|
else
|
2017-02-06 20:57:12 +00:00
|
|
|
flags |= MAP_PRIVATE;
|
1994-10-09 01:52:19 +00:00
|
|
|
if (uap->flags & OMAP_FIXED)
|
2017-02-06 20:57:12 +00:00
|
|
|
flags |= MAP_FIXED;
|
2021-01-23 00:08:59 +00:00
|
|
|
return (kern_mmap(td, &(struct mmap_req){
|
|
|
|
.mr_hint = (uintptr_t)uap->addr,
|
|
|
|
.mr_len = uap->len,
|
|
|
|
.mr_prot = prot,
|
|
|
|
.mr_flags = flags,
|
|
|
|
.mr_fd = uap->fd,
|
|
|
|
.mr_pos = uap->pos,
|
|
|
|
}));
|
1994-10-09 01:52:19 +00:00
|
|
|
}
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-10-09 01:52:19 +00:00
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct msync_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
2007-10-18 22:47:39 +00:00
|
|
|
size_t len;
|
1995-03-25 16:55:46 +00:00
|
|
|
int flags;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2017-02-06 20:57:12 +00:00
|
|
|
sys_msync(struct thread *td, struct msync_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2017-02-06 20:57:12 +00:00
|
|
|
|
2017-02-13 09:04:38 +00:00
|
|
|
return (kern_msync(td, (uintptr_t)uap->addr, uap->len, uap->flags));
|
2017-02-06 20:57:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-02-13 09:04:38 +00:00
|
|
|
kern_msync(struct thread *td, uintptr_t addr0, size_t size, int flags)
|
2017-02-06 20:57:12 +00:00
|
|
|
{
|
2017-02-13 09:04:38 +00:00
|
|
|
vm_offset_t addr;
|
2017-02-06 20:57:12 +00:00
|
|
|
vm_size_t pageoff;
|
1994-05-24 10:09:53 +00:00
|
|
|
vm_map_t map;
|
|
|
|
int rv;
|
|
|
|
|
2017-02-13 09:04:38 +00:00
|
|
|
addr = addr0;
|
1996-02-23 18:49:25 +00:00
|
|
|
pageoff = (addr & PAGE_MASK);
|
|
|
|
addr -= pageoff;
|
|
|
|
size += pageoff;
|
|
|
|
size = (vm_size_t) round_page(size);
|
1996-03-02 17:14:09 +00:00
|
|
|
if (addr + size < addr)
|
2002-03-10 21:52:48 +00:00
|
|
|
return (EINVAL);
|
1996-02-23 18:49:25 +00:00
|
|
|
|
|
|
|
if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE))
|
1995-03-25 17:36:00 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2001-09-12 08:38:13 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
1996-03-02 17:14:09 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Clean the pages and interpret the return value.
|
|
|
|
*/
|
2003-11-09 05:25:35 +00:00
|
|
|
rv = vm_map_sync(map, addr, addr + size, (flags & MS_ASYNC) == 0,
|
1995-03-25 16:55:46 +00:00
|
|
|
(flags & MS_INVALIDATE) != 0);
|
1994-05-24 10:09:53 +00:00
|
|
|
switch (rv) {
|
|
|
|
case KERN_SUCCESS:
|
2002-03-10 21:52:48 +00:00
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
case KERN_INVALID_ADDRESS:
|
2014-05-07 08:38:02 +00:00
|
|
|
return (ENOMEM);
|
2003-11-14 06:55:11 +00:00
|
|
|
case KERN_INVALID_ARGUMENT:
|
|
|
|
return (EBUSY);
|
2012-03-17 23:00:32 +00:00
|
|
|
case KERN_FAILURE:
|
|
|
|
return (EIO);
|
1994-05-24 10:09:53 +00:00
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct munmap_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2017-02-06 20:57:12 +00:00
|
|
|
sys_munmap(struct thread *td, struct munmap_args *uap)
|
|
|
|
{
|
|
|
|
|
2017-02-13 09:04:38 +00:00
|
|
|
return (kern_munmap(td, (uintptr_t)uap->addr, uap->len));
|
2017-02-06 20:57:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-02-13 09:04:38 +00:00
|
|
|
kern_munmap(struct thread *td, uintptr_t addr0, size_t size)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2006-03-26 12:20:54 +00:00
|
|
|
#ifdef HWPMC_HOOKS
|
|
|
|
struct pmckern_map_out pkm;
|
|
|
|
vm_map_entry_t entry;
|
2017-01-24 22:00:16 +00:00
|
|
|
bool pmc_handled;
|
2006-03-26 12:20:54 +00:00
|
|
|
#endif
|
2020-06-19 03:32:04 +00:00
|
|
|
vm_offset_t addr, end;
|
2017-02-06 20:57:12 +00:00
|
|
|
vm_size_t pageoff;
|
1994-05-24 10:09:53 +00:00
|
|
|
vm_map_t map;
|
2020-09-09 21:34:31 +00:00
|
|
|
int rv;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2003-11-10 01:37:40 +00:00
|
|
|
if (size == 0)
|
|
|
|
return (EINVAL);
|
1996-02-23 18:49:25 +00:00
|
|
|
|
2017-02-13 09:04:38 +00:00
|
|
|
addr = addr0;
|
1996-02-23 18:49:25 +00:00
|
|
|
pageoff = (addr & PAGE_MASK);
|
|
|
|
addr -= pageoff;
|
|
|
|
size += pageoff;
|
|
|
|
size = (vm_size_t) round_page(size);
|
2020-06-19 03:32:04 +00:00
|
|
|
end = addr + size;
|
2001-09-12 08:38:13 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
2020-06-19 03:32:04 +00:00
|
|
|
if (!vm_map_range_valid(map, addr, end))
|
2002-09-21 22:07:17 +00:00
|
|
|
return (EINVAL);
|
2020-06-19 03:32:04 +00:00
|
|
|
|
2003-11-10 01:37:40 +00:00
|
|
|
vm_map_lock(map);
|
2006-03-26 12:20:54 +00:00
|
|
|
#ifdef HWPMC_HOOKS
|
2017-01-24 22:00:16 +00:00
|
|
|
pmc_handled = false;
|
|
|
|
if (PMC_HOOK_INSTALLED(PMC_FN_MUNMAP)) {
|
|
|
|
pmc_handled = true;
|
|
|
|
/*
|
|
|
|
* Inform hwpmc if the address range being unmapped contains
|
|
|
|
* an executable region.
|
|
|
|
*/
|
|
|
|
pkm.pm_address = (uintptr_t) NULL;
|
|
|
|
if (vm_map_lookup_entry(map, addr, &entry)) {
|
2020-06-19 03:32:04 +00:00
|
|
|
for (; entry->start < end;
|
2019-11-13 15:56:07 +00:00
|
|
|
entry = vm_map_entry_succ(entry)) {
|
2017-01-24 22:00:16 +00:00
|
|
|
if (vm_map_check_protection(map, entry->start,
|
|
|
|
entry->end, VM_PROT_EXECUTE) == TRUE) {
|
|
|
|
pkm.pm_address = (uintptr_t) addr;
|
|
|
|
pkm.pm_size = (size_t) size;
|
|
|
|
break;
|
|
|
|
}
|
2006-03-26 12:20:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2020-09-09 21:34:31 +00:00
|
|
|
rv = vm_map_delete(map, addr, end);
|
2010-09-07 00:23:45 +00:00
|
|
|
|
|
|
|
#ifdef HWPMC_HOOKS
|
2020-09-09 21:34:31 +00:00
|
|
|
if (rv == KERN_SUCCESS && __predict_false(pmc_handled)) {
|
2017-01-24 22:00:16 +00:00
|
|
|
/* downgrade the lock to prevent a LOR with the pmc-sx lock */
|
|
|
|
vm_map_lock_downgrade(map);
|
|
|
|
if (pkm.pm_address != (uintptr_t) NULL)
|
|
|
|
PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm);
|
|
|
|
vm_map_unlock_read(map);
|
|
|
|
} else
|
2010-09-07 00:23:45 +00:00
|
|
|
#endif
|
2017-01-24 22:00:16 +00:00
|
|
|
vm_map_unlock(map);
|
|
|
|
|
2020-09-09 21:34:31 +00:00
|
|
|
return (vm_mmap_to_errno(rv));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mprotect_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
const void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
int prot;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2017-02-06 20:57:12 +00:00
|
|
|
sys_mprotect(struct thread *td, struct mprotect_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
|
2017-02-13 09:04:38 +00:00
|
|
|
return (kern_mprotect(td, (uintptr_t)uap->addr, uap->len, uap->prot));
|
2017-02-06 20:57:12 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2017-02-06 20:57:12 +00:00
|
|
|
int
|
2017-02-13 09:04:38 +00:00
|
|
|
kern_mprotect(struct thread *td, uintptr_t addr0, size_t size, int prot)
|
2017-02-06 20:57:12 +00:00
|
|
|
{
|
2017-02-13 09:04:38 +00:00
|
|
|
vm_offset_t addr;
|
2017-02-06 20:57:12 +00:00
|
|
|
vm_size_t pageoff;
|
2019-06-20 18:24:16 +00:00
|
|
|
int vm_error, max_prot;
|
2021-01-12 12:43:39 +00:00
|
|
|
int flags;
|
2017-02-06 20:57:12 +00:00
|
|
|
|
2017-02-13 09:04:38 +00:00
|
|
|
addr = addr0;
|
2019-06-20 18:24:16 +00:00
|
|
|
if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0)
|
|
|
|
return (EINVAL);
|
|
|
|
max_prot = PROT_MAX_EXTRACT(prot);
|
|
|
|
prot = PROT_EXTRACT(prot);
|
1996-02-23 18:49:25 +00:00
|
|
|
pageoff = (addr & PAGE_MASK);
|
|
|
|
addr -= pageoff;
|
|
|
|
size += pageoff;
|
|
|
|
size = (vm_size_t) round_page(size);
|
2018-07-31 18:00:47 +00:00
|
|
|
#ifdef COMPAT_FREEBSD32
|
|
|
|
if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
|
|
|
|
if (((addr + size) & 0xffffffff) < addr)
|
|
|
|
return (EINVAL);
|
|
|
|
} else
|
|
|
|
#endif
|
1996-03-02 17:14:09 +00:00
|
|
|
if (addr + size < addr)
|
2002-03-10 21:52:48 +00:00
|
|
|
return (EINVAL);
|
1996-02-23 18:49:25 +00:00
|
|
|
|
2021-01-12 12:43:39 +00:00
|
|
|
flags = VM_MAP_PROTECT_SET_PROT;
|
|
|
|
if (max_prot != 0)
|
|
|
|
flags |= VM_MAP_PROTECT_SET_MAXPROT;
|
|
|
|
vm_error = vm_map_protect(&td->td_proc->p_vmspace->vm_map,
|
|
|
|
addr, addr + size, prot, max_prot, flags);
|
2019-06-20 18:24:16 +00:00
|
|
|
|
|
|
|
switch (vm_error) {
|
1994-05-24 10:09:53 +00:00
|
|
|
case KERN_SUCCESS:
|
|
|
|
return (0);
|
|
|
|
case KERN_PROTECTION_FAILURE:
|
|
|
|
return (EACCES);
|
Implement global and per-uid accounting of the anonymous memory. Add
rlimit RLIMIT_SWAP that limits the amount of swap that may be reserved
for the uid.
The accounting information (charge) is associated with either map entry,
or vm object backing the entry, assuming the object is the first one
in the shadow chain and entry does not require COW. Charge is moved
from entry to object on allocation of the object, e.g. during the mmap,
assuming the object is allocated, or on the first page fault on the
entry. It moves back to the entry on forks due to COW setup.
The per-entry granularity of accounting makes the charge process fair
for processes that change uid during lifetime, and decrements charge
for proper uid when region is unmapped.
The interface of vm_pager_allocate(9) is extended by adding struct ucred *,
that is used to charge appropriate uid when allocation if performed by
kernel, e.g. md(4).
Several syscalls, among them is fork(2), may now return ENOMEM when
global or per-uid limits are enforced.
In collaboration with: pho
Reviewed by: alc
Approved by: re (kensmith)
2009-06-23 20:45:22 +00:00
|
|
|
case KERN_RESOURCE_SHORTAGE:
|
|
|
|
return (ENOMEM);
|
2021-01-12 12:43:39 +00:00
|
|
|
case KERN_OUT_OF_BOUNDS:
|
|
|
|
return (ENOTSUP);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
1996-02-23 18:49:25 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct minherit_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
1996-02-23 18:49:25 +00:00
|
|
|
int inherit;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-02-13 00:40:55 +00:00
|
|
|
sys_minherit(struct thread *td, struct minherit_args *uap)
|
2020-06-20 18:29:22 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_minherit(td, (uintptr_t)uap->addr, uap->len,
|
|
|
|
uap->inherit));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_minherit(struct thread *td, uintptr_t addr0, size_t len, int inherit0)
|
1996-02-23 18:49:25 +00:00
|
|
|
{
|
|
|
|
vm_offset_t addr;
|
|
|
|
vm_size_t size, pageoff;
|
2001-07-04 19:00:13 +00:00
|
|
|
vm_inherit_t inherit;
|
1996-02-23 18:49:25 +00:00
|
|
|
|
2020-06-20 18:29:22 +00:00
|
|
|
addr = (vm_offset_t)addr0;
|
|
|
|
size = len;
|
|
|
|
inherit = inherit0;
|
1996-02-23 18:49:25 +00:00
|
|
|
|
|
|
|
pageoff = (addr & PAGE_MASK);
|
|
|
|
addr -= pageoff;
|
|
|
|
size += pageoff;
|
|
|
|
size = (vm_size_t) round_page(size);
|
1996-03-02 17:14:09 +00:00
|
|
|
if (addr + size < addr)
|
2002-03-10 21:52:48 +00:00
|
|
|
return (EINVAL);
|
1996-02-23 18:49:25 +00:00
|
|
|
|
2002-05-18 18:59:00 +00:00
|
|
|
switch (vm_map_inherit(&td->td_proc->p_vmspace->vm_map, addr,
|
|
|
|
addr + size, inherit)) {
|
1996-02-23 18:49:25 +00:00
|
|
|
case KERN_SUCCESS:
|
|
|
|
return (0);
|
|
|
|
case KERN_PROTECTION_FAILURE:
|
|
|
|
return (EACCES);
|
|
|
|
}
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct madvise_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
int behav;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2017-02-13 00:40:55 +00:00
|
|
|
sys_madvise(struct thread *td, struct madvise_args *uap)
|
2017-02-06 20:57:12 +00:00
|
|
|
{
|
|
|
|
|
2017-02-13 09:04:38 +00:00
|
|
|
return (kern_madvise(td, (uintptr_t)uap->addr, uap->len, uap->behav));
|
2017-02-06 20:57:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-02-13 09:04:38 +00:00
|
|
|
kern_madvise(struct thread *td, uintptr_t addr0, size_t len, int behav)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2002-09-21 22:07:17 +00:00
|
|
|
vm_map_t map;
|
2017-02-13 09:04:38 +00:00
|
|
|
vm_offset_t addr, end, start;
|
2013-09-19 18:53:42 +00:00
|
|
|
int flags;
|
1999-09-21 05:00:48 +00:00
|
|
|
|
2003-03-31 21:09:57 +00:00
|
|
|
/*
|
|
|
|
* Check for our special case, advising the swap pager we are
|
|
|
|
* "immortal."
|
|
|
|
*/
|
2017-02-06 20:57:12 +00:00
|
|
|
if (behav == MADV_PROTECT) {
|
2013-09-19 18:53:42 +00:00
|
|
|
flags = PPROT_SET;
|
|
|
|
return (kern_procctl(td, P_PID, td->td_proc->p_pid,
|
|
|
|
PROC_SPROTECT, &flags));
|
2003-03-31 21:09:57 +00:00
|
|
|
}
|
2013-09-19 18:53:42 +00:00
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* Check for illegal addresses. Watch out for address wrap... Note
|
|
|
|
* that VM_*_ADDRESS are not constants due to casts (argh).
|
|
|
|
*/
|
2002-09-21 22:07:17 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
2017-02-13 09:04:38 +00:00
|
|
|
addr = addr0;
|
2020-06-19 03:32:04 +00:00
|
|
|
if (!vm_map_range_valid(map, addr, addr + len))
|
1996-05-19 07:36:50 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since this routine is only advisory, we default to conservative
|
|
|
|
* behavior.
|
|
|
|
*/
|
2017-02-06 20:57:12 +00:00
|
|
|
start = trunc_page(addr);
|
|
|
|
end = round_page(addr + len);
|
2003-12-08 02:45:45 +00:00
|
|
|
|
Use a single, consistent approach to returning success versus failure in
vm_map_madvise(). Previously, vm_map_madvise() used a traditional Unix-
style "return (0);" to indicate success in the common case, but Mach-
style return values in the edge cases. Since KERN_SUCCESS equals zero,
the only problem with this inconsistency was stylistic. vm_map_madvise()
has exactly two callers in the entire source tree, and only one of them
cares about the return value. That caller, kern_madvise(), can be
simplified if vm_map_madvise() consistently uses Unix-style return
values.
Since vm_map_madvise() uses the variable modify_map as a Boolean, make it
one.
Eliminate a redundant error check from kern_madvise(). Add a comment
explaining where the check is performed.
Explicitly note that exec_release_args_kva() doesn't care about
vm_map_madvise()'s return value. Since MADV_FREE is passed as the
behavior, the return value will always be zero.
Reviewed by: kib, markj
MFC after: 7 days
2018-06-04 16:28:06 +00:00
|
|
|
/*
|
|
|
|
* vm_map_madvise() checks for illegal values of behav.
|
|
|
|
*/
|
|
|
|
return (vm_map_madvise(map, start, end, behav));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mincore_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
const void *addr;
|
1996-03-02 17:14:09 +00:00
|
|
|
size_t len;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
char *vec;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2017-02-13 00:40:55 +00:00
|
|
|
sys_mincore(struct thread *td, struct mincore_args *uap)
|
2017-03-30 19:42:49 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_mincore(td, (uintptr_t)uap->addr, uap->len, uap->vec));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_mincore(struct thread *td, uintptr_t addr0, size_t len, char *vec)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1996-05-19 07:36:50 +00:00
|
|
|
pmap_t pmap;
|
|
|
|
vm_map_t map;
|
2019-10-16 22:03:27 +00:00
|
|
|
vm_map_entry_t current, entry;
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
vm_object_t object;
|
2019-10-16 22:03:27 +00:00
|
|
|
vm_offset_t addr, cend, end, first_addr;
|
|
|
|
vm_paddr_t pa;
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
vm_page_t m;
|
|
|
|
vm_pindex_t pindex;
|
2019-10-16 22:03:27 +00:00
|
|
|
int error, lastvecindex, mincoreinfo, vecindex;
|
1999-03-02 22:55:02 +00:00
|
|
|
unsigned int timestamp;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* Make sure that the addresses presented are valid for user
|
|
|
|
* mode.
|
|
|
|
*/
|
2017-03-30 19:42:49 +00:00
|
|
|
first_addr = addr = trunc_page(addr0);
|
2019-10-16 21:47:58 +00:00
|
|
|
end = round_page(addr0 + len);
|
2002-09-21 22:07:17 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
|
|
|
if (end > vm_map_max(map) || end < addr)
|
2006-06-21 12:59:05 +00:00
|
|
|
return (ENOMEM);
|
1995-10-21 17:42:28 +00:00
|
|
|
|
2001-09-12 08:38:13 +00:00
|
|
|
pmap = vmspace_pmap(td->td_proc->p_vmspace);
|
1996-05-19 07:36:50 +00:00
|
|
|
|
1999-03-01 20:42:16 +00:00
|
|
|
vm_map_lock_read(map);
|
1999-03-02 22:55:02 +00:00
|
|
|
RestartScan:
|
|
|
|
timestamp = map->timestamp;
|
1996-05-19 07:36:50 +00:00
|
|
|
|
2006-06-21 12:59:05 +00:00
|
|
|
if (!vm_map_lookup_entry(map, addr, &entry)) {
|
|
|
|
vm_map_unlock_read(map);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
1996-05-19 07:36:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do this on a map entry basis so that if the pages are not
|
|
|
|
* in the current processes address space, we can easily look
|
|
|
|
* up the pages elsewhere.
|
|
|
|
*/
|
|
|
|
lastvecindex = -1;
|
2019-11-13 15:56:07 +00:00
|
|
|
while (entry->start < end) {
|
2006-06-21 12:59:05 +00:00
|
|
|
/*
|
|
|
|
* check for contiguity
|
|
|
|
*/
|
2019-11-13 15:56:07 +00:00
|
|
|
current = entry;
|
|
|
|
entry = vm_map_entry_succ(current);
|
|
|
|
if (current->end < end &&
|
|
|
|
entry->start > current->end) {
|
2006-06-21 12:59:05 +00:00
|
|
|
vm_map_unlock_read(map);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* ignore submaps (for now) or null objects
|
|
|
|
*/
|
1999-02-07 21:48:23 +00:00
|
|
|
if ((current->eflags & MAP_ENTRY_IS_SUB_MAP) ||
|
2019-10-16 22:03:27 +00:00
|
|
|
current->object.vm_object == NULL)
|
1996-05-19 07:36:50 +00:00
|
|
|
continue;
|
2003-12-08 02:45:45 +00:00
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* limit this scan to the current map entry and the
|
|
|
|
* limits for the mincore call
|
|
|
|
*/
|
|
|
|
if (addr < current->start)
|
|
|
|
addr = current->start;
|
|
|
|
cend = current->end;
|
|
|
|
if (cend > end)
|
|
|
|
cend = end;
|
|
|
|
|
2019-10-16 22:03:27 +00:00
|
|
|
for (; addr < cend; addr += PAGE_SIZE) {
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* Check pmap first, it is likely faster, also
|
|
|
|
* it can provide info as to whether we are the
|
|
|
|
* one referencing or modifying the page.
|
|
|
|
*/
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
m = NULL;
|
2019-10-16 22:03:27 +00:00
|
|
|
object = NULL;
|
|
|
|
retry:
|
|
|
|
pa = 0;
|
|
|
|
mincoreinfo = pmap_mincore(pmap, addr, &pa);
|
2019-01-07 22:10:48 +00:00
|
|
|
if (mincore_mapped) {
|
|
|
|
/*
|
|
|
|
* We only care about this pmap's
|
|
|
|
* mapping of the page, if any.
|
|
|
|
*/
|
2019-10-16 22:03:27 +00:00
|
|
|
;
|
|
|
|
} else if (pa != 0) {
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
* The page is mapped by this process but not
|
|
|
|
* both accessed and modified. It is also
|
|
|
|
* managed. Acquire the object lock so that
|
2019-10-16 22:03:27 +00:00
|
|
|
* other mappings might be examined. The page's
|
|
|
|
* identity may change at any point before its
|
|
|
|
* object lock is acquired, so re-validate if
|
|
|
|
* necessary.
|
1996-05-19 07:36:50 +00:00
|
|
|
*/
|
2019-10-16 22:03:27 +00:00
|
|
|
m = PHYS_TO_VM_PAGE(pa);
|
|
|
|
while (object == NULL || m->object != object) {
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
if (object != NULL)
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WUNLOCK(object);
|
2020-02-14 23:16:29 +00:00
|
|
|
object = atomic_load_ptr(&m->object);
|
2019-10-16 22:03:27 +00:00
|
|
|
if (object == NULL)
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
goto retry;
|
2019-10-16 22:03:27 +00:00
|
|
|
VM_OBJECT_WLOCK(object);
|
|
|
|
}
|
|
|
|
if (pa != pmap_extract(pmap, addr))
|
|
|
|
goto retry;
|
2019-10-15 03:45:41 +00:00
|
|
|
KASSERT(vm_page_all_valid(m),
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
("mincore: page %p is mapped but invalid",
|
|
|
|
m));
|
|
|
|
} else if (mincoreinfo == 0) {
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
* The page is not mapped by this process. If
|
|
|
|
* the object implements managed pages, then
|
|
|
|
* determine if the page is resident so that
|
|
|
|
* the mappings might be examined.
|
1996-05-19 07:36:50 +00:00
|
|
|
*/
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
if (current->object.vm_object != object) {
|
|
|
|
if (object != NULL)
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WUNLOCK(object);
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
object = current->object.vm_object;
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WLOCK(object);
|
1996-05-19 07:36:50 +00:00
|
|
|
}
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
if (object->type == OBJT_DEFAULT ||
|
|
|
|
object->type == OBJT_SWAP ||
|
|
|
|
object->type == OBJT_VNODE) {
|
|
|
|
pindex = OFF_TO_IDX(current->offset +
|
|
|
|
(addr - current->start));
|
|
|
|
m = vm_page_lookup(object, pindex);
|
2019-10-15 03:45:41 +00:00
|
|
|
if (m != NULL && vm_page_none_valid(m))
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
m = NULL;
|
|
|
|
if (m != NULL)
|
|
|
|
mincoreinfo = MINCORE_INCORE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m != NULL) {
|
2019-10-16 22:03:27 +00:00
|
|
|
VM_OBJECT_ASSERT_WLOCKED(m->object);
|
|
|
|
|
|
|
|
/* Examine other mappings of the page. */
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
if (m->dirty == 0 && pmap_is_modified(m))
|
|
|
|
vm_page_dirty(m);
|
|
|
|
if (m->dirty != 0)
|
|
|
|
mincoreinfo |= MINCORE_MODIFIED_OTHER;
|
2019-10-16 22:03:27 +00:00
|
|
|
|
2010-05-26 18:00:44 +00:00
|
|
|
/*
|
2011-09-06 10:30:11 +00:00
|
|
|
* The first test for PGA_REFERENCED is an
|
2010-05-26 18:00:44 +00:00
|
|
|
* optimization. The second test is
|
|
|
|
* required because a concurrent pmap
|
|
|
|
* operation could clear the last reference
|
2011-09-06 10:30:11 +00:00
|
|
|
* and set PGA_REFERENCED before the call to
|
2010-05-26 18:00:44 +00:00
|
|
|
* pmap_is_referenced().
|
|
|
|
*/
|
2019-12-10 18:14:50 +00:00
|
|
|
if ((m->a.flags & PGA_REFERENCED) != 0 ||
|
2010-05-26 18:00:44 +00:00
|
|
|
pmap_is_referenced(m) ||
|
2019-12-10 18:14:50 +00:00
|
|
|
(m->a.flags & PGA_REFERENCED) != 0)
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
mincoreinfo |= MINCORE_REFERENCED_OTHER;
|
1996-05-19 07:36:50 +00:00
|
|
|
}
|
Roughly half of a typical pmap_mincore() implementation is machine-
independent code. Move this code into mincore(), and eliminate the
page queues lock from pmap_mincore().
Push down the page queues lock into pmap_clear_modify(),
pmap_clear_reference(), and pmap_is_modified(). Assert that these
functions are never passed an unmanaged page.
Eliminate an inaccurate comment from powerpc/powerpc/mmu_if.m:
Contrary to what the comment says, pmap_mincore() is not simply an
optimization. Without a complete pmap_mincore() implementation,
mincore() cannot return either MINCORE_MODIFIED or MINCORE_REFERENCED
because only the pmap can provide this information.
Eliminate the page queues lock from vfs_setdirty_locked_object(),
vm_pageout_clean(), vm_object_page_collect_flush(), and
vm_object_page_clean(). Generally speaking, these are all accesses
to the page's dirty field, which are synchronized by the containing
vm object's lock.
Reduce the scope of the page queues lock in vm_object_madvise() and
vm_page_dontneed().
Reviewed by: kib (an earlier version)
2010-05-24 14:26:57 +00:00
|
|
|
if (object != NULL)
|
2013-03-09 02:32:23 +00:00
|
|
|
VM_OBJECT_WUNLOCK(object);
|
1996-05-19 07:36:50 +00:00
|
|
|
|
1999-03-02 22:55:02 +00:00
|
|
|
/*
|
|
|
|
* subyte may page fault. In case it needs to modify
|
|
|
|
* the map, we release the lock.
|
|
|
|
*/
|
|
|
|
vm_map_unlock_read(map);
|
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* calculate index into user supplied byte vector
|
|
|
|
*/
|
2017-03-14 19:39:17 +00:00
|
|
|
vecindex = atop(addr - first_addr);
|
1996-05-19 07:36:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we have skipped map entries, we need to make sure that
|
|
|
|
* the byte vector is zeroed for those skipped entries.
|
|
|
|
*/
|
2001-07-04 19:00:13 +00:00
|
|
|
while ((lastvecindex + 1) < vecindex) {
|
2013-09-12 20:46:32 +00:00
|
|
|
++lastvecindex;
|
2002-03-10 21:52:48 +00:00
|
|
|
error = subyte(vec + lastvecindex, 0);
|
1996-05-19 07:36:50 +00:00
|
|
|
if (error) {
|
2001-08-31 01:26:30 +00:00
|
|
|
error = EFAULT;
|
|
|
|
goto done2;
|
1996-05-19 07:36:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pass the page information to the user
|
|
|
|
*/
|
2002-03-10 21:52:48 +00:00
|
|
|
error = subyte(vec + vecindex, mincoreinfo);
|
1996-05-19 07:36:50 +00:00
|
|
|
if (error) {
|
2001-08-31 01:26:30 +00:00
|
|
|
error = EFAULT;
|
|
|
|
goto done2;
|
1996-05-19 07:36:50 +00:00
|
|
|
}
|
1999-03-02 22:55:02 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the map has changed, due to the subyte, the previous
|
|
|
|
* output may be invalid.
|
|
|
|
*/
|
|
|
|
vm_map_lock_read(map);
|
|
|
|
if (timestamp != map->timestamp)
|
|
|
|
goto RestartScan;
|
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
lastvecindex = vecindex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-02 22:55:02 +00:00
|
|
|
/*
|
|
|
|
* subyte may page fault. In case it needs to modify
|
|
|
|
* the map, we release the lock.
|
|
|
|
*/
|
|
|
|
vm_map_unlock_read(map);
|
|
|
|
|
1996-05-19 07:36:50 +00:00
|
|
|
/*
|
|
|
|
* Zero the last entries in the byte vector.
|
|
|
|
*/
|
2017-03-14 19:39:17 +00:00
|
|
|
vecindex = atop(end - first_addr);
|
2001-07-04 19:00:13 +00:00
|
|
|
while ((lastvecindex + 1) < vecindex) {
|
2013-09-12 20:46:32 +00:00
|
|
|
++lastvecindex;
|
2002-03-10 21:52:48 +00:00
|
|
|
error = subyte(vec + lastvecindex, 0);
|
1996-05-19 07:36:50 +00:00
|
|
|
if (error) {
|
2001-08-31 01:26:30 +00:00
|
|
|
error = EFAULT;
|
|
|
|
goto done2;
|
1995-10-21 17:42:28 +00:00
|
|
|
}
|
|
|
|
}
|
2003-12-08 02:45:45 +00:00
|
|
|
|
1999-03-02 22:55:02 +00:00
|
|
|
/*
|
|
|
|
* If the map has changed, due to the subyte, the previous
|
|
|
|
* output may be invalid.
|
|
|
|
*/
|
|
|
|
vm_map_lock_read(map);
|
|
|
|
if (timestamp != map->timestamp)
|
|
|
|
goto RestartScan;
|
1999-03-01 20:42:16 +00:00
|
|
|
vm_map_unlock_read(map);
|
2001-08-31 01:26:30 +00:00
|
|
|
done2:
|
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct mlock_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
const void *addr;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
size_t len;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2017-02-13 00:40:55 +00:00
|
|
|
sys_mlock(struct thread *td, struct mlock_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2013-06-08 13:13:40 +00:00
|
|
|
|
2017-02-13 09:04:38 +00:00
|
|
|
return (kern_mlock(td->td_proc, td->td_ucred,
|
|
|
|
__DECONST(uintptr_t, uap->addr), uap->len));
|
2013-06-08 13:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-02-13 09:04:38 +00:00
|
|
|
kern_mlock(struct proc *proc, struct ucred *cred, uintptr_t addr0, size_t len)
|
2013-06-08 13:13:40 +00:00
|
|
|
{
|
2004-03-15 09:11:23 +00:00
|
|
|
vm_offset_t addr, end, last, start;
|
|
|
|
vm_size_t npages, size;
|
2013-01-10 12:43:58 +00:00
|
|
|
vm_map_t map;
|
2011-04-05 20:23:59 +00:00
|
|
|
unsigned long nsize;
|
2004-03-15 09:11:23 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2018-12-11 19:32:16 +00:00
|
|
|
error = priv_check_cred(cred, PRIV_VM_MLOCK);
|
2004-02-26 00:27:04 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2017-02-13 09:04:38 +00:00
|
|
|
addr = addr0;
|
2013-06-08 13:13:40 +00:00
|
|
|
size = len;
|
2004-03-15 09:11:23 +00:00
|
|
|
last = addr + size;
|
2004-03-05 22:03:11 +00:00
|
|
|
start = trunc_page(addr);
|
2004-03-15 09:11:23 +00:00
|
|
|
end = round_page(last);
|
|
|
|
if (last < addr || end < addr)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
2004-03-05 22:03:11 +00:00
|
|
|
npages = atop(end - start);
|
Provide separate accounting for user-wired pages.
Historically we have not distinguished between kernel wirings and user
wirings for accounting purposes. User wirings (via mlock(2)) were
subject to a global limit on the number of wired pages, so if large
swaths of physical memory were wired by the kernel, as happens with
the ZFS ARC among other things, the limit could be exceeded, causing
user wirings to fail.
The change adds a new counter, v_user_wire_count, which counts the
number of virtual pages wired by user processes via mlock(2) and
mlockall(2). Only user-wired pages are subject to the system-wide
limit which helps provide some safety against deadlocks. In
particular, while sources of kernel wirings typically support some
backpressure mechanism, there is no way to reclaim user-wired pages
shorting of killing the wiring process. The limit is exported as
vm.max_user_wired, renamed from vm.max_wired, and changed from u_int
to u_long.
The choice to count virtual user-wired pages rather than physical
pages was done for simplicity. There are mechanisms that can cause
user-wired mappings to be destroyed while maintaining a wiring of
the backing physical page; these make it difficult to accurately
track user wirings at the physical page layer.
The change also closes some holes which allowed user wirings to succeed
even when they would cause the system limit to be exceeded. For
instance, mmap() may now fail with ENOMEM in a process that has called
mlockall(MCL_FUTURE) if the new mapping would cause the user wiring
limit to be exceeded.
Note that bhyve -S is subject to the user wiring limit, which defaults
to 1/3 of physical RAM. Users that wish to exceed the limit must tune
vm.max_user_wired.
Reviewed by: kib, ngie (mlock() test changes)
Tested by: pho (earlier version)
MFC after: 45 days
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D19908
2019-05-13 16:38:48 +00:00
|
|
|
if (npages > vm_page_max_user_wired)
|
2004-03-05 22:03:11 +00:00
|
|
|
return (ENOMEM);
|
2013-01-10 12:43:58 +00:00
|
|
|
map = &proc->p_vmspace->vm_map;
|
2004-02-26 00:27:04 +00:00
|
|
|
PROC_LOCK(proc);
|
2013-01-10 12:43:58 +00:00
|
|
|
nsize = ptoa(npages + pmap_wired_count(map->pmap));
|
2015-06-10 10:48:12 +00:00
|
|
|
if (nsize > lim_cur_proc(proc, RLIMIT_MEMLOCK)) {
|
2004-02-26 00:27:04 +00:00
|
|
|
PROC_UNLOCK(proc);
|
1997-06-15 23:35:32 +00:00
|
|
|
return (ENOMEM);
|
2004-02-04 21:52:57 +00:00
|
|
|
}
|
2004-02-26 00:27:04 +00:00
|
|
|
PROC_UNLOCK(proc);
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2015-04-29 10:23:02 +00:00
|
|
|
if (racct_enable) {
|
|
|
|
PROC_LOCK(proc);
|
|
|
|
error = racct_set(proc, RACCT_MEMLOCK, nsize);
|
|
|
|
PROC_UNLOCK(proc);
|
|
|
|
if (error != 0)
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
2013-01-10 12:43:58 +00:00
|
|
|
error = vm_map_wire(map, start, end,
|
2004-03-15 06:43:51 +00:00
|
|
|
VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2015-04-29 10:23:02 +00:00
|
|
|
if (racct_enable && error != KERN_SUCCESS) {
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_LOCK(proc);
|
|
|
|
racct_set(proc, RACCT_MEMLOCK,
|
2013-01-10 12:43:58 +00:00
|
|
|
ptoa(pmap_wired_count(map->pmap)));
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_UNLOCK(proc);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
2020-09-09 22:12:51 +00:00
|
|
|
switch (error) {
|
|
|
|
case KERN_SUCCESS:
|
|
|
|
return (0);
|
|
|
|
case KERN_INVALID_ARGUMENT:
|
|
|
|
return (EINVAL);
|
|
|
|
default:
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-06-15 23:35:32 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct mlockall_args {
|
|
|
|
int how;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int
|
2017-02-13 00:40:55 +00:00
|
|
|
sys_mlockall(struct thread *td, struct mlockall_args *uap)
|
1997-06-15 23:35:32 +00:00
|
|
|
{
|
2003-08-11 07:14:08 +00:00
|
|
|
vm_map_t map;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
2012-12-18 07:35:01 +00:00
|
|
|
error = priv_check(td, PRIV_VM_MLOCK);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2003-08-11 07:14:08 +00:00
|
|
|
|
|
|
|
if ((uap->how == 0) || ((uap->how & ~(MCL_CURRENT|MCL_FUTURE)) != 0))
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If wiring all pages in the process would cause it to exceed
|
|
|
|
* a hard resource limit, return ENOMEM.
|
|
|
|
*/
|
2012-12-18 07:35:01 +00:00
|
|
|
if (!old_mlock && uap->how & MCL_CURRENT) {
|
2018-09-18 01:24:30 +00:00
|
|
|
if (map->size > lim_cur(td, RLIMIT_MEMLOCK))
|
2012-12-18 07:35:01 +00:00
|
|
|
return (ENOMEM);
|
2004-02-04 21:52:57 +00:00
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2015-04-29 10:23:02 +00:00
|
|
|
if (racct_enable) {
|
|
|
|
PROC_LOCK(td->td_proc);
|
|
|
|
error = racct_set(td->td_proc, RACCT_MEMLOCK, map->size);
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
if (error != 0)
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
2003-08-11 07:14:08 +00:00
|
|
|
|
|
|
|
if (uap->how & MCL_FUTURE) {
|
|
|
|
vm_map_lock(map);
|
|
|
|
vm_map_modflags(map, MAP_WIREFUTURE, 0);
|
|
|
|
vm_map_unlock(map);
|
|
|
|
error = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uap->how & MCL_CURRENT) {
|
|
|
|
/*
|
|
|
|
* P1003.1-2001 mandates that all currently mapped pages
|
|
|
|
* will be memory resident and locked (wired) upon return
|
|
|
|
* from mlockall(). vm_map_wire() will wire pages, by
|
|
|
|
* calling vm_fault_wire() for each page in the region.
|
|
|
|
*/
|
|
|
|
error = vm_map_wire(map, vm_map_min(map), vm_map_max(map),
|
|
|
|
VM_MAP_WIRE_USER|VM_MAP_WIRE_HOLESOK);
|
Provide separate accounting for user-wired pages.
Historically we have not distinguished between kernel wirings and user
wirings for accounting purposes. User wirings (via mlock(2)) were
subject to a global limit on the number of wired pages, so if large
swaths of physical memory were wired by the kernel, as happens with
the ZFS ARC among other things, the limit could be exceeded, causing
user wirings to fail.
The change adds a new counter, v_user_wire_count, which counts the
number of virtual pages wired by user processes via mlock(2) and
mlockall(2). Only user-wired pages are subject to the system-wide
limit which helps provide some safety against deadlocks. In
particular, while sources of kernel wirings typically support some
backpressure mechanism, there is no way to reclaim user-wired pages
shorting of killing the wiring process. The limit is exported as
vm.max_user_wired, renamed from vm.max_wired, and changed from u_int
to u_long.
The choice to count virtual user-wired pages rather than physical
pages was done for simplicity. There are mechanisms that can cause
user-wired mappings to be destroyed while maintaining a wiring of
the backing physical page; these make it difficult to accurately
track user wirings at the physical page layer.
The change also closes some holes which allowed user wirings to succeed
even when they would cause the system limit to be exceeded. For
instance, mmap() may now fail with ENOMEM in a process that has called
mlockall(MCL_FUTURE) if the new mapping would cause the user wiring
limit to be exceeded.
Note that bhyve -S is subject to the user wiring limit, which defaults
to 1/3 of physical RAM. Users that wish to exceed the limit must tune
vm.max_user_wired.
Reviewed by: kib, ngie (mlock() test changes)
Tested by: pho (earlier version)
MFC after: 45 days
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D19908
2019-05-13 16:38:48 +00:00
|
|
|
if (error == KERN_SUCCESS)
|
|
|
|
error = 0;
|
|
|
|
else if (error == KERN_RESOURCE_SHORTAGE)
|
|
|
|
error = ENOMEM;
|
|
|
|
else
|
|
|
|
error = EAGAIN;
|
2003-08-11 07:14:08 +00:00
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2015-04-29 10:23:02 +00:00
|
|
|
if (racct_enable && error != KERN_SUCCESS) {
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_LOCK(td->td_proc);
|
|
|
|
racct_set(td->td_proc, RACCT_MEMLOCK,
|
2013-01-10 12:43:58 +00:00
|
|
|
ptoa(pmap_wired_count(map->pmap)));
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
2003-08-11 07:14:08 +00:00
|
|
|
|
|
|
|
return (error);
|
1997-06-15 23:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
2002-06-06 18:51:14 +00:00
|
|
|
struct munlockall_args {
|
2003-08-11 07:14:08 +00:00
|
|
|
register_t dummy;
|
1997-06-15 23:35:32 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int
|
2017-02-13 00:40:55 +00:00
|
|
|
sys_munlockall(struct thread *td, struct munlockall_args *uap)
|
1997-06-15 23:35:32 +00:00
|
|
|
{
|
2003-08-11 07:14:08 +00:00
|
|
|
vm_map_t map;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VM_MUNLOCK);
|
2003-08-11 07:14:08 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
/* Clear the MAP_WIREFUTURE flag from this vm_map. */
|
|
|
|
vm_map_lock(map);
|
|
|
|
vm_map_modflags(map, 0, MAP_WIREFUTURE);
|
|
|
|
vm_map_unlock(map);
|
|
|
|
|
|
|
|
/* Forcibly unwire all pages. */
|
|
|
|
error = vm_map_unwire(map, vm_map_min(map), vm_map_max(map),
|
|
|
|
VM_MAP_WIRE_USER|VM_MAP_WIRE_HOLESOK);
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2015-04-29 10:23:02 +00:00
|
|
|
if (racct_enable && error == KERN_SUCCESS) {
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_LOCK(td->td_proc);
|
|
|
|
racct_set(td->td_proc, RACCT_MEMLOCK, 0);
|
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
2003-08-11 07:14:08 +00:00
|
|
|
|
|
|
|
return (error);
|
1997-06-15 23:35:32 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct munlock_args {
|
1997-12-31 02:35:29 +00:00
|
|
|
const void *addr;
|
These changes embody the support of the fully coherent merged VM buffer cache,
much higher filesystem I/O performance, and much better paging performance. It
represents the culmination of over 6 months of R&D.
The majority of the merged VM/cache work is by John Dyson.
The following highlights the most significant changes. Additionally, there are
(mostly minor) changes to the various filesystem modules (nfs, msdosfs, etc) to
support the new VM/buffer scheme.
vfs_bio.c:
Significant rewrite of most of vfs_bio to support the merged VM buffer cache
scheme. The scheme is almost fully compatible with the old filesystem
interface. Significant improvement in the number of opportunities for write
clustering.
vfs_cluster.c, vfs_subr.c
Upgrade and performance enhancements in vfs layer code to support merged
VM/buffer cache. Fixup of vfs_cluster to eliminate the bogus pagemove stuff.
vm_object.c:
Yet more improvements in the collapse code. Elimination of some windows that
can cause list corruption.
vm_pageout.c:
Fixed it, it really works better now. Somehow in 2.0, some "enhancements"
broke the code. This code has been reworked from the ground-up.
vm_fault.c, vm_page.c, pmap.c, vm_object.c
Support for small-block filesystems with merged VM/buffer cache scheme.
pmap.c vm_map.c
Dynamic kernel VM size, now we dont have to pre-allocate excessive numbers of
kernel PTs.
vm_glue.c
Much simpler and more effective swapping code. No more gratuitous swapping.
proc.h
Fixed the problem that the p_lock flag was not being cleared on a fork.
swap_pager.c, vnode_pager.c
Removal of old vfs_bio cruft to support the past pseudo-coherency. Now the
code doesn't need it anymore.
machdep.c
Changes to better support the parameter values for the merged VM/buffer cache
scheme.
machdep.c, kern_exec.c, vm_glue.c
Implemented a seperate submap for temporary exec string space and another one
to contain process upages. This eliminates all map fragmentation problems
that previously existed.
ffs_inode.c, ufs_inode.c, ufs_readwrite.c
Changes for merged VM/buffer cache. Add "bypass" support for sneaking in on
busy buffers.
Submitted by: John Dyson and David Greenman
1995-01-09 16:06:02 +00:00
|
|
|
size_t len;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
int
|
2017-02-06 20:57:12 +00:00
|
|
|
sys_munlock(struct thread *td, struct munlock_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2017-02-06 20:57:12 +00:00
|
|
|
|
2017-02-13 09:04:38 +00:00
|
|
|
return (kern_munlock(td, (uintptr_t)uap->addr, uap->len));
|
2017-02-06 20:57:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-02-13 09:04:38 +00:00
|
|
|
kern_munlock(struct thread *td, uintptr_t addr0, size_t size)
|
2017-02-06 20:57:12 +00:00
|
|
|
{
|
2017-02-13 09:04:38 +00:00
|
|
|
vm_offset_t addr, end, last, start;
|
2013-07-22 22:16:47 +00:00
|
|
|
#ifdef RACCT
|
2013-07-22 21:47:14 +00:00
|
|
|
vm_map_t map;
|
2013-07-22 22:16:47 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
int error;
|
|
|
|
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_VM_MUNLOCK);
|
2004-02-26 00:27:04 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2017-02-13 09:04:38 +00:00
|
|
|
addr = addr0;
|
2004-03-15 09:11:23 +00:00
|
|
|
last = addr + size;
|
2004-03-05 22:03:11 +00:00
|
|
|
start = trunc_page(addr);
|
2004-03-15 09:11:23 +00:00
|
|
|
end = round_page(last);
|
|
|
|
if (last < addr || end < addr)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
2004-03-05 22:03:11 +00:00
|
|
|
error = vm_map_unwire(&td->td_proc->p_vmspace->vm_map, start, end,
|
2004-03-15 06:43:51 +00:00
|
|
|
VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
|
2011-07-06 20:06:44 +00:00
|
|
|
#ifdef RACCT
|
2015-04-29 10:23:02 +00:00
|
|
|
if (racct_enable && error == KERN_SUCCESS) {
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_LOCK(td->td_proc);
|
2013-07-22 21:47:14 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
|
|
|
racct_set(td->td_proc, RACCT_MEMLOCK,
|
|
|
|
ptoa(pmap_wired_count(map->pmap)));
|
2011-04-05 20:23:59 +00:00
|
|
|
PROC_UNLOCK(td->td_proc);
|
|
|
|
}
|
2011-07-06 20:06:44 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error == KERN_SUCCESS ? 0 : ENOMEM);
|
|
|
|
}
|
|
|
|
|
2004-02-27 22:02:15 +00:00
|
|
|
/*
|
|
|
|
* vm_mmap_vnode()
|
|
|
|
*
|
|
|
|
* Helper function for vm_mmap. Perform sanity check specific for mmap
|
|
|
|
* operations on vnodes.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
vm_mmap_vnode(struct thread *td, vm_size_t objsize,
|
|
|
|
vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp,
|
2012-02-23 21:07:16 +00:00
|
|
|
struct vnode *vp, vm_ooffset_t *foffp, vm_object_t *objp,
|
|
|
|
boolean_t *writecounted)
|
2004-02-27 22:02:15 +00:00
|
|
|
{
|
|
|
|
struct vattr va;
|
|
|
|
vm_object_t obj;
|
2017-11-08 01:53:03 +00:00
|
|
|
vm_ooffset_t foff;
|
2008-08-28 15:23:18 +00:00
|
|
|
struct ucred *cred;
|
Switch to use shared vnode locks for text files during image activation.
kern_execve() locks text vnode exclusive to be able to set and clear
VV_TEXT flag. VV_TEXT is mutually exclusive with the v_writecount > 0
condition.
The change removes VV_TEXT, replacing it with the condition
v_writecount <= -1, and puts v_writecount under the vnode interlock.
Each text reference decrements v_writecount. To clear the text
reference when the segment is unmapped, it is recorded in the
vm_map_entry backed by the text file as MAP_ENTRY_VN_TEXT flag, and
v_writecount is incremented on the map entry removal
The operations like VOP_ADD_WRITECOUNT() and VOP_SET_TEXT() check that
v_writecount does not contradict the desired change. vn_writecheck()
is now racy and its use was eliminated everywhere except access.
Atomic check for writeability and increment of v_writecount is
performed by the VOP. vn_truncate() now increments v_writecount
around VOP_SETATTR() call, lack of which is arguably a bug on its own.
nullfs bypasses v_writecount to the lower vnode always, so nullfs
vnode has its own v_writecount correct, and lower vnode gets all
references, since object->handle is always lower vnode.
On the text vnode' vm object dealloc, the v_writecount value is reset
to zero, and deadfs vop_unset_text short-circuit the operation.
Reclamation of lowervp always reclaims all nullfs vnodes referencing
lowervp first, so no stray references are left.
Reviewed by: markj, trasz
Tested by: mjg, pho
Sponsored by: The FreeBSD Foundation
MFC after: 1 month
Differential revision: https://reviews.freebsd.org/D19923
2019-05-05 11:20:43 +00:00
|
|
|
int error, flags;
|
|
|
|
bool writex;
|
2004-02-27 22:02:15 +00:00
|
|
|
|
2008-08-28 15:23:18 +00:00
|
|
|
cred = td->td_ucred;
|
Switch to use shared vnode locks for text files during image activation.
kern_execve() locks text vnode exclusive to be able to set and clear
VV_TEXT flag. VV_TEXT is mutually exclusive with the v_writecount > 0
condition.
The change removes VV_TEXT, replacing it with the condition
v_writecount <= -1, and puts v_writecount under the vnode interlock.
Each text reference decrements v_writecount. To clear the text
reference when the segment is unmapped, it is recorded in the
vm_map_entry backed by the text file as MAP_ENTRY_VN_TEXT flag, and
v_writecount is incremented on the map entry removal
The operations like VOP_ADD_WRITECOUNT() and VOP_SET_TEXT() check that
v_writecount does not contradict the desired change. vn_writecheck()
is now racy and its use was eliminated everywhere except access.
Atomic check for writeability and increment of v_writecount is
performed by the VOP. vn_truncate() now increments v_writecount
around VOP_SETATTR() call, lack of which is arguably a bug on its own.
nullfs bypasses v_writecount to the lower vnode always, so nullfs
vnode has its own v_writecount correct, and lower vnode gets all
references, since object->handle is always lower vnode.
On the text vnode' vm object dealloc, the v_writecount value is reset
to zero, and deadfs vop_unset_text short-circuit the operation.
Reclamation of lowervp always reclaims all nullfs vnodes referencing
lowervp first, so no stray references are left.
Reviewed by: markj, trasz
Tested by: mjg, pho
Sponsored by: The FreeBSD Foundation
MFC after: 1 month
Differential revision: https://reviews.freebsd.org/D19923
2019-05-05 11:20:43 +00:00
|
|
|
writex = (*maxprotp & VM_PROT_WRITE) != 0 &&
|
|
|
|
(*flagsp & MAP_SHARED) != 0;
|
2020-08-16 17:18:54 +00:00
|
|
|
if ((error = vget(vp, LK_SHARED)) != 0)
|
2004-02-27 22:02:15 +00:00
|
|
|
return (error);
|
2016-07-10 11:49:10 +00:00
|
|
|
AUDIT_ARG_VNODE1(vp);
|
2009-06-01 21:32:52 +00:00
|
|
|
foff = *foffp;
|
2004-02-27 22:02:15 +00:00
|
|
|
flags = *flagsp;
|
2005-01-25 00:40:01 +00:00
|
|
|
obj = vp->v_object;
|
2004-02-27 22:02:15 +00:00
|
|
|
if (vp->v_type == VREG) {
|
|
|
|
/*
|
|
|
|
* Get the proper underlying object
|
|
|
|
*/
|
2005-01-25 00:40:01 +00:00
|
|
|
if (obj == NULL) {
|
2004-02-27 22:02:15 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
2013-04-28 19:25:09 +00:00
|
|
|
if (obj->type == OBJT_VNODE && obj->handle != vp) {
|
2004-02-27 22:02:15 +00:00
|
|
|
vput(vp);
|
2012-02-23 21:07:16 +00:00
|
|
|
vp = (struct vnode *)obj->handle;
|
|
|
|
/*
|
|
|
|
* Bypass filesystems obey the mpsafety of the
|
2013-05-02 18:35:12 +00:00
|
|
|
* underlying fs. Tmpfs never bypasses.
|
2012-02-23 21:07:16 +00:00
|
|
|
*/
|
2020-08-16 17:18:54 +00:00
|
|
|
error = vget(vp, LK_SHARED);
|
2012-10-22 17:50:54 +00:00
|
|
|
if (error != 0)
|
2012-02-23 21:07:16 +00:00
|
|
|
return (error);
|
2012-02-24 10:41:58 +00:00
|
|
|
}
|
Switch to use shared vnode locks for text files during image activation.
kern_execve() locks text vnode exclusive to be able to set and clear
VV_TEXT flag. VV_TEXT is mutually exclusive with the v_writecount > 0
condition.
The change removes VV_TEXT, replacing it with the condition
v_writecount <= -1, and puts v_writecount under the vnode interlock.
Each text reference decrements v_writecount. To clear the text
reference when the segment is unmapped, it is recorded in the
vm_map_entry backed by the text file as MAP_ENTRY_VN_TEXT flag, and
v_writecount is incremented on the map entry removal
The operations like VOP_ADD_WRITECOUNT() and VOP_SET_TEXT() check that
v_writecount does not contradict the desired change. vn_writecheck()
is now racy and its use was eliminated everywhere except access.
Atomic check for writeability and increment of v_writecount is
performed by the VOP. vn_truncate() now increments v_writecount
around VOP_SETATTR() call, lack of which is arguably a bug on its own.
nullfs bypasses v_writecount to the lower vnode always, so nullfs
vnode has its own v_writecount correct, and lower vnode gets all
references, since object->handle is always lower vnode.
On the text vnode' vm object dealloc, the v_writecount value is reset
to zero, and deadfs vop_unset_text short-circuit the operation.
Reclamation of lowervp always reclaims all nullfs vnodes referencing
lowervp first, so no stray references are left.
Reviewed by: markj, trasz
Tested by: mjg, pho
Sponsored by: The FreeBSD Foundation
MFC after: 1 month
Differential revision: https://reviews.freebsd.org/D19923
2019-05-05 11:20:43 +00:00
|
|
|
if (writex) {
|
2012-02-24 10:41:58 +00:00
|
|
|
*writecounted = TRUE;
|
2019-09-03 20:31:48 +00:00
|
|
|
vm_pager_update_writecount(obj, 0, objsize);
|
2004-02-27 22:02:15 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
error = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
2008-08-28 15:23:18 +00:00
|
|
|
if ((error = VOP_GETATTR(vp, &va, cred)))
|
2004-02-27 22:02:15 +00:00
|
|
|
goto done;
|
2005-04-14 16:03:30 +00:00
|
|
|
#ifdef MAC
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
/* This relies on VM_PROT_* matching PROT_*. */
|
|
|
|
error = mac_vnode_check_mmap(cred, vp, (int)prot, flags);
|
2005-04-14 16:03:30 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto done;
|
|
|
|
#endif
|
2004-02-27 22:02:15 +00:00
|
|
|
if ((flags & MAP_SHARED) != 0) {
|
|
|
|
if ((va.va_flags & (SF_SNAPSHOT|IMMUTABLE|APPEND)) != 0) {
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
if (prot & VM_PROT_WRITE) {
|
2004-02-27 22:02:15 +00:00
|
|
|
error = EPERM;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
*maxprotp &= ~VM_PROT_WRITE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If it is a regular file without any references
|
|
|
|
* we do not need to sync it.
|
|
|
|
* Adjust object size to be the size of actual file.
|
|
|
|
*/
|
2009-06-01 21:32:52 +00:00
|
|
|
objsize = round_page(va.va_size);
|
|
|
|
if (va.va_nlink == 0)
|
|
|
|
flags |= MAP_NOSYNC;
|
2015-03-21 17:56:55 +00:00
|
|
|
if (obj->type == OBJT_VNODE) {
|
2013-04-28 19:25:09 +00:00
|
|
|
obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff,
|
|
|
|
cred);
|
2015-03-21 17:56:55 +00:00
|
|
|
if (obj == NULL) {
|
|
|
|
error = ENOMEM;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
} else {
|
2013-04-28 19:25:09 +00:00
|
|
|
KASSERT(obj->type == OBJT_DEFAULT || obj->type == OBJT_SWAP,
|
|
|
|
("wrong object type"));
|
2019-11-29 19:49:20 +00:00
|
|
|
vm_object_reference(obj);
|
2015-03-21 17:56:55 +00:00
|
|
|
#if VM_NRESERVLEVEL > 0
|
2019-11-29 19:49:20 +00:00
|
|
|
if ((obj->flags & OBJ_COLORED) == 0) {
|
|
|
|
VM_OBJECT_WLOCK(obj);
|
|
|
|
vm_object_color(obj, 0);
|
|
|
|
VM_OBJECT_WUNLOCK(obj);
|
|
|
|
}
|
2015-03-21 17:56:55 +00:00
|
|
|
#endif
|
2004-02-27 22:02:15 +00:00
|
|
|
}
|
|
|
|
*objp = obj;
|
|
|
|
*flagsp = flags;
|
2009-06-01 21:32:52 +00:00
|
|
|
|
2020-02-01 06:46:55 +00:00
|
|
|
VOP_MMAPPED(vp);
|
2005-10-04 14:58:58 +00:00
|
|
|
|
2004-02-27 22:02:15 +00:00
|
|
|
done:
|
2013-03-28 06:39:27 +00:00
|
|
|
if (error != 0 && *writecounted) {
|
|
|
|
*writecounted = FALSE;
|
2019-09-03 20:31:48 +00:00
|
|
|
vm_pager_update_writecount(obj, objsize, 0);
|
2013-03-28 06:39:27 +00:00
|
|
|
}
|
2004-02-27 22:02:15 +00:00
|
|
|
vput(vp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2005-04-01 20:00:11 +00:00
|
|
|
/*
|
|
|
|
* vm_mmap_cdev()
|
|
|
|
*
|
|
|
|
* Helper function for vm_mmap. Perform sanity check specific for mmap
|
|
|
|
* operations on cdevs.
|
|
|
|
*/
|
|
|
|
int
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
vm_mmap_cdev(struct thread *td, vm_size_t objsize, vm_prot_t prot,
|
|
|
|
vm_prot_t *maxprotp, int *flagsp, struct cdev *cdev, struct cdevsw *dsw,
|
|
|
|
vm_ooffset_t *foff, vm_object_t *objp)
|
2005-04-01 20:00:11 +00:00
|
|
|
{
|
|
|
|
vm_object_t obj;
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
int error, flags;
|
2005-04-01 20:00:11 +00:00
|
|
|
|
|
|
|
flags = *flagsp;
|
|
|
|
|
2008-03-20 16:08:42 +00:00
|
|
|
if (dsw->d_flags & D_MMAP_ANON) {
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
*objp = NULL;
|
|
|
|
*foff = 0;
|
2005-04-01 20:00:11 +00:00
|
|
|
*maxprotp = VM_PROT_ALL;
|
|
|
|
*flagsp |= MAP_ANON;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
/*
|
2009-06-01 21:32:52 +00:00
|
|
|
* cdevs do not provide private mappings of any kind.
|
2005-04-01 20:00:11 +00:00
|
|
|
*/
|
|
|
|
if ((*maxprotp & VM_PROT_WRITE) == 0 &&
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
(prot & VM_PROT_WRITE) != 0)
|
2005-04-01 20:00:11 +00:00
|
|
|
return (EACCES);
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
if (flags & (MAP_PRIVATE|MAP_COPY))
|
2005-04-01 20:00:11 +00:00
|
|
|
return (EINVAL);
|
|
|
|
/*
|
|
|
|
* Force device mappings to be shared.
|
|
|
|
*/
|
|
|
|
flags |= MAP_SHARED;
|
|
|
|
#ifdef MAC_XXX
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
error = mac_cdev_check_mmap(td->td_ucred, cdev, (int)prot);
|
|
|
|
if (error != 0)
|
2005-04-01 20:00:11 +00:00
|
|
|
return (error);
|
|
|
|
#endif
|
2009-06-01 21:32:52 +00:00
|
|
|
/*
|
|
|
|
* First, try d_mmap_single(). If that is not implemented
|
|
|
|
* (returns ENODEV), fall back to using the device pager.
|
|
|
|
* Note that d_mmap_single() must return a reference to the
|
|
|
|
* object (it needs to bump the reference count of the object
|
|
|
|
* it returns somehow).
|
|
|
|
*
|
|
|
|
* XXX assumes VM_PROT_* == PROT_*
|
|
|
|
*/
|
|
|
|
error = dsw->d_mmap_single(cdev, foff, objsize, objp, (int)prot);
|
|
|
|
if (error != ENODEV)
|
|
|
|
return (error);
|
Implement global and per-uid accounting of the anonymous memory. Add
rlimit RLIMIT_SWAP that limits the amount of swap that may be reserved
for the uid.
The accounting information (charge) is associated with either map entry,
or vm object backing the entry, assuming the object is the first one
in the shadow chain and entry does not require COW. Charge is moved
from entry to object on allocation of the object, e.g. during the mmap,
assuming the object is allocated, or on the first page fault on the
entry. It moves back to the entry on forks due to COW setup.
The per-entry granularity of accounting makes the charge process fair
for processes that change uid during lifetime, and decrements charge
for proper uid when region is unmapped.
The interface of vm_pager_allocate(9) is extended by adding struct ucred *,
that is used to charge appropriate uid when allocation if performed by
kernel, e.g. md(4).
Several syscalls, among them is fork(2), may now return ENOMEM when
global or per-uid limits are enforced.
In collaboration with: pho
Reviewed by: alc
Approved by: re (kensmith)
2009-06-23 20:45:22 +00:00
|
|
|
obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff,
|
|
|
|
td->td_ucred);
|
2005-04-01 20:00:11 +00:00
|
|
|
if (obj == NULL)
|
|
|
|
return (EINVAL);
|
|
|
|
*objp = obj;
|
|
|
|
*flagsp = flags;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
/*
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
* vm_mmap()
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
*
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
* Internal version of mmap used by exec, sys5 shared memory, and
|
|
|
|
* various device drivers. Handle is either a vnode pointer, a
|
|
|
|
* character device, or NULL for MAP_ANON.
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
*/
|
|
|
|
int
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
|
|
|
|
vm_prot_t maxprot, int flags,
|
|
|
|
objtype_t handle_type, void *handle,
|
|
|
|
vm_ooffset_t foff)
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
{
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
vm_object_t object;
|
|
|
|
struct thread *td = curthread;
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
int error;
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
boolean_t writecounted;
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
if (size == 0)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
size = round_page(size);
|
2015-07-05 22:26:19 +00:00
|
|
|
object = NULL;
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
writecounted = FALSE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lookup/allocate object.
|
|
|
|
*/
|
|
|
|
switch (handle_type) {
|
|
|
|
case OBJT_DEVICE: {
|
|
|
|
struct cdevsw *dsw;
|
|
|
|
struct cdev *cdev;
|
|
|
|
int ref;
|
|
|
|
|
|
|
|
cdev = handle;
|
|
|
|
dsw = dev_refthread(cdev, &ref);
|
|
|
|
if (dsw == NULL)
|
|
|
|
return (ENXIO);
|
|
|
|
error = vm_mmap_cdev(td, size, prot, &maxprot, &flags, cdev,
|
|
|
|
dsw, &foff, &object);
|
|
|
|
dev_relthread(cdev, ref);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OBJT_VNODE:
|
|
|
|
error = vm_mmap_vnode(td, size, prot, &maxprot, &flags,
|
|
|
|
handle, &foff, &object, &writecounted);
|
|
|
|
break;
|
|
|
|
case OBJT_DEFAULT:
|
|
|
|
if (handle == NULL) {
|
|
|
|
error = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
|
|
|
|
error = vm_mmap_object(map, addr, size, prot, maxprot, flags, object,
|
|
|
|
foff, writecounted, td);
|
|
|
|
if (error != 0 && object != NULL) {
|
|
|
|
/*
|
|
|
|
* If this mapping was accounted for in the vnode's
|
|
|
|
* writecount, then undo that now.
|
|
|
|
*/
|
|
|
|
if (writecounted)
|
2019-09-03 20:31:48 +00:00
|
|
|
vm_pager_release_writecount(object, 0, size);
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
vm_object_deallocate(object);
|
|
|
|
}
|
|
|
|
return (error);
|
Add a new file descriptor type for IPC shared memory objects and use it to
implement shm_open(2) and shm_unlink(2) in the kernel:
- Each shared memory file descriptor is associated with a swap-backed vm
object which provides the backing store. Each descriptor starts off with
a size of zero, but the size can be altered via ftruncate(2). The shared
memory file descriptors also support fstat(2). read(2), write(2),
ioctl(2), select(2), poll(2), and kevent(2) are not supported on shared
memory file descriptors.
- shm_open(2) and shm_unlink(2) are now implemented as system calls that
manage shared memory file descriptors. The virtual namespace that maps
pathnames to shared memory file descriptors is implemented as a hash
table where the hash key is generated via the 32-bit Fowler/Noll/Vo hash
of the pathname.
- As an extension, the constant 'SHM_ANON' may be specified in place of the
path argument to shm_open(2). In this case, an unnamed shared memory
file descriptor will be created similar to the IPC_PRIVATE key for
shmget(2). Note that the shared memory object can still be shared among
processes by sharing the file descriptor via fork(2) or sendmsg(2), but
it is unnamed. This effectively serves to implement the getmemfd() idea
bandied about the lists several times over the years.
- The backing store for shared memory file descriptors are garbage
collected when they are not referenced by any open file descriptors or
the shm_open(2) virtual namespace.
Submitted by: dillon, peter (previous versions)
Submitted by: rwatson (I based this on his version)
Reviewed by: alc (suggested converting getmemfd() to shm_open())
2008-01-08 21:58:16 +00:00
|
|
|
}
|
|
|
|
|
2020-09-08 23:48:19 +00:00
|
|
|
int
|
|
|
|
kern_mmap_racct_check(struct thread *td, vm_map_t map, vm_size_t size)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
RACCT_PROC_LOCK(td->td_proc);
|
|
|
|
if (map->size + size > lim_cur(td, RLIMIT_VMEM)) {
|
|
|
|
RACCT_PROC_UNLOCK(td->td_proc);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
|
|
|
if (racct_set(td->td_proc, RACCT_VMEM, map->size + size)) {
|
|
|
|
RACCT_PROC_UNLOCK(td->td_proc);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
|
|
|
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
|
|
|
|
if (ptoa(pmap_wired_count(map->pmap)) + size >
|
|
|
|
lim_cur(td, RLIMIT_MEMLOCK)) {
|
|
|
|
racct_set_force(td->td_proc, RACCT_VMEM, map->size);
|
|
|
|
RACCT_PROC_UNLOCK(td->td_proc);
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
|
|
|
error = racct_set(td->td_proc, RACCT_MEMLOCK,
|
|
|
|
ptoa(pmap_wired_count(map->pmap)) + size);
|
|
|
|
if (error != 0) {
|
|
|
|
racct_set_force(td->td_proc, RACCT_VMEM, map->size);
|
|
|
|
RACCT_PROC_UNLOCK(td->td_proc);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RACCT_PROC_UNLOCK(td->td_proc);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
* Internal version of mmap that maps a specific VM object into an
|
|
|
|
* map. Called by mmap for MAP_ANON, vm_mmap, shm_mmap, and vn_mmap.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
|
|
|
int
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
|
|
|
|
vm_prot_t maxprot, int flags, vm_object_t object, vm_ooffset_t foff,
|
|
|
|
boolean_t writecounted, struct thread *td)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
Treat the addr argument for mmap(2) request without MAP_FIXED flag as
a hint.
Right now, for non-fixed mmap(2) calls, addr is de-facto interpreted
as the absolute minimal address of the range where the mapping is
created. The VA allocator only allocates in the range [addr,
VM_MAXUSER_ADDRESS]. This is too restrictive, the mmap(2) call might
unduly fail if there is no free addresses above addr but a lot of
usable space below it.
Lift this implementation limitation by allocating VA in two passes.
First, try to allocate above addr, as before. If that fails, do the
second pass with less restrictive constraints for the start of
allocation by specifying minimal allocation address at the max bss
end, if this limit is less than addr.
One important case where this change makes a difference is the
allocation of the stacks for new threads in libthr. Under some
configuration conditions, libthr tries to hint kernel to reuse the
main thread stack grow area for the new stacks. This cannot work by
design now after grow area is converted to stack, and there is no
unallocated VA above the main stack. Interpreting requested stack
base address as the hint provides compatibility with old libthr and
with (mis-)configured current libthr.
Reviewed by: alc
Tested by: dim (previous version)
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2017-06-28 04:02:36 +00:00
|
|
|
vm_offset_t max_addr;
|
2013-08-16 21:13:55 +00:00
|
|
|
int docow, error, findspace, rv;
|
2020-09-08 23:48:19 +00:00
|
|
|
bool curmap, fitit;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
Treat the addr argument for mmap(2) request without MAP_FIXED flag as
a hint.
Right now, for non-fixed mmap(2) calls, addr is de-facto interpreted
as the absolute minimal address of the range where the mapping is
created. The VA allocator only allocates in the range [addr,
VM_MAXUSER_ADDRESS]. This is too restrictive, the mmap(2) call might
unduly fail if there is no free addresses above addr but a lot of
usable space below it.
Lift this implementation limitation by allocating VA in two passes.
First, try to allocate above addr, as before. If that fails, do the
second pass with less restrictive constraints for the start of
allocation by specifying minimal allocation address at the max bss
end, if this limit is less than addr.
One important case where this change makes a difference is the
allocation of the stacks for new threads in libthr. Under some
configuration conditions, libthr tries to hint kernel to reuse the
main thread stack grow area for the new stacks. This cannot work by
design now after grow area is converted to stack, and there is no
unallocated VA above the main stack. Interpreting requested stack
base address as the hint provides compatibility with old libthr and
with (mis-)configured current libthr.
Reviewed by: alc
Tested by: dim (previous version)
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2017-06-28 04:02:36 +00:00
|
|
|
curmap = map == &td->td_proc->p_vmspace->vm_map;
|
|
|
|
if (curmap) {
|
2020-09-08 23:48:19 +00:00
|
|
|
error = kern_mmap_racct_check(td, map, size);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2011-04-05 20:23:59 +00:00
|
|
|
}
|
2002-06-26 00:29:28 +00:00
|
|
|
|
1995-03-21 10:15:52 +00:00
|
|
|
/*
|
|
|
|
* We currently can only deal with page aligned file offsets.
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
* The mmap() system call already enforces this by subtracting
|
|
|
|
* the page offset from the file offset, but checking here
|
|
|
|
* catches errors in device drivers (e.g. d_single_mmap()
|
|
|
|
* callbacks) and other internal mapping requests (such as in
|
|
|
|
* exec).
|
1995-03-21 10:15:52 +00:00
|
|
|
*/
|
|
|
|
if (foff & PAGE_MASK)
|
|
|
|
return (EINVAL);
|
|
|
|
|
1995-07-09 06:58:03 +00:00
|
|
|
if ((flags & MAP_FIXED) == 0) {
|
|
|
|
fitit = TRUE;
|
|
|
|
*addr = round_page(*addr);
|
|
|
|
} else {
|
|
|
|
if (*addr != trunc_page(*addr))
|
|
|
|
return (EINVAL);
|
|
|
|
fitit = FALSE;
|
|
|
|
}
|
2012-02-23 21:07:16 +00:00
|
|
|
|
2004-02-27 22:02:15 +00:00
|
|
|
if (flags & MAP_ANON) {
|
Add a new file operations hook for mmap operations. File type-specific
logic is now placed in the mmap hook implementation rather than requiring
it to be placed in sys/vm/vm_mmap.c. This hook allows new file types to
support mmap() as well as potentially allowing mmap() for existing file
types that do not currently support any mapping.
The vm_mmap() function is now split up into two functions. A new
vm_mmap_object() function handles the "back half" of vm_mmap() and accepts
a referenced VM object to map rather than a (handle, handle_type) tuple.
vm_mmap() is now reduced to converting a (handle, handle_type) tuple to a
a VM object and then calling vm_mmap_object() to handle the actual mapping.
The vm_mmap() function remains for use by other parts of the kernel
(e.g. device drivers and exec) but now only supports mapping vnodes,
character devices, and anonymous memory.
The mmap() system call invokes vm_mmap_object() directly with a NULL object
for anonymous mappings. For mappings using a file descriptor, the
descriptors fo_mmap() hook is invoked instead. The fo_mmap() hook is
responsible for performing type-specific checks and adjustments to
arguments as well as possibly modifying mapping parameters such as flags
or the object offset. The fo_mmap() hook routines then call
vm_mmap_object() to handle the actual mapping.
The fo_mmap() hook is optional. If it is not set, then fo_mmap() will
fail with ENODEV. A fo_mmap() hook is implemented for regular files,
character devices, and shared memory objects (created via shm_open()).
While here, consistently use the VM_PROT_* constants for the vm_prot_t
type for the 'prot' variable passed to vm_mmap() and vm_mmap_object()
as well as the vm_mmap_vnode() and vm_mmap_cdev() helper routines.
Previously some places were using the mmap()-specific PROT_* constants
instead. While this happens to work because PROT_xx == VM_PROT_xx,
using VM_PROT_* is more correct.
Differential Revision: https://reviews.freebsd.org/D2658
Reviewed by: alc (glanced over), kib
MFC after: 1 month
Sponsored by: Chelsio
2015-06-04 19:41:15 +00:00
|
|
|
if (object != NULL || foff != 0)
|
|
|
|
return (EINVAL);
|
1999-06-05 18:21:53 +00:00
|
|
|
docow = 0;
|
2010-08-28 16:57:07 +00:00
|
|
|
} else if (flags & MAP_PREFAULT_READ)
|
|
|
|
docow = MAP_PREFAULT;
|
|
|
|
else
|
1999-06-05 18:21:53 +00:00
|
|
|
docow = MAP_PREFAULT_PARTIAL;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-12-12 03:19:33 +00:00
|
|
|
if ((flags & (MAP_ANON|MAP_SHARED)) == 0)
|
1999-06-05 18:21:53 +00:00
|
|
|
docow |= MAP_COPY_ON_WRITE;
|
1999-12-12 03:19:33 +00:00
|
|
|
if (flags & MAP_NOSYNC)
|
|
|
|
docow |= MAP_DISABLE_SYNCER;
|
2000-02-28 04:10:35 +00:00
|
|
|
if (flags & MAP_NOCORE)
|
|
|
|
docow |= MAP_DISABLE_COREDUMP;
|
2012-02-11 17:29:07 +00:00
|
|
|
/* Shared memory is also shared with children. */
|
|
|
|
if (flags & MAP_SHARED)
|
|
|
|
docow |= MAP_INHERIT_SHARE;
|
2012-02-23 21:07:16 +00:00
|
|
|
if (writecounted)
|
2019-09-03 20:31:48 +00:00
|
|
|
docow |= MAP_WRITECOUNT;
|
2014-06-09 03:37:41 +00:00
|
|
|
if (flags & MAP_STACK) {
|
|
|
|
if (object != NULL)
|
|
|
|
return (EINVAL);
|
|
|
|
docow |= MAP_STACK_GROWS_DOWN;
|
|
|
|
}
|
2014-06-19 05:00:39 +00:00
|
|
|
if ((flags & MAP_EXCL) != 0)
|
|
|
|
docow |= MAP_CHECK_EXCL;
|
Implement address space guards.
Guard, requested by the MAP_GUARD mmap(2) flag, prevents the reuse of
the allocated address space, but does not allow instantiation of the
pages in the range. It is useful for more explicit support for usual
two-stage reserve then commit allocators, since it prevents accidental
instantiation of the mapping, e.g. by mprotect(2).
Use guards to reimplement stack grow code. Explicitely track stack
grow area with the guard, including the stack guard page. On stack
grow, trivial shift of the guard map entry and stack map entry limits
makes the stack expansion. Move the code to detect stack grow and
call vm_map_growstack(), from vm_fault() into vm_map_lookup().
As result, it is impossible to get random mapping to occur in the
stack grow area, or to overlap the stack guard page.
Enable stack guard page by default.
Reviewed by: alc, markj
Man page update reviewed by: alc, bjk, emaste, markj, pho
Tested by: pho, Qualys
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D11306 (man pages)
2017-06-24 17:01:11 +00:00
|
|
|
if ((flags & MAP_GUARD) != 0)
|
|
|
|
docow |= MAP_CREATE_GUARD;
|
1996-03-12 02:27:20 +00:00
|
|
|
|
2014-06-09 03:37:41 +00:00
|
|
|
if (fitit) {
|
2013-08-16 21:13:55 +00:00
|
|
|
if ((flags & MAP_ALIGNMENT_MASK) == MAP_ALIGNED_SUPER)
|
|
|
|
findspace = VMFS_SUPER_SPACE;
|
|
|
|
else if ((flags & MAP_ALIGNMENT_MASK) != 0)
|
|
|
|
findspace = VMFS_ALIGNED_SPACE(flags >>
|
|
|
|
MAP_ALIGNMENT_SHIFT);
|
|
|
|
else
|
|
|
|
findspace = VMFS_OPTIMAL_SPACE;
|
Treat the addr argument for mmap(2) request without MAP_FIXED flag as
a hint.
Right now, for non-fixed mmap(2) calls, addr is de-facto interpreted
as the absolute minimal address of the range where the mapping is
created. The VA allocator only allocates in the range [addr,
VM_MAXUSER_ADDRESS]. This is too restrictive, the mmap(2) call might
unduly fail if there is no free addresses above addr but a lot of
usable space below it.
Lift this implementation limitation by allocating VA in two passes.
First, try to allocate above addr, as before. If that fails, do the
second pass with less restrictive constraints for the start of
allocation by specifying minimal allocation address at the max bss
end, if this limit is less than addr.
One important case where this change makes a difference is the
allocation of the stacks for new threads in libthr. Under some
configuration conditions, libthr tries to hint kernel to reuse the
main thread stack grow area for the new stacks. This cannot work by
design now after grow area is converted to stack, and there is no
unallocated VA above the main stack. Interpreting requested stack
base address as the hint provides compatibility with old libthr and
with (mis-)configured current libthr.
Reviewed by: alc
Tested by: dim (previous version)
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2017-06-28 04:02:36 +00:00
|
|
|
max_addr = 0;
|
2013-09-09 18:11:59 +00:00
|
|
|
#ifdef MAP_32BIT
|
Treat the addr argument for mmap(2) request without MAP_FIXED flag as
a hint.
Right now, for non-fixed mmap(2) calls, addr is de-facto interpreted
as the absolute minimal address of the range where the mapping is
created. The VA allocator only allocates in the range [addr,
VM_MAXUSER_ADDRESS]. This is too restrictive, the mmap(2) call might
unduly fail if there is no free addresses above addr but a lot of
usable space below it.
Lift this implementation limitation by allocating VA in two passes.
First, try to allocate above addr, as before. If that fails, do the
second pass with less restrictive constraints for the start of
allocation by specifying minimal allocation address at the max bss
end, if this limit is less than addr.
One important case where this change makes a difference is the
allocation of the stacks for new threads in libthr. Under some
configuration conditions, libthr tries to hint kernel to reuse the
main thread stack grow area for the new stacks. This cannot work by
design now after grow area is converted to stack, and there is no
unallocated VA above the main stack. Interpreting requested stack
base address as the hint provides compatibility with old libthr and
with (mis-)configured current libthr.
Reviewed by: alc
Tested by: dim (previous version)
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2017-06-28 04:02:36 +00:00
|
|
|
if ((flags & MAP_32BIT) != 0)
|
|
|
|
max_addr = MAP_32BIT_MAX_ADDR;
|
2013-09-09 18:11:59 +00:00
|
|
|
#endif
|
Treat the addr argument for mmap(2) request without MAP_FIXED flag as
a hint.
Right now, for non-fixed mmap(2) calls, addr is de-facto interpreted
as the absolute minimal address of the range where the mapping is
created. The VA allocator only allocates in the range [addr,
VM_MAXUSER_ADDRESS]. This is too restrictive, the mmap(2) call might
unduly fail if there is no free addresses above addr but a lot of
usable space below it.
Lift this implementation limitation by allocating VA in two passes.
First, try to allocate above addr, as before. If that fails, do the
second pass with less restrictive constraints for the start of
allocation by specifying minimal allocation address at the max bss
end, if this limit is less than addr.
One important case where this change makes a difference is the
allocation of the stacks for new threads in libthr. Under some
configuration conditions, libthr tries to hint kernel to reuse the
main thread stack grow area for the new stacks. This cannot work by
design now after grow area is converted to stack, and there is no
unallocated VA above the main stack. Interpreting requested stack
base address as the hint provides compatibility with old libthr and
with (mis-)configured current libthr.
Reviewed by: alc
Tested by: dim (previous version)
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
2017-06-28 04:02:36 +00:00
|
|
|
if (curmap) {
|
|
|
|
rv = vm_map_find_min(map, object, foff, addr, size,
|
|
|
|
round_page((vm_offset_t)td->td_proc->p_vmspace->
|
|
|
|
vm_daddr + lim_max(td, RLIMIT_DATA)), max_addr,
|
|
|
|
findspace, prot, maxprot, docow);
|
|
|
|
} else {
|
|
|
|
rv = vm_map_find(map, object, foff, addr, size,
|
|
|
|
max_addr, findspace, prot, maxprot, docow);
|
|
|
|
}
|
2014-06-09 03:37:41 +00:00
|
|
|
} else {
|
2008-04-28 05:30:23 +00:00
|
|
|
rv = vm_map_fixed(map, object, foff, *addr, size,
|
2014-06-09 03:37:41 +00:00
|
|
|
prot, maxprot, docow);
|
|
|
|
}
|
1996-07-30 03:08:57 +00:00
|
|
|
|
2012-02-25 21:06:39 +00:00
|
|
|
if (rv == KERN_SUCCESS) {
|
|
|
|
/*
|
|
|
|
* If the process has requested that all future mappings
|
|
|
|
* be wired, then heed this.
|
|
|
|
*/
|
Provide separate accounting for user-wired pages.
Historically we have not distinguished between kernel wirings and user
wirings for accounting purposes. User wirings (via mlock(2)) were
subject to a global limit on the number of wired pages, so if large
swaths of physical memory were wired by the kernel, as happens with
the ZFS ARC among other things, the limit could be exceeded, causing
user wirings to fail.
The change adds a new counter, v_user_wire_count, which counts the
number of virtual pages wired by user processes via mlock(2) and
mlockall(2). Only user-wired pages are subject to the system-wide
limit which helps provide some safety against deadlocks. In
particular, while sources of kernel wirings typically support some
backpressure mechanism, there is no way to reclaim user-wired pages
shorting of killing the wiring process. The limit is exported as
vm.max_user_wired, renamed from vm.max_wired, and changed from u_int
to u_long.
The choice to count virtual user-wired pages rather than physical
pages was done for simplicity. There are mechanisms that can cause
user-wired mappings to be destroyed while maintaining a wiring of
the backing physical page; these make it difficult to accurately
track user wirings at the physical page layer.
The change also closes some holes which allowed user wirings to succeed
even when they would cause the system limit to be exceeded. For
instance, mmap() may now fail with ENOMEM in a process that has called
mlockall(MCL_FUTURE) if the new mapping would cause the user wiring
limit to be exceeded.
Note that bhyve -S is subject to the user wiring limit, which defaults
to 1/3 of physical RAM. Users that wish to exceed the limit must tune
vm.max_user_wired.
Reviewed by: kib, ngie (mlock() test changes)
Tested by: pho (earlier version)
MFC after: 45 days
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D19908
2019-05-13 16:38:48 +00:00
|
|
|
if ((map->flags & MAP_WIREFUTURE) != 0) {
|
|
|
|
vm_map_lock(map);
|
|
|
|
if ((map->flags & MAP_WIREFUTURE) != 0)
|
2019-05-13 18:40:01 +00:00
|
|
|
(void)vm_map_wire_locked(map, *addr,
|
Provide separate accounting for user-wired pages.
Historically we have not distinguished between kernel wirings and user
wirings for accounting purposes. User wirings (via mlock(2)) were
subject to a global limit on the number of wired pages, so if large
swaths of physical memory were wired by the kernel, as happens with
the ZFS ARC among other things, the limit could be exceeded, causing
user wirings to fail.
The change adds a new counter, v_user_wire_count, which counts the
number of virtual pages wired by user processes via mlock(2) and
mlockall(2). Only user-wired pages are subject to the system-wide
limit which helps provide some safety against deadlocks. In
particular, while sources of kernel wirings typically support some
backpressure mechanism, there is no way to reclaim user-wired pages
shorting of killing the wiring process. The limit is exported as
vm.max_user_wired, renamed from vm.max_wired, and changed from u_int
to u_long.
The choice to count virtual user-wired pages rather than physical
pages was done for simplicity. There are mechanisms that can cause
user-wired mappings to be destroyed while maintaining a wiring of
the backing physical page; these make it difficult to accurately
track user wirings at the physical page layer.
The change also closes some holes which allowed user wirings to succeed
even when they would cause the system limit to be exceeded. For
instance, mmap() may now fail with ENOMEM in a process that has called
mlockall(MCL_FUTURE) if the new mapping would cause the user wiring
limit to be exceeded.
Note that bhyve -S is subject to the user wiring limit, which defaults
to 1/3 of physical RAM. Users that wish to exceed the limit must tune
vm.max_user_wired.
Reviewed by: kib, ngie (mlock() test changes)
Tested by: pho (earlier version)
MFC after: 45 days
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D19908
2019-05-13 16:38:48 +00:00
|
|
|
*addr + size, VM_MAP_WIRE_USER |
|
|
|
|
((flags & MAP_STACK) ? VM_MAP_WIRE_HOLESOK :
|
|
|
|
VM_MAP_WIRE_NOHOLES));
|
|
|
|
vm_map_unlock(map);
|
2012-04-21 18:36:53 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2011-07-10 20:49:13 +00:00
|
|
|
return (vm_mmap_to_errno(rv));
|
|
|
|
}
|
|
|
|
|
2012-02-25 21:06:39 +00:00
|
|
|
/*
|
|
|
|
* Translate a Mach VM return code to zero on success or the appropriate errno
|
|
|
|
* on failure.
|
|
|
|
*/
|
2011-07-10 20:49:13 +00:00
|
|
|
int
|
|
|
|
vm_mmap_to_errno(int rv)
|
|
|
|
{
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
switch (rv) {
|
|
|
|
case KERN_SUCCESS:
|
|
|
|
return (0);
|
|
|
|
case KERN_INVALID_ADDRESS:
|
|
|
|
case KERN_NO_SPACE:
|
|
|
|
return (ENOMEM);
|
|
|
|
case KERN_PROTECTION_FAILURE:
|
|
|
|
return (EACCES);
|
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
}
|