vm_page.h revision 45347
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 *
6445347Sjulian * $Id: vm_page.h,v 1.58 1999/03/15 05:09:48 julian Exp $
651541Srgrimes */
661541Srgrimes
671541Srgrimes/*
681541Srgrimes *	Resident memory system definitions.
691541Srgrimes */
701541Srgrimes
711541Srgrimes#ifndef	_VM_PAGE_
721541Srgrimes#define	_VM_PAGE_
731541Srgrimes
7444754Sjulian#if !defined(KLD_MODULE)
7537282Sjmg#include "opt_vmpage.h"
7644754Sjulian#endif
7737282Sjmg
786816Sdg#include <vm/pmap.h>
7938517Sdfr#include <machine/atomic.h>
8038517Sdfr
811541Srgrimes/*
821541Srgrimes *	Management of resident (logical) pages.
831541Srgrimes *
841541Srgrimes *	A small structure is kept for each resident
851541Srgrimes *	page, indexed by page number.  Each structure
861541Srgrimes *	is an element of several lists:
871541Srgrimes *
881541Srgrimes *		A hash table bucket used to quickly
891541Srgrimes *		perform object/offset lookups
901541Srgrimes *
911541Srgrimes *		A list of all pages for a given object,
921541Srgrimes *		so they can be quickly deactivated at
931541Srgrimes *		time of deallocation.
941541Srgrimes *
951541Srgrimes *		An ordered list of pages due for pageout.
961541Srgrimes *
971541Srgrimes *	In addition, the structure contains the object
981541Srgrimes *	and offset to which this page belongs (for pageout),
991541Srgrimes *	and sundry status bits.
1001541Srgrimes *
1011541Srgrimes *	Fields in this structure are locked either by the lock on the
1021541Srgrimes *	object that the page belongs to (O) or by the lock on the page
1031541Srgrimes *	queues (P).
1041541Srgrimes */
1051541Srgrimes
1061541SrgrimesTAILQ_HEAD(pglist, vm_page);
1071541Srgrimes
1081541Srgrimesstruct vm_page {
1095455Sdg	TAILQ_ENTRY(vm_page) pageq;	/* queue info for FIFO queue or free list (P) */
11042957Sdillon	struct vm_page	*hnext;		/* hash table link (O,P)	*/
11142957Sdillon	TAILQ_ENTRY(vm_page) listq;	/* pages in same object (O) 	*/
1121541Srgrimes
11342957Sdillon	vm_object_t object;		/* which object am I in (O,P)*/
11412767Sdyson	vm_pindex_t pindex;		/* offset into object (O,P) */
1155455Sdg	vm_offset_t phys_addr;		/* physical address of page */
11618169Sdyson	u_short	queue;			/* page queue index */
11718169Sdyson	u_short	flags,			/* see below */
11818169Sdyson		pc;			/* page color */
1195455Sdg	u_short wire_count;		/* wired down maps refs (P) */
1205455Sdg	short hold_count;		/* page hold count */
12113490Sdyson	u_char	act_count;		/* page usage count */
12213490Sdyson	u_char	busy;			/* page busy count */
12313490Sdyson	/* NOTE that these must support one bit per DEV_BSIZE in a page!!! */
12413490Sdyson	/* so, on normal X86 kernels, they must be at least 8 bits wide */
12536735Sdfr#if PAGE_SIZE == 4096
12613490Sdyson	u_char	valid;			/* map of valid DEV_BSIZE chunks */
12713490Sdyson	u_char	dirty;			/* map of dirty DEV_BSIZE chunks */
12836735Sdfr#elif PAGE_SIZE == 8192
12936735Sdfr	u_short	valid;			/* map of valid DEV_BSIZE chunks */
13036735Sdfr	u_short	dirty;			/* map of dirty DEV_BSIZE chunks */
13136735Sdfr#endif
1321541Srgrimes};
1331541Srgrimes
13418169Sdyson/*
13542957Sdillon * note SWAPBLK_NONE is a flag, basically the high bit.
13642957Sdillon */
13742957Sdillon
13842957Sdillon#define SWAPBLK_MASK	((daddr_t)((u_daddr_t)-1 >> 1))		/* mask */
13942957Sdillon#define SWAPBLK_NONE	((daddr_t)((u_daddr_t)SWAPBLK_MASK + 1))/* flag */
14042957Sdillon
14144754Sjulian#if !defined(KLD_MODULE)
14244754Sjulian
14342957Sdillon/*
14418169Sdyson * Page coloring parameters
14518169Sdyson */
14643752Sdillon/* Each of PQ_FREE, and PQ_CACHE have PQ_HASH_SIZE entries */
14718169Sdyson
14818169Sdyson/* Define one of the following */
14936326Sdyson#if defined(PQ_HUGECACHE)
15036326Sdyson#define PQ_PRIME1 31	/* Prime number somewhat less than PQ_HASH_SIZE */
15136326Sdyson#define PQ_PRIME2 23	/* Prime number somewhat less than PQ_HASH_SIZE */
15236326Sdyson#define PQ_PRIME3 17	/* Prime number somewhat less than PQ_HASH_SIZE */
15336326Sdyson#define PQ_L2_SIZE 256	/* A number of colors opt for 1M cache */
15436326Sdyson#endif
15536326Sdyson
15636326Sdyson/* Define one of the following */
15718169Sdyson#if defined(PQ_LARGECACHE)
15818169Sdyson#define PQ_PRIME1 31	/* Prime number somewhat less than PQ_HASH_SIZE */
15918169Sdyson#define PQ_PRIME2 23	/* Prime number somewhat less than PQ_HASH_SIZE */
16018169Sdyson#define PQ_PRIME3 17	/* Prime number somewhat less than PQ_HASH_SIZE */
16118169Sdyson#define PQ_L2_SIZE 128	/* A number of colors opt for 512K cache */
16218169Sdyson#endif
16318169Sdyson
16418169Sdyson
16518169Sdyson/*
16618169Sdyson * Use 'options PQ_NOOPT' to disable page coloring
16718169Sdyson */
16818169Sdyson#if defined(PQ_NOOPT)
16918169Sdyson#define PQ_PRIME1 1
17018169Sdyson#define PQ_PRIME2 1
17118169Sdyson#define PQ_PRIME3 1
17218169Sdyson#define PQ_L2_SIZE 1
17318169Sdyson#endif
17418169Sdyson
17518779Sdyson#if defined(PQ_NORMALCACHE)
17618169Sdyson#define PQ_PRIME1 5	/* Prime number somewhat less than PQ_HASH_SIZE */
17718169Sdyson#define PQ_PRIME2 3	/* Prime number somewhat less than PQ_HASH_SIZE */
17818169Sdyson#define PQ_PRIME3 11	/* Prime number somewhat less than PQ_HASH_SIZE */
17918169Sdyson#define PQ_L2_SIZE 16	/* A reasonable number of colors (opt for 64K cache) */
18018169Sdyson#endif
18118169Sdyson
18218779Sdyson#if defined(PQ_MEDIUMCACHE) || !defined(PQ_L2_SIZE)
18318779Sdyson#define PQ_PRIME1 13	/* Prime number somewhat less than PQ_HASH_SIZE */
18418779Sdyson#define PQ_PRIME2 7	/* Prime number somewhat less than PQ_HASH_SIZE */
18518779Sdyson#define PQ_PRIME3 5	/* Prime number somewhat less than PQ_HASH_SIZE */
18618779Sdyson#define PQ_L2_SIZE 64	/* A number of colors opt for 256K cache */
18718779Sdyson#endif
18818779Sdyson
18918169Sdyson#define PQ_L2_MASK (PQ_L2_SIZE - 1)
19018169Sdyson
19113490Sdyson#define PQ_NONE 0
19213490Sdyson#define PQ_FREE	1
19343752Sdillon/* #define PQ_ZERO (1 + PQ_L2_SIZE) */
19443752Sdillon#define PQ_INACTIVE (1 + 1*PQ_L2_SIZE)
19543752Sdillon#define PQ_ACTIVE (2 + 1*PQ_L2_SIZE)
19643752Sdillon#define PQ_CACHE (3 + 1*PQ_L2_SIZE)
19743752Sdillon#define PQ_COUNT (3 + 2*PQ_L2_SIZE)
19813490Sdyson
19918169Sdysonextern struct vpgqueues {
20018169Sdyson	struct pglist *pl;
20118169Sdyson	int	*cnt;
20218169Sdyson	int	*lcnt;
20318169Sdyson} vm_page_queues[PQ_COUNT];
20418169Sdyson
20544754Sjulian#endif
20644754Sjulian
2071541Srgrimes/*
2081541Srgrimes * These are the flags defined for vm_page.
2091541Srgrimes *
2101541Srgrimes * Note: PG_FILLED and PG_DIRTY are added for the filesystems.
2111541Srgrimes */
21242957Sdillon#define	PG_BUSY		0x0001		/* page is in transit (O) */
21342957Sdillon#define	PG_WANTED	0x0002		/* someone is waiting for page (O) */
21442957Sdillon#define	PG_FICTITIOUS	0x0008		/* physical page doesn't exist (O) */
21542957Sdillon#define	PG_WRITEABLE	0x0010		/* page is mapped writeable */
21642957Sdillon#define PG_MAPPED	0x0020		/* page is mapped */
21742957Sdillon#define	PG_ZERO		0x0040		/* page is zeroed */
21842957Sdillon#define PG_REFERENCED	0x0080		/* page has been referenced */
21942957Sdillon#define PG_CLEANCHK	0x0100		/* page will be checked for cleaning */
22042957Sdillon#define PG_SWAPINPROG	0x0200		/* swap I/O in progress on page	     */
2211541Srgrimes
2229507Sdg/*
2239507Sdg * Misc constants.
2249507Sdg */
2251541Srgrimes
2269507Sdg#define ACT_DECLINE		1
2279507Sdg#define ACT_ADVANCE		3
22816750Sdyson#define ACT_INIT		5
22918169Sdyson#define ACT_MAX			64
2309507Sdg#define PFCLUSTER_BEHIND	3
2319507Sdg#define PFCLUSTER_AHEAD		3
2329507Sdg
2331541Srgrimes#ifdef KERNEL
2341541Srgrimes/*
2359507Sdg * Each pageable resident page falls into one of four lists:
2361541Srgrimes *
2375455Sdg *	free
2381541Srgrimes *		Available for allocation now.
2399507Sdg *
2409507Sdg * The following are all LRU sorted:
2419507Sdg *
2429507Sdg *	cache
2439507Sdg *		Almost available for allocation. Still in an
2449507Sdg *		object, but clean and immediately freeable at
2459507Sdg *		non-interrupt times.
2469507Sdg *
2471541Srgrimes *	inactive
24813765Smpp *		Low activity, candidates for reclamation.
2491541Srgrimes *		This is the list of pages that should be
2501541Srgrimes *		paged out next.
2519507Sdg *
2521541Srgrimes *	active
2539507Sdg *		Pages that are "active" i.e. they have been
2549507Sdg *		recently referenced.
25510544Sdyson *
25610544Sdyson *	zero
25710544Sdyson *		Pages that are really free and have been pre-zeroed
25810544Sdyson *
2591541Srgrimes */
2601541Srgrimes
26144754Sjulian#if !defined(KLD_MODULE)
26244754Sjulian
26318169Sdysonextern struct pglist vm_page_queue_free[PQ_L2_SIZE];/* memory free queue */
2645455Sdgextern struct pglist vm_page_queue_active;	/* active memory queue */
2655455Sdgextern struct pglist vm_page_queue_inactive;	/* inactive memory queue */
26618169Sdysonextern struct pglist vm_page_queue_cache[PQ_L2_SIZE];/* cache memory queue */
2671541Srgrimes
26844754Sjulian#endif
26944754Sjulian
27012767Sdysonextern int vm_page_zero_count;
27112767Sdyson
2725455Sdgextern vm_page_t vm_page_array;		/* First resident page in table */
2735455Sdgextern long first_page;			/* first physical page number */
2741541Srgrimes
2755455Sdg /* ... represented in vm_page_array */
2765455Sdgextern long last_page;			/* last physical page number */
2775455Sdg
2785455Sdg /* ... represented in vm_page_array */
2795455Sdg /* [INCLUSIVE] */
2805455Sdgextern vm_offset_t first_phys_addr;	/* physical address for first_page */
2815455Sdgextern vm_offset_t last_phys_addr;	/* physical address for last_page */
2825455Sdg
2831541Srgrimes#define VM_PAGE_TO_PHYS(entry)	((entry)->phys_addr)
2841541Srgrimes
2851541Srgrimes#define IS_VM_PHYSADDR(pa) \
2861541Srgrimes		((pa) >= first_phys_addr && (pa) <= last_phys_addr)
2871541Srgrimes
2881541Srgrimes#define PHYS_TO_VM_PAGE(pa) \
2891541Srgrimes		(&vm_page_array[atop(pa) - first_page ])
2901541Srgrimes
2911541Srgrimes/*
2921541Srgrimes *	Functions implemented as macros
2931541Srgrimes */
2941541Srgrimes
29538799Sdfrstatic __inline void
29638799Sdfrvm_page_flag_set(vm_page_t m, unsigned int bits)
29738799Sdfr{
29838799Sdfr	atomic_set_short(&(m)->flags, bits);
29938799Sdfr}
30038517Sdfr
30138799Sdfrstatic __inline void
30238799Sdfrvm_page_flag_clear(vm_page_t m, unsigned int bits)
30338799Sdfr{
30438799Sdfr	atomic_clear_short(&(m)->flags, bits);
30538799Sdfr}
30638517Sdfr
30738799Sdfr#if 0
30838799Sdfrstatic __inline void
30938799Sdfrvm_page_assert_wait(vm_page_t m, int interruptible)
31038799Sdfr{
31138799Sdfr	vm_page_flag_set(m, PG_WANTED);
31238799Sdfr	assert_wait((int) m, interruptible);
31333936Sdyson}
31438799Sdfr#endif
3151541Srgrimes
31638799Sdfrstatic __inline void
31738799Sdfrvm_page_busy(vm_page_t m)
31838799Sdfr{
31943122Sdillon	KASSERT((m->flags & PG_BUSY) == 0, ("vm_page_busy: page already busy!!!"));
32038799Sdfr	vm_page_flag_set(m, PG_BUSY);
32133936Sdyson}
3221541Srgrimes
32342957Sdillon/*
32442957Sdillon *	vm_page_flash:
32542957Sdillon *
32642957Sdillon *	wakeup anyone waiting for the page.
32742957Sdillon */
32842957Sdillon
32938799Sdfrstatic __inline void
33042957Sdillonvm_page_flash(vm_page_t m)
33138799Sdfr{
33238799Sdfr	if (m->flags & PG_WANTED) {
33338799Sdfr		vm_page_flag_clear(m, PG_WANTED);
33438799Sdfr		wakeup(m);
33538799Sdfr	}
33638799Sdfr}
33738517Sdfr
33842957Sdillon/*
33942957Sdillon *	vm_page_wakeup:
34042957Sdillon *
34142957Sdillon *	clear the PG_BUSY flag and wakeup anyone waiting for the
34242957Sdillon *	page.
34342957Sdillon *
34442957Sdillon */
34542957Sdillon
34638799Sdfrstatic __inline void
34742957Sdillonvm_page_wakeup(vm_page_t m)
34842957Sdillon{
34943122Sdillon	KASSERT(m->flags & PG_BUSY, ("vm_page_wakeup: page not busy!!!"));
35042957Sdillon	vm_page_flag_clear(m, PG_BUSY);
35142957Sdillon	vm_page_flash(m);
35242957Sdillon}
35342957Sdillon
35443134Sdillon/*
35543134Sdillon *
35643134Sdillon *
35743134Sdillon */
35843134Sdillon
35942957Sdillonstatic __inline void
36038799Sdfrvm_page_io_start(vm_page_t m)
36138799Sdfr{
36238799Sdfr	atomic_add_char(&(m)->busy, 1);
36334206Sdyson}
36434206Sdyson
36538799Sdfrstatic __inline void
36638799Sdfrvm_page_io_finish(vm_page_t m)
36738799Sdfr{
36838799Sdfr	atomic_subtract_char(&m->busy, 1);
36942957Sdillon	if (m->busy == 0)
37042957Sdillon		vm_page_flash(m);
37138799Sdfr}
37234206Sdyson
37338799Sdfr
3745455Sdg#if PAGE_SIZE == 4096
3755455Sdg#define VM_PAGE_BITS_ALL 0xff
3765455Sdg#endif
3771541Srgrimes
3785455Sdg#if PAGE_SIZE == 8192
3795455Sdg#define VM_PAGE_BITS_ALL 0xffff
3805455Sdg#endif
3811549Srgrimes
38233109Sdyson#define VM_ALLOC_NORMAL		0
38333109Sdyson#define VM_ALLOC_INTERRUPT	1
38433109Sdyson#define VM_ALLOC_SYSTEM		2
38533109Sdyson#define	VM_ALLOC_ZERO		3
38633109Sdyson#define	VM_ALLOC_RETRY		0x80
3875455Sdg
3885455Sdgvoid vm_page_activate __P((vm_page_t));
38912767Sdysonvm_page_t vm_page_alloc __P((vm_object_t, vm_pindex_t, int));
39033109Sdysonvm_page_t vm_page_grab __P((vm_object_t, vm_pindex_t, int));
3916357Sphkvoid vm_page_cache __P((register vm_page_t));
39215811Sdysonstatic __inline void vm_page_copy __P((vm_page_t, vm_page_t));
39342957Sdillonstatic __inline void vm_page_free __P((vm_page_t));
39442957Sdillonstatic __inline void vm_page_free_zero __P((vm_page_t));
39542957Sdillonvoid vm_page_destroy __P((vm_page_t));
3965455Sdgvoid vm_page_deactivate __P((vm_page_t));
39712767Sdysonvoid vm_page_insert __P((vm_page_t, vm_object_t, vm_pindex_t));
39812767Sdysonvm_page_t vm_page_lookup __P((vm_object_t, vm_pindex_t));
39944051Sdillonvoid vm_page_remove __P((vm_page_t));
40012767Sdysonvoid vm_page_rename __P((vm_page_t, vm_object_t, vm_pindex_t));
4015455Sdgvm_offset_t vm_page_startup __P((vm_offset_t, vm_offset_t, vm_offset_t));
40240700Sdgvoid vm_page_unwire __P((vm_page_t, int));
4035455Sdgvoid vm_page_wire __P((vm_page_t));
40417334Sdysonvoid vm_page_unqueue __P((vm_page_t));
40517334Sdysonvoid vm_page_unqueue_nowakeup __P((vm_page_t));
40610544Sdysonvoid vm_page_set_validclean __P((vm_page_t, int, int));
4075455Sdgvoid vm_page_set_invalid __P((vm_page_t, int, int));
40815811Sdysonstatic __inline boolean_t vm_page_zero_fill __P((vm_page_t));
4095455Sdgint vm_page_is_valid __P((vm_page_t, int, int));
4105455Sdgvoid vm_page_test_dirty __P((vm_page_t));
4116357Sphkint vm_page_bits __P((int, int));
41243747Sdillonvm_page_t _vm_page_list_find __P((int, int));
41318169Sdysonint vm_page_queue_index __P((vm_offset_t, int));
41442957Sdillon#if 0
41533936Sdysonint vm_page_sleep(vm_page_t m, char *msg, char *busy);
41642957Sdillonint vm_page_asleep(vm_page_t m, char *msg, char *busy);
41742957Sdillon#endif
41845347Sjulianvoid vm_page_zero_invalid(vm_page_t m, boolean_t setvalid);
41943752Sdillonvoid vm_page_free_toq(vm_page_t m);
4205455Sdg
4211549Srgrimes/*
4221549Srgrimes * Keep page from being freed by the page daemon
4231549Srgrimes * much of the same effect as wiring, except much lower
4241549Srgrimes * overhead and should be used only for *very* temporary
4251549Srgrimes * holding ("wiring").
4261549Srgrimes */
4278010Sbdestatic __inline void
4284461Sbdevm_page_hold(vm_page_t mem)
4291549Srgrimes{
4301549Srgrimes	mem->hold_count++;
4311549Srgrimes}
4321549Srgrimes
4338010Sbdestatic __inline void
4344461Sbdevm_page_unhold(vm_page_t mem)
4351549Srgrimes{
4363660Sdg	--mem->hold_count;
43742408Seivind	KASSERT(mem->hold_count >= 0, ("vm_page_unhold: hold count < 0!!!"));
4381549Srgrimes}
4391549Srgrimes
44043122Sdillon/*
44143122Sdillon * 	vm_page_protect:
44243122Sdillon *
44343122Sdillon *	Reduce the protection of a page.  This routine never
44443122Sdillon *	raises the protection and therefore can be safely
44543122Sdillon *	called if the page is already at VM_PROT_NONE ( it
44643122Sdillon *	will be a NOP effectively ).
44743122Sdillon */
44843122Sdillon
4498010Sbdestatic __inline void
4506816Sdgvm_page_protect(vm_page_t mem, int prot)
4516816Sdg{
4526816Sdg	if (prot == VM_PROT_NONE) {
4536816Sdg		if (mem->flags & (PG_WRITEABLE|PG_MAPPED)) {
45434206Sdyson			pmap_page_protect(VM_PAGE_TO_PHYS(mem), VM_PROT_NONE);
45538799Sdfr			vm_page_flag_clear(mem, PG_WRITEABLE|PG_MAPPED);
4566816Sdg		}
4576816Sdg	} else if ((prot == VM_PROT_READ) && (mem->flags & PG_WRITEABLE)) {
45834206Sdyson		pmap_page_protect(VM_PAGE_TO_PHYS(mem), VM_PROT_READ);
45938799Sdfr		vm_page_flag_clear(mem, PG_WRITEABLE);
4606816Sdg	}
4616816Sdg}
4626816Sdg
46315811Sdyson/*
46415811Sdyson *	vm_page_zero_fill:
46515811Sdyson *
46615811Sdyson *	Zero-fill the specified page.
46715811Sdyson *	Written as a standard pagein routine, to
46815811Sdyson *	be used by the zero-fill object.
46915811Sdyson */
47015811Sdysonstatic __inline boolean_t
47115811Sdysonvm_page_zero_fill(m)
47215811Sdyson	vm_page_t m;
47315811Sdyson{
47415811Sdyson	pmap_zero_page(VM_PAGE_TO_PHYS(m));
47515811Sdyson	return (TRUE);
47615811Sdyson}
4776816Sdg
47815811Sdyson/*
47915811Sdyson *	vm_page_copy:
48015811Sdyson *
48115811Sdyson *	Copy one page to another
48215811Sdyson */
48315811Sdysonstatic __inline void
48415811Sdysonvm_page_copy(src_m, dest_m)
48515811Sdyson	vm_page_t src_m;
48615811Sdyson	vm_page_t dest_m;
48715811Sdyson{
48815811Sdyson	pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m));
48915811Sdyson	dest_m->valid = VM_PAGE_BITS_ALL;
49015811Sdyson}
49115811Sdyson
49242957Sdillon/*
49342957Sdillon *	vm_page_free:
49442957Sdillon *
49542957Sdillon *	Free a page
49643752Sdillon *
49743752Sdillon *	The clearing of PG_ZERO is a temporary safety until the code can be
49843752Sdillon *	reviewed to determine that PG_ZERO is being properly cleared on
49943752Sdillon *	write faults or maps.  PG_ZERO was previously cleared in
50043752Sdillon *	vm_page_alloc().
50142957Sdillon */
50242957Sdillonstatic __inline void
50342957Sdillonvm_page_free(m)
50442957Sdillon	vm_page_t m;
50542957Sdillon{
50643752Sdillon	vm_page_flag_clear(m, PG_ZERO);
50743752Sdillon	vm_page_free_toq(m);
50842957Sdillon}
50942957Sdillon
51042957Sdillon/*
51142957Sdillon *	vm_page_free_zero:
51242957Sdillon *
51342957Sdillon *	Free a page to the zerod-pages queue
51442957Sdillon */
51542957Sdillonstatic __inline void
51642957Sdillonvm_page_free_zero(m)
51742957Sdillon	vm_page_t m;
51842957Sdillon{
51943752Sdillon	vm_page_flag_set(m, PG_ZERO);
52043752Sdillon	vm_page_free_toq(m);
52142957Sdillon}
52242957Sdillon
52342957Sdillon/*
52442957Sdillon *	vm_page_sleep_busy:
52542957Sdillon *
52642957Sdillon *	Wait until page is no longer PG_BUSY or (if also_m_busy is TRUE)
52742957Sdillon *	m->busy is zero.  Returns TRUE if it had to sleep ( including if
52842957Sdillon *	it almost had to sleep and made temporary spl*() mods), FALSE
52942957Sdillon *	otherwise.
53042957Sdillon *
53142957Sdillon *	This routine assumes that interrupts can only remove the busy
53242957Sdillon *	status from a page, not set the busy status or change it from
53342957Sdillon *	PG_BUSY to m->busy or vise versa (which would create a timing
53442957Sdillon *	window).
53542957Sdillon *
53642957Sdillon *	Note that being an inline, this code will be well optimized.
53742957Sdillon */
53842957Sdillon
53942957Sdillonstatic __inline int
54042957Sdillonvm_page_sleep_busy(vm_page_t m, int also_m_busy, const char *msg)
54142957Sdillon{
54242957Sdillon	if ((m->flags & PG_BUSY) || (also_m_busy && m->busy))  {
54342957Sdillon		int s = splvm();
54442957Sdillon		if ((m->flags & PG_BUSY) || (also_m_busy && m->busy)) {
54542957Sdillon			/*
54642957Sdillon			 * Page is busy. Wait and retry.
54742957Sdillon			 */
54842957Sdillon			vm_page_flag_set(m, PG_WANTED | PG_REFERENCED);
54942957Sdillon			tsleep(m, PVM, msg, 0);
55042957Sdillon		}
55142957Sdillon		splx(s);
55242957Sdillon		return(TRUE);
55342957Sdillon		/* not reached */
55442957Sdillon	}
55542957Sdillon	return(FALSE);
55642957Sdillon}
55742957Sdillon
55844771Sjulian#if !defined(KLD_MODULE)
55944771Sjulian
56043134Sdillon/*
56143134Sdillon *	vm_page_dirty:
56243134Sdillon *
56343134Sdillon *	make page all dirty
56443134Sdillon */
56543134Sdillon
56643134Sdillonstatic __inline void
56743134Sdillonvm_page_dirty(vm_page_t m)
56843134Sdillon{
56943134Sdillon	KASSERT(m->queue - m->pc != PQ_CACHE, ("vm_page_dirty: page in cache!"));
57043134Sdillon	m->dirty = VM_PAGE_BITS_ALL;
57143134Sdillon}
57243134Sdillon
57343747Sdillonstatic __inline vm_page_t
57443752Sdillonvm_page_list_find(int basequeue, int index, boolean_t prefer_zero)
57543747Sdillon{
57643747Sdillon	vm_page_t m;
57743134Sdillon
57843747Sdillon#if PQ_L2_SIZE > 1
57943752Sdillon	if (prefer_zero) {
58043752Sdillon		m = TAILQ_LAST(vm_page_queues[basequeue+index].pl, pglist);
58143752Sdillon	} else {
58243752Sdillon		m = TAILQ_FIRST(vm_page_queues[basequeue+index].pl);
58343752Sdillon	}
58443747Sdillon	if (m == NULL)
58543747Sdillon		m = _vm_page_list_find(basequeue, index);
58643747Sdillon#else
58743752Sdillon	if (prefer_zero) {
58843752Sdillon		m = TAILQ_LAST(vm_page_queues[basequeue].pl, pglist);
58943752Sdillon	} else {
59043752Sdillon		m = TAILQ_FIRST(vm_page_queues[basequeue].pl);
59143752Sdillon	}
59243747Sdillon#endif
59343747Sdillon	return(m);
59443747Sdillon}
59543747Sdillon
59644754Sjulian#endif
59744754Sjulian
5985455Sdg#endif				/* KERNEL */
5995455Sdg#endif				/* !_VM_PAGE_ */
600