xref: /netbsd-src/share/man/man9/uvm_hotplug.9 (revision 2098dd207ba9ff1225a8b4f13afae498a058cf11)
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