vm_page.h revision 1817
11541Srgrimes/*
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
431541Srgrimes *
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.
491541Srgrimes *
501541Srgrimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
511541Srgrimes * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
521541Srgrimes * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
531541Srgrimes *
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 *
641817Sdg * $Id$
651541Srgrimes */
661541Srgrimes
671541Srgrimes/*
681541Srgrimes *	Resident memory system definitions.
691541Srgrimes */
701541Srgrimes
711541Srgrimes#ifndef	_VM_PAGE_
721541Srgrimes#define	_VM_PAGE_
731541Srgrimes
741541Srgrimes/*
751541Srgrimes *	Management of resident (logical) pages.
761541Srgrimes *
771541Srgrimes *	A small structure is kept for each resident
781541Srgrimes *	page, indexed by page number.  Each structure
791541Srgrimes *	is an element of several lists:
801541Srgrimes *
811541Srgrimes *		A hash table bucket used to quickly
821541Srgrimes *		perform object/offset lookups
831541Srgrimes *
841541Srgrimes *		A list of all pages for a given object,
851541Srgrimes *		so they can be quickly deactivated at
861541Srgrimes *		time of deallocation.
871541Srgrimes *
881541Srgrimes *		An ordered list of pages due for pageout.
891541Srgrimes *
901541Srgrimes *	In addition, the structure contains the object
911541Srgrimes *	and offset to which this page belongs (for pageout),
921541Srgrimes *	and sundry status bits.
931541Srgrimes *
941541Srgrimes *	Fields in this structure are locked either by the lock on the
951541Srgrimes *	object that the page belongs to (O) or by the lock on the page
961541Srgrimes *	queues (P).
971541Srgrimes */
981541Srgrimes
991541SrgrimesTAILQ_HEAD(pglist, vm_page);
1001541Srgrimes
1011541Srgrimesstruct vm_page {
1021541Srgrimes	TAILQ_ENTRY(vm_page)	pageq;		/* queue info for FIFO
1031541Srgrimes						 * queue or free list (P) */
1041541Srgrimes	TAILQ_ENTRY(vm_page)	hashq;		/* hash table links (O)*/
1051541Srgrimes	TAILQ_ENTRY(vm_page)	listq;		/* pages in same object (O)*/
1061541Srgrimes
1071541Srgrimes	vm_object_t		object;		/* which object am I in (O,P)*/
1081541Srgrimes	vm_offset_t		offset;		/* offset into object (O,P) */
1091541Srgrimes
1101541Srgrimes	u_short			wire_count;	/* wired down maps refs (P) */
1111541Srgrimes	u_short			flags;		/* see below */
1121549Srgrimes	short			hold_count;	/* page hold count */
1131549Srgrimes	u_short			act_count;	/* page usage count */
1141541Srgrimes
1151541Srgrimes	vm_offset_t		phys_addr;	/* physical address of page */
1161541Srgrimes};
1171541Srgrimes
1181541Srgrimes/*
1191541Srgrimes * These are the flags defined for vm_page.
1201541Srgrimes *
1211541Srgrimes * Note: PG_FILLED and PG_DIRTY are added for the filesystems.
1221541Srgrimes */
1231541Srgrimes#define	PG_INACTIVE	0x0001		/* page is in inactive list (P) */
1241541Srgrimes#define	PG_ACTIVE	0x0002		/* page is in active list (P) */
1251541Srgrimes#define	PG_LAUNDRY	0x0004		/* page is being cleaned now (P)*/
1261541Srgrimes#define	PG_CLEAN	0x0008		/* page has not been modified */
1271541Srgrimes#define	PG_BUSY		0x0010		/* page is in transit (O) */
1281541Srgrimes#define	PG_WANTED	0x0020		/* someone is waiting for page (O) */
1291541Srgrimes#define	PG_TABLED	0x0040		/* page is in VP table (O) */
1301541Srgrimes#define	PG_COPYONWRITE	0x0080		/* must copy page before changing (O) */
1311541Srgrimes#define	PG_FICTITIOUS	0x0100		/* physical page doesn't exist (O) */
1321541Srgrimes#define	PG_FAKE		0x0200		/* page is placeholder for pagein (O) */
1331541Srgrimes#define	PG_FILLED	0x0400		/* client flag to set when filled */
1341541Srgrimes#define	PG_DIRTY	0x0800		/* client flag to set when dirty */
1351541Srgrimes#define	PG_PAGEROWNED	0x4000		/* DEBUG: async paging op in progress */
1361541Srgrimes#define	PG_PTPAGE	0x8000		/* DEBUG: is a user page table page */
1371541Srgrimes
1381541Srgrimes#if	VM_PAGE_DEBUG
1391541Srgrimes#define	VM_PAGE_CHECK(mem) { \
1401541Srgrimes	if ((((unsigned int) mem) < ((unsigned int) &vm_page_array[0])) || \
1411541Srgrimes	    (((unsigned int) mem) > \
1421541Srgrimes		((unsigned int) &vm_page_array[last_page-first_page])) || \
1431541Srgrimes	    ((mem->flags & (PG_ACTIVE | PG_INACTIVE)) == \
1441541Srgrimes		(PG_ACTIVE | PG_INACTIVE))) \
1451541Srgrimes		panic("vm_page_check: not valid!"); \
1461541Srgrimes}
1471541Srgrimes#else /* VM_PAGE_DEBUG */
1481541Srgrimes#define	VM_PAGE_CHECK(mem)
1491541Srgrimes#endif /* VM_PAGE_DEBUG */
1501541Srgrimes
1511541Srgrimes#ifdef KERNEL
1521541Srgrimes/*
1531541Srgrimes *	Each pageable resident page falls into one of three lists:
1541541Srgrimes *
1551541Srgrimes *	free
1561541Srgrimes *		Available for allocation now.
1571541Srgrimes *	inactive
1581541Srgrimes *		Not referenced in any map, but still has an
1591541Srgrimes *		object/offset-page mapping, and may be dirty.
1601541Srgrimes *		This is the list of pages that should be
1611541Srgrimes *		paged out next.
1621541Srgrimes *	active
1631541Srgrimes *		A list of pages which have been placed in
1641541Srgrimes *		at least one physical map.  This list is
1651541Srgrimes *		ordered, in LRU-like fashion.
1661541Srgrimes */
1671541Srgrimes
1681541Srgrimesextern
1691541Srgrimesstruct pglist	vm_page_queue_free;	/* memory free queue */
1701541Srgrimesextern
1711541Srgrimesstruct pglist	vm_page_queue_active;	/* active memory queue */
1721541Srgrimesextern
1731541Srgrimesstruct pglist	vm_page_queue_inactive;	/* inactive memory queue */
1741541Srgrimes
1751541Srgrimesextern
1761541Srgrimesvm_page_t	vm_page_array;		/* First resident page in table */
1771541Srgrimesextern
1781541Srgrimeslong		first_page;		/* first physical page number */
1791541Srgrimes					/* ... represented in vm_page_array */
1801541Srgrimesextern
1811541Srgrimeslong		last_page;		/* last physical page number */
1821541Srgrimes					/* ... represented in vm_page_array */
1831541Srgrimes					/* [INCLUSIVE] */
1841541Srgrimesextern
1851541Srgrimesvm_offset_t	first_phys_addr;	/* physical address for first_page */
1861541Srgrimesextern
1871541Srgrimesvm_offset_t	last_phys_addr;		/* physical address for last_page */
1881541Srgrimes
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
1971541Srgrimesextern
1981541Srgrimessimple_lock_data_t	vm_page_queue_lock;	/* lock on active and inactive
1991541Srgrimes						   page queues */
2001541Srgrimesextern						/* lock on free page queue */
2011541Srgrimessimple_lock_data_t	vm_page_queue_free_lock;
2021541Srgrimes
2031541Srgrimes/*
2041541Srgrimes *	Functions implemented as macros
2051541Srgrimes */
2061541Srgrimes
2071541Srgrimes#define PAGE_ASSERT_WAIT(m, interruptible)	{ \
2081541Srgrimes				(m)->flags |= PG_WANTED; \
2091541Srgrimes				assert_wait((int) (m), (interruptible)); \
2101541Srgrimes			}
2111541Srgrimes
2121541Srgrimes#define PAGE_WAKEUP(m)	{ \
2131541Srgrimes				(m)->flags &= ~PG_BUSY; \
2141541Srgrimes				if ((m)->flags & PG_WANTED) { \
2151541Srgrimes					(m)->flags &= ~PG_WANTED; \
2161549Srgrimes					wakeup((caddr_t) (m)); \
2171541Srgrimes				} \
2181541Srgrimes			}
2191541Srgrimes
2201541Srgrimes#define	vm_page_lock_queues()	simple_lock(&vm_page_queue_lock)
2211541Srgrimes#define	vm_page_unlock_queues()	simple_unlock(&vm_page_queue_lock)
2221541Srgrimes
2231541Srgrimes#define vm_page_set_modified(m)	{ (m)->flags &= ~PG_CLEAN; }
2241541Srgrimes
2251541Srgrimes#define	VM_PAGE_INIT(mem, object, offset) { \
2261541Srgrimes	(mem)->flags = PG_BUSY | PG_CLEAN | PG_FAKE; \
2271541Srgrimes	vm_page_insert((mem), (object), (offset)); \
2281541Srgrimes	(mem)->wire_count = 0; \
2291549Srgrimes	(mem)->hold_count = 0; \
2301549Srgrimes	(mem)->act_count = 0; \
2311541Srgrimes}
2321541Srgrimes
2331541Srgrimesvoid		 vm_page_activate __P((vm_page_t));
2341541Srgrimesvm_page_t	 vm_page_alloc __P((vm_object_t, vm_offset_t));
2351541Srgrimesvoid		 vm_page_copy __P((vm_page_t, vm_page_t));
2361541Srgrimesvoid		 vm_page_deactivate __P((vm_page_t));
2371541Srgrimesvoid		 vm_page_free __P((vm_page_t));
2381541Srgrimesvoid		 vm_page_insert __P((vm_page_t, vm_object_t, vm_offset_t));
2391541Srgrimesvm_page_t	 vm_page_lookup __P((vm_object_t, vm_offset_t));
2401541Srgrimesvoid		 vm_page_remove __P((vm_page_t));
2411541Srgrimesvoid		 vm_page_rename __P((vm_page_t, vm_object_t, vm_offset_t));
2421549Srgrimesvm_offset_t	 vm_page_startup __P((vm_offset_t, vm_offset_t, vm_offset_t));
2431541Srgrimesvoid		 vm_page_unwire __P((vm_page_t));
2441541Srgrimesvoid		 vm_page_wire __P((vm_page_t));
2451541Srgrimesboolean_t	 vm_page_zero_fill __P((vm_page_t));
2461541Srgrimes
2471549Srgrimes
2481549Srgrimes/*
2491549Srgrimes * Keep page from being freed by the page daemon
2501549Srgrimes * much of the same effect as wiring, except much lower
2511549Srgrimes * overhead and should be used only for *very* temporary
2521549Srgrimes * holding ("wiring").
2531549Srgrimes */
2541549Srgrimesstatic inline void
2551549Srgrimesvm_page_hold(mem)
2561549Srgrimes	vm_page_t mem;
2571549Srgrimes{
2581549Srgrimes	mem->hold_count++;
2591549Srgrimes}
2601549Srgrimes
2611549Srgrimesstatic inline void
2621549Srgrimesvm_page_unhold(mem)
2631549Srgrimes	vm_page_t mem;
2641549Srgrimes{
2651549Srgrimes	if( --mem->hold_count < 0)
2661549Srgrimes		panic("vm_page_unhold: hold count < 0!!!");
2671549Srgrimes}
2681549Srgrimes
2691541Srgrimes#endif /* KERNEL */
2701541Srgrimes#endif /* !_VM_PAGE_ */
271