/*-1* SPDX-License-Identifier: (BSD-3-Clause AND MIT-CMU)2*3* Copyright (c) 1991, 19934* The Regents of the University of California. All rights reserved.5*6* This code is derived from software contributed to Berkeley by7* The Mach Operating System project at Carnegie-Mellon University.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17* 3. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*33*34* Copyright (c) 1987, 1990 Carnegie-Mellon University.35* All rights reserved.36*37* Authors: Avadis Tevanian, Jr., Michael Wayne Young38*39* Permission to use, copy, modify and distribute this software and40* its documentation is hereby granted, provided that both the copyright41* notice and this permission notice appear in all copies of the42* software, derivative works or modified versions, and any portions43* thereof, and that both notices appear in supporting documentation.44*45* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"46* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND47* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.48*49* Carnegie Mellon requests users of this software to return to50*51* Software Distribution Coordinator or [email protected]52* School of Computer Science53* Carnegie Mellon University54* Pittsburgh PA 15213-389055*56* any improvements or extensions that they make and grant Carnegie the57* rights to redistribute these changes.58*/5960/*61* Virtual memory object module definitions.62*/6364#ifndef _VM_OBJECT_65#define _VM_OBJECT_6667#include <sys/queue.h>68#include <sys/_blockcount.h>69#include <sys/_lock.h>70#include <sys/_mutex.h>71#include <sys/_pctrie.h>72#include <sys/_rwlock.h>73#include <sys/_domainset.h>7475#include <vm/_vm_radix.h>7677/*78* Types defined:79*80* vm_object_t Virtual memory object.81*82* List of locks83* (a) atomic84* (c) const until freed85* (o) per-object lock86* (f) free pages queue mutex87*88*/8990#ifndef VM_PAGE_HAVE_PGLIST91TAILQ_HEAD(pglist, vm_page);92#define VM_PAGE_HAVE_PGLIST93#endif9495struct vm_object {96struct rwlock lock;97TAILQ_ENTRY(vm_object) object_list; /* list of all objects */98LIST_HEAD(, vm_object) shadow_head; /* objects that this is a shadow for */99LIST_ENTRY(vm_object) shadow_list; /* chain of shadow objects */100struct vm_radix rtree; /* root of the resident page radix trie*/101vm_pindex_t size; /* Object size */102struct domainset_ref domain; /* NUMA policy. */103volatile int generation; /* generation ID */104int cleangeneration; /* Generation at clean time */105volatile u_int ref_count; /* How many refs?? */106int shadow_count; /* how many objects that this is a shadow for */107vm_memattr_t memattr; /* default memory attribute for pages */108objtype_t type; /* type of pager */109u_short pg_color; /* (c) color of first page in obj */110u_int flags; /* see below */111blockcount_t paging_in_progress; /* (a) Paging (in or out) so don't collapse or destroy */112blockcount_t busy; /* (a) object is busy, disallow page busy. */113int resident_page_count; /* number of resident pages */114struct vm_object *backing_object; /* object that I'm a shadow of */115vm_ooffset_t backing_object_offset;/* Offset in backing object */116TAILQ_ENTRY(vm_object) pager_object_list; /* list of all objects of this pager type */117LIST_HEAD(, vm_reserv) rvq; /* list of reservations */118void *handle;119union {120/*121* VNode pager122*123* vnp_size - current size of file124*/125struct {126off_t vnp_size;127vm_ooffset_t writemappings;128} vnp;129130/*131* Device pager132*133* devp_pglist - list of allocated pages134*/135struct {136TAILQ_HEAD(, vm_page) devp_pglist;137const struct cdev_pager_ops *ops;138void *handle;139} devp;140141/*142* SG pager143*144* sgp_pglist - list of allocated pages145*/146struct {147TAILQ_HEAD(, vm_page) sgp_pglist;148} sgp;149150/*151* Swap pager152*153* swp_priv - pager-private.154* swp_blks - pc-trie of the allocated swap blocks.155* writemappings - count of bytes mapped for write156*157*/158struct {159void *swp_priv;160struct pctrie swp_blks;161vm_ooffset_t writemappings;162} swp;163164/*165* Phys pager166*/167struct {168const struct phys_pager_ops *ops;169union {170void *data_ptr;171uintptr_t data_val;172};173void *phys_priv;174} phys;175} un_pager;176struct ucred *cred;177vm_ooffset_t charge;178void *umtx_data;179};180181/*182* Flags183*/184#define OBJ_FICTITIOUS 0x00000001 /* (c) contains fictitious pages */185#define OBJ_UNMANAGED 0x00000002 /* (c) contains unmanaged pages */186#define OBJ_POPULATE 0x00000004 /* pager implements populate() */187#define OBJ_DEAD 0x00000008 /* dead objects (during rundown) */188#define OBJ_ANON 0x00000010 /* (c) contains anonymous memory */189#define OBJ_UMTXDEAD 0x00000020 /* umtx pshared was terminated */190#define OBJ_SIZEVNLOCK 0x00000040 /* lock vnode to check obj size */191#define OBJ_PG_DTOR 0x00000080 /* do not reset object, leave that192for dtor */193#define OBJ_SHADOWLIST 0x00000100 /* Object is on the shadow list. */194#define OBJ_SWAP 0x00000200 /* object swaps, type will be OBJT_SWAP195or dynamically registered */196#define OBJ_SPLIT 0x00000400 /* object is being split */197#define OBJ_COLLAPSING 0x00000800 /* Parent of collapse. */198#define OBJ_COLORED 0x00001000 /* pg_color is defined */199#define OBJ_ONEMAPPING 0x00002000 /* One USE (a single, non-forked)200mapping flag */201#define OBJ_PAGERPRIV1 0x00004000 /* Pager private */202#define OBJ_PAGERPRIV2 0x00008000 /* Pager private */203#define OBJ_SYSVSHM 0x00010000 /* SysV SHM */204#define OBJ_POSIXSHM 0x00020000 /* Posix SHM */205206/*207* Helpers to perform conversion between vm_object page indexes and offsets.208* IDX_TO_OFF() converts an index into an offset.209* OFF_TO_IDX() converts an offset into an index.210* OBJ_MAX_SIZE specifies the maximum page index corresponding to the211* maximum unsigned offset.212*/213#define IDX_TO_OFF(idx) (((vm_ooffset_t)(idx)) << PAGE_SHIFT)214#define OFF_TO_IDX(off) ((vm_pindex_t)(((vm_ooffset_t)(off)) >> PAGE_SHIFT))215#define OBJ_MAX_SIZE (OFF_TO_IDX(UINT64_MAX) + 1)216217#ifdef _KERNEL218219#define OBJPC_SYNC 0x1 /* sync I/O */220#define OBJPC_INVAL 0x2 /* invalidate */221#define OBJPC_NOSYNC 0x4 /* skip if PGA_NOSYNC */222223/*224* The following options are supported by vm_object_page_remove().225*/226#define OBJPR_CLEANONLY 0x1 /* Don't remove dirty pages. */227#define OBJPR_NOTMAPPED 0x2 /* Don't unmap pages. */228#define OBJPR_VALIDONLY 0x4 /* Ignore invalid pages. */229230TAILQ_HEAD(object_q, vm_object);231232extern struct object_q vm_object_list; /* list of allocated objects */233extern struct mtx vm_object_list_mtx; /* lock for object list and count */234235extern struct vm_object kernel_object_store;236237#define kernel_object (&kernel_object_store)238239#define VM_OBJECT_ASSERT_LOCKED(object) \240rw_assert(&(object)->lock, RA_LOCKED)241#define VM_OBJECT_ASSERT_RLOCKED(object) \242rw_assert(&(object)->lock, RA_RLOCKED)243#define VM_OBJECT_ASSERT_WLOCKED(object) \244rw_assert(&(object)->lock, RA_WLOCKED)245#define VM_OBJECT_ASSERT_UNLOCKED(object) \246rw_assert(&(object)->lock, RA_UNLOCKED)247#define VM_OBJECT_LOCK_DOWNGRADE(object) \248rw_downgrade(&(object)->lock)249#define VM_OBJECT_RLOCK(object) \250rw_rlock(&(object)->lock)251#define VM_OBJECT_RUNLOCK(object) \252rw_runlock(&(object)->lock)253#define VM_OBJECT_SLEEP(object, wchan, pri, wmesg, timo) \254rw_sleep((wchan), &(object)->lock, (pri), (wmesg), (timo))255#define VM_OBJECT_TRYRLOCK(object) \256rw_try_rlock(&(object)->lock)257#define VM_OBJECT_TRYWLOCK(object) \258rw_try_wlock(&(object)->lock)259#define VM_OBJECT_TRYUPGRADE(object) \260rw_try_upgrade(&(object)->lock)261#define VM_OBJECT_WLOCK(object) \262rw_wlock(&(object)->lock)263#define VM_OBJECT_WOWNED(object) \264rw_wowned(&(object)->lock)265#define VM_OBJECT_WUNLOCK(object) \266rw_wunlock(&(object)->lock)267#define VM_OBJECT_UNLOCK(object) \268rw_unlock(&(object)->lock)269#define VM_OBJECT_DROP(object) \270lock_class_rw.lc_unlock(&(object)->lock.lock_object)271#define VM_OBJECT_PICKUP(object, state) \272lock_class_rw.lc_lock(&(object)->lock.lock_object, (state))273274#define VM_OBJECT_ASSERT_PAGING(object) \275KASSERT(blockcount_read(&(object)->paging_in_progress) != 0, \276("vm_object %p is not paging", object))277#define VM_OBJECT_ASSERT_REFERENCE(object) \278KASSERT((object)->reference_count != 0, \279("vm_object %p is not referenced", object))280281struct vnode;282283/*284* The object must be locked or thread private.285*/286static __inline void287vm_object_set_flag(vm_object_t object, u_int bits)288{289290object->flags |= bits;291}292293/*294* Conditionally set the object's color, which (1) enables the allocation295* of physical memory reservations for anonymous objects and larger-than-296* superpage-sized named objects and (2) determines the first page offset297* within the object at which a reservation may be allocated. In other298* words, the color determines the alignment of the object with respect299* to the largest superpage boundary. When mapping named objects, like300* files or POSIX shared memory objects, the color should be set to zero301* before a virtual address is selected for the mapping. In contrast,302* for anonymous objects, the color may be set after the virtual address303* is selected.304*305* The object must be locked.306*/307static __inline void308vm_object_color(vm_object_t object, u_short color)309{310311if ((object->flags & OBJ_COLORED) == 0) {312object->pg_color = color;313vm_object_set_flag(object, OBJ_COLORED);314}315}316317static __inline bool318vm_object_reserv(vm_object_t object)319{320321if (object != NULL &&322(object->flags & (OBJ_COLORED | OBJ_FICTITIOUS)) == OBJ_COLORED) {323return (true);324}325return (false);326}327328void vm_object_clear_flag(vm_object_t object, u_short bits);329void vm_object_pip_add(vm_object_t object, short i);330void vm_object_pip_wakeup(vm_object_t object);331void vm_object_pip_wakeupn(vm_object_t object, short i);332void vm_object_pip_wait(vm_object_t object, const char *waitid);333void vm_object_pip_wait_unlocked(vm_object_t object, const char *waitid);334335void vm_object_busy(vm_object_t object);336void vm_object_unbusy(vm_object_t object);337void vm_object_busy_wait(vm_object_t object, const char *wmesg);338339static inline bool340vm_object_busied(vm_object_t object)341{342343return (blockcount_read(&object->busy) != 0);344}345#define VM_OBJECT_ASSERT_BUSY(object) MPASS(vm_object_busied((object)))346347void umtx_shm_object_init(vm_object_t object);348void umtx_shm_object_terminated(vm_object_t object);349extern int umtx_shm_vnobj_persistent;350351vm_object_t vm_object_allocate (objtype_t, vm_pindex_t);352vm_object_t vm_object_allocate_anon(vm_pindex_t, vm_object_t, struct ucred *,353vm_size_t);354vm_object_t vm_object_allocate_dyn(objtype_t, vm_pindex_t, u_short);355boolean_t vm_object_coalesce(vm_object_t, vm_ooffset_t, vm_size_t, vm_size_t,356boolean_t);357void vm_object_collapse (vm_object_t);358void vm_object_deallocate (vm_object_t);359void vm_object_destroy (vm_object_t);360void vm_object_terminate (vm_object_t);361void vm_object_set_writeable_dirty (vm_object_t);362void vm_object_set_writeable_dirty_(vm_object_t object);363bool vm_object_mightbedirty(vm_object_t object);364bool vm_object_mightbedirty_(vm_object_t object);365void vm_object_init (void);366int vm_object_kvme_type(vm_object_t object, struct vnode **vpp);367void vm_object_madvise(vm_object_t, vm_pindex_t, vm_pindex_t, int);368boolean_t vm_object_page_clean(vm_object_t object, vm_ooffset_t start,369vm_ooffset_t end, int flags);370void vm_object_page_noreuse(vm_object_t object, vm_pindex_t start,371vm_pindex_t end);372void vm_object_page_remove(vm_object_t object, vm_pindex_t start,373vm_pindex_t end, int options);374boolean_t vm_object_populate(vm_object_t, vm_pindex_t, vm_pindex_t);375void vm_object_prepare_buf_pages(vm_object_t object, vm_page_t *ma_dst,376int count, int *rbehind, int *rahead, vm_page_t *ma_src);377void vm_object_print(long addr, boolean_t have_addr, long count, char *modif);378void vm_object_reference (vm_object_t);379void vm_object_reference_locked(vm_object_t);380int vm_object_set_memattr(vm_object_t object, vm_memattr_t memattr);381void vm_object_shadow(vm_object_t *, vm_ooffset_t *, vm_size_t, struct ucred *,382bool);383void vm_object_split(vm_map_entry_t);384boolean_t vm_object_sync(vm_object_t, vm_ooffset_t, vm_size_t, boolean_t,385boolean_t);386void vm_object_unwire(vm_object_t object, vm_ooffset_t offset,387vm_size_t length, uint8_t queue);388struct vnode *vm_object_vnode(vm_object_t object);389bool vm_object_is_active(vm_object_t obj);390#endif /* _KERNEL */391392#endif /* _VM_OBJECT_ */393394395