145748Smckusick /* 263379Sbostic * Copyright (c) 1991, 1993 363379Sbostic * The Regents of the University of California. All rights reserved. 445748Smckusick * 545748Smckusick * This code is derived from software contributed to Berkeley by 645748Smckusick * The Mach Operating System project at Carnegie-Mellon University. 745748Smckusick * 848493Smckusick * %sccs.include.redist.c% 945748Smckusick * 10*68164Scgd * @(#)vm_page.h 8.3 (Berkeley) 01/09/95 1148493Smckusick * 1248493Smckusick * 1348493Smckusick * Copyright (c) 1987, 1990 Carnegie-Mellon University. 1448493Smckusick * All rights reserved. 1548493Smckusick * 1648493Smckusick * Authors: Avadis Tevanian, Jr., Michael Wayne Young 1748493Smckusick * 1848493Smckusick * Permission to use, copy, modify and distribute this software and 1948493Smckusick * its documentation is hereby granted, provided that both the copyright 2048493Smckusick * notice and this permission notice appear in all copies of the 2148493Smckusick * software, derivative works or modified versions, and any portions 2248493Smckusick * thereof, and that both notices appear in supporting documentation. 2348493Smckusick * 2448493Smckusick * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 2548493Smckusick * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 2648493Smckusick * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 2748493Smckusick * 2848493Smckusick * Carnegie Mellon requests users of this software to return to 2948493Smckusick * 3048493Smckusick * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 3148493Smckusick * School of Computer Science 3248493Smckusick * Carnegie Mellon University 3348493Smckusick * Pittsburgh PA 15213-3890 3448493Smckusick * 3548493Smckusick * any improvements or extensions that they make and grant Carnegie the 3648493Smckusick * rights to redistribute these changes. 3745748Smckusick */ 3845748Smckusick 3945748Smckusick /* 4045748Smckusick * Resident memory system definitions. 4145748Smckusick */ 4245748Smckusick 4345748Smckusick #ifndef _VM_PAGE_ 4445748Smckusick #define _VM_PAGE_ 4545748Smckusick 4645748Smckusick /* 4745748Smckusick * Management of resident (logical) pages. 4845748Smckusick * 4945748Smckusick * A small structure is kept for each resident 5045748Smckusick * page, indexed by page number. Each structure 5145748Smckusick * is an element of several lists: 5245748Smckusick * 5345748Smckusick * A hash table bucket used to quickly 5445748Smckusick * perform object/offset lookups 5545748Smckusick * 5645748Smckusick * A list of all pages for a given object, 5745748Smckusick * so they can be quickly deactivated at 5845748Smckusick * time of deallocation. 5945748Smckusick * 6045748Smckusick * An ordered list of pages due for pageout. 6145748Smckusick * 6245748Smckusick * In addition, the structure contains the object 6345748Smckusick * and offset to which this page belongs (for pageout), 6445748Smckusick * and sundry status bits. 6545748Smckusick * 6645748Smckusick * Fields in this structure are locked either by the lock on the 6745748Smckusick * object that the page belongs to (O) or by the lock on the page 6845748Smckusick * queues (P). 6945748Smckusick */ 7045748Smckusick 7165127Smckusick TAILQ_HEAD(pglist, vm_page); 7265127Smckusick 7345748Smckusick struct vm_page { 7465127Smckusick TAILQ_ENTRY(vm_page) pageq; /* queue info for FIFO 7565127Smckusick * queue or free list (P) */ 7665127Smckusick TAILQ_ENTRY(vm_page) hashq; /* hash table links (O)*/ 7765127Smckusick TAILQ_ENTRY(vm_page) listq; /* pages in same object (O)*/ 7845748Smckusick 7965127Smckusick vm_object_t object; /* which object am I in (O,P)*/ 8065127Smckusick vm_offset_t offset; /* offset into object (O,P) */ 8145748Smckusick 8265127Smckusick u_short wire_count; /* wired down maps refs (P) */ 8365127Smckusick u_short flags; /* see below */ 8445748Smckusick 8565127Smckusick vm_offset_t phys_addr; /* physical address of page */ 8645748Smckusick }; 8745748Smckusick 8856383Smckusick /* 8956383Smckusick * These are the flags defined for vm_page. 9056909Smckusick * 9156909Smckusick * Note: PG_FILLED and PG_DIRTY are added for the filesystems. 9256383Smckusick */ 9356383Smckusick #define PG_INACTIVE 0x0001 /* page is in inactive list (P) */ 9456383Smckusick #define PG_ACTIVE 0x0002 /* page is in active list (P) */ 9556383Smckusick #define PG_LAUNDRY 0x0004 /* page is being cleaned now (P)*/ 9656383Smckusick #define PG_CLEAN 0x0008 /* page has not been modified */ 9756383Smckusick #define PG_BUSY 0x0010 /* page is in transit (O) */ 9856383Smckusick #define PG_WANTED 0x0020 /* someone is waiting for page (O) */ 9956383Smckusick #define PG_TABLED 0x0040 /* page is in VP table (O) */ 10056383Smckusick #define PG_COPYONWRITE 0x0080 /* must copy page before changing (O) */ 10156383Smckusick #define PG_FICTITIOUS 0x0100 /* physical page doesn't exist (O) */ 10256916Shibler #define PG_FAKE 0x0200 /* page is placeholder for pagein (O) */ 10356916Shibler #define PG_FILLED 0x0400 /* client flag to set when filled */ 10456916Shibler #define PG_DIRTY 0x0800 /* client flag to set when dirty */ 10556383Smckusick #define PG_PAGEROWNED 0x4000 /* DEBUG: async paging op in progress */ 10656383Smckusick #define PG_PTPAGE 0x8000 /* DEBUG: is a user page table page */ 10756383Smckusick 10845748Smckusick #if VM_PAGE_DEBUG 10945748Smckusick #define VM_PAGE_CHECK(mem) { \ 11056383Smckusick if ((((unsigned int) mem) < ((unsigned int) &vm_page_array[0])) || \ 11156383Smckusick (((unsigned int) mem) > \ 11256383Smckusick ((unsigned int) &vm_page_array[last_page-first_page])) || \ 11356383Smckusick ((mem->flags & (PG_ACTIVE | PG_INACTIVE)) == \ 11456383Smckusick (PG_ACTIVE | PG_INACTIVE))) \ 11556383Smckusick panic("vm_page_check: not valid!"); \ 11656383Smckusick } 11760344Storek #else /* VM_PAGE_DEBUG */ 11845748Smckusick #define VM_PAGE_CHECK(mem) 11960344Storek #endif /* VM_PAGE_DEBUG */ 12045748Smckusick 12153332Sbostic #ifdef KERNEL 12245748Smckusick /* 12345748Smckusick * Each pageable resident page falls into one of three lists: 12445748Smckusick * 12545748Smckusick * free 12645748Smckusick * Available for allocation now. 12745748Smckusick * inactive 12845748Smckusick * Not referenced in any map, but still has an 12945748Smckusick * object/offset-page mapping, and may be dirty. 13045748Smckusick * This is the list of pages that should be 13145748Smckusick * paged out next. 13245748Smckusick * active 13345748Smckusick * A list of pages which have been placed in 13445748Smckusick * at least one physical map. This list is 13545748Smckusick * ordered, in LRU-like fashion. 13645748Smckusick */ 13745748Smckusick 13845748Smckusick extern 13965127Smckusick struct pglist vm_page_queue_free; /* memory free queue */ 14045748Smckusick extern 14165127Smckusick struct pglist vm_page_queue_active; /* active memory queue */ 14245748Smckusick extern 14365127Smckusick struct pglist vm_page_queue_inactive; /* inactive memory queue */ 14445748Smckusick 14545748Smckusick extern 14645748Smckusick vm_page_t vm_page_array; /* First resident page in table */ 14745748Smckusick extern 14845748Smckusick long first_page; /* first physical page number */ 14945748Smckusick /* ... represented in vm_page_array */ 15045748Smckusick extern 15145748Smckusick long last_page; /* last physical page number */ 15245748Smckusick /* ... represented in vm_page_array */ 15345748Smckusick /* [INCLUSIVE] */ 15445748Smckusick extern 15545748Smckusick vm_offset_t first_phys_addr; /* physical address for first_page */ 15645748Smckusick extern 15745748Smckusick vm_offset_t last_phys_addr; /* physical address for last_page */ 15845748Smckusick 15945748Smckusick #define VM_PAGE_TO_PHYS(entry) ((entry)->phys_addr) 16045748Smckusick 16145748Smckusick #define IS_VM_PHYSADDR(pa) \ 16245748Smckusick ((pa) >= first_phys_addr && (pa) <= last_phys_addr) 16345748Smckusick 16445748Smckusick #define PHYS_TO_VM_PAGE(pa) \ 16545748Smckusick (&vm_page_array[atop(pa) - first_page ]) 16645748Smckusick 16745748Smckusick extern 16845748Smckusick simple_lock_data_t vm_page_queue_lock; /* lock on active and inactive 16945748Smckusick page queues */ 17053332Sbostic extern /* lock on free page queue */ 17145748Smckusick simple_lock_data_t vm_page_queue_free_lock; 17245748Smckusick 17345748Smckusick /* 17445748Smckusick * Functions implemented as macros 17545748Smckusick */ 17645748Smckusick 17745748Smckusick #define PAGE_ASSERT_WAIT(m, interruptible) { \ 17856383Smckusick (m)->flags |= PG_WANTED; \ 179*68164Scgd assert_wait((m), (interruptible)); \ 18045748Smckusick } 18145748Smckusick 18245748Smckusick #define PAGE_WAKEUP(m) { \ 18356383Smckusick (m)->flags &= ~PG_BUSY; \ 18456383Smckusick if ((m)->flags & PG_WANTED) { \ 18556383Smckusick (m)->flags &= ~PG_WANTED; \ 186*68164Scgd thread_wakeup((m)); \ 18745748Smckusick } \ 18845748Smckusick } 18945748Smckusick 19045748Smckusick #define vm_page_lock_queues() simple_lock(&vm_page_queue_lock) 19145748Smckusick #define vm_page_unlock_queues() simple_unlock(&vm_page_queue_lock) 19245748Smckusick 19356383Smckusick #define vm_page_set_modified(m) { (m)->flags &= ~PG_CLEAN; } 19452593Storek 19552593Storek #define VM_PAGE_INIT(mem, object, offset) { \ 19656383Smckusick (mem)->flags = PG_BUSY | PG_CLEAN | PG_FAKE; \ 19752593Storek vm_page_insert((mem), (object), (offset)); \ 19852593Storek (mem)->wire_count = 0; \ 19952593Storek } 20052593Storek 20153332Sbostic void vm_page_activate __P((vm_page_t)); 20253332Sbostic vm_page_t vm_page_alloc __P((vm_object_t, vm_offset_t)); 20353332Sbostic void vm_page_copy __P((vm_page_t, vm_page_t)); 20453332Sbostic void vm_page_deactivate __P((vm_page_t)); 20553332Sbostic void vm_page_free __P((vm_page_t)); 20653332Sbostic void vm_page_insert __P((vm_page_t, vm_object_t, vm_offset_t)); 20753332Sbostic vm_page_t vm_page_lookup __P((vm_object_t, vm_offset_t)); 20853332Sbostic void vm_page_remove __P((vm_page_t)); 20953332Sbostic void vm_page_rename __P((vm_page_t, vm_object_t, vm_offset_t)); 21053332Sbostic void vm_page_startup __P((vm_offset_t *, vm_offset_t *)); 21153332Sbostic void vm_page_unwire __P((vm_page_t)); 21253332Sbostic void vm_page_wire __P((vm_page_t)); 21353332Sbostic boolean_t vm_page_zero_fill __P((vm_page_t)); 21453332Sbostic 21553332Sbostic #endif /* KERNEL */ 21653332Sbostic #endif /* !_VM_PAGE_ */ 217