vm_page.h revision 9507
15455Sdg/*
21541Srgrimes * Copyright (c) 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * This code is derived from software contributed to Berkeley by
61541Srgrimes * The Mach Operating System project at Carnegie-Mellon University.
71541Srgrimes *
81541Srgrimes * Redistribution and use in source and binary forms, with or without
91541Srgrimes * modification, are permitted provided that the following conditions
101541Srgrimes * are met:
111541Srgrimes * 1. Redistributions of source code must retain the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer.
131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer in the
151541Srgrimes *    documentation and/or other materials provided with the distribution.
161541Srgrimes * 3. All advertising materials mentioning features or use of this software
171541Srgrimes *    must display the following acknowledgement:
181541Srgrimes *	This product includes software developed by the University of
191541Srgrimes *	California, Berkeley and its contributors.
201541Srgrimes * 4. Neither the name of the University nor the names of its contributors
211541Srgrimes *    may be used to endorse or promote products derived from this software
221541Srgrimes *    without specific prior written permission.
231541Srgrimes *
241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341541Srgrimes * SUCH DAMAGE.
351541Srgrimes *
361817Sdg *	from: @(#)vm_page.h	8.2 (Berkeley) 12/13/93
371541Srgrimes *
381541Srgrimes *
391541Srgrimes * Copyright (c) 1987, 1990 Carnegie-Mellon University.
401541Srgrimes * All rights reserved.
411541Srgrimes *
421541Srgrimes * Authors: Avadis Tevanian, Jr., Michael Wayne Young
435455Sdg *
441541Srgrimes * Permission to use, copy, modify and distribute this software and
451541Srgrimes * its documentation is hereby granted, provided that both the copyright
461541Srgrimes * notice and this permission notice appear in all copies of the
471541Srgrimes * software, derivative works or modified versions, and any portions
481541Srgrimes * thereof, and that both notices appear in supporting documentation.
495455Sdg *
505455Sdg * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
515455Sdg * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
521541Srgrimes * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
535455Sdg *
541541Srgrimes * Carnegie Mellon requests users of this software to return to
551541Srgrimes *
561541Srgrimes *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
571541Srgrimes *  School of Computer Science
581541Srgrimes *  Carnegie Mellon University
591541Srgrimes *  Pittsburgh PA 15213-3890
601541Srgrimes *
611541Srgrimes * any improvements or extensions that they make and grant Carnegie the
621541Srgrimes * rights to redistribute these changes.
631817Sdg *
649507Sdg * $Id: vm_page.h,v 1.18 1995/04/23 08:05:49 bde Exp $
651541Srgrimes */
661541Srgrimes
671541Srgrimes/*
681541Srgrimes *	Resident memory system definitions.
691541Srgrimes */
701541Srgrimes
711541Srgrimes#ifndef	_VM_PAGE_
721541Srgrimes#define	_VM_PAGE_
731541Srgrimes
746816Sdg#include <vm/pmap.h>
751541Srgrimes/*
761541Srgrimes *	Management of resident (logical) pages.
771541Srgrimes *
781541Srgrimes *	A small structure is kept for each resident
791541Srgrimes *	page, indexed by page number.  Each structure
801541Srgrimes *	is an element of several lists:
811541Srgrimes *
821541Srgrimes *		A hash table bucket used to quickly
831541Srgrimes *		perform object/offset lookups
841541Srgrimes *
851541Srgrimes *		A list of all pages for a given object,
861541Srgrimes *		so they can be quickly deactivated at
871541Srgrimes *		time of deallocation.
881541Srgrimes *
891541Srgrimes *		An ordered list of pages due for pageout.
901541Srgrimes *
911541Srgrimes *	In addition, the structure contains the object
921541Srgrimes *	and offset to which this page belongs (for pageout),
931541Srgrimes *	and sundry status bits.
941541Srgrimes *
951541Srgrimes *	Fields in this structure are locked either by the lock on the
961541Srgrimes *	object that the page belongs to (O) or by the lock on the page
971541Srgrimes *	queues (P).
981541Srgrimes */
991541Srgrimes
1001541SrgrimesTAILQ_HEAD(pglist, vm_page);
1011541Srgrimes
1021541Srgrimesstruct vm_page {
1035455Sdg	TAILQ_ENTRY(vm_page) pageq;	/* queue info for FIFO queue or free list (P) */
1045455Sdg	TAILQ_ENTRY(vm_page) hashq;	/* hash table links (O) */
1055455Sdg	TAILQ_ENTRY(vm_page) listq;	/* pages in same object (O) */
1061541Srgrimes
1075455Sdg	vm_object_t object;		/* which object am I in (O,P) */
1085455Sdg	vm_offset_t offset;		/* offset into object (O,P) */
1095455Sdg	vm_offset_t phys_addr;		/* physical address of page */
1101541Srgrimes
1115455Sdg	u_short wire_count;		/* wired down maps refs (P) */
1125455Sdg	u_short flags;			/* see below */
1135455Sdg	short hold_count;		/* page hold count */
1145455Sdg	u_short act_count;		/* page usage count */
1155455Sdg	u_short bmapped;		/* number of buffers mapped */
1165455Sdg	u_short busy;			/* page busy count */
1175455Sdg	u_short valid;			/* map of valid DEV_BSIZE chunks */
1185455Sdg	u_short dirty;			/* map of dirty DEV_BSIZE chunks */
1191541Srgrimes};
1201541Srgrimes
1211541Srgrimes/*
1221541Srgrimes * These are the flags defined for vm_page.
1231541Srgrimes *
1241541Srgrimes * Note: PG_FILLED and PG_DIRTY are added for the filesystems.
1251541Srgrimes */
1261541Srgrimes#define	PG_INACTIVE	0x0001		/* page is in inactive list (P) */
1271541Srgrimes#define	PG_ACTIVE	0x0002		/* page is in active list (P) */
1281541Srgrimes#define	PG_BUSY		0x0010		/* page is in transit (O) */
1291541Srgrimes#define	PG_WANTED	0x0020		/* someone is waiting for page (O) */
1301541Srgrimes#define	PG_TABLED	0x0040		/* page is in VP table (O) */
1311541Srgrimes#define	PG_COPYONWRITE	0x0080		/* must copy page before changing (O) */
1321541Srgrimes#define	PG_FICTITIOUS	0x0100		/* physical page doesn't exist (O) */
1337400Sdg#define	PG_WRITEABLE	0x0200		/* page is mapped writeable */
1347400Sdg#define PG_MAPPED	0x0400		/* page is mapped */
1351827Sdg#define PG_REFERENCED	0x1000		/* page has been referenced */
1365455Sdg#define	PG_CACHE	0x4000		/* On VMIO cache */
1373145Sdg#define	PG_FREE		0x8000		/* page is in free list */
1381541Srgrimes
1399507Sdg/*
1409507Sdg * Misc constants.
1419507Sdg */
1421541Srgrimes
1439507Sdg#define ACT_DECLINE		1
1449507Sdg#define ACT_ADVANCE		3
1459507Sdg#define ACT_MAX			100
1469507Sdg#define PFCLUSTER_BEHIND	3
1479507Sdg#define PFCLUSTER_AHEAD		3
1489507Sdg
1491541Srgrimes#ifdef KERNEL
1501541Srgrimes/*
1519507Sdg * Each pageable resident page falls into one of four lists:
1521541Srgrimes *
1535455Sdg *	free
1541541Srgrimes *		Available for allocation now.
1559507Sdg *
1569507Sdg * The following are all LRU sorted:
1579507Sdg *
1589507Sdg *	cache
1599507Sdg *		Almost available for allocation. Still in an
1609507Sdg *		object, but clean and immediately freeable at
1619507Sdg *		non-interrupt times.
1629507Sdg *
1631541Srgrimes *	inactive
1649507Sdg *		Low activity, candidates for reclaimation.
1651541Srgrimes *		This is the list of pages that should be
1661541Srgrimes *		paged out next.
1679507Sdg *
1681541Srgrimes *	active
1699507Sdg *		Pages that are "active" i.e. they have been
1709507Sdg *		recently referenced.
1711541Srgrimes */
1721541Srgrimes
1735455Sdgextern struct pglist vm_page_queue_free;	/* memory free queue */
1745455Sdgextern struct pglist vm_page_queue_active;	/* active memory queue */
1755455Sdgextern struct pglist vm_page_queue_inactive;	/* inactive memory queue */
1765455Sdgextern struct pglist vm_page_queue_cache;	/* cache memory queue */
1771541Srgrimes
1785455Sdgextern vm_page_t vm_page_array;		/* First resident page in table */
1795455Sdgextern long first_page;			/* first physical page number */
1801541Srgrimes
1815455Sdg /* ... represented in vm_page_array */
1825455Sdgextern long last_page;			/* last physical page number */
1835455Sdg
1845455Sdg /* ... represented in vm_page_array */
1855455Sdg /* [INCLUSIVE] */
1865455Sdgextern vm_offset_t first_phys_addr;	/* physical address for first_page */
1875455Sdgextern vm_offset_t last_phys_addr;	/* physical address for last_page */
1885455Sdg
1891541Srgrimes#define VM_PAGE_TO_PHYS(entry)	((entry)->phys_addr)
1901541Srgrimes
1911541Srgrimes#define IS_VM_PHYSADDR(pa) \
1921541Srgrimes		((pa) >= first_phys_addr && (pa) <= last_phys_addr)
1931541Srgrimes
1941541Srgrimes#define PHYS_TO_VM_PAGE(pa) \
1951541Srgrimes		(&vm_page_array[atop(pa) - first_page ])
1961541Srgrimes
1971541Srgrimes/*
1981541Srgrimes *	Functions implemented as macros
1991541Srgrimes */
2001541Srgrimes
2011541Srgrimes#define PAGE_ASSERT_WAIT(m, interruptible)	{ \
2021541Srgrimes				(m)->flags |= PG_WANTED; \
2031541Srgrimes				assert_wait((int) (m), (interruptible)); \
2041541Srgrimes			}
2051541Srgrimes
2061541Srgrimes#define PAGE_WAKEUP(m)	{ \
2071541Srgrimes				(m)->flags &= ~PG_BUSY; \
2081541Srgrimes				if ((m)->flags & PG_WANTED) { \
2091541Srgrimes					(m)->flags &= ~PG_WANTED; \
2101549Srgrimes					wakeup((caddr_t) (m)); \
2111541Srgrimes				} \
2121541Srgrimes			}
2131541Srgrimes
2145455Sdg#if PAGE_SIZE == 4096
2155455Sdg#define VM_PAGE_BITS_ALL 0xff
2165455Sdg#endif
2171541Srgrimes
2185455Sdg#if PAGE_SIZE == 8192
2195455Sdg#define VM_PAGE_BITS_ALL 0xffff
2205455Sdg#endif
2211549Srgrimes
2225841Sdg#define VM_ALLOC_NORMAL 0
2235841Sdg#define VM_ALLOC_INTERRUPT 1
2245841Sdg#define VM_ALLOC_SYSTEM 2
2255455Sdg
2265455Sdgvoid vm_page_activate __P((vm_page_t));
2275455Sdgvm_page_t vm_page_alloc __P((vm_object_t, vm_offset_t, int));
2286357Sphkvoid vm_page_cache __P((register vm_page_t));
2295455Sdgvoid vm_page_copy __P((vm_page_t, vm_page_t));
2305455Sdgvoid vm_page_deactivate __P((vm_page_t));
2315455Sdgvoid vm_page_free __P((vm_page_t));
2325455Sdgvoid vm_page_insert __P((vm_page_t, vm_object_t, vm_offset_t));
2335455Sdgvm_page_t vm_page_lookup __P((vm_object_t, vm_offset_t));
2345455Sdgvoid vm_page_remove __P((vm_page_t));
2355455Sdgvoid vm_page_rename __P((vm_page_t, vm_object_t, vm_offset_t));
2365455Sdgvm_offset_t vm_page_startup __P((vm_offset_t, vm_offset_t, vm_offset_t));
2375455Sdgvoid vm_page_unwire __P((vm_page_t));
2385455Sdgvoid vm_page_wire __P((vm_page_t));
2395455Sdgboolean_t vm_page_zero_fill __P((vm_page_t));
2405455Sdgvoid vm_page_set_dirty __P((vm_page_t, int, int));
2415455Sdgvoid vm_page_set_clean __P((vm_page_t, int, int));
2425455Sdgint vm_page_is_clean __P((vm_page_t, int, int));
2435455Sdgvoid vm_page_set_valid __P((vm_page_t, int, int));
2445455Sdgvoid vm_page_set_invalid __P((vm_page_t, int, int));
2455455Sdgint vm_page_is_valid __P((vm_page_t, int, int));
2465455Sdgvoid vm_page_test_dirty __P((vm_page_t));
2476816Sdgvoid vm_page_unqueue __P((vm_page_t ));
2486357Sphkint vm_page_bits __P((int, int));
2495455Sdg
2505455Sdg
2511549Srgrimes/*
2521549Srgrimes * Keep page from being freed by the page daemon
2531549Srgrimes * much of the same effect as wiring, except much lower
2541549Srgrimes * overhead and should be used only for *very* temporary
2551549Srgrimes * holding ("wiring").
2561549Srgrimes */
2578010Sbdestatic __inline void
2584461Sbdevm_page_hold(vm_page_t mem)
2591549Srgrimes{
2601549Srgrimes	mem->hold_count++;
2611549Srgrimes}
2621549Srgrimes
2633745Swollman#ifdef DIAGNOSTIC
2643745Swollman#include <sys/systm.h>		/* make GCC shut up */
2653745Swollman#endif
2663745Swollman
2678010Sbdestatic __inline void
2684461Sbdevm_page_unhold(vm_page_t mem)
2691549Srgrimes{
2703660Sdg#ifdef DIAGNOSTIC
2715455Sdg	if (--mem->hold_count < 0)
2721549Srgrimes		panic("vm_page_unhold: hold count < 0!!!");
2733660Sdg#else
2743660Sdg	--mem->hold_count;
2753660Sdg#endif
2761549Srgrimes}
2771549Srgrimes
2788010Sbdestatic __inline void
2796816Sdgvm_page_protect(vm_page_t mem, int prot)
2806816Sdg{
2816816Sdg	if (prot == VM_PROT_NONE) {
2826816Sdg		if (mem->flags & (PG_WRITEABLE|PG_MAPPED)) {
2836816Sdg			pmap_page_protect(VM_PAGE_TO_PHYS(mem), prot);
2846816Sdg			mem->flags &= ~(PG_WRITEABLE|PG_MAPPED);
2856816Sdg		}
2866816Sdg	} else if ((prot == VM_PROT_READ) && (mem->flags & PG_WRITEABLE)) {
2876816Sdg		pmap_page_protect(VM_PAGE_TO_PHYS(mem), prot);
2886816Sdg		mem->flags &= ~PG_WRITEABLE;
2896816Sdg	}
2906816Sdg}
2916816Sdg
2926816Sdg
2935455Sdg#endif				/* KERNEL */
2945455Sdg#endif				/* !_VM_PAGE_ */
295