120 /* * Management of resident (logical) pages. * * Each resident page has a vm_page structure, indexed by page number. * There are several lists in the structure: * * - A red-black tree rooted with the containing object is used to * quickly perform object+offset lookups. * - A list of all pages for a given object, for a quick deactivation * at a 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. * * Note that the page structure has no lock of its own. The page is * generally protected by its owner's lock (UVM object or amap/anon). * It should be noted that UVM has to serialize pmap(9) operations on * the managed pages, e.g. for pmap_enter() calls. Hence, the lock * order is as follows: * * [vmpage-owner-lock] -> * any pmap locks (e.g. PV hash lock) * * Since the kernel is always self-consistent, no serialization is * required for unmanaged mappings, e.g. for pmap_kenter_pa() calls. * * Field markings and the corresponding locks: * * f: free page queue lock, uvm_fpageqlock * o: page owner (uvm_object::vmobjlock, vm_amap::am_lock, vm_anon::an_lock) * p: page queue lock, uvm_pageqlock * o,p: o|p for read, o&p for write * w: wired page queue or uvm_pglistalloc: * => wired page queue: o&p to change, stable from wire to unwire * XXX What about concurrent or nested wire? * => uvm_pglistalloc: owned by caller * ?: locked by pmap or assumed page owner's lock * * UVM and pmap(9) may use uvm_page_locked_p() to assert whether the * page owner's lock is acquired. * * A page can have one of four identities: * * o free * => pageq.list is entry on global free page queue * => listq.list is entry on per-CPU free page queue * => uanon is unused (or (void *)0xdeadbeef for DEBUG) * => uobject is unused (or (void *)0xdeadbeef for DEBUG) * => PQ_FREE is set in pqflags * o owned by a uvm_object * => pageq.queue is entry on wired page queue, if any * => listq.queue is entry on list of pages in object * => uanon is NULL or the vm_anon to which it has been O->A loaned * => uobject is owner * o owned by a vm_anon * => pageq is unused (XXX correct?) * => listq is unused (XXX correct?) * => uanon is owner * => uobject is NULL * => PQ_ANON is set in pqflags * o allocated by uvm_pglistalloc * => pageq.queue is entry on resulting pglist, owned by caller * => listq is unused (XXX correct?) * => uanon is unused * => uobject is unused * * The following transitions are allowed: * * - uvm_pagealloc: free -> owned by a uvm_object/vm_anon * - uvm_pagefree: owned by a uvm_object/vm_anon -> free * - uvm_pglistalloc: free -> allocated by uvm_pglistalloc * - uvm_pglistfree: allocated by uvm_pglistalloc -> free */