| UVM_HOTPLUG(9) | Kernel Developer's Manual | UVM_HOTPLUG(9) | 
uvm_physseg_init,
  uvm_physseg_valid,
  uvm_physseg_get_start,
  uvm_physseg_get_end,
  uvm_physseg_get_avail_start,
  uvm_physseg_get_avail_end,
  uvm_physseg_get_pg,
  uvm_physseg_get_pmseg,
  uvm_physseg_get_free_list,
  uvm_physseg_get_start_hint,
  uvm_physseg_set_start_hint,
  uvm_physseg_get_next,
  uvm_physseg_get_prev,
  uvm_physseg_get_first,
  uvm_physseg_get_last,
  uvm_physseg_get_highest_frame,
  uvm_physseg_find,
  uvm_page_physload,
  uvm_page_physunload,
  uvm_page_physunload_force,
  uvm_physseg_plug,
  uvm_physseg_unplug,
  uvm_physseg_set_avail_start,
  uvm_physseg_set_avail_end —
#include <uvm/uvm_physseg.h>
void
  
  uvm_physseg_init(void);
uvm_physseg_t
  
  uvm_page_physload(paddr_t
    start, paddr_t end,
    paddr_t avail_start,
    paddr_t avail_end,
    int free_list);
bool
  
  uvm_page_physunload(uvm_physseg_t
    upm, int free_list,
    paddr_t *paddrp);
bool
  
  uvm_page_physunload_force(uvm_physseg_t
    upm, int free_list,
    paddr_t *paddrp);
bool
  
  uvm_physseg_plug(paddr_t
    pfn, size_t npages,
    uvm_physseg_t *upmp);
bool
  
  uvm_physseg_unplug(paddr_t
    pfn, size_t
    npages);
'options
  UVM_HOTPLUG', memory segments are handled in a dynamic data structure
  (rbtree(3)) compared to a static
  array when not. This enables kernel code to add or remove information about
  memory segments at any point after boot - thus "hotplug".
uvm_page_physload(),
    uvm_page_physunload(), and
    uvm_page_physunload_force() are legacy interfaces
    which may be removed in the future. They must never be used after
    uvm_init(9).
WARNING: This is an experimental feature and
    should not be used in production environments. Furthermore, attempting to
    "hotplug" without 'options UVM_HOTPLUG'
    after boot will almost certainly end in a
    panic(9).
uvm_physseg_init() initializes the hotplug
  subsystem. This is expected to happen exactly once, at boot time, and from MD
  code.
uvm_page_physload() registers
  uvm(9) with a memory segment span,
  and on a specified free_list. It must be called at
  system boot time as part of setting up memory management. The arguments
  describe the start and end of the physical addresses of the segment, and the
  available start and end addresses of pages not already in use. If a system has
  memory banks of different speeds the slower memory should be given a higher
  free_list value.
This function returns a valid
    uvm_physseg_t handle when a successful plug occurs,
    else it will return UVM_PHYSSEG_TYPE_INVALID when
    the plug fails.
uvm_physseg_plug() registers
    uvm(9) with a memory segment
    span. It can also be called to initiate a hotplug and register a newly
    "hotplugged" physical memory range into the VM. Unlike
    uvm_page_physload() this function can, if
    'options UVM_HOTPLUG' is enabled at compile time, be
    used after uvm_init(9). The
    arguments describe the start page frame, the number of pages to plug
    starting from the start page frame and an optional return variable, which
    points to a valid uvm_physseg_t handle when a
    successful plug occurs.
NULL, then on a successful plug, a
      valid pointer to the uvm_physseg_t handle for the segment which was
      plugged is returned.This function returns true when a successful plug occurs, false otherwise.
uvm_page_physunload(),
  uvm_page_physunload_force(), and
  uvm_physseg_unplug() make
  uvm(9) forget about previously
  registered memory segments or portions of such.
uvm_page_physunload() unloads pages from a
    segment (from the front or from the back) depending on its availability.
    When the last page is removed, the segment handle is invalidated and
    supporting metadata is freed.
Note: This function can only be used during boot time. Pages, once
    unloaded, are unregistered from uvm and are therefore assumed to be managed
    by the code which called
    uvm_page_physunload(9)
    (usually boot time MD code, for boottime memory "allocation").
The arguments are:
If the unload was successful, true is returned, false otherwise.
uvm_page_physunload_force()
    unconditionally unloads pages from a segment. When the last page is removed,
    the segment handle is invalidated and supporting metadata is freed.
Note: This function can only be used during boot time. Pages, once
    unloaded, are unregistered from uvm and are therefore assumed to be managed
    by the code which called
    uvm_page_physunload_force(9)
    (usually boot time MD code, for boottime memory "allocation").
The arguments are:
If the unload was successful true is returned, false otherwise.
uvm_physseg_unplug() can be called to
    unplug an existing physical memory segment. Unlike
    uvm_page_physunload() and
    uvm_page_physunload_force(), it can be called after
    uvm_init(9), if
    'options UVM_HOTPLUG' is enabled at compile time.
    uvm_hotplug(9) makes no effort
    to manage the state of the underlying physical memory. It is up to the
    caller to ensure that it is not in use, either by
    uvm(9), or by any other
    sub-system. Further, any hardware quiescing that may be required is the
    responsibility of MD code. The arguments describe the start page frame and
    the number of pages to unplug. The arguments are:
Returns true or false depending on success or failure respectively.
uvm_physseg_valid(uvm_physseg_t
      upm)uvm_physseg_get_start(uvm_physseg_t
      upm)uvm_physseg_get_end(uvm_physseg_t
      upm)uvm_physseg_get_avail_start(uvm_physseg_t
      upm)uvm_physseg_get_avail_end(uvm_physseg_t
      upm)uvm_physseg_get_pg(uvm_physseg_t
      upm, paddr_t index)uvm_physseg_get_pmesg(uvm_physseg_t
      upm)uvm_physseg_get_free_list(uvm_physseg_t
      upm)uvm_physseg_get_start_hint(uvm_physseg_t
      upm)uvm_physseg_set_start_hint(uvm_physseg_t
      upm, u_int start_hint)uvm_physseg_get_next(uvm_physseg_t
      upm)uvm_physseg_get_prev(uvm_physseg_t
      upm)uvm_physseg_get_first(void)uvm_physseg_get_last(void)uvm_physseg_get_highest_frame(void)uvm_physseg_find(paddr
      pframe, psize_t *offsetp)uvm_physseg_set_avail_start(uvm_physseg_t
      upm, paddr_t avail_start)uvm_physseg_set_avail_end(uvm_physseg_t
      upm, paddr_t avail_end)uvm_physseg_valid() validates a handle
    that is passed in, returns true if the given handle is
    valid, false otherwise.
uvm_physseg_get_start() if a valid
    uvm_physseg_t handle is passed in, it returns the
    starting physical address of the segment. The returned value is of type
    paddr_t. In case the handle is invalid the returned
    value will match (paddr_t) -1.
uvm_physseg_get_end() if a valid
    uvm_physseg_t handle is passed in, it returns the
    ending physical address of the segment. The returned value is of type
    paddr_t. In case the handle is invalid the returned
    value will match (paddr_t) -1.
uvm_physseg_get_avail_start() if a valid
    uvm_physseg_t handle is passed in, it returns the
    available starting physical address of the segment. The returned value is of
    type paddr_t. In case the handle is invalid the
    returned value will match (paddr_t) -1.
uvm_physseg_get_avail_end() if a valid
    uvm_physseg_t handle is passed in, it returns the
    available ending physical address of the segment. The returned value is of
    type paddr_t. In case the handle is invalid the
    returned value will match (paddr_t) -1.
uvm_physseg_get_pg() if a valid
    uvm_physseg_t handle along with an index value is
    passed in, it returns the struct vm_page * object
    contained in that location.
uvm_physseg_get_pmseg() if a valid
    uvm_physseg_t handle is passed in, it returns the
    struct pmap_physseg * object contained in the
  handle.
uvm_physseg_get_free_list() if a valid
    uvm_physseg_t handle is passed in, it returns the
    free_list type for which the current segment is
    associated with. The returned value is of type
  int.
uvm_physseg_get_start_hint() if a valid
    uvm_physseg_t handle is passed in, it returns the
    start_hint type for the current segment. The returned
    value is of type u_int.
uvm_physseg_set_start_hint() if a valid
    handle along with the start_hint is passed in, the
    value is set in the segment. And a true is returned to
    indicate a successful value setting. In case the handle is invalid a
    false is returned.
uvm_physseg_get_next() if a valid handle
    is passed in, it returns the next valid uvm_physseg_t
    handle in the sequence. However if the handle passed is the last segment in
    the sequence the function returns
    UVM_PHYSSEG_TYPE_INVALID_OVERFLOW. Passing an invalid
    handle is not fatal, and returns
    UVM_PHYSSEG_TYPE_INVALID.
uvm_physseg_get_prev() if a valid handle
    is passed in, it returns the previous validh
    uvm_physseg_t handle in the sequence. However if the
    handle passed is the first segment in the sequence the function returns
    UVM_PHYSSEG_TYPE_INVALID_EMPTY. Passing an invalid
    handle is not fatal, and returns
    UVM_PHYSSEG_TYPE_INVALID.
uvm_physseg_get_first() returns the first
    valid uvm_physseg_t handle in the sequence. However if
    there are no valid handles in the sequence yet, the function returns
    UVM_PHYSSEG_TYPE_INVALID_EMPTY.
uvm_physseg_get_last() returns the last
    valid uvm_physseg_t handle in the sequence. However if
    there are no valid handles in the sequence yet, the function returns
    UVM_PHYSSEG_TYPE_INVALID_EMPTY.
uvm_physseg_get_highest_frame() returns
    the frame number of the highest registered physical page frame which is of
    type paddr_t. XXX: Searching on empty sequences are
    not yet processed in the function.
uvm_physseg_find() searches for a given
    segment containing the page frame (paddr_t) passed in.
    If a segment that falls between starting and ending addresses is found, the
    corresponding uvm_physseg_t handle is returned else a
    UVM_PHYSSEG_TYPE_INVALID is returned. The second
    parameter, if not set to NULL, the offset value of
    the page frame passed in with respect to the starting address is set to the
    appropriate psize_t value if the search was successful
    in finding the segment.
uvm_physseg_set_avail_start() if a valid
    uvm_physseg_t handle is passed in along with the
    available starting physical address of the segment of type
    paddr_t, the value is set in the segment.
uvm_physseg_set_avail_end() if a valid
    uvm_physseg_t handle is passed in along with the
    available ending physical address of the segment of type
    paddr_t, the value is set in the segment.
uvm_physseg_plug() and
  uvm_physseg_unplug() must never be used after
  uvm_init(9) in a kernel build
  where 'options UVM_HOTPLUG' is not enabled.
uvm_physseg_init are in
  tests/sys/uvm.
Unit / functional tests are in
    tests/sys/uvm/t_uvm_physseg.c. These tests focus on
    the expected working of the uvm_physseg_init API and
    its utility functions.
Load tests can be found in
    tests/sys/uvm/t_uvm_physseg_load.c. These tests
    focus on stressing the uvm_physseg_init
    implementation in order to make performance comparisons between kernel
    builds with and without 'options UVM_HOTPLUG'
Santhosh N. Raju <santhosh.raju@gmail.com> implemented the dynamic segment handling code and all tests for this API.
Nick Hudson <skrll@NetBSD.org> contributed bugfixes and testing on a wide range of hardware ports.
| November 20, 2016 | NetBSD 9.3 |