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
*/