xref: /original-bsd/sys/vm/vm_page.h (revision 358f5c7d)
1 /*
2  * Copyright (c) 1991 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * The Mach Operating System project at Carnegie-Mellon University.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)vm_page.h	7.7 (Berkeley) 05/04/92
11  *
12  *
13  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
14  * All rights reserved.
15  *
16  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
17  *
18  * Permission to use, copy, modify and distribute this software and
19  * its documentation is hereby granted, provided that both the copyright
20  * notice and this permission notice appear in all copies of the
21  * software, derivative works or modified versions, and any portions
22  * thereof, and that both notices appear in supporting documentation.
23  *
24  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
25  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
26  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
27  *
28  * Carnegie Mellon requests users of this software to return to
29  *
30  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
31  *  School of Computer Science
32  *  Carnegie Mellon University
33  *  Pittsburgh PA 15213-3890
34  *
35  * any improvements or extensions that they make and grant Carnegie the
36  * rights to redistribute these changes.
37  */
38 
39 /*
40  *	Resident memory system definitions.
41  */
42 
43 #ifndef	_VM_PAGE_
44 #define	_VM_PAGE_
45 
46 /*
47  *	Management of resident (logical) pages.
48  *
49  *	A small structure is kept for each resident
50  *	page, indexed by page number.  Each structure
51  *	is an element of several lists:
52  *
53  *		A hash table bucket used to quickly
54  *		perform object/offset lookups
55  *
56  *		A list of all pages for a given object,
57  *		so they can be quickly deactivated at
58  *		time of deallocation.
59  *
60  *		An ordered list of pages due for pageout.
61  *
62  *	In addition, the structure contains the object
63  *	and offset to which this page belongs (for pageout),
64  *	and sundry status bits.
65  *
66  *	Fields in this structure are locked either by the lock on the
67  *	object that the page belongs to (O) or by the lock on the page
68  *	queues (P).
69  */
70 
71 struct vm_page {
72 	queue_chain_t	pageq;		/* queue info for FIFO
73 					 * queue or free list (P) */
74 	queue_chain_t	hashq;		/* hash table links (O)*/
75 	queue_chain_t	listq;		/* all pages in same object (O)*/
76 
77 	vm_object_t	object;		/* which object am I in (O,P)*/
78 	vm_offset_t	offset;		/* offset into that object (O,P) */
79 
80 	unsigned int	wire_count:16,	/* how many wired down maps use me?
81 					   (P) */
82 	/* boolean_t */	inactive:1,	/* page is in inactive list (P) */
83 			active:1,	/* page is in active list (P) */
84 			laundry:1,	/* page is being cleaned now (P)*/
85 #ifdef DEBUG
86 			pagerowned:1,	/* async paging op in progress */
87 			ptpage:1,	/* is a user page table page */
88 #endif
89 			:0;		/* (force to 'long' boundary) */
90 #ifdef	ns32000
91 	int		pad;		/* extra space for ns32000 bit ops */
92 #endif	ns32000
93 	boolean_t	clean;		/* page has not been modified */
94 	unsigned int
95 	/* boolean_t */	busy:1,		/* page is in transit (O) */
96 			wanted:1,	/* someone is waiting for page (O) */
97 			tabled:1,	/* page is in VP table (O) */
98 			copy_on_write:1,/* page must be copied before being
99 					   changed (O) */
100 			fictitious:1,	/* physical page doesn't exist (O) */
101 			absent:1,	/* virtual page doesn't exist (O) */
102 			fake:1,		/* page is a placeholder for page-in
103 					   (O) */
104 			:0;
105 
106 	vm_offset_t	phys_addr;	/* physical address of page */
107 	vm_prot_t	page_lock;	/* Uses prohibited by data manager */
108 	vm_prot_t	unlock_request;	/* Outstanding unlock request */
109 };
110 
111 #if	VM_PAGE_DEBUG
112 #define	VM_PAGE_CHECK(mem) { \
113 		if ( (((unsigned int) mem) < ((unsigned int) &vm_page_array[0])) || \
114 		     (((unsigned int) mem) > ((unsigned int) &vm_page_array[last_page-first_page])) || \
115 		     (mem->active && mem->inactive) \
116 		    ) panic("vm_page_check: not valid!"); \
117 		}
118 #else	VM_PAGE_DEBUG
119 #define	VM_PAGE_CHECK(mem)
120 #endif	VM_PAGE_DEBUG
121 
122 #ifdef KERNEL
123 /*
124  *	Each pageable resident page falls into one of three lists:
125  *
126  *	free
127  *		Available for allocation now.
128  *	inactive
129  *		Not referenced in any map, but still has an
130  *		object/offset-page mapping, and may be dirty.
131  *		This is the list of pages that should be
132  *		paged out next.
133  *	active
134  *		A list of pages which have been placed in
135  *		at least one physical map.  This list is
136  *		ordered, in LRU-like fashion.
137  */
138 
139 extern
140 queue_head_t	vm_page_queue_free;	/* memory free queue */
141 extern
142 queue_head_t	vm_page_queue_active;	/* active memory queue */
143 extern
144 queue_head_t	vm_page_queue_inactive;	/* inactive memory queue */
145 
146 extern
147 vm_page_t	vm_page_array;		/* First resident page in table */
148 extern
149 long		first_page;		/* first physical page number */
150 					/* ... represented in vm_page_array */
151 extern
152 long		last_page;		/* last physical page number */
153 					/* ... represented in vm_page_array */
154 					/* [INCLUSIVE] */
155 extern
156 vm_offset_t	first_phys_addr;	/* physical address for first_page */
157 extern
158 vm_offset_t	last_phys_addr;		/* physical address for last_page */
159 
160 #define VM_PAGE_TO_PHYS(entry)	((entry)->phys_addr)
161 
162 #define IS_VM_PHYSADDR(pa) \
163 		((pa) >= first_phys_addr && (pa) <= last_phys_addr)
164 
165 #define PHYS_TO_VM_PAGE(pa) \
166 		(&vm_page_array[atop(pa) - first_page ])
167 
168 extern
169 simple_lock_data_t	vm_page_queue_lock;	/* lock on active and inactive
170 						   page queues */
171 extern						/* lock on free page queue */
172 simple_lock_data_t	vm_page_queue_free_lock;
173 
174 /*
175  *	Functions implemented as macros
176  */
177 
178 #define PAGE_ASSERT_WAIT(m, interruptible)	{ \
179 				(m)->wanted = TRUE; \
180 				assert_wait((int) (m), (interruptible)); \
181 			}
182 
183 #define PAGE_WAKEUP(m)	{ \
184 				(m)->busy = FALSE; \
185 				if ((m)->wanted) { \
186 					(m)->wanted = FALSE; \
187 					thread_wakeup((int) (m)); \
188 				} \
189 			}
190 
191 #define	vm_page_lock_queues()	simple_lock(&vm_page_queue_lock)
192 #define	vm_page_unlock_queues()	simple_unlock(&vm_page_queue_lock)
193 
194 #define vm_page_set_modified(m)	{ (m)->clean = FALSE; }
195 
196 #ifdef DEBUG
197 #define	VM_PAGE_DEBUG_INIT(m) ((m)->pagerowned = 0, (m)->ptpage = 0)
198 #else
199 #define	VM_PAGE_DEBUG_INIT(m)
200 #endif
201 
202 #define	VM_PAGE_INIT(mem, object, offset) { \
203 	(mem)->busy = TRUE; \
204 	(mem)->tabled = FALSE; \
205 	vm_page_insert((mem), (object), (offset)); \
206 	(mem)->absent = FALSE; \
207 	(mem)->fictitious = FALSE; \
208 	(mem)->page_lock = VM_PROT_NONE; \
209 	(mem)->unlock_request = VM_PROT_NONE; \
210 	(mem)->laundry = FALSE; \
211 	(mem)->active = FALSE; \
212 	(mem)->inactive = FALSE; \
213 	(mem)->wire_count = 0; \
214 	(mem)->clean = TRUE; \
215 	(mem)->copy_on_write = FALSE; \
216 	(mem)->fake = TRUE; \
217 	VM_PAGE_DEBUG_INIT(mem); \
218 }
219 
220 void		 vm_page_activate __P((vm_page_t));
221 vm_page_t	 vm_page_alloc __P((vm_object_t, vm_offset_t));
222 void		 vm_page_copy __P((vm_page_t, vm_page_t));
223 void		 vm_page_deactivate __P((vm_page_t));
224 void		 vm_page_free __P((vm_page_t));
225 void		 vm_page_insert __P((vm_page_t, vm_object_t, vm_offset_t));
226 vm_page_t	 vm_page_lookup __P((vm_object_t, vm_offset_t));
227 void		 vm_page_remove __P((vm_page_t));
228 void		 vm_page_rename __P((vm_page_t, vm_object_t, vm_offset_t));
229 void		 vm_page_startup __P((vm_offset_t *, vm_offset_t *));
230 void		 vm_page_unwire __P((vm_page_t));
231 void		 vm_page_wire __P((vm_page_t));
232 boolean_t	 vm_page_zero_fill __P((vm_page_t));
233 
234 #endif /* KERNEL */
235 #endif /* !_VM_PAGE_ */
236