2 .\" Copyright (c) 2018-2021 Maxime Villard, m00nbsd.net
3 .\" All rights reserved.
5 .\" This code is part of the NVMM hypervisor.
7 .\" Redistribution and use in source and binary forms, with or without
8 .\" modification, are permitted provided that the following conditions
10 .\" 1. Redistributions of source code must retain the above copyright
11 .\" notice, this list of conditions and the following disclaimer.
12 .\" 2. Redistributions in binary form must reproduce the above copyright
13 .\" notice, this list of conditions and the following disclaimer in the
14 .\" documentation and/or other materials provided with the distribution.
16 .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 .\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 .\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 .\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 .\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 .Nm nvmm_machine_create ,
36 .Nm nvmm_machine_destroy ,
37 .Nm nvmm_machine_configure ,
38 .Nm nvmm_vcpu_create ,
39 .Nm nvmm_vcpu_destroy ,
40 .Nm nvmm_vcpu_configure ,
41 .Nm nvmm_vcpu_getstate ,
42 .Nm nvmm_vcpu_setstate ,
43 .Nm nvmm_vcpu_inject ,
53 .Nd NVMM Virtualization API
61 .Fn nvmm_capability "struct nvmm_capability *cap"
63 .Fn nvmm_machine_create "struct nvmm_machine *mach"
65 .Fn nvmm_machine_destroy "struct nvmm_machine *mach"
67 .Fn nvmm_machine_configure "struct nvmm_machine *mach" "uint64_t op" \
70 .Fn nvmm_vcpu_create "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \
71 "struct nvmm_vcpu *vcpu"
73 .Fn nvmm_vcpu_destroy "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu"
75 .Fn nvmm_vcpu_configure "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" \
76 "uint64_t op" "void *conf"
78 .Fn nvmm_vcpu_getstate "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" \
81 .Fn nvmm_vcpu_setstate "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" \
84 .Fn nvmm_vcpu_inject "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu"
86 .Fn nvmm_vcpu_run "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu"
88 .Fn nvmm_hva_map "struct nvmm_machine *mach" "uintptr_t hva" "size_t size"
90 .Fn nvmm_hva_unmap "struct nvmm_machine *mach" "uintptr_t hva" "size_t size"
92 .Fn nvmm_gpa_map "struct nvmm_machine *mach" "uintptr_t hva" "gpaddr_t gpa" \
93 "size_t size" "int prot"
95 .Fn nvmm_gpa_unmap "struct nvmm_machine *mach" "uintptr_t hva" "gpaddr_t gpa" \
98 .Fn nvmm_gva_to_gpa "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" \
99 "gvaddr_t gva" "gpaddr_t *gpa" "nvmm_prot_t *prot"
101 .Fn nvmm_gpa_to_hva "struct nvmm_machine *mach" "gpaddr_t gpa" \
102 "uintptr_t *hva" "nvmm_prot_t *prot"
104 .Fn nvmm_assist_io "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu"
106 .Fn nvmm_assist_mem "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu"
109 provides a library for emulator software to handle hardware-accelerated virtual
112 A virtual machine is described by an opaque structure,
114 Emulator software should not attempt to modify this structure directly, and
115 should use the API provided by
117 to manage virtual machines.
118 A virtual CPU is described by a public structure,
124 .Sx NVMM Initialization
128 gets the capabilities of NVMM.
133 .Fn nvmm_machine_create
134 creates a virtual machine in the kernel.
137 structure is initialized, and describes the machine.
139 .Fn nvmm_machine_destroy
140 destroys the virtual machine described in
143 .Fn nvmm_machine_configure
144 configures, on the machine
146 the parameter indicated in
149 describes the value of the parameter.
152 creates a virtual CPU in the machine
159 .Fn nvmm_vcpu_destroy
160 destroys the virtual CPU identified by
165 .Fn nvmm_vcpu_configure
166 configures, on the VCPU
170 the parameter indicated in
173 describes the value of the parameter.
175 .Fn nvmm_vcpu_getstate
176 gets the state of the virtual CPU identified by
181 is the bitmap of the components that are to be retrieved.
182 The components are located in
188 .Fn nvmm_vcpu_setstate
189 sets the state of the virtual CPU identified by
194 is the bitmap of the components that are to be set.
195 The components are located in
202 injects into the CPU identified by
206 an event described by
213 runs the CPU identified by
217 until a VM exit is triggered.
220 structure is filled to indicate the exit reason, and the associated parameters
228 in the calling process' virtual address space.
229 This buffer is allowed to be subsequently mapped in a virtual machine.
232 unmaps the buffer of size
236 from the calling process' virtual address space.
239 maps into the guest physical memory beginning on address
245 of the calling process' virtual address space.
248 parameter must point to a buffer that was previously mapped with
252 removes the guest physical memory area beginning on address
260 translates, on the CPU
264 the guest virtual address given in
266 into a guest physical address returned in
268 The associated page permissions are returned in
271 must be page-aligned.
274 translates, on the machine
276 the guest physical address indicated in
278 into a host virtual address returned in
280 The associated page permissions are returned in
283 must be page-aligned.
286 emulates the I/O operation described in
297 emulates the Mem operation described in
306 .Ss NVMM Initialization
307 NVMM initialization is performed by the
309 function, which must be invoked by emulator software before any other NVMM
313 opens the NVMM device, and expects to have the proper permissions to do so.
314 In a default configuration, this implies being part of the "nvmm" group.
315 If using a special configuration, emulator software should arrange to have the
316 proper permissions before invoking
318 and can drop them after the call has completed.
320 It is to be noted that
322 may perform non-re-entrant operations, and should be called only once.
326 structure helps emulator software identify the capabilities offered by NVMM on
329 struct nvmm_capability {
333 uint64_t max_machines;
344 field indicates the maximum number of virtual machines supported, while
346 indicates the maximum number of VCPUs supported per virtual machine.
347 .Ss Machine Ownership
348 When a process creates a virtual machine via
349 .Fn nvmm_machine_create ,
350 it is considered the owner of this machine.
351 No other processes than the owner can operate a virtual machine.
353 When an owner exits, all the virtual machines associated with it are destroyed,
354 if they were not already destroyed by the owner itself via
355 .Fn nvmm_machine_destroy .
357 Virtual machines are not inherited across
360 .Ss Machine Configuration
361 Emulator software can configure several parameters of a virtual machine by using
362 .Fn nvmm_machine_configure .
363 Currently, no parameters are implemented.
364 .Ss VCPU Configuration
365 Emulator software can configure several parameters of a VCPU by using
366 .Fn nvmm_vcpu_configure ,
367 which can take the following operations:
369 .Bl -bullet -offset indent -compact
371 .Dv NVMM_VCPU_CONF_CALLBACKS :
372 register assist callbacks.
378 The other fields depend on the architecture.
380 On x86 there are two additional operations available:
382 .Bl -bullet -offset indent -compact
384 .Dv NVMM_VCPU_CONF_CPUID :
385 configure the information returned to the guest by the CPUID instruction.
387 .Dv NVMM_VCPU_CONF_TPR :
388 configure whether to return to the emulator when the guest updates its TPR.
390 .Ss Guest-Host Mappings
391 Each virtual machine has an associated guest physical memory.
392 Emulator software is allowed to modify this guest physical memory by mapping
393 it into some parts of its virtual address space.
395 Emulator software should follow the following steps to achieve that:
397 .Bl -bullet -offset indent -compact
401 to create in the host's virtual address space an area of memory that can
402 be shared with a guest.
405 parameter will be a pointer to an area that was previously mapped via
408 will replace the content of the area, and will make it read-write (but not
411 Make available in the guest an area of guest physical memory, by calling
415 parameter the value that was previously given to
418 does not replace the content of any memory, it only creates a direct link
424 removes this link without modifying
428 The guest will then be able to use the guest physical address passed in the
432 Each change the guest makes in
434 will be reflected in the host's
438 It is illegal for emulator software to use
440 on an area that was mapped via
443 A VCPU state area is a structure that entirely defines the content of the
445 Only one such structure exists, for x86:
447 struct nvmm_x64_state {
448 struct nvmm_x64_state_seg segs[NVMM_X64_NSEG];
449 uint64_t gprs[NVMM_X64_NGPR];
450 uint64_t crs[NVMM_X64_NCR];
451 uint64_t drs[NVMM_X64_NDR];
452 uint64_t msrs[NVMM_X64_NMSR];
453 struct nvmm_x64_state_intr intr;
454 struct nvmm_x64_state_fpu fpu;
456 #define nvmm_vcpu_state nvmm_x64_state
459 Refer to functional examples to see precisely how to use this structure.
461 A VCPU state area is divided in sub-states.
464 parameter is used to get and set the VCPU state; it acts as a bitmap which
465 indicates which sub-states to get or set.
467 During VM exits, a partial VCPU state area is provided in
472 .Ss VCPU Programming Model
473 A VCPU is described by a public structure,
478 struct nvmm_vcpu_state *state;
479 struct nvmm_vcpu_event *event;
480 struct nvmm_vcpu_exit *exit;
484 This structure is used both publicly by emulator software and internally by
486 Emulator software should not modify the pointers of this structure, because
487 they are initialized to special values by
491 .Fn nvmm_vcpu_getstate
492 will fetch the desired parts of the VCPU state and put them in
495 .Fn nvmm_vcpu_setstate
496 will install in the VCPU the desired parts of
500 will inject in the VCPU the event in
506 with the VCPU exit information.
508 If emulator software uses several threads, a VCPU should be associated with
509 only one thread, and only this thread should perform VCPU modifications.
510 Emulator software should not modify the state of a VCPU with several
515 structure is used to handle VM exits:
518 #define NVMM_VCPU_EXIT_NONE 0x0000000000000000ULL
519 #define NVMM_VCPU_EXIT_INVALID 0xFFFFFFFFFFFFFFFFULL
520 /* x86: operations. */
521 #define NVMM_VCPU_EXIT_MEMORY 0x0000000000000001ULL
522 #define NVMM_VCPU_EXIT_IO 0x0000000000000002ULL
523 /* x86: changes in VCPU state. */
524 #define NVMM_VCPU_EXIT_SHUTDOWN 0x0000000000001000ULL
525 #define NVMM_VCPU_EXIT_INT_READY 0x0000000000001001ULL
526 #define NVMM_VCPU_EXIT_NMI_READY 0x0000000000001002ULL
527 #define NVMM_VCPU_EXIT_HALTED 0x0000000000001003ULL
528 #define NVMM_VCPU_EXIT_TPR_CHANGED 0x0000000000001004ULL
529 /* x86: instructions. */
530 #define NVMM_VCPU_EXIT_RDMSR 0x0000000000002000ULL
531 #define NVMM_VCPU_EXIT_WRMSR 0x0000000000002001ULL
532 #define NVMM_VCPU_EXIT_MONITOR 0x0000000000002002ULL
533 #define NVMM_VCPU_EXIT_MWAIT 0x0000000000002003ULL
534 #define NVMM_VCPU_EXIT_CPUID 0x0000000000002004ULL
536 struct nvmm_vcpu_exit {
549 field indicates the reason of the VM exit.
550 Additional parameters describing the exit can be present in
553 contains a partial, implementation-specific VCPU state, usable as a fast-path
554 to retrieve certain state values.
556 It is possible that a VM exit was caused by a reason internal to the host
557 kernel, and that emulator software should not be concerned with.
558 In this case, the exit reason is set to
559 .Dv NVMM_VCPU_EXIT_NONE .
560 This gives a chance for emulator software to halt the VM in its tracks.
562 Refer to functional examples to see precisely how to handle VM exits.
564 It is possible to inject an event into a VCPU.
565 An event can be a hardware interrupt, a software interrupt, or a software
566 exception, defined by:
568 #define NVMM_VCPU_EVENT_EXCP 0
569 #define NVMM_VCPU_EVENT_INTR 1
571 struct nvmm_vcpu_event {
582 This describes an event of type
584 to be sent to vector number
586 with a possible additional
588 code that is implementation-specific.
590 It is possible that the VCPU is in a state where it cannot receive this
593 .Bl -bullet -offset indent -compact
595 the event is a hardware interrupt, and the VCPU runs with interrupts disabled,
598 the event is a non-maskable interrupt (NMI), and the VCPU is already in an
602 Emulator software can manage interrupt and NMI window-exiting via the
604 component of the VCPU state.
605 When such window-exiting is enabled, NVMM will cause a VM exit with reason
606 .Dv NVMM_VCPU_EXIT_INT_READY
608 .Dv NVMM_VCPU_EXIT_NMI_READY
609 to indicate that the guest is now able to handle the corresponding class
612 In order to assist emulation of certain operations,
614 requires emulator software to register, via
615 .Fn nvmm_vcpu_configure ,
616 a set of callbacks described in the following structure:
618 struct nvmm_assist_callbacks {
619 void (*io)(struct nvmm_io *);
620 void (*mem)(struct nvmm_mem *);
624 These callbacks are used by
631 Emulator software that does not intend to use either of these assists can put
635 When a VM exit occurs with reason
636 .Dv NVMM_VCPU_EXIT_IO ,
637 it is necessary for emulator software to emulate the associated I/O operation.
639 provides an easy way for emulator software to perform that.
642 will call the registered
644 callback function and give it a
646 structure as argument.
647 This structure describes an I/O transaction:
650 struct nvmm_machine *mach;
651 struct nvmm_vcpu *vcpu;
659 The callback can emulate the operation using this descriptor, following two
662 .Bl -bullet -offset indent -compact
664 The operation is an input.
665 In this case, the callback should fill
667 with the desired value.
669 The operation is an output.
670 In this case, the callback should read
672 to retrieve the desired value.
677 will indicate the I/O port,
679 will indicate if the operation is an input, and
681 will indicate the size of the access.
683 When a VM exit occurs with reason
684 .Dv NVMM_VCPU_EXIT_MEMORY ,
685 it is necessary for emulator software to emulate the associated memory
688 provides an easy way for emulator software to perform that, similar to the I/O
692 will call the registered
694 callback function and give it a
696 structure as argument.
697 This structure describes a Mem transaction:
700 struct nvmm_machine *mach;
701 struct nvmm_vcpu *vcpu;
709 The callback can emulate the operation using this descriptor, following two
712 .Bl -bullet -offset indent -compact
714 The operation is a read.
715 In this case, the callback should fill
717 with the desired value.
719 The operation is a write.
720 In this case, the callback should read
722 to retrieve the desired value.
727 will indicate the guest physical address,
729 will indicate if the access is a write, and
731 will indicate the size of the access.
733 Upon successful completion, each of these functions returns zero.
734 Otherwise, a value of \-1 is returned and the global
737 is set to indicate the error.
739 .Bl -tag -width indent
740 .It Pa src/lib/libnvmm/
744 .It Pa src/sys/dev/virtual/nvmm/
745 Source code of the kernel
748 .It Pa src/test/testcases/libnvmm
749 Regression test cases for the
752 .It Pa src/test/nvmm/calc-vm.c
753 A minimal example that uses the
755 API to create a VM and perform a calculation within it.
756 .It Pa src/test/nvmm/demo
757 Functional demonstrator.
758 Contains an emulator that uses the
760 API, and a small kernel that exercises this emulator.
762 Originally obtained from
763 .Lk https://www.netbsd.org/~maxv/nvmm/nvmm-demo.zip
764 but has been updated to match the current
766 API, cleaned up, and ported to
770 These functions will fail if:
773 An attempt was made to create a machine or a VCPU that already exists.
775 An attempt was made to emulate a memory-based operation in a guest, and the
776 guest page tables did not have the permissions necessary for the operation
777 to complete successfully.
779 An inappropriate parameter was used.
781 The maximum number of machines or VCPUs was reached.
783 A query was made on a machine or a VCPU that does not exist.
785 An attempt was made to access a machine that does not belong to the process.
791 NVMM was designed and implemented by