UVM_HOTPLUG(9)
π UVM_HOTPLUG(9) β memory hotplug manager π
okay bestie, welcome to UVM_HOTPLUG(9) from the Kernel Developer's Manual. It's literally the page for the kernel's memory hotplug manager, and it is giving experimental main character energy. π«Ά
β¨ NAME β¨
gather round, because the whole hotplug squad is here: uvm_physseg_init, uvm_physseg_valid_p, 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, and uvm_physseg_set_avail_end β together they're the memory hotplug manager. π
πΈ SYNOPSIS πΈ
#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);
π DESCRIPTION π
So these utility routines are the ones that let you tell uvm(9) about system memory segments. Obsessed. When the kernel is compiled with 'options UVM_HOTPLUG', memory segments are handled in a dynamic data structure (rbtree(3)) compared to a static array when not. That means kernel code can add or remove information about memory segments at any point after boot β hence, β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). no cap, that part is serious.
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 apanic(9). π
π USAGE π
INITIALIZING HOTPLUG
The function uvm_physseg_init() initializes the hotplug subsystem. This is expected to happen exactly once, at boot time, and from MD code. π§
PLUGGING IN MEMORY
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.
The arguments are:
startβ Starting page frame number of the physical memory segments.endβ Ending page frame number of the physical memory segments.avail_startβ Available starting page frame number of the physical memory segments.avail_endβ Available ending page frame number of the physical memory segments.free_listβ The free list types are defined in the Machine Dependent code.
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.
The arguments are:
pfnβ Starting page frame number of the physical memory segment.npagesβ Total number of pages from the starting page frame number to plug in.upmpβ Ifupmpis notNULL, then on a successful plug, a valid pointer to theuvm_physseg_thandle for the segment which was plugged is returned.
This function returns true when a successful plug occurs, false otherwise. β
UNPLUGGING MEMORY
The functions 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:
upmβ The handle identifying segment from which we are trying to unload memory.free_listβ The free list types are defined in the Machine Dependent code.paddrpβ The pointer to the physical address that was unloaded.
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:
upmβ The handle identifying segment from which we are trying to unload memory.free_listβ The free list types are defined in the Machine Dependent code.paddrpβ The pointer to the physical address that was unloaded.
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:
pfnβ Starting page frame number of the physical memory segment.npagesβ Total number of pages from the starting page frame number to unplug.
Returns true or false depending on success or failure respectively. π
β¨ UTILITY FUNCTIONS β¨
bool
uvm_physseg_valid_p(uvm_physseg_t upm)
paddr_t
uvm_physseg_get_start(uvm_physseg_t upm)
paddr_t
uvm_physseg_get_end(uvm_physseg_t upm)
paddr_t
uvm_physseg_get_avail_start(uvm_physseg_t upm)
paddr_t
uvm_physseg_get_avail_end(uvm_physseg_t upm)
struct vm_page *
uvm_physseg_get_pg(uvm_physseg_t upm, paddr_t index)
struct pmap_physseg *
uvm_physseg_get_pmesg(uvm_physseg_t upm)
int
uvm_physseg_get_free_list(uvm_physseg_t upm)
u_int
uvm_physseg_get_start_hint(uvm_physseg_t upm)
bool
uvm_physseg_set_start_hint(uvm_physseg_t upm, u_int start_hint)
uvm_physseg_t
uvm_physseg_get_next(uvm_physseg_t upm)
uvm_physseg_t
uvm_physseg_get_prev(uvm_physseg_t upm)
uvm_physseg_t
uvm_physseg_get_first(void)
uvm_physseg_t
uvm_physseg_get_last(void)
paddr_t
uvm_physseg_get_highest_frame(void)
paddr_t
uvm_physseg_find(paddr pframe, psize_t *offsetp)
void
uvm_physseg_set_avail_start(uvm_physseg_t upm, paddr_t avail_start)
void
uvm_physseg_set_avail_end(uvm_physseg_t upm, paddr_t avail_end)
uvm_physseg_valid_p()β vibe check for a handle: returnstrueif theuvm_physseg_tyou passed in is valid, andfalseif it's not. πuvm_physseg_get_start()β if a validuvm_physseg_thandle is passed in, it returns the starting physical address of the segment as apaddr_t. If the handle is invalid, you get(paddr_t) -1. No cap. β¨uvm_physseg_get_end()β same deal but for the ending physical address. Valid handle βpaddr_tend address; invalid handle β(paddr_t) -1. πuvm_physseg_get_avail_start()β returns the available starting physical address of the segment aspaddr_twhen the handle is valid. Invalid handle?(paddr_t) -1. π¦uvm_physseg_get_avail_end()β returns the available ending physical address of the segment aspaddr_tfor a valid handle. Invalid handle gives(paddr_t) -1. πΈuvm_physseg_get_pg()β give it a validuvm_physseg_thandle plus an index, and it returns thestruct vm_page *object chillin' at that location. π«Άuvm_physseg_get_pmseg()β okay so the signature above saysuvm_physseg_get_pmesgbut the description calls ituvm_physseg_get_pmseg()β iconic typo energy, we keep both. With a valid handle it returns thestruct pmap_physseg *object contained in the handle. πuvm_physseg_get_free_list()β valid handle in, and it returns thefree_listtype that the current segment is associated with. Return type isint. π₯uvm_physseg_get_start_hint()β valid handle in, and it returns thestart_hinttype for the current segment. Return type isu_int. βuvm_physseg_set_start_hint()β pass a valid handle plus astart_hint, and the value gets set in the segment. Returnstrueto say βslay, it workedβ. Invalid handle βfalse. πuvm_physseg_get_next()β valid handle β next validuvm_physseg_thandle in the sequence. But if the handle you passed is the last segment in the sequence, it returnsUVM_PHYSSEG_TYPE_INVALID_OVERFLOW. Passing an invalid handle is not fatal and returnsUVM_PHYSSEG_TYPE_INVALID. πuvm_physseg_get_prev()β valid handle β previous validuvm_physseg_thandle in the sequence. If you're at the first segment, it returnsUVM_PHYSSEG_TYPE_INVALID_EMPTY. Passing an invalid handle is not fatal and returnsUVM_PHYSSEG_TYPE_INVALID. πuvm_physseg_get_first()β returns the first validuvm_physseg_thandle in the sequence. If there are no valid handles in the sequence yet, you getUVM_PHYSSEG_TYPE_INVALID_EMPTY. π§uvm_physseg_get_last()β returns the last validuvm_physseg_thandle in the sequence. If there are no valid handles in the sequence yet, it'sUVM_PHYSSEG_TYPE_INVALID_EMPTY. πuvm_physseg_get_highest_frame()β returns the frame number of the highest registered physical page frame, typepaddr_t. There's a lilXXX:note: β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) you pass in. If a segment that falls between the starting and ending addresses is found, the correspondinguvm_physseg_thandle is returned; otherwiseUVM_PHYSSEG_TYPE_INVALIDis returned. The second parameter, if not set toNULL, gets the offset value of the page frame passed in with respect to the starting address set to the appropriatepsize_tvalue if the search was successful in finding the segment. πuvm_physseg_set_avail_start()β if you pass a validuvm_physseg_thandle along with the available starting physical address of the segment (typepaddr_t), the value is set in the segment. πuvm_physseg_set_avail_end()β same but for the available ending physical address of the segment (typepaddr_t). Valid handle β value set in the segment. π
πΈ NOTES πΈ
okay so the big never energy here: 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. Periodt. π¨
π©Ί DIAGNOSTICS π©Ί
- Tests for
uvm_physseg_initare intests/sys/uvm. π©Ί - Unit / functional tests live in
tests/sys/uvm/t_uvm_physseg.c. These tests focus on the expected working of theuvm_physseg_initAPI and its utility functions. π - Load tests can be found in
tests/sys/uvm/t_uvm_physseg_load.c. These tests focus on stressing theuvm_physseg_initimplementation in order to make performance comparisons between kernel builds with and without'options UVM_HOTPLUG'. π₯
π CODE REFERENCES π
The uvm hotplug feature is implemented in sys/uvm/uvm_physseg.c. The uvm hotplug API is exported via sys/uvm/uvm_physseg.h. iykyk. π«Ά
π SEE ALSO π
π HISTORY π
This API emerged out of the need to insert new pages at runtime in the Xen x86/balloon(4) driver. iconic origin story tbh. β¨
π AUTHORS π
- Cherry G. Mathew β¨cherry@NetBSD.orgβ© β designed and integrated the API. π
- 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. π«Ά
That's the whole page, bestie! This edition is from Debian, dated January 17, 2020, and the manpage is UVM_HOTPLUG(9). Stay iconic! πβ¨
π¦ where this page comes from
- nixpkgs unstable: netbsd-source 11.0
- Copyright (c) 2016 The NetBSD Foundation, Inc
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms