Annotation of Gnu-Mach/vm/vm_page.h, revision 1.1.1.6

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>
                     43: #include <kern/lock.h>
1.1.1.6 ! root       44: #include <kern/log2.h>
1.1       root       45: 
1.1.1.5   root       46: #include <kern/macros.h>
1.1       root       47: #include <kern/sched_prim.h>   /* definitions of wait/wakeup */
                     48: 
                     49: #if    MACH_VM_DEBUG
                     50: #include <mach_debug/hash_info.h>
                     51: #endif
                     52: 
                     53: /*
                     54:  *     Management of resident (logical) pages.
                     55:  *
                     56:  *     A small structure is kept for each resident
                     57:  *     page, indexed by page number.  Each structure
                     58:  *     is an element of several lists:
                     59:  *
                     60:  *             A hash table bucket used to quickly
                     61:  *             perform object/offset lookups
                     62:  *
                     63:  *             A list of all pages for a given object,
                     64:  *             so they can be quickly deactivated at
                     65:  *             time of deallocation.
                     66:  *
                     67:  *             An ordered list of pages due for pageout.
                     68:  *
                     69:  *     In addition, the structure contains the object
                     70:  *     and offset to which this page belongs (for pageout),
                     71:  *     and sundry status bits.
                     72:  *
                     73:  *     Fields in this structure are locked either by the lock on the
                     74:  *     object that the page belongs to (O) or by the lock on the page
                     75:  *     queues (P).  [Some fields require that both locks be held to
                     76:  *     change that field; holding either lock is sufficient to read.]
                     77:  */
                     78: 
                     79: struct vm_page {
1.1.1.6 ! root       80:        /* Members used in the vm_page module only */
        !            81:        struct list node;
        !            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: 
        !            93:        /* We use an empty struct as the delimiter.  */
        !            94:        struct {} vm_page_header;
        !            95: #define VM_PAGE_HEADER_SIZE    offsetof(struct vm_page, vm_page_header)
        !            96: 
1.1       root       97:        queue_chain_t   pageq;          /* queue info for FIFO
                     98:                                         * queue or free list (P) */
                     99:        queue_chain_t   listq;          /* all pages in same object (O) */
                    100:        struct vm_page  *next;          /* VP bucket link (O) */
                    101: 
                    102:        vm_object_t     object;         /* which object am I in (O,P) */
                    103:        vm_offset_t     offset;         /* offset into that object (O,P) */
                    104: 
1.1.1.4   root      105:        unsigned int    wire_count:15,  /* how many wired down maps use me?
1.1       root      106:                                           (O&P) */
                    107:        /* boolean_t */ inactive:1,     /* page is in inactive list (P) */
                    108:                        active:1,       /* page is in active list (P) */
                    109:                        laundry:1,      /* page is being cleaned now (P)*/
                    110:                        free:1,         /* page is on free list (P) */
                    111:                        reference:1,    /* page has been used (P) */
1.1.1.2   root      112:                        external:1,     /* page considered external (P) */
1.1.1.4   root      113:                        extcounted:1,   /* page counted in ext counts (P) */
                    114:                        busy:1,         /* page is in transit (O) */
1.1       root      115:                        wanted:1,       /* someone is waiting for page (O) */
                    116:                        tabled:1,       /* page is in VP table (O) */
                    117:                        fictitious:1,   /* Physical page doesn't exist (O) */
                    118:                        private:1,      /* Page should not be returned to
                    119:                                         *  the free list (O) */
                    120:                        absent:1,       /* Data has been requested, but is
                    121:                                         *  not yet available (O) */
                    122:                        error:1,        /* Data manager was unable to provide
                    123:                                         *  data due to error (O) */
                    124:                        dirty:1,        /* Page must be cleaned (O) */
                    125:                        precious:1,     /* Page is precious; data must be
                    126:                                         *  returned even if clean (O) */
1.1.1.4   root      127:                        overwriting:1;  /* Request to unlock has been made
1.1       root      128:                                         * without having data. (O)
                    129:                                         * [See vm_object_overwrite] */
                    130: 
                    131:        vm_prot_t       page_lock;      /* Uses prohibited by data manager (O) */
                    132:        vm_prot_t       unlock_request; /* Outstanding unlock request (O) */
                    133: };
                    134: 
                    135: /*
                    136:  *     For debugging, this macro can be defined to perform
                    137:  *     some useful check on a page structure.
                    138:  */
                    139: 
                    140: #define VM_PAGE_CHECK(mem)
                    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: vm_page_t      vm_page_queue_fictitious;       /* fictitious free queue */
                    160: extern
                    161: queue_head_t   vm_page_queue_active;   /* active memory queue */
                    162: extern
                    163: queue_head_t   vm_page_queue_inactive; /* inactive memory queue */
                    164: 
                    165: extern
                    166: int    vm_page_fictitious_count;/* How many fictitious pages are free? */
                    167: extern
                    168: int    vm_page_active_count;   /* How many pages are active? */
                    169: extern
                    170: int    vm_page_inactive_count; /* How many pages are inactive? */
                    171: extern
                    172: int    vm_page_wire_count;     /* How many pages are wired? */
                    173: extern
                    174: int    vm_page_free_target;    /* How many do we want free? */
                    175: extern
                    176: int    vm_page_free_min;       /* When to wakeup pageout */
                    177: extern
                    178: int    vm_page_inactive_target;/* How many do we want inactive? */
                    179: extern
                    180: int    vm_page_free_reserved;  /* How many pages reserved to do pageout */
                    181: extern
                    182: int    vm_page_laundry_count;  /* How many pages being laundered? */
1.1.1.2   root      183: extern
                    184: int    vm_page_external_limit; /* Max number of pages for external objects  */
                    185: 
                    186: /* Only objects marked with the extcounted bit are included in this total.
                    187:    Pages which we scan for possible pageout, but which are not actually
                    188:    dirty, don't get considered against the external page limits any more
                    189:    in this way.  */
                    190: extern
                    191: int    vm_page_external_count; /* How many pages for external objects? */
                    192: 
                    193: 
1.1       root      194: 
                    195: decl_simple_lock_data(extern,vm_page_queue_lock)/* lock on active and inactive
                    196:                                                   page queues */
                    197: decl_simple_lock_data(extern,vm_page_queue_free_lock)
                    198:                                                /* lock on free page queue */
                    199: 
                    200: extern unsigned int    vm_page_free_wanted;
                    201:                                /* how many threads are waiting for memory */
                    202: 
                    203: extern vm_offset_t     vm_page_fictitious_addr;
                    204:                                /* (fake) phys_addr of fictitious pages */
                    205: 
                    206: extern void            vm_page_bootstrap(
                    207:        vm_offset_t     *startp,
                    208:        vm_offset_t     *endp);
                    209: extern void            vm_page_module_init(void);
                    210: 
                    211: extern vm_page_t       vm_page_lookup(
                    212:        vm_object_t     object,
                    213:        vm_offset_t     offset);
                    214: extern vm_page_t       vm_page_grab_fictitious(void);
1.1.1.6 ! root      215: extern boolean_t       vm_page_convert(vm_page_t *, boolean_t);
1.1       root      216: extern void            vm_page_more_fictitious(void);
1.1.1.2   root      217: extern vm_page_t       vm_page_grab(boolean_t);
1.1.1.6 ! root      218: extern vm_page_t       vm_page_grab_contig(vm_size_t, unsigned int);
        !           219: extern void            vm_page_free_contig(vm_page_t, vm_size_t);
1.1       root      220: extern void            vm_page_wait(void (*)(void));
                    221: extern vm_page_t       vm_page_alloc(
                    222:        vm_object_t     object,
                    223:        vm_offset_t     offset);
                    224: extern void            vm_page_init(
1.1.1.6 ! root      225:        vm_page_t       mem);
1.1       root      226: extern void            vm_page_free(vm_page_t);
                    227: extern void            vm_page_activate(vm_page_t);
                    228: extern void            vm_page_deactivate(vm_page_t);
                    229: extern void            vm_page_rename(
                    230:        vm_page_t       mem,
                    231:        vm_object_t     new_object,
                    232:        vm_offset_t     new_offset);
                    233: extern void            vm_page_insert(
                    234:        vm_page_t       mem,
                    235:        vm_object_t     object,
                    236:        vm_offset_t     offset);
                    237: extern void            vm_page_remove(
                    238:        vm_page_t       mem);
                    239: 
                    240: extern void            vm_page_zero_fill(vm_page_t);
                    241: extern void            vm_page_copy(vm_page_t src_m, vm_page_t dest_m);
                    242: 
                    243: extern void            vm_page_wire(vm_page_t);
                    244: extern void            vm_page_unwire(vm_page_t);
                    245: 
                    246: #if    MACH_VM_DEBUG
                    247: extern unsigned int    vm_page_info(
                    248:        hash_info_bucket_t      *info,
                    249:        unsigned int            count);
                    250: #endif
                    251: 
                    252: /*
                    253:  *     Functions implemented as macros
                    254:  */
                    255: 
                    256: #define PAGE_ASSERT_WAIT(m, interruptible)                     \
                    257:                MACRO_BEGIN                                     \
                    258:                (m)->wanted = TRUE;                             \
                    259:                assert_wait((event_t) (m), (interruptible));    \
                    260:                MACRO_END
                    261: 
                    262: #define PAGE_WAKEUP_DONE(m)                                    \
                    263:                MACRO_BEGIN                                     \
                    264:                (m)->busy = FALSE;                              \
                    265:                if ((m)->wanted) {                              \
                    266:                        (m)->wanted = FALSE;                    \
                    267:                        thread_wakeup(((event_t) m));           \
                    268:                }                                               \
                    269:                MACRO_END
                    270: 
                    271: #define PAGE_WAKEUP(m)                                         \
                    272:                MACRO_BEGIN                                     \
                    273:                if ((m)->wanted) {                              \
                    274:                        (m)->wanted = FALSE;                    \
                    275:                        thread_wakeup((event_t) (m));           \
                    276:                }                                               \
                    277:                MACRO_END
                    278: 
                    279: #define VM_PAGE_FREE(p)                        \
                    280:                MACRO_BEGIN                     \
                    281:                vm_page_lock_queues();          \
                    282:                vm_page_free(p);                \
                    283:                vm_page_unlock_queues();        \
                    284:                MACRO_END
                    285: 
                    286: /*
                    287:  *     Macro to be used in place of pmap_enter()
                    288:  */
                    289: 
                    290: #define PMAP_ENTER(pmap, virtual_address, page, protection, wired) \
                    291:                MACRO_BEGIN                                     \
                    292:                pmap_enter(                                     \
                    293:                        (pmap),                                 \
                    294:                        (virtual_address),                      \
                    295:                        (page)->phys_addr,                      \
                    296:                        (protection) & ~(page)->page_lock,      \
                    297:                        (wired)                                 \
                    298:                 );                                             \
                    299:                MACRO_END
                    300: 
                    301: #define        VM_PAGE_WAIT(continuation)      vm_page_wait(continuation)
                    302: 
                    303: #define vm_page_lock_queues()  simple_lock(&vm_page_queue_lock)
                    304: #define vm_page_unlock_queues()        simple_unlock(&vm_page_queue_lock)
                    305: 
                    306: #define VM_PAGE_QUEUES_REMOVE(mem)                             \
                    307:        MACRO_BEGIN                                             \
                    308:        if (mem->active) {                                      \
                    309:                queue_remove(&vm_page_queue_active,             \
                    310:                        mem, vm_page_t, pageq);                 \
                    311:                mem->active = FALSE;                            \
                    312:                vm_page_active_count--;                         \
                    313:        }                                                       \
                    314:                                                                \
                    315:        if (mem->inactive) {                                    \
                    316:                queue_remove(&vm_page_queue_inactive,           \
                    317:                        mem, vm_page_t, pageq);                 \
                    318:                mem->inactive = FALSE;                          \
                    319:                vm_page_inactive_count--;                       \
                    320:        }                                                       \
                    321:        MACRO_END
                    322: 
1.1.1.6 ! root      323: /*
        !           324:  * Copyright (c) 2010-2014 Richard Braun.
        !           325:  *
        !           326:  * This program is free software: you can redistribute it and/or modify
        !           327:  * it under the terms of the GNU General Public License as published by
        !           328:  * the Free Software Foundation, either version 2 of the License, or
        !           329:  * (at your option) any later version.
        !           330:  *
        !           331:  * This program is distributed in the hope that it will be useful,
        !           332:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !           333:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !           334:  * GNU General Public License for more details.
        !           335:  *
        !           336:  * You should have received a copy of the GNU General Public License
        !           337:  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
        !           338:  *
        !           339:  *
        !           340:  * Physical page management.
        !           341:  */
        !           342: 
        !           343: /*
        !           344:  * Address/page conversion and rounding macros (not inline functions to
        !           345:  * be easily usable on both virtual and physical addresses, which may not
        !           346:  * have the same type size).
        !           347:  */
        !           348: #define vm_page_atop(addr)      ((addr) >> PAGE_SHIFT)
        !           349: #define vm_page_ptoa(page)      ((page) << PAGE_SHIFT)
        !           350: #define vm_page_trunc(addr)     P2ALIGN(addr, PAGE_SIZE)
        !           351: #define vm_page_round(addr)     P2ROUND(addr, PAGE_SIZE)
        !           352: #define vm_page_aligned(addr)   P2ALIGNED(addr, PAGE_SIZE)
        !           353: 
        !           354: /*
        !           355:  * Segment selectors.
        !           356:  *
        !           357:  * Selector-to-segment-list translation table :
        !           358:  * DMA          DMA
        !           359:  * DMA32        DMA32 DMA
        !           360:  * DIRECTMAP    DIRECTMAP DMA32 DMA
        !           361:  * HIGHMEM      HIGHMEM DIRECTMAP DMA32 DMA
        !           362:  */
        !           363: #define VM_PAGE_SEL_DMA         0
        !           364: #define VM_PAGE_SEL_DMA32       1
        !           365: #define VM_PAGE_SEL_DIRECTMAP   2
        !           366: #define VM_PAGE_SEL_HIGHMEM     3
        !           367: 
        !           368: /*
        !           369:  * Page usage types.
        !           370:  *
        !           371:  * Failing to allocate pmap pages will cause a kernel panic.
        !           372:  * TODO Obviously, this needs to be addressed, e.g. with a reserved pool of
        !           373:  * pages.
        !           374:  */
        !           375: #define VM_PT_FREE          0   /* Page unused */
        !           376: #define VM_PT_RESERVED      1   /* Page reserved at boot time */
        !           377: #define VM_PT_TABLE         2   /* Page is part of the page table */
        !           378: #define VM_PT_PMAP          3   /* Page stores pmap-specific data */
        !           379: #define VM_PT_KMEM          4   /* Page is part of a kmem slab */
        !           380: #define VM_PT_STACK         5   /* Type for generic kernel allocations */
        !           381: #define VM_PT_KERNEL        6   /* Type for generic kernel allocations */
        !           382: 
        !           383: static inline unsigned short
        !           384: vm_page_type(const struct vm_page *page)
        !           385: {
        !           386:     return page->type;
        !           387: }
        !           388: 
        !           389: void vm_page_set_type(struct vm_page *page, unsigned int order,
        !           390:                       unsigned short type);
        !           391: 
        !           392: static inline unsigned int
        !           393: vm_page_order(size_t size)
        !           394: {
        !           395:     return iorder2(vm_page_atop(vm_page_round(size)));
        !           396: }
        !           397: 
        !           398: static inline phys_addr_t
        !           399: vm_page_to_pa(const struct vm_page *page)
        !           400: {
        !           401:     return page->phys_addr;
        !           402: }
        !           403: 
        !           404: #if 0
        !           405: static inline unsigned long
        !           406: vm_page_direct_va(phys_addr_t pa)
        !           407: {
        !           408:     assert(pa < VM_PAGE_DIRECTMAP_LIMIT);
        !           409:     return ((unsigned long)pa + VM_MIN_DIRECTMAP_ADDRESS);
        !           410: }
        !           411: 
        !           412: static inline phys_addr_t
        !           413: vm_page_direct_pa(unsigned long va)
        !           414: {
        !           415:     assert(va >= VM_MIN_DIRECTMAP_ADDRESS);
        !           416:     assert(va < VM_MAX_DIRECTMAP_ADDRESS);
        !           417:     return (va - VM_MIN_DIRECTMAP_ADDRESS);
        !           418: }
        !           419: 
        !           420: static inline void *
        !           421: vm_page_direct_ptr(const struct vm_page *page)
        !           422: {
        !           423:     return (void *)vm_page_direct_va(vm_page_to_pa(page));
        !           424: }
        !           425: #endif
        !           426: 
        !           427: /*
        !           428:  * Associate private data with a page.
        !           429:  */
        !           430: static inline void
        !           431: vm_page_set_priv(struct vm_page *page, void *priv)
        !           432: {
        !           433:     page->priv = priv;
        !           434: }
        !           435: 
        !           436: static inline void *
        !           437: vm_page_get_priv(const struct vm_page *page)
        !           438: {
        !           439:     return page->priv;
        !           440: }
        !           441: 
        !           442: /*
        !           443:  * Load physical memory into the vm_page module at boot time.
        !           444:  *
        !           445:  * The avail_start and avail_end parameters are used to maintain a simple
        !           446:  * heap for bootstrap allocations.
        !           447:  *
        !           448:  * All addresses must be page-aligned. Segments can be loaded in any order.
        !           449:  */
        !           450: void vm_page_load(unsigned int seg_index, phys_addr_t start, phys_addr_t end,
        !           451:                   phys_addr_t avail_start, phys_addr_t avail_end);
        !           452: 
        !           453: /*
        !           454:  * Return true if the vm_page module is completely initialized, false
        !           455:  * otherwise, in which case only vm_page_bootalloc() can be used for
        !           456:  * allocations.
        !           457:  */
        !           458: int vm_page_ready(void);
        !           459: 
        !           460: /*
        !           461:  * Early allocation function.
        !           462:  *
        !           463:  * This function is used by the vm_resident module to implement
        !           464:  * pmap_steal_memory. It can be used after physical segments have been loaded
        !           465:  * and before the vm_page module is initialized.
        !           466:  */
        !           467: unsigned long vm_page_bootalloc(size_t size);
        !           468: 
        !           469: /*
        !           470:  * Set up the vm_page module.
        !           471:  *
        !           472:  * Architecture-specific code must have loaded segments before calling this
        !           473:  * function. Segments must comply with the selector-to-segment-list table,
        !           474:  * e.g. HIGHMEM is loaded if and only if DIRECTMAP, DMA32 and DMA are loaded,
        !           475:  * notwithstanding segment aliasing.
        !           476:  *
        !           477:  * Once this function returns, the vm_page module is ready, and normal
        !           478:  * allocation functions can be used.
        !           479:  */
        !           480: void vm_page_setup(void);
        !           481: 
        !           482: /*
        !           483:  * Make the given page managed by the vm_page module.
        !           484:  *
        !           485:  * If additional memory can be made usable after the VM system is initialized,
        !           486:  * it should be reported through this function.
        !           487:  */
        !           488: void vm_page_manage(struct vm_page *page);
        !           489: 
        !           490: /*
        !           491:  * Return the page descriptor for the given physical address.
        !           492:  */
        !           493: struct vm_page * vm_page_lookup_pa(phys_addr_t pa);
        !           494: 
        !           495: /*
        !           496:  * Allocate a block of 2^order physical pages.
        !           497:  *
        !           498:  * The selector is used to determine the segments from which allocation can
        !           499:  * be attempted.
        !           500:  *
        !           501:  * This function should only be used by the vm_resident module.
        !           502:  */
        !           503: struct vm_page * vm_page_alloc_pa(unsigned int order, unsigned int selector,
        !           504:                                   unsigned short type);
        !           505: 
        !           506: /*
        !           507:  * Release a block of 2^order physical pages.
        !           508:  *
        !           509:  * This function should only be used by the vm_resident module.
        !           510:  */
        !           511: void vm_page_free_pa(struct vm_page *page, unsigned int order);
        !           512: 
        !           513: /*
        !           514:  * Return the name of the given segment.
        !           515:  */
        !           516: const char * vm_page_seg_name(unsigned int seg_index);
        !           517: 
        !           518: /*
        !           519:  * Display internal information about the module.
        !           520:  */
        !           521: void vm_page_info_all(void);
        !           522: 
        !           523: /*
        !           524:  * Return the total amount of physical memory.
        !           525:  */
        !           526: phys_addr_t vm_page_mem_size(void);
        !           527: 
        !           528: /*
        !           529:  * Return the amount of free (unused) pages.
        !           530:  *
        !           531:  * XXX This currently relies on the kernel being non preemptible and
        !           532:  * uniprocessor.
        !           533:  */
        !           534: unsigned long vm_page_mem_free(void);
        !           535: 
1.1       root      536: #endif /* _VM_VM_PAGE_H_ */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.