1.\" $NetBSD: uvm_hotplug.9,v 1.6 2020/01/17 12:34:55 skrll Exp $ 2.\" 3.\" Copyright (c) 2016 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" This code is derived from software contributed to The NetBSD Foundation 7.\" by Cherry G Mathew and Santhosh N Raju. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28.\" POSSIBILITY OF SUCH DAMAGE. 29.\" 30.Dd January 17, 2020 31.Dt UVM_HOTPLUG 9 32.Os 33.Sh NAME 34.Nm uvm_physseg_init , 35.Nm uvm_physseg_valid_p , 36.Nm uvm_physseg_get_start , 37.Nm uvm_physseg_get_end , 38.Nm uvm_physseg_get_avail_start , 39.Nm uvm_physseg_get_avail_end , 40.Nm uvm_physseg_get_pg , 41.Nm uvm_physseg_get_pmseg , 42.Nm uvm_physseg_get_free_list , 43.Nm uvm_physseg_get_start_hint , 44.Nm uvm_physseg_set_start_hint , 45.Nm uvm_physseg_get_next , 46.Nm uvm_physseg_get_prev , 47.Nm uvm_physseg_get_first , 48.Nm uvm_physseg_get_last , 49.Nm uvm_physseg_get_highest_frame , 50.Nm uvm_physseg_find , 51.Nm uvm_page_physload , 52.Nm uvm_page_physunload , 53.Nm uvm_page_physunload_force , 54.Nm uvm_physseg_plug , 55.Nm uvm_physseg_unplug , 56.Nm uvm_physseg_set_avail_start , 57.Nm uvm_physseg_set_avail_end 58.Nd memory hotplug manager 59.Sh SYNOPSIS 60.In uvm/uvm_physseg.h 61.Ft void 62.Fn uvm_physseg_init "void" 63.Ft uvm_physseg_t 64.Fn uvm_page_physload "paddr_t start" "paddr_t end" "paddr_t avail_start" \ 65"paddr_t avail_end" "int free_list" 66.Ft bool 67.Fn uvm_page_physunload "uvm_physseg_t upm" "int free_list" \ 68"paddr_t *paddrp" 69.Ft bool 70.Fn uvm_page_physunload_force "uvm_physseg_t upm" "int free_list" \ 71"paddr_t *paddrp" 72.Ft bool 73.Fn uvm_physseg_plug "paddr_t pfn" "size_t npages" "uvm_physseg_t *upmp" 74.Ft bool 75.Fn uvm_physseg_unplug "paddr_t pfn" "size_t npages" 76.Sh DESCRIPTION 77These utility routines provide the ability to tell 78.Xr uvm 9 79about system memory segments. 80When the kernel is compiled with 81.Cd 'options UVM_HOTPLUG' , 82memory segments are handled in a dynamic data structure 83.Pq Xr rbtree 3 84compared to a static array when not. 85This enables kernel code to add 86or remove information about memory segments at any point after boot - 87thus "hotplug". 88.Pp 89.Fn uvm_page_physload , 90.Fn uvm_page_physunload , 91and 92.Fn uvm_page_physunload_force 93are legacy interfaces which may be removed in the future. 94They must 95never be used after 96.Xr uvm_init 9 . 97.Pp 98.Sy WARNING : 99This is an experimental feature and should not be used in production 100environments. 101Furthermore, attempting to "hotplug" without 102.Cd 'options UVM_HOTPLUG' 103after boot will almost certainly end in a 104.Xr panic 9 . 105.Sh USAGE 106.Ss INITIALIZING HOTPLUG 107The function 108.Fn uvm_physseg_init 109initializes the hotplug subsystem. 110This is expected to happen exactly 111once, at boot time, and from MD code. 112.Ss PLUGGING IN MEMORY 113.Fn uvm_page_physload 114registers 115.Xr uvm 9 116with a memory segment span, and on a specified 117.Fa free_list . 118It must be called at system boot time as part of setting up memory 119management. 120The arguments describe the start and end of the physical addresses of the 121segment, and the available start and end addresses of pages not already in use. 122If a system has memory banks of different speeds the slower memory should be 123given a higher 124.Fa free_list 125value. 126.Bl -tag -offset indent -width "avail_start" 127.It Fa start 128Starting page frame number of the physical memory segments. 129.It Fa end 130Ending page frame number of the physical memory segments. 131.It Fa avail_start 132Available starting page frame number of the physical memory segments. 133.It Fa avail_end 134Available ending page frame number of the physical memory segments. 135.It Fa free_list 136The free list types are defined in the Machine Dependent code. 137.El 138.Pp 139This function returns a valid 140.Dv uvm_physseg_t 141handle when a successful plug occurs, else it will return 142.Dv UVM_PHYSSEG_TYPE_INVALID 143when the plug fails. 144.Pp 145.Fn uvm_physseg_plug 146registers 147.Xr uvm 9 148with a memory segment span. 149It can also be called to initiate a hotplug and register a newly 150"hotplugged" physical memory range into the VM. 151Unlike 152.Fn uvm_page_physload 153this function can, if 154.Cd 'options UVM_HOTPLUG' 155is enabled at compile time, be used after 156.Xr uvm_init 9 . 157The arguments describe the start page frame, the number of pages to 158plug starting from the start page frame and an optional return variable, which 159points to a valid 160.Fa uvm_physseg_t 161handle when a successful plug occurs. 162.Bl -tag -offset indent -width "npages" 163.It Fa pfn 164Starting page frame number of the physical memory segment. 165.It Fa npages 166Total number of pages from the starting page frame number to plug in. 167.It Fa upmp 168If upmp is not 169.Dv NULL , 170then on a successful plug, a valid pointer to the uvm_physseg_t handle 171for the segment which was plugged is returned. 172.El 173.Pp 174This function returns 175.Fa true 176when a successful plug occurs, 177.Fa false 178otherwise. 179.Ss UNPLUGGING MEMORY 180The functions 181.Fn uvm_page_physunload , 182.Fn uvm_page_physunload_force , 183and 184.Fn uvm_physseg_unplug 185make 186.Xr uvm 9 187forget about previously registered memory segments or portions of 188such. 189.Pp 190.Fn uvm_page_physunload 191unloads pages from a segment (from the front or from the back) 192depending on its availability. 193When the last page is removed, the 194segment handle is invalidated and supporting metadata is freed. 195.Pp 196Note: This function can only be used during boot time. 197Pages, once unloaded, are unregistered from uvm and are therefore 198assumed to be managed by the code which called 199.Fn uvm_page_physunload 9 200(usually boot time MD code, for boottime memory "allocation"). 201.Pp 202The arguments are: 203.Bl -tag -offset indent -width "free_list" 204.It Fa upm 205The handle identifying segment from which we are trying to unload memory. 206.It Fa free_list 207The free list types are defined in the Machine Dependent code. 208.It Fa paddrp 209The pointer to the physical address that was unloaded. 210.El 211.Pp 212If the unload was successful, 213.Fa true 214is returned, 215.Fa false 216otherwise. 217.Pp 218.Fn uvm_page_physunload_force 219unconditionally unloads pages from a segment. 220When the last page is removed, the segment handle 221is invalidated and supporting metadata is freed. 222.Pp 223Note: This function can only be used during boot time. 224Pages, once unloaded, are unregistered from uvm and are therefore 225assumed to be managed by the code which called 226.Fn uvm_page_physunload_force 9 227(usually boot time MD code, for boottime memory "allocation"). 228.Pp 229The arguments are: 230.Bl -tag -offset indent -width "free_list" 231.It Fa upm 232The handle identifying segment from which we are trying to unload memory. 233.It Fa free_list 234The free list types are defined in the Machine Dependent code. 235.It Fa paddrp 236The pointer to the physical address that was unloaded. 237.El 238.Pp 239If the unload was successful 240.Fa true 241is returned, 242.Fa false 243otherwise. 244.Pp 245.Fn uvm_physseg_unplug 246can be called to unplug an existing physical memory segment. 247Unlike 248.Fn uvm_page_physunload 249and 250.Fn uvm_page_physunload_force , 251it can be called after 252.Xr uvm_init 9 , 253if 254.Cd 'options UVM_HOTPLUG' 255is enabled at compile time. 256.Fn uvm_hotplug 9 257makes no effort to manage the state of the underlying physical 258memory. 259It is up to the caller to ensure that it is not in use, 260either by 261.Xr uvm 9 , 262or by any other sub-system. 263Further, any hardware 264quiescing that may be required is the responsibility of MD code. 265The arguments 266describe the start page frame and the number of pages to unplug. 267The arguments are: 268.Bl -tag -offset indent -width "npages" 269.It Fa pfn 270Starting page frame number of the physical memory segment. 271.It Fa npages 272Total number of pages from the starting page frame number to unplug. 273.El 274.Pp 275Returns 276.Fa true 277or 278.Fa false 279depending on success or failure respectively. 280.Sh UTILITY FUNCTIONS 281.Bl -ohang 282.It Ft bool 283.Fn uvm_physseg_valid_p "uvm_physseg_t upm" 284.It Ft paddr_t 285.Fn uvm_physseg_get_start "uvm_physseg_t upm" 286.It Ft paddr_t 287.Fn uvm_physseg_get_end "uvm_physseg_t upm" 288.It Ft paddr_t 289.Fn uvm_physseg_get_avail_start "uvm_physseg_t upm" 290.It Ft paddr_t 291.Fn uvm_physseg_get_avail_end "uvm_physseg_t upm" 292.It Ft struct vm_page * 293.Fn uvm_physseg_get_pg "uvm_physseg_t upm" "paddr_t index" 294.It Ft struct pmap_physseg * 295.Fn uvm_physseg_get_pmesg "uvm_physseg_t upm" 296.It Ft int 297.Fn uvm_physseg_get_free_list "uvm_physseg_t upm" 298.It Ft u_int 299.Fn uvm_physseg_get_start_hint "uvm_physseg_t upm" 300.It Ft bool 301.Fn uvm_physseg_set_start_hint "uvm_physseg_t upm" "u_int start_hint" 302.It Ft uvm_physseg_t 303.Fn uvm_physseg_get_next "uvm_physseg_t upm" 304.It Ft uvm_physseg_t 305.Fn uvm_physseg_get_prev "uvm_physseg_t upm" 306.It Ft uvm_physseg_t 307.Fn uvm_physseg_get_first "void" 308.It Ft uvm_physseg_t 309.Fn uvm_physseg_get_last "void" 310.It Ft paddr_t 311.Fn uvm_physseg_get_highest_frame "void" 312.It Ft paddr_t 313.Fn uvm_physseg_find "paddr pframe" "psize_t *offsetp" 314.It Ft void 315.Fn uvm_physseg_set_avail_start "uvm_physseg_t upm" "paddr_t avail_start" 316.It Ft void 317.Fn uvm_physseg_set_avail_end "uvm_physseg_t upm" "paddr_t avail_end" 318.El 319.Pp 320.Fn uvm_physseg_valid_p 321validates a handle that is passed in, returns 322.Fa true 323if the given handle is valid, 324.Fa false 325otherwise. 326.Pp 327.Fn uvm_physseg_get_start 328if a valid 329.Fa uvm_physseg_t 330handle is passed in, it returns the starting physical address of 331the segment. 332The returned value is of type 333.Ft paddr_t . 334In case the handle is invalid the returned value will match 335.Ft ( paddr_t ) 336\-1. 337.Pp 338.Fn uvm_physseg_get_end 339if a valid 340.Fa uvm_physseg_t 341handle is passed in, it returns the ending physical address of the 342segment. 343The returned value is of type 344.Ft paddr_t . 345In case the handle is invalid the returned value will match 346.Ft ( paddr_t ) 347\-1. 348.Pp 349.Fn uvm_physseg_get_avail_start 350if a valid 351.Fa uvm_physseg_t 352handle is passed in, it returns the available starting physical 353address of the segment. 354The returned value is of type 355.Ft paddr_t . 356In case the handle is invalid the returned value will match 357.Ft ( paddr_t ) 358\-1. 359.Pp 360.Fn uvm_physseg_get_avail_end 361if a valid 362.Fa uvm_physseg_t 363handle is passed in, it returns the available ending physical 364address of the segment. 365The returned value is of type 366.Ft paddr_t . 367In case the handle is invalid the returned value will match 368.Ft ( paddr_t ) 369\-1. 370.Pp 371.Fn uvm_physseg_get_pg 372if a valid 373.Fa uvm_physseg_t 374handle along with an index value is passed in, it returns the 375.Fa struct vm_page * 376object contained in that location. 377.Pp 378.Fn uvm_physseg_get_pmseg 379if a valid 380.Fa uvm_physseg_t 381handle is passed in, it returns the 382.Fa struct pmap_physseg * 383object contained in the handle. 384.Pp 385.Fn uvm_physseg_get_free_list 386if a valid 387.Fa uvm_physseg_t 388handle is passed in, it returns the 389.Fa free_list 390type for which the current segment is associated with. 391The returned value is of 392type 393.Fa int . 394.Pp 395.Fn uvm_physseg_get_start_hint 396if a valid 397.Fa uvm_physseg_t 398handle is passed in, it returns the 399.Fa start_hint 400type for the current segment. 401The returned value is of type 402.Fa u_int . 403.Pp 404.Fn uvm_physseg_set_start_hint 405if a valid handle along with the 406.Fa start_hint 407is passed in, the value is set in the segment. 408And a 409.Fa true 410is returned to indicate a successful value setting. 411In case the handle is invalid a 412.Fa false 413is returned. 414.Pp 415.Fn uvm_physseg_get_next 416if a valid handle is passed in, it returns the next valid 417.Fa uvm_physseg_t 418handle in the sequence. 419However if the handle passed is the last segment in the 420sequence the function returns 421.Fa UVM_PHYSSEG_TYPE_INVALID_OVERFLOW . 422Passing an invalid handle is not fatal, and returns 423.Fa UVM_PHYSSEG_TYPE_INVALID . 424. 425.Pp 426.Fn uvm_physseg_get_prev 427if a valid handle is passed in, it returns the previous validh 428.Fa uvm_physseg_t 429handle in the sequence. 430However if the handle passed is the first segment in 431the sequence the function returns 432.Fa UVM_PHYSSEG_TYPE_INVALID_EMPTY . 433Passing an invalid handle is not fatal, and returns 434.Fa UVM_PHYSSEG_TYPE_INVALID . 435. 436.Pp 437.Fn uvm_physseg_get_first 438returns the first valid 439.Fa uvm_physseg_t 440handle in the sequence. 441However if there are no valid handles in the sequence 442yet, the function returns 443.Fa UVM_PHYSSEG_TYPE_INVALID_EMPTY . 444.Pp 445.Fn uvm_physseg_get_last 446returns the last valid 447.Fa uvm_physseg_t 448handle in the sequence. 449However if there are no valid handles in the sequence 450yet, the function returns 451.Fa UVM_PHYSSEG_TYPE_INVALID_EMPTY . 452.Pp 453.Fn uvm_physseg_get_highest_frame 454returns the frame number of the highest registered physical page frame 455which is of type 456.Ft paddr_t . 457XXX: Searching on empty sequences are not yet processed in the function. 458.Pp 459.Fn uvm_physseg_find 460searches for a given segment containing the page frame 461.Ft ( paddr_t ) 462passed in. 463If a segment that falls between starting and ending addresses is 464found, the corresponding 465.Fa uvm_physseg_t 466handle is returned else a 467.Fa UVM_PHYSSEG_TYPE_INVALID 468is returned. 469The second parameter, if not set to 470.Dv NULL , 471the offset value of the page frame passed in with respect to the 472starting address is set to the appropriate 473.Fa psize_t 474value if the search was successful in finding the segment. 475.Pp 476.Fn uvm_physseg_set_avail_start 477if a valid 478.Fa uvm_physseg_t 479handle is passed in along with the available starting physical address of the 480segment of type 481.Ft paddr_t , 482the value is set in the segment. 483.Pp 484.Fn uvm_physseg_set_avail_end 485if a valid 486.Fa uvm_physseg_t 487handle is passed in along with the available ending physical address of the 488segment of type 489.Ft paddr_t , 490the value is set in the segment. 491.Sh NOTES 492.Fn uvm_physseg_plug 493and 494.Fn uvm_physseg_unplug 495must never be used after 496.Xr uvm_init 9 497in a kernel build where 498.Cd 'options UVM_HOTPLUG' 499is not enabled. 500.Sh DIAGNOSTICS 501Tests for 502.Nm 503are in 504.Pa tests/sys/uvm . 505.Pp 506Unit / functional tests are in 507.Pa tests/sys/uvm/t_uvm_physseg.c . 508These tests focus on the expected working of the 509.Nm 510API and its utility functions. 511.Pp 512Load tests can be found in 513.Pa tests/sys/uvm/t_uvm_physseg_load.c . 514These tests focus on stressing the 515.Nm 516implementation in order to make performance comparisons between kernel 517builds with and without 518.Cd 'options UVM_HOTPLUG' 519. 520.\" .Sh RETURN VALUES 521.\" .Sh EXAMPLES 522.Sh CODE REFERENCES 523The uvm hotplug feature is implemented in the file 524.Pa sys/uvm/uvm_physseg.c . 525The uvm hotplug API is exported via 526.Pa sys/uvm/uvm_physseg.h . 527.Sh SEE ALSO 528.Xr extent 9 , 529.Xr free 9 , 530.Xr malloc 9 , 531.Xr memoryallocators 9 , 532.Xr uvm 9 533.Sh HISTORY 534This API emerged out of the need to insert new pages at runtime in the 535Xen 536.Xr x86/balloon 4 537driver. 538.Sh AUTHORS 539.An -nosplit 540.An Cherry G. Mathew 541.Aq Mt cherry@NetBSD.org 542designed and integrated the API. 543.Pp 544.An Santhosh N. Raju 545.Aq Mt santhosh.raju@gmail.com 546implemented the dynamic segment handling code and all tests for this API. 547.Pp 548.An Nick Hudson 549.Aq Mt skrll@NetBSD.org 550contributed bugfixes and testing on a wide range of hardware ports. 551