123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538 |
- /*
- * Mach Operating System
- * Copyright (c) 1993-1988 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
- /*
- * File: vm/vm_page.h
- * Author: Avadis Tevanian, Jr., Michael Wayne Young
- * Date: 1985
- *
- * Resident memory system definitions.
- */
- #ifndef _VM_VM_PAGE_H_
- #define _VM_VM_PAGE_H_
- #include <mach/boolean.h>
- #include <mach/vm_prot.h>
- #include <machine/vm_param.h>
- #include <vm/vm_object.h>
- #include <vm/vm_types.h>
- #include <kern/queue.h>
- #include <kern/list.h>
- #include <kern/lock.h>
- #include <kern/log2.h>
- #include <kern/macros.h>
- #include <kern/sched_prim.h> /* definitions of wait/wakeup */
- #if MACH_VM_DEBUG
- #include <mach_debug/hash_info.h>
- #endif
- /*
- * Management of resident (logical) pages.
- *
- * A small structure is kept for each resident
- * page, indexed by page number. Each structure
- * is an element of several lists:
- *
- * A hash table bucket used to quickly
- * perform object/offset lookups
- *
- * A list of all pages for a given object,
- * so they can be quickly deactivated at
- * time of deallocation.
- *
- * An ordered list of pages due for pageout.
- *
- * In addition, the structure contains the object
- * and offset to which this page belongs (for pageout),
- * and sundry status bits.
- *
- * Fields in this structure are locked either by the lock on the
- * object that the page belongs to (O) or by the lock on the page
- * queues (P). [Some fields require that both locks be held to
- * change that field; holding either lock is sufficient to read.]
- */
- struct vm_page {
- struct list node; /* page queues or free list (P) */
- unsigned short type;
- unsigned short seg_index;
- unsigned short order;
- void *priv;
- /*
- * This member is used throughout the code and may only change for
- * fictitious pages.
- */
- phys_addr_t phys_addr;
- queue_chain_t listq; /* all pages in same object (O) */
- struct vm_page *next; /* VP bucket link (O) */
- /* We use an empty struct as the delimiter. */
- struct {} vm_page_header;
- #define VM_PAGE_HEADER_SIZE offsetof(struct vm_page, vm_page_header)
- vm_object_t object; /* which object am I in (O,P) */
- vm_offset_t offset; /* offset into that object (O,P) */
- unsigned int wire_count:15, /* how many wired down maps use me?
- (O&P) */
- /* boolean_t */ inactive:1, /* page is in inactive list (P) */
- active:1, /* page is in active list (P) */
- laundry:1, /* page is being cleaned now (P)*/
- external_laundry:1, /* same as laundry for external pagers (P)*/
- free:1, /* page is on free list (P) */
- reference:1, /* page has been used (P) */
- external:1, /* page in external object (P) */
- busy:1, /* page is in transit (O) */
- wanted:1, /* someone is waiting for page (O) */
- tabled:1, /* page is in VP table (O) */
- fictitious:1, /* Physical page doesn't exist (O) */
- private:1, /* Page should not be returned to
- * the free list (O) */
- absent:1, /* Data has been requested, but is
- * not yet available (O) */
- error:1, /* Data manager was unable to provide
- * data due to error (O) */
- dirty:1, /* Page must be cleaned (O) */
- precious:1, /* Page is precious; data must be
- * returned even if clean (O) */
- overwriting:1; /* Request to unlock has been made
- * without having data. (O)
- * [See vm_object_overwrite] */
- vm_prot_t page_lock; /* Uses prohibited by data manager (O) */
- vm_prot_t unlock_request; /* Outstanding unlock request (O) */
- };
- /*
- * For debugging, this macro can be defined to perform
- * some useful check on a page structure.
- */
- #define VM_PAGE_CHECK(mem) vm_page_check(mem)
- void vm_page_check(const struct vm_page *page);
- /*
- * Each pageable resident page falls into one of three lists:
- *
- * free
- * Available for allocation now.
- * inactive
- * Not referenced in any map, but still has an
- * object/offset-page mapping, and may be dirty.
- * This is the list of pages that should be
- * paged out next.
- * active
- * A list of pages which have been placed in
- * at least one physical map. This list is
- * ordered, in LRU-like fashion.
- */
- extern
- int vm_page_fictitious_count;/* How many fictitious pages are free? */
- extern
- int vm_page_active_count; /* How many pages are active? */
- extern
- int vm_page_inactive_count; /* How many pages are inactive? */
- extern
- int vm_page_wire_count; /* How many pages are wired? */
- extern
- int vm_page_laundry_count; /* How many pages being laundered? */
- extern
- int vm_page_external_laundry_count; /* How many external pages being paged out? */
- decl_simple_lock_data(extern,vm_page_queue_lock)/* lock on active and inactive
- page queues */
- decl_simple_lock_data(extern,vm_page_queue_free_lock)
- /* lock on free page queue */
- extern phys_addr_t vm_page_fictitious_addr;
- /* (fake) phys_addr of fictitious pages */
- extern void vm_page_bootstrap(
- vm_offset_t *startp,
- vm_offset_t *endp);
- extern void vm_page_module_init(void);
- extern vm_page_t vm_page_lookup(
- vm_object_t object,
- vm_offset_t offset);
- extern vm_page_t vm_page_grab_fictitious(void);
- extern boolean_t vm_page_convert(vm_page_t *);
- extern void vm_page_more_fictitious(void);
- extern vm_page_t vm_page_grab(void);
- extern void vm_page_release(vm_page_t, boolean_t, boolean_t);
- extern phys_addr_t vm_page_grab_phys_addr(void);
- extern vm_page_t vm_page_grab_contig(vm_size_t, unsigned int);
- extern void vm_page_free_contig(vm_page_t, vm_size_t);
- extern void vm_page_wait(void (*)(void));
- extern vm_page_t vm_page_alloc(
- vm_object_t object,
- vm_offset_t offset);
- extern void vm_page_init(
- vm_page_t mem);
- extern void vm_page_free(vm_page_t);
- extern void vm_page_activate(vm_page_t);
- extern void vm_page_deactivate(vm_page_t);
- extern void vm_page_rename(
- vm_page_t mem,
- vm_object_t new_object,
- vm_offset_t new_offset);
- extern void vm_page_insert(
- vm_page_t mem,
- vm_object_t object,
- vm_offset_t offset);
- extern void vm_page_remove(
- vm_page_t mem);
- extern void vm_page_zero_fill(vm_page_t);
- extern void vm_page_copy(vm_page_t src_m, vm_page_t dest_m);
- extern void vm_page_wire(vm_page_t);
- extern void vm_page_unwire(vm_page_t);
- #if MACH_VM_DEBUG
- extern unsigned int vm_page_info(
- hash_info_bucket_t *info,
- unsigned int count);
- #endif
- /*
- * Functions implemented as macros
- */
- #define PAGE_ASSERT_WAIT(m, interruptible) \
- MACRO_BEGIN \
- (m)->wanted = TRUE; \
- assert_wait((event_t) (m), (interruptible)); \
- MACRO_END
- #define PAGE_WAKEUP_DONE(m) \
- MACRO_BEGIN \
- (m)->busy = FALSE; \
- if ((m)->wanted) { \
- (m)->wanted = FALSE; \
- thread_wakeup(((event_t) m)); \
- } \
- MACRO_END
- #define PAGE_WAKEUP(m) \
- MACRO_BEGIN \
- if ((m)->wanted) { \
- (m)->wanted = FALSE; \
- thread_wakeup((event_t) (m)); \
- } \
- MACRO_END
- #define VM_PAGE_FREE(p) \
- MACRO_BEGIN \
- vm_page_lock_queues(); \
- vm_page_free(p); \
- vm_page_unlock_queues(); \
- MACRO_END
- /*
- * Macro to be used in place of pmap_enter()
- */
- #define PMAP_ENTER(pmap, virtual_address, page, protection, wired) \
- MACRO_BEGIN \
- pmap_enter( \
- (pmap), \
- (virtual_address), \
- (page)->phys_addr, \
- (protection) & ~(page)->page_lock, \
- (wired) \
- ); \
- MACRO_END
- #define VM_PAGE_WAIT(continuation) vm_page_wait(continuation)
- #define vm_page_lock_queues() simple_lock(&vm_page_queue_lock)
- #define vm_page_unlock_queues() simple_unlock(&vm_page_queue_lock)
- #define VM_PAGE_QUEUES_REMOVE(mem) vm_page_queues_remove(mem)
- /*
- * Copyright (c) 2010-2014 Richard Braun.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- * Physical page management.
- */
- /*
- * Address/page conversion and rounding macros (not inline functions to
- * be easily usable on both virtual and physical addresses, which may not
- * have the same type size).
- */
- #define vm_page_atop(addr) ((addr) >> PAGE_SHIFT)
- #define vm_page_ptoa(page) ((page) << PAGE_SHIFT)
- #define vm_page_trunc(addr) P2ALIGN(addr, PAGE_SIZE)
- #define vm_page_round(addr) P2ROUND(addr, PAGE_SIZE)
- #define vm_page_aligned(addr) P2ALIGNED(addr, PAGE_SIZE)
- /*
- * Segment selectors.
- *
- * Selector-to-segment-list translation table :
- * DMA DMA
- * DMA32 DMA32 DMA
- * DIRECTMAP DIRECTMAP DMA32 DMA
- * HIGHMEM HIGHMEM DIRECTMAP DMA32 DMA
- */
- #define VM_PAGE_SEL_DMA 0
- #define VM_PAGE_SEL_DMA32 1
- #define VM_PAGE_SEL_DIRECTMAP 2
- #define VM_PAGE_SEL_HIGHMEM 3
- /*
- * Page usage types.
- */
- #define VM_PT_FREE 0 /* Page unused */
- #define VM_PT_RESERVED 1 /* Page reserved at boot time */
- #define VM_PT_TABLE 2 /* Page is part of the page table */
- #define VM_PT_KERNEL 3 /* Type for generic kernel allocations */
- static inline unsigned short
- vm_page_type(const struct vm_page *page)
- {
- return page->type;
- }
- void vm_page_set_type(struct vm_page *page, unsigned int order,
- unsigned short type);
- #if 0
- static inline unsigned int
- vm_page_order(size_t size)
- {
- return gnumach_iorder2(vm_page_atop(vm_page_round(size)));
- }
- #endif
- static inline phys_addr_t
- vm_page_to_pa(const struct vm_page *page)
- {
- return page->phys_addr;
- }
- /*
- * Associate private data with a page.
- */
- static inline void
- vm_page_set_priv(struct vm_page *page, void *priv)
- {
- page->priv = priv;
- }
- static inline void *
- vm_page_get_priv(const struct vm_page *page)
- {
- return page->priv;
- }
- /*
- * Load physical memory into the vm_page module at boot time.
- *
- * All addresses must be page-aligned. Segments can be loaded in any order.
- */
- void vm_page_load(unsigned int seg_index, phys_addr_t start, phys_addr_t end);
- /*
- * Load available physical memory into the vm_page module at boot time.
- *
- * The segment referred to must have been loaded with vm_page_load
- * before loading its heap.
- */
- void vm_page_load_heap(unsigned int seg_index, phys_addr_t start,
- phys_addr_t end);
- /*
- * Return true if the vm_page module is completely initialized, false
- * otherwise, in which case only vm_page_bootalloc() can be used for
- * allocations.
- */
- int vm_page_ready(void);
- /*
- * Early allocation function.
- *
- * This function is used by the vm_resident module to implement
- * pmap_steal_memory. It can be used after physical segments have been loaded
- * and before the vm_page module is initialized.
- */
- unsigned long vm_page_bootalloc(size_t size);
- /*
- * Set up the vm_page module.
- *
- * Architecture-specific code must have loaded segments before calling this
- * function. Segments must comply with the selector-to-segment-list table,
- * e.g. HIGHMEM is loaded if and only if DIRECTMAP, DMA32 and DMA are loaded,
- * notwithstanding segment aliasing.
- *
- * Once this function returns, the vm_page module is ready, and normal
- * allocation functions can be used.
- */
- void vm_page_setup(void);
- /*
- * Make the given page managed by the vm_page module.
- *
- * If additional memory can be made usable after the VM system is initialized,
- * it should be reported through this function.
- */
- void vm_page_manage(struct vm_page *page);
- /*
- * Return the page descriptor for the given physical address.
- */
- struct vm_page * vm_page_lookup_pa(phys_addr_t pa);
- /*
- * Allocate a block of 2^order physical pages.
- *
- * The selector is used to determine the segments from which allocation can
- * be attempted.
- *
- * This function should only be used by the vm_resident module.
- */
- struct vm_page * vm_page_alloc_pa(unsigned int order, unsigned int selector,
- unsigned short type);
- /*
- * Release a block of 2^order physical pages.
- *
- * This function should only be used by the vm_resident module.
- */
- void vm_page_free_pa(struct vm_page *page, unsigned int order);
- /*
- * Return the name of the given segment.
- */
- const char * vm_page_seg_name(unsigned int seg_index);
- /*
- * Display internal information about the module.
- */
- void vm_page_info_all(void);
- /*
- * Return the maximum physical address for a given segment selector.
- */
- phys_addr_t vm_page_seg_end(unsigned int selector);
- /*
- * Return the total number of physical pages.
- */
- unsigned long vm_page_table_size(void);
- /*
- * Return the index of a page in the page table.
- */
- unsigned long vm_page_table_index(phys_addr_t pa);
- /*
- * Return the total amount of physical memory.
- */
- phys_addr_t vm_page_mem_size(void);
- /*
- * Return the amount of free (unused) pages.
- *
- * XXX This currently relies on the kernel being non preemptible and
- * uniprocessor.
- */
- unsigned long vm_page_mem_free(void);
- /*
- * Remove the given page from any page queue it might be in.
- */
- void vm_page_queues_remove(struct vm_page *page);
- /*
- * Balance physical pages among segments.
- *
- * This function should be called first by the pageout daemon
- * on memory pressure, since it may be unnecessary to perform any
- * other operation, let alone shrink caches, if balancing is
- * enough to make enough free pages.
- *
- * Return TRUE if balancing made enough free pages for unprivileged
- * allocations to succeed, in which case pending allocations are resumed.
- *
- * This function acquires vm_page_queue_free_lock, which is held on return.
- */
- boolean_t vm_page_balance(void);
- /*
- * Evict physical pages.
- *
- * This function should be called by the pageout daemon after balancing
- * the segments and shrinking kernel caches.
- *
- * Return TRUE if eviction made enough free pages for unprivileged
- * allocations to succeed, in which case pending allocations are resumed.
- *
- * Otherwise, report whether the pageout daemon should wait (some pages
- * have been paged out) or not (only clean pages have been released).
- *
- * This function acquires vm_page_queue_free_lock, which is held on return.
- */
- boolean_t vm_page_evict(boolean_t *should_wait);
- /*
- * Turn active pages into inactive ones for second-chance LRU
- * approximation.
- *
- * This function should be called by the pageout daemon on memory pressure,
- * i.e. right before evicting pages.
- *
- * XXX This is probably not the best strategy, compared to keeping the
- * active/inactive ratio in check at all times, but this means less
- * frequent refills.
- */
- void vm_page_refill_inactive(void);
- #endif /* _VM_VM_PAGE_H_ */
|