[BACK]Return to uvm_page.h CVS log [TXT][DIR] Up to [local] / sys / uvm

Annotation of sys/uvm/uvm_page.h, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: uvm_page.h,v 1.25 2007/04/18 18:51:37 art Exp $       */
        !             2: /*     $NetBSD: uvm_page.h,v 1.19 2000/12/28 08:24:55 chs Exp $        */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1997 Charles D. Cranor and Washington University.
        !             6:  * Copyright (c) 1991, 1993, The Regents of the University of California.
        !             7:  *
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * This code is derived from software contributed to Berkeley by
        !            11:  * The Mach Operating System project at Carnegie-Mellon University.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. All advertising materials mentioning features or use of this software
        !            22:  *    must display the following acknowledgement:
        !            23:  *     This product includes software developed by Charles D. Cranor,
        !            24:  *      Washington University, the University of California, Berkeley and
        !            25:  *      its contributors.
        !            26:  * 4. Neither the name of the University nor the names of its contributors
        !            27:  *    may be used to endorse or promote products derived from this software
        !            28:  *    without specific prior written permission.
        !            29:  *
        !            30:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            31:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            32:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            33:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            34:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            35:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            36:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            37:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            38:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            39:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            40:  * SUCH DAMAGE.
        !            41:  *
        !            42:  *     @(#)vm_page.h   7.3 (Berkeley) 4/21/91
        !            43:  * from: Id: uvm_page.h,v 1.1.2.6 1998/02/04 02:31:42 chuck Exp
        !            44:  *
        !            45:  *
        !            46:  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
        !            47:  * All rights reserved.
        !            48:  *
        !            49:  * Permission to use, copy, modify and distribute this software and
        !            50:  * its documentation is hereby granted, provided that both the copyright
        !            51:  * notice and this permission notice appear in all copies of the
        !            52:  * software, derivative works or modified versions, and any portions
        !            53:  * thereof, and that both notices appear in supporting documentation.
        !            54:  *
        !            55:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            56:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
        !            57:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            58:  *
        !            59:  * Carnegie Mellon requests users of this software to return to
        !            60:  *
        !            61:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
        !            62:  *  School of Computer Science
        !            63:  *  Carnegie Mellon University
        !            64:  *  Pittsburgh PA 15213-3890
        !            65:  *
        !            66:  * any improvements or extensions that they make and grant Carnegie the
        !            67:  * rights to redistribute these changes.
        !            68:  */
        !            69:
        !            70: #ifndef _UVM_UVM_PAGE_H_
        !            71: #define _UVM_UVM_PAGE_H_
        !            72:
        !            73: /*
        !            74:  * uvm_page.h
        !            75:  */
        !            76:
        !            77: /*
        !            78:  *     Resident memory system definitions.
        !            79:  */
        !            80:
        !            81: /*
        !            82:  *     Management of resident (logical) pages.
        !            83:  *
        !            84:  *     A small structure is kept for each resident
        !            85:  *     page, indexed by page number.  Each structure
        !            86:  *     is an element of several lists:
        !            87:  *
        !            88:  *             A hash table bucket used to quickly
        !            89:  *             perform object/offset lookups
        !            90:  *
        !            91:  *             A list of all pages for a given object,
        !            92:  *             so they can be quickly deactivated at
        !            93:  *             time of deallocation.
        !            94:  *
        !            95:  *             An ordered list of pages due for pageout.
        !            96:  *
        !            97:  *     In addition, the structure contains the object
        !            98:  *     and offset to which this page belongs (for pageout),
        !            99:  *     and sundry status bits.
        !           100:  *
        !           101:  *     Fields in this structure are locked either by the lock on the
        !           102:  *     object that the page belongs to (O) or by the lock on the page
        !           103:  *     queues (P) [or both].
        !           104:  */
        !           105:
        !           106: #include <uvm/uvm_extern.h>
        !           107: #include <uvm/uvm_pglist.h>
        !           108:
        !           109: struct vm_page {
        !           110:        TAILQ_ENTRY(vm_page)    pageq;          /* queue info for FIFO
        !           111:                                                 * queue or free list (P) */
        !           112:        TAILQ_ENTRY(vm_page)    hashq;          /* hash table links (O)*/
        !           113:        TAILQ_ENTRY(vm_page)    listq;          /* pages in same object (O)*/
        !           114:
        !           115:        struct vm_anon          *uanon;         /* anon (O,P) */
        !           116:        struct uvm_object       *uobject;       /* object (O,P) */
        !           117:        voff_t                  offset;         /* offset into object (O,P) */
        !           118:
        !           119:        u_int                   pg_flags;       /* object flags [O or P] */
        !           120:
        !           121:        u_int                   pg_version;     /* version count [O] */
        !           122:        u_int                   wire_count;     /* wired down map refs [P] */
        !           123:
        !           124:        u_int                   loan_count;     /* number of active loans
        !           125:                                                 * to read: [O or P]
        !           126:                                                 * to modify: [O _and_ P] */
        !           127:        paddr_t                 phys_addr;      /* physical address of page */
        !           128:
        !           129: #ifdef __HAVE_VM_PAGE_MD
        !           130:        struct vm_page_md       mdpage;         /* pmap-specific data */
        !           131: #endif
        !           132: #if defined(UVM_PAGE_TRKOWN)
        !           133:        /* debugging fields to track page ownership */
        !           134:        pid_t                   owner;          /* proc that set PG_BUSY */
        !           135:        char                    *owner_tag;     /* why it was set busy */
        !           136: #endif
        !           137: };
        !           138:
        !           139: /*
        !           140:  * These are the flags defined for vm_page.
        !           141:  *
        !           142:  * Note: PG_FILLED and PG_DIRTY are added for the filesystems.
        !           143:  */
        !           144:
        !           145: /*
        !           146:  * locking rules:
        !           147:  *   PG_ ==> locked by object lock
        !           148:  *   PQ_ ==> lock by page queue lock
        !           149:  *   PQ_FREE is locked by free queue lock and is mutex with all other PQs
        !           150:  *   pg_flags may only be changed using the atomic operations.
        !           151:  *
        !           152:  * PG_ZERO is used to indicate that a page has been pre-zero'd.  This flag
        !           153:  * is only set when the page is on no queues, and is cleared when the page
        !           154:  * is placed on the free list.
        !           155:  */
        !           156:
        !           157: #define        PG_BUSY         0x00000001      /* page is locked */
        !           158: #define        PG_WANTED       0x00000002      /* someone is waiting for page */
        !           159: #define        PG_TABLED       0x00000004      /* page is in VP table  */
        !           160: #define        PG_CLEAN        0x00000008      /* page has not been modified */
        !           161: #define PG_CLEANCHK    0x00000010      /* clean bit has been checked */
        !           162: #define PG_RELEASED    0x00000020      /* page released while paging */
        !           163: #define        PG_FAKE         0x00000040      /* page is not yet initialized */
        !           164: #define PG_RDONLY      0x00000080      /* page must be mapped read-only */
        !           165: #define PG_ZERO                0x00000100      /* page is pre-zero'd */
        !           166:
        !           167: #define PG_PAGER1      0x00001000      /* pager-specific flag */
        !           168: #define PG_MASK                0x0000ffff
        !           169:
        !           170: #define PQ_FREE                0x00010000      /* page is on free list */
        !           171: #define PQ_INACTIVE    0x00020000      /* page is in inactive list */
        !           172: #define PQ_ACTIVE      0x00040000      /* page is in active list */
        !           173: #define PQ_ANON                0x00100000      /* page is part of an anon, rather
        !           174:                                           than an uvm_object */
        !           175: #define PQ_AOBJ                0x00200000      /* page is part of an anonymous
        !           176:                                           uvm_object */
        !           177: #define PQ_SWAPBACKED  (PQ_ANON|PQ_AOBJ)
        !           178: #define        PQ_ENCRYPT      0x00400000      /* page needs {en,de}cryption */
        !           179: #define PQ_MASK                0x00ff0000
        !           180:
        !           181: #define PG_PMAP0       0x01000000      /* Used by some pmaps. */
        !           182: #define PG_PMAP1       0x02000000      /* Used by some pmaps. */
        !           183: #define PG_PMAP2       0x04000000      /* Used by some pmaps. */
        !           184: #define PG_PMAP3       0x08000000      /* Used by some pmaps. */
        !           185:
        !           186: /*
        !           187:  * physical memory layout structure
        !           188:  *
        !           189:  * MD vmparam.h must #define:
        !           190:  *   VM_PHYSEG_MAX = max number of physical memory segments we support
        !           191:  *                (if this is "1" then we revert to a "contig" case)
        !           192:  *   VM_PHYSSEG_STRAT: memory sort/search options (for VM_PHYSEG_MAX > 1)
        !           193:  *     - VM_PSTRAT_RANDOM:   linear search (random order)
        !           194:  *     - VM_PSTRAT_BSEARCH:  binary search (sorted by address)
        !           195:  *     - VM_PSTRAT_BIGFIRST: linear search (sorted by largest segment first)
        !           196:  *      - others?
        !           197:  *   XXXCDC: eventually we should purge all left-over global variables...
        !           198:  */
        !           199: #define VM_PSTRAT_RANDOM       1
        !           200: #define VM_PSTRAT_BSEARCH      2
        !           201: #define VM_PSTRAT_BIGFIRST     3
        !           202:
        !           203: /*
        !           204:  * vm_physmemseg: describes one segment of physical memory
        !           205:  */
        !           206: struct vm_physseg {
        !           207:        paddr_t start;                  /* PF# of first page in segment */
        !           208:        paddr_t end;                    /* (PF# of last page in segment) + 1 */
        !           209:        paddr_t avail_start;            /* PF# of first free page in segment */
        !           210:        paddr_t avail_end;              /* (PF# of last free page in segment) +1  */
        !           211:        int     free_list;              /* which free list they belong on */
        !           212:        struct  vm_page *pgs;           /* vm_page structures (from start) */
        !           213:        struct  vm_page *lastpg;        /* vm_page structure for end */
        !           214: #ifdef __HAVE_PMAP_PHYSSEG
        !           215:        struct  pmap_physseg pmseg;     /* pmap specific (MD) data */
        !           216: #endif
        !           217: };
        !           218:
        !           219: #ifdef _KERNEL
        !           220:
        !           221: /*
        !           222:  * globals
        !           223:  */
        !           224:
        !           225: extern boolean_t vm_page_zero_enable;
        !           226:
        !           227: /*
        !           228:  *     Each pageable resident page falls into one of three lists:
        !           229:  *
        !           230:  *     free
        !           231:  *             Available for allocation now.
        !           232:  *     inactive
        !           233:  *             Not referenced in any map, but still has an
        !           234:  *             object/offset-page mapping, and may be dirty.
        !           235:  *             This is the list of pages that should be
        !           236:  *             paged out next.
        !           237:  *     active
        !           238:  *             A list of pages which have been placed in
        !           239:  *             at least one physical map.  This list is
        !           240:  *             ordered, in LRU-like fashion.
        !           241:  */
        !           242:
        !           243: extern struct pglist   vm_page_queue_free;     /* memory free queue */
        !           244: extern struct pglist   vm_page_queue_active;   /* active memory queue */
        !           245: extern struct pglist   vm_page_queue_inactive; /* inactive memory queue */
        !           246:
        !           247: /*
        !           248:  * physical memory config is stored in vm_physmem.
        !           249:  */
        !           250:
        !           251: extern struct vm_physseg vm_physmem[VM_PHYSSEG_MAX];
        !           252: extern int vm_nphysseg;
        !           253:
        !           254: /*
        !           255:  * handle inline options
        !           256:  */
        !           257:
        !           258: #ifdef UVM_PAGE_INLINE
        !           259: #define PAGE_INLINE static __inline
        !           260: #else
        !           261: #define PAGE_INLINE /* nothing */
        !           262: #endif /* UVM_PAGE_INLINE */
        !           263:
        !           264: /*
        !           265:  * prototypes: the following prototypes define the interface to pages
        !           266:  */
        !           267:
        !           268: void uvm_page_init(vaddr_t *, vaddr_t *);
        !           269: #if defined(UVM_PAGE_TRKOWN)
        !           270: void uvm_page_own(struct vm_page *, char *);
        !           271: #endif
        !           272: #if !defined(PMAP_STEAL_MEMORY)
        !           273: boolean_t uvm_page_physget(paddr_t *);
        !           274: #endif
        !           275: void uvm_page_rehash(void);
        !           276: void uvm_pageidlezero(void);
        !           277:
        !           278: PAGE_INLINE int uvm_lock_fpageq(void);
        !           279: PAGE_INLINE void uvm_unlock_fpageq(int);
        !           280:
        !           281: PAGE_INLINE void uvm_pageactivate(struct vm_page *);
        !           282: vaddr_t uvm_pageboot_alloc(vsize_t);
        !           283: PAGE_INLINE void uvm_pagecopy(struct vm_page *, struct vm_page *);
        !           284: PAGE_INLINE void uvm_pagedeactivate(struct vm_page *);
        !           285: void uvm_pagefree(struct vm_page *);
        !           286: void uvm_page_unbusy(struct vm_page **, int);
        !           287: PAGE_INLINE struct vm_page *uvm_pagelookup(struct uvm_object *, voff_t);
        !           288: PAGE_INLINE void uvm_pageunwire(struct vm_page *);
        !           289: PAGE_INLINE void uvm_pagewait(struct vm_page *, int);
        !           290: PAGE_INLINE void uvm_pagewake(struct vm_page *);
        !           291: PAGE_INLINE void uvm_pagewire(struct vm_page *);
        !           292: PAGE_INLINE void uvm_pagezero(struct vm_page *);
        !           293:
        !           294: PAGE_INLINE int uvm_page_lookup_freelist(struct vm_page *);
        !           295:
        !           296: static struct vm_page *PHYS_TO_VM_PAGE(paddr_t);
        !           297: static int vm_physseg_find(paddr_t, int *);
        !           298:
        !           299: /*
        !           300:  * macros
        !           301:  */
        !           302:
        !           303: #define uvm_lock_pageq()       simple_lock(&uvm.pageqlock)
        !           304: #define uvm_unlock_pageq()     simple_unlock(&uvm.pageqlock)
        !           305:
        !           306: #define uvm_pagehash(obj,off) \
        !           307:        (((unsigned long)obj+(unsigned long)atop(off)) & uvm.page_hashmask)
        !           308:
        !           309: #define        UVM_PAGEZERO_TARGET     (uvmexp.free)
        !           310:
        !           311: #define VM_PAGE_TO_PHYS(entry) ((entry)->phys_addr)
        !           312:
        !           313: /*
        !           314:  * when VM_PHYSSEG_MAX is 1, we can simplify these functions
        !           315:  */
        !           316:
        !           317: /*
        !           318:  * vm_physseg_find: find vm_physseg structure that belongs to a PA
        !           319:  */
        !           320: static __inline int
        !           321: vm_physseg_find(pframe, offp)
        !           322:        paddr_t pframe;
        !           323:        int     *offp;
        !           324: {
        !           325: #if VM_PHYSSEG_MAX == 1
        !           326:
        !           327:        /* 'contig' case */
        !           328:        if (pframe >= vm_physmem[0].start && pframe < vm_physmem[0].end) {
        !           329:                if (offp)
        !           330:                        *offp = pframe - vm_physmem[0].start;
        !           331:                return(0);
        !           332:        }
        !           333:        return(-1);
        !           334:
        !           335: #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH)
        !           336:        /* binary search for it */
        !           337:        int     start, len, try;
        !           338:
        !           339:        /*
        !           340:         * if try is too large (thus target is less than than try) we reduce
        !           341:         * the length to trunc(len/2) [i.e. everything smaller than "try"]
        !           342:         *
        !           343:         * if the try is too small (thus target is greater than try) then
        !           344:         * we set the new start to be (try + 1).   this means we need to
        !           345:         * reduce the length to (round(len/2) - 1).
        !           346:         *
        !           347:         * note "adjust" below which takes advantage of the fact that
        !           348:         *  (round(len/2) - 1) == trunc((len - 1) / 2)
        !           349:         * for any value of len we may have
        !           350:         */
        !           351:
        !           352:        for (start = 0, len = vm_nphysseg ; len != 0 ; len = len / 2) {
        !           353:                try = start + (len / 2);        /* try in the middle */
        !           354:
        !           355:                /* start past our try? */
        !           356:                if (pframe >= vm_physmem[try].start) {
        !           357:                        /* was try correct? */
        !           358:                        if (pframe < vm_physmem[try].end) {
        !           359:                                if (offp)
        !           360:                                        *offp = pframe - vm_physmem[try].start;
        !           361:                                return(try);            /* got it */
        !           362:                        }
        !           363:                        start = try + 1;        /* next time, start here */
        !           364:                        len--;                  /* "adjust" */
        !           365:                } else {
        !           366:                        /*
        !           367:                         * pframe before try, just reduce length of
        !           368:                         * region, done in "for" loop
        !           369:                         */
        !           370:                }
        !           371:        }
        !           372:        return(-1);
        !           373:
        !           374: #else
        !           375:        /* linear search for it */
        !           376:        int     lcv;
        !           377:
        !           378:        for (lcv = 0; lcv < vm_nphysseg; lcv++) {
        !           379:                if (pframe >= vm_physmem[lcv].start &&
        !           380:                    pframe < vm_physmem[lcv].end) {
        !           381:                        if (offp)
        !           382:                                *offp = pframe - vm_physmem[lcv].start;
        !           383:                        return(lcv);               /* got it */
        !           384:                }
        !           385:        }
        !           386:        return(-1);
        !           387:
        !           388: #endif
        !           389: }
        !           390:
        !           391: /*
        !           392:  * PHYS_TO_VM_PAGE: find vm_page for a PA.   used by MI code to get vm_pages
        !           393:  * back from an I/O mapping (ugh!).   used in some MD code as well.
        !           394:  */
        !           395: static __inline struct vm_page *
        !           396: PHYS_TO_VM_PAGE(pa)
        !           397:        paddr_t pa;
        !           398: {
        !           399:        paddr_t pf = atop(pa);
        !           400:        int     off;
        !           401:        int     psi;
        !           402:
        !           403:        psi = vm_physseg_find(pf, &off);
        !           404:        if (psi != -1)
        !           405:                return(&vm_physmem[psi].pgs[off]);
        !           406:        return(NULL);
        !           407: }
        !           408:
        !           409: #define VM_PAGE_IS_FREE(entry)  ((entry)->pg_flags & PQ_FREE)
        !           410:
        !           411: #endif /* _KERNEL */
        !           412:
        !           413: #endif /* _UVM_UVM_PAGE_H_ */

CVSweb