|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1993-1988 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * File: vm/vm_page.h
28: * Author: Avadis Tevanian, Jr., Michael Wayne Young
29: * Date: 1985
30: *
31: * Resident memory system definitions.
32: */
33:
34: #ifndef _VM_VM_PAGE_H_
35: #define _VM_VM_PAGE_H_
36:
37: #include <mach/boolean.h>
38: #include <mach/vm_prot.h>
1.1.1.6 root 39: #include <machine/vm_param.h>
1.1 root 40: #include <vm/vm_object.h>
1.1.1.3 root 41: #include <vm/vm_types.h>
1.1 root 42: #include <kern/queue.h>
1.1.1.7 ! root 43: #include <kern/list.h>
1.1 root 44: #include <kern/lock.h>
1.1.1.6 root 45: #include <kern/log2.h>
1.1 root 46:
1.1.1.5 root 47: #include <kern/macros.h>
1.1 root 48: #include <kern/sched_prim.h> /* definitions of wait/wakeup */
49:
50: #if MACH_VM_DEBUG
51: #include <mach_debug/hash_info.h>
52: #endif
53:
54: /*
55: * Management of resident (logical) pages.
56: *
57: * A small structure is kept for each resident
58: * page, indexed by page number. Each structure
59: * is an element of several lists:
60: *
61: * A hash table bucket used to quickly
62: * perform object/offset lookups
63: *
64: * A list of all pages for a given object,
65: * so they can be quickly deactivated at
66: * time of deallocation.
67: *
68: * An ordered list of pages due for pageout.
69: *
70: * In addition, the structure contains the object
71: * and offset to which this page belongs (for pageout),
72: * and sundry status bits.
73: *
74: * Fields in this structure are locked either by the lock on the
75: * object that the page belongs to (O) or by the lock on the page
76: * queues (P). [Some fields require that both locks be held to
77: * change that field; holding either lock is sufficient to read.]
78: */
79:
80: struct vm_page {
1.1.1.7 ! root 81: struct list node; /* page queues or free list (P) */
1.1.1.6 root 82: unsigned short type;
83: unsigned short seg_index;
84: unsigned short order;
85: void *priv;
86:
87: /*
88: * This member is used throughout the code and may only change for
89: * fictitious pages.
90: */
91: phys_addr_t phys_addr;
92:
1.1.1.7 ! root 93: queue_chain_t listq; /* all pages in same object (O) */
! 94: struct vm_page *next; /* VP bucket link (O) */
! 95:
1.1.1.6 root 96: /* We use an empty struct as the delimiter. */
97: struct {} vm_page_header;
98: #define VM_PAGE_HEADER_SIZE offsetof(struct vm_page, vm_page_header)
99:
1.1 root 100: vm_object_t object; /* which object am I in (O,P) */
101: vm_offset_t offset; /* offset into that object (O,P) */
102:
1.1.1.4 root 103: unsigned int wire_count:15, /* how many wired down maps use me?
1.1 root 104: (O&P) */
105: /* boolean_t */ inactive:1, /* page is in inactive list (P) */
106: active:1, /* page is in active list (P) */
107: laundry:1, /* page is being cleaned now (P)*/
1.1.1.7 ! root 108: external_laundry:1, /* same as laundry for external pagers (P)*/
1.1 root 109: free:1, /* page is on free list (P) */
110: reference:1, /* page has been used (P) */
1.1.1.7 ! root 111: external:1, /* page in external object (P) */
1.1.1.4 root 112: busy:1, /* page is in transit (O) */
1.1 root 113: wanted:1, /* someone is waiting for page (O) */
114: tabled:1, /* page is in VP table (O) */
115: fictitious:1, /* Physical page doesn't exist (O) */
116: private:1, /* Page should not be returned to
117: * the free list (O) */
118: absent:1, /* Data has been requested, but is
119: * not yet available (O) */
120: error:1, /* Data manager was unable to provide
121: * data due to error (O) */
122: dirty:1, /* Page must be cleaned (O) */
123: precious:1, /* Page is precious; data must be
124: * returned even if clean (O) */
1.1.1.4 root 125: overwriting:1; /* Request to unlock has been made
1.1 root 126: * without having data. (O)
127: * [See vm_object_overwrite] */
128:
129: vm_prot_t page_lock; /* Uses prohibited by data manager (O) */
130: vm_prot_t unlock_request; /* Outstanding unlock request (O) */
131: };
132:
133: /*
134: * For debugging, this macro can be defined to perform
135: * some useful check on a page structure.
136: */
137:
1.1.1.7 ! root 138: #define VM_PAGE_CHECK(mem) vm_page_check(mem)
! 139:
! 140: void vm_page_check(const struct vm_page *page);
1.1 root 141:
142: /*
143: * Each pageable resident page falls into one of three lists:
144: *
145: * free
146: * Available for allocation now.
147: * inactive
148: * Not referenced in any map, but still has an
149: * object/offset-page mapping, and may be dirty.
150: * This is the list of pages that should be
151: * paged out next.
152: * active
153: * A list of pages which have been placed in
154: * at least one physical map. This list is
155: * ordered, in LRU-like fashion.
156: */
157:
158: extern
159: int vm_page_fictitious_count;/* How many fictitious pages are free? */
160: extern
161: int vm_page_active_count; /* How many pages are active? */
162: extern
163: int vm_page_inactive_count; /* How many pages are inactive? */
164: extern
165: int vm_page_wire_count; /* How many pages are wired? */
166: extern
167: int vm_page_laundry_count; /* How many pages being laundered? */
1.1.1.2 root 168: extern
1.1.1.7 ! root 169: int vm_page_external_laundry_count; /* How many external pages being paged out? */
1.1 root 170:
171: decl_simple_lock_data(extern,vm_page_queue_lock)/* lock on active and inactive
172: page queues */
173: decl_simple_lock_data(extern,vm_page_queue_free_lock)
174: /* lock on free page queue */
175:
1.1.1.7 ! root 176: extern phys_addr_t vm_page_fictitious_addr;
1.1 root 177: /* (fake) phys_addr of fictitious pages */
178:
179: extern void vm_page_bootstrap(
180: vm_offset_t *startp,
181: vm_offset_t *endp);
182: extern void vm_page_module_init(void);
183:
184: extern vm_page_t vm_page_lookup(
185: vm_object_t object,
186: vm_offset_t offset);
187: extern vm_page_t vm_page_grab_fictitious(void);
1.1.1.7 ! root 188: extern boolean_t vm_page_convert(vm_page_t *);
1.1 root 189: extern void vm_page_more_fictitious(void);
1.1.1.7 ! root 190: extern vm_page_t vm_page_grab(void);
! 191: extern void vm_page_release(vm_page_t, boolean_t, boolean_t);
! 192: extern phys_addr_t vm_page_grab_phys_addr(void);
1.1.1.6 root 193: extern vm_page_t vm_page_grab_contig(vm_size_t, unsigned int);
194: extern void vm_page_free_contig(vm_page_t, vm_size_t);
1.1 root 195: extern void vm_page_wait(void (*)(void));
196: extern vm_page_t vm_page_alloc(
197: vm_object_t object,
198: vm_offset_t offset);
199: extern void vm_page_init(
1.1.1.6 root 200: vm_page_t mem);
1.1 root 201: extern void vm_page_free(vm_page_t);
202: extern void vm_page_activate(vm_page_t);
203: extern void vm_page_deactivate(vm_page_t);
204: extern void vm_page_rename(
205: vm_page_t mem,
206: vm_object_t new_object,
207: vm_offset_t new_offset);
208: extern void vm_page_insert(
209: vm_page_t mem,
210: vm_object_t object,
211: vm_offset_t offset);
212: extern void vm_page_remove(
213: vm_page_t mem);
214:
215: extern void vm_page_zero_fill(vm_page_t);
216: extern void vm_page_copy(vm_page_t src_m, vm_page_t dest_m);
217:
218: extern void vm_page_wire(vm_page_t);
219: extern void vm_page_unwire(vm_page_t);
220:
221: #if MACH_VM_DEBUG
222: extern unsigned int vm_page_info(
223: hash_info_bucket_t *info,
224: unsigned int count);
225: #endif
226:
227: /*
228: * Functions implemented as macros
229: */
230:
231: #define PAGE_ASSERT_WAIT(m, interruptible) \
232: MACRO_BEGIN \
233: (m)->wanted = TRUE; \
234: assert_wait((event_t) (m), (interruptible)); \
235: MACRO_END
236:
237: #define PAGE_WAKEUP_DONE(m) \
238: MACRO_BEGIN \
239: (m)->busy = FALSE; \
240: if ((m)->wanted) { \
241: (m)->wanted = FALSE; \
242: thread_wakeup(((event_t) m)); \
243: } \
244: MACRO_END
245:
246: #define PAGE_WAKEUP(m) \
247: MACRO_BEGIN \
248: if ((m)->wanted) { \
249: (m)->wanted = FALSE; \
250: thread_wakeup((event_t) (m)); \
251: } \
252: MACRO_END
253:
254: #define VM_PAGE_FREE(p) \
255: MACRO_BEGIN \
256: vm_page_lock_queues(); \
257: vm_page_free(p); \
258: vm_page_unlock_queues(); \
259: MACRO_END
260:
261: /*
262: * Macro to be used in place of pmap_enter()
263: */
264:
265: #define PMAP_ENTER(pmap, virtual_address, page, protection, wired) \
266: MACRO_BEGIN \
267: pmap_enter( \
268: (pmap), \
269: (virtual_address), \
270: (page)->phys_addr, \
271: (protection) & ~(page)->page_lock, \
272: (wired) \
273: ); \
274: MACRO_END
275:
276: #define VM_PAGE_WAIT(continuation) vm_page_wait(continuation)
277:
278: #define vm_page_lock_queues() simple_lock(&vm_page_queue_lock)
279: #define vm_page_unlock_queues() simple_unlock(&vm_page_queue_lock)
280:
1.1.1.7 ! root 281: #define VM_PAGE_QUEUES_REMOVE(mem) vm_page_queues_remove(mem)
1.1 root 282:
1.1.1.6 root 283: /*
284: * Copyright (c) 2010-2014 Richard Braun.
285: *
286: * This program is free software: you can redistribute it and/or modify
287: * it under the terms of the GNU General Public License as published by
288: * the Free Software Foundation, either version 2 of the License, or
289: * (at your option) any later version.
290: *
291: * This program is distributed in the hope that it will be useful,
292: * but WITHOUT ANY WARRANTY; without even the implied warranty of
293: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
294: * GNU General Public License for more details.
295: *
296: * You should have received a copy of the GNU General Public License
297: * along with this program. If not, see <http://www.gnu.org/licenses/>.
298: *
299: *
300: * Physical page management.
301: */
302:
303: /*
304: * Address/page conversion and rounding macros (not inline functions to
305: * be easily usable on both virtual and physical addresses, which may not
306: * have the same type size).
307: */
308: #define vm_page_atop(addr) ((addr) >> PAGE_SHIFT)
309: #define vm_page_ptoa(page) ((page) << PAGE_SHIFT)
310: #define vm_page_trunc(addr) P2ALIGN(addr, PAGE_SIZE)
311: #define vm_page_round(addr) P2ROUND(addr, PAGE_SIZE)
312: #define vm_page_aligned(addr) P2ALIGNED(addr, PAGE_SIZE)
313:
314: /*
315: * Segment selectors.
316: *
317: * Selector-to-segment-list translation table :
318: * DMA DMA
319: * DMA32 DMA32 DMA
320: * DIRECTMAP DIRECTMAP DMA32 DMA
321: * HIGHMEM HIGHMEM DIRECTMAP DMA32 DMA
322: */
323: #define VM_PAGE_SEL_DMA 0
324: #define VM_PAGE_SEL_DMA32 1
325: #define VM_PAGE_SEL_DIRECTMAP 2
326: #define VM_PAGE_SEL_HIGHMEM 3
327:
328: /*
329: * Page usage types.
330: */
331: #define VM_PT_FREE 0 /* Page unused */
332: #define VM_PT_RESERVED 1 /* Page reserved at boot time */
333: #define VM_PT_TABLE 2 /* Page is part of the page table */
1.1.1.7 ! root 334: #define VM_PT_KERNEL 3 /* Type for generic kernel allocations */
1.1.1.6 root 335:
336: static inline unsigned short
337: vm_page_type(const struct vm_page *page)
338: {
339: return page->type;
340: }
341:
342: void vm_page_set_type(struct vm_page *page, unsigned int order,
343: unsigned short type);
344:
345: static inline unsigned int
346: vm_page_order(size_t size)
347: {
348: return iorder2(vm_page_atop(vm_page_round(size)));
349: }
350:
351: static inline phys_addr_t
352: vm_page_to_pa(const struct vm_page *page)
353: {
354: return page->phys_addr;
355: }
356:
357: /*
358: * Associate private data with a page.
359: */
360: static inline void
361: vm_page_set_priv(struct vm_page *page, void *priv)
362: {
363: page->priv = priv;
364: }
365:
366: static inline void *
367: vm_page_get_priv(const struct vm_page *page)
368: {
369: return page->priv;
370: }
371:
372: /*
373: * Load physical memory into the vm_page module at boot time.
374: *
375: * All addresses must be page-aligned. Segments can be loaded in any order.
376: */
1.1.1.7 ! root 377: void vm_page_load(unsigned int seg_index, phys_addr_t start, phys_addr_t end);
! 378:
! 379: /*
! 380: * Load available physical memory into the vm_page module at boot time.
! 381: *
! 382: * The segment referred to must have been loaded with vm_page_load
! 383: * before loading its heap.
! 384: */
! 385: void vm_page_load_heap(unsigned int seg_index, phys_addr_t start,
! 386: phys_addr_t end);
1.1.1.6 root 387:
388: /*
389: * Return true if the vm_page module is completely initialized, false
390: * otherwise, in which case only vm_page_bootalloc() can be used for
391: * allocations.
392: */
393: int vm_page_ready(void);
394:
395: /*
396: * Early allocation function.
397: *
398: * This function is used by the vm_resident module to implement
399: * pmap_steal_memory. It can be used after physical segments have been loaded
400: * and before the vm_page module is initialized.
401: */
402: unsigned long vm_page_bootalloc(size_t size);
403:
404: /*
405: * Set up the vm_page module.
406: *
407: * Architecture-specific code must have loaded segments before calling this
408: * function. Segments must comply with the selector-to-segment-list table,
409: * e.g. HIGHMEM is loaded if and only if DIRECTMAP, DMA32 and DMA are loaded,
410: * notwithstanding segment aliasing.
411: *
412: * Once this function returns, the vm_page module is ready, and normal
413: * allocation functions can be used.
414: */
415: void vm_page_setup(void);
416:
417: /*
418: * Make the given page managed by the vm_page module.
419: *
420: * If additional memory can be made usable after the VM system is initialized,
421: * it should be reported through this function.
422: */
423: void vm_page_manage(struct vm_page *page);
424:
425: /*
426: * Return the page descriptor for the given physical address.
427: */
428: struct vm_page * vm_page_lookup_pa(phys_addr_t pa);
429:
430: /*
431: * Allocate a block of 2^order physical pages.
432: *
433: * The selector is used to determine the segments from which allocation can
434: * be attempted.
435: *
436: * This function should only be used by the vm_resident module.
437: */
438: struct vm_page * vm_page_alloc_pa(unsigned int order, unsigned int selector,
439: unsigned short type);
440:
441: /*
442: * Release a block of 2^order physical pages.
443: *
444: * This function should only be used by the vm_resident module.
445: */
446: void vm_page_free_pa(struct vm_page *page, unsigned int order);
447:
448: /*
449: * Return the name of the given segment.
450: */
451: const char * vm_page_seg_name(unsigned int seg_index);
452:
453: /*
454: * Display internal information about the module.
455: */
456: void vm_page_info_all(void);
457:
458: /*
1.1.1.7 ! root 459: * Return the maximum physical address for a given segment selector.
! 460: */
! 461: phys_addr_t vm_page_seg_end(unsigned int selector);
! 462:
! 463: /*
! 464: * Return the total number of physical pages.
! 465: */
! 466: unsigned long vm_page_table_size(void);
! 467:
! 468: /*
! 469: * Return the index of a page in the page table.
! 470: */
! 471: unsigned long vm_page_table_index(phys_addr_t pa);
! 472:
! 473: /*
1.1.1.6 root 474: * Return the total amount of physical memory.
475: */
476: phys_addr_t vm_page_mem_size(void);
477:
478: /*
479: * Return the amount of free (unused) pages.
480: *
481: * XXX This currently relies on the kernel being non preemptible and
482: * uniprocessor.
483: */
484: unsigned long vm_page_mem_free(void);
485:
1.1.1.7 ! root 486: /*
! 487: * Remove the given page from any page queue it might be in.
! 488: */
! 489: void vm_page_queues_remove(struct vm_page *page);
! 490:
! 491: /*
! 492: * Balance physical pages among segments.
! 493: *
! 494: * This function should be called first by the pageout daemon
! 495: * on memory pressure, since it may be unnecessary to perform any
! 496: * other operation, let alone shrink caches, if balancing is
! 497: * enough to make enough free pages.
! 498: *
! 499: * Return TRUE if balancing made enough free pages for unprivileged
! 500: * allocations to succeed, in which case pending allocations are resumed.
! 501: *
! 502: * This function acquires vm_page_queue_free_lock, which is held on return.
! 503: */
! 504: boolean_t vm_page_balance(void);
! 505:
! 506: /*
! 507: * Evict physical pages.
! 508: *
! 509: * This function should be called by the pageout daemon after balancing
! 510: * the segments and shrinking kernel caches.
! 511: *
! 512: * Return TRUE if eviction made enough free pages for unprivileged
! 513: * allocations to succeed, in which case pending allocations are resumed.
! 514: *
! 515: * Otherwise, report whether the pageout daemon should wait (some pages
! 516: * have been paged out) or not (only clean pages have been released).
! 517: *
! 518: * This function acquires vm_page_queue_free_lock, which is held on return.
! 519: */
! 520: boolean_t vm_page_evict(boolean_t *should_wait);
! 521:
! 522: /*
! 523: * Turn active pages into inactive ones for second-chance LRU
! 524: * approximation.
! 525: *
! 526: * This function should be called by the pageout daemon on memory pressure,
! 527: * i.e. right before evicting pages.
! 528: *
! 529: * XXX This is probably not the best strategy, compared to keeping the
! 530: * active/inactive ratio in check at all times, but this means less
! 531: * frequent refills.
! 532: */
! 533: void vm_page_refill_inactive(void);
! 534:
1.1 root 535: #endif /* _VM_VM_PAGE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.