- 1. Introduction
- 2. Hypercall Interface
- 2.1. Legal Hypercall Environments
- 2.2. Alignment Requirements
- 2.3. Hypercall Status Codes
- 2.4. Hypercall Inputs
- 2.5. Hypercall Outputs
- 2.6. Hypercall Opcodes
- 2.7. Hypercall Specification IDs
- 2.8. Hypercall Continuation
- 2.9. ID Hypercalls
- 2.10. Handle Hypercalls
- 2.11. Debug Hypercalls
- 2.12. Physical Processor Hypercalls
- 2.12.1. mv_pp_op_ppid, OP=0x3, IDX=0x0
- 2.12.2. mv_pp_op_online_pps, OP=0x3, IDX=0x1
- 2.12.3. mv_pp_op_clr_shared_page_gpa, OP=0x3, IDX=0x2
- 2.12.4. mv_pp_op_set_shared_page_gpa, OP=0x3, IDX=0x3
- 2.12.5. mv_pp_op_cpuid_get_supported, OP=0x3, IDX=0x4
- 2.12.6. mv_pp_op_cpuid_get_supported_list, OP=0x3, IDX=0x5
- 2.12.7. mv_pp_op_cpuid_get_permissable, OP=0x3, IDX=0x6
- 2.12.8. mv_pp_op_cpuid_get_permissable_list, OP=0x3, IDX=0x7
- 2.12.9. mv_pp_op_cpuid_get_emulated, OP=0x3, IDX=0x8
- 2.12.10. mv_pp_op_cpuid_get_emulated_list, OP=0x3, IDX=0x9
- 2.12.11. mv_pp_op_reg_get_supported, OP=0x3, IDX=0xA
- 2.12.12. mv_pp_op_reg_get_supported_list, OP=0x3, IDX=0xB
- 2.12.13. mv_pp_op_reg_get_permissable, OP=0x3, IDX=0xC
- 2.12.14. mv_pp_op_reg_get_permissable_list, OP=0x3, IDX=0xD
- 2.12.15. mv_pp_op_reg_get_emulated, OP=0x3, IDX=0xE
- 2.12.16. mv_pp_op_reg_get_emulated_list, OP=0x3, IDX=0xF
- 2.12.17. mv_pp_op_msr_get_supported, OP=0x3, IDX=010
- 2.12.18. mv_pp_op_msr_get_supported_list, OP=0x3, IDX=0x11
- 2.12.19. mv_pp_op_msr_get_permissable, OP=0x3, IDX=0x12
- 2.12.20. mv_pp_op_msr_get_permissable_list, OP=0x3, IDX=0x13
- 2.12.21. mv_pp_op_msr_get_emulated, OP=0x3, IDX=0x14
- 2.12.22. mv_pp_op_msr_get_emulated_list, OP=0x3, IDX=0x15
- 2.12.23. mv_pp_op_tsc_get_khz, OP=0x3, IDX=0x16
- 2.12.24. mv_pp_op_tsc_set_khz, OP=0x3, IDX=0x17
- 2.13. Virtual Machine Hypercalls
- 2.14. Virtual Processor Hypercalls
- 2.15. Virtual Processor State Hypercalls
- 2.15.1. mv_vs_op_create_vs, OP=0x6, IDX=0x0
- 2.15.2. mv_vs_op_destroy_vs, OP=0x6, IDX=0x1
- 2.15.3. mv_vs_op_vmid, OP=0x6, IDX=0x2
- 2.15.4. mv_vs_op_vpid, OP=0x6, IDX=0x3
- 2.15.5. mv_vs_op_vsid, OP=0x6, IDX=0x4
- 2.15.6. mv_vs_op_gva_to_gla, OP=0x6, IDX=0x5
- 2.15.7. mv_vs_op_gla_to_gpa, OP=0x6, IDX=0x6
- 2.15.8. mv_vs_op_gva_to_gpa, OP=0x6, IDX=0x7
- 2.15.9. mv_vs_op_run, OP=0x6, IDX=0x8
- 2.15.10. mv_vs_op_cpuid_get, OP=0x6, IDX=0x9
- 2.15.11. mv_vs_op_cpuid_set, OP=0x6, IDX=0xA
- 2.15.12. mv_vs_op_cpuid_get_list, OP=0x6, IDX=0xB
- 2.15.13. mv_vs_op_cpuid_set_list, OP=0x6, IDX=0xC
- 2.15.14. mv_vs_op_reg_get, OP=0x6, IDX=0xD
- 2.15.15. mv_vs_op_reg_set, OP=0x6, IDX=0xE
- 2.15.16. mv_vs_op_reg_get_list, OP=0x6, IDX=0xF
- 2.15.17. mv_vs_op_reg_set_list, OP=0x6, IDX=0x10
- 2.15.18. mv_vs_op_msr_get, OP=0x6, IDX=0x17
- 2.15.19. mv_vs_op_msr_set, OP=0x6, IDX=0x18
- 2.15.20. mv_vs_op_msr_get_list, OP=0x6, IDX=0x19
- 2.15.21. mv_vs_op_msr_set_list, OP=0x6, IDX=0x1A
- 2.15.22. mv_vs_op_fpu_get, OP=0x6, IDX=0x1B
- 2.15.23. mv_vs_op_fpu_set, OP=0x6, IDX=0x1C
- 2.15.24. mv_vs_op_fpu_get_all, OP=0x6, IDX=0x1D
- 2.15.25. mv_vs_op_fpu_set_all, OP=0x6, IDX=0x1E
- 2.15.26. mv_vs_op_xsave_get, OP=0x6, IDX=0x1F
- 2.15.27. mv_vs_op_xsave_set, OP=0x6, IDX=0x20
- 2.15.28. mv_vs_op_xsave_get_all, OP=0x6, IDX=0x21
- 2.15.29. mv_vs_op_xsave_set_all, OP=0x6, IDX=0x22
- 2.15.30. mv_vs_op_mp_state_get, OP=0x6, IDX=0x23
- 2.15.31. mv_vs_op_mp_state_set, OP=0x6, IDX=0x24
- 2.15.32. mv_vs_op_inject_exception, OP=0x6, IDX=0x25
- 2.15.33. mv_vs_op_queue_interrupt, OP=0x6, IDX=0x26
This specification defines the ABI between VM software and the MicroV hypervisor (including both root VMs and guest VMs). This includes the use of CPUID and Hypercalls. This specification does not define the ABI between the MicroV Microkernel and MicroV Extensions. Please see the Microkernel Syscall Specification for more information on the ABI supported by the MicroV Microkernel for writing custom hypervisor extensions. This specification also does not define the ABI for any support drivers like the MicroV Loader or the MicroV KVM Shim Driver. Please see the their specifications for more information.
This specification is specific to 64bit Intel and AMD processors conforming to the amd64 specification. Future revisions of this specification may include ARM64, RISC-V and PowerPC.
Name | Description |
---|---|
REVZ | reserved zero, meaning the value must be set to 0 |
REVI | reserved ignore, meaning the value is ignored |
Version | Description |
---|---|
Mv#1 | The initial version of this specification |
Abbreviation | Description |
---|---|
PP | Physical Processor |
VM | Virtual Machine |
VP | Virtual Processor |
VS | Virtual Processor State |
PPID | Physical Processor Identifier |
VMID | Virtual Machine Identifier |
VPID | Virtual Processor Identifier |
VSID | Virtual Processor State Identifier |
SSID | Segment Selector Identifier |
OS | Operating System |
BIOS | Basic Input/Output System |
UEFI | Unified Extensible Firmware Interface |
Root VM | The first VM created when MicroV is launched. The OS/BIOS/UEFI that is running when MicroV is launch is placed in the Root VM. Sometimes this is called Dom0 or the Root Partition |
Guest VM | Any additional VM created by MicroV. Sometimes called a DomU or Guest Partition |
Root VP | A virtual processor assigned to the root VM |
Guest VP | A virtual processor assigned to a guest VM |
Root VS | A virtual processor state assigned to a root VP |
Guest VS | A virtual processor state assigned to a guest VP |
Parent VS | The VS that was active prior to mv_vs_op_run being called (if they are different) |
Child VS | The VS that was made active by the call to mv_vs_op_run (if they are different) |
SPA | A System Physical Address (SPA) refers to a physical address as seen by the system without paging, second level paging or segmentation |
GPA | A Guest Physical Address (GPA) refers to a physical address as seen by a VM. For the Root VM, most GPA == SPA. For a Guest VM, converting from a GPA to an SPA required translating second level paging structures |
GLA | A Guest Linear Address (GLA) refers to a linear address as seen by a VM. GLAs require guest paging structures to convert from a GLA to a GPA |
GVA | A Guest Virtual Address (GVA) refers to a virtual address as seen by a VM. GVAs require guest segmentation to convert from a GVA to a GLA. On architectures that do not support segmentation, a GVA is a GLA |
Page Aligned | A region of memory whose address is divisible by 0x1000 |
Page | A page aligned region of memory that is 0x1000 bytes in size |
Host | Refers to the hypervisor. For MicroV, this consists of both the Bareflank Microkernel and the MicroV extension. Referred to VMX root or Ring -1 on Intel |
Guest | Refers to software running under the control of the Host. Referred to as VMX non-root on Intel |
Defines which register a hypercall is requesting.
enum, int32_t: mv_reg_t
Name | Value | Description |
---|---|---|
mv_reg_t_rax | 1 | defines the rax register |
mv_reg_t_rbx | 2 | defines the rbx register |
mv_reg_t_rcx | 3 | defines the rcx register |
mv_reg_t_rdx | 4 | defines the rdx register |
mv_reg_t_rbp | 5 | defines the rbp register |
mv_reg_t_rsi | 6 | defines the rsi register |
mv_reg_t_rdi | 7 | defines the rdi register |
mv_reg_t_r8 | 8 | defines the r8 register |
mv_reg_t_r9 | 9 | defines the r9 register |
mv_reg_t_r10 | 10 | defines the r10 register |
mv_reg_t_r11 | 11 | defines the r11 register |
mv_reg_t_r12 | 12 | defines the r12 register |
mv_reg_t_r13 | 13 | defines the r13 register |
mv_reg_t_r14 | 14 | defines the r14 register |
mv_reg_t_r15 | 15 | defines the r15 register |
mv_reg_t_rsp | 16 | defines the rsp register |
mv_reg_t_rip | 17 | defines the rip register |
mv_reg_t_rflags | 18 | defines the rflags register |
mv_reg_t_es_selector | 19 | defines the es_selector register |
mv_reg_t_es_attrib | 20 | defines the es_attrib register |
mv_reg_t_es_limit | 21 | defines the es_limit register |
mv_reg_t_es_base | 22 | defines the es_base register |
mv_reg_t_cs_selector | 23 | defines the cs_selector register |
mv_reg_t_cs_attrib | 24 | defines the cs_attrib register |
mv_reg_t_cs_limit | 25 | defines the cs_limit register |
mv_reg_t_cs_base | 26 | defines the cs_base register |
mv_reg_t_ss_selector | 27 | defines the ss_selector register |
mv_reg_t_ss_attrib | 28 | defines the ss_attrib register |
mv_reg_t_ss_limit | 29 | defines the ss_limit register |
mv_reg_t_ss_base | 30 | defines the ss_base register |
mv_reg_t_ds_selector | 31 | defines the ds_selector register |
mv_reg_t_ds_attrib | 32 | defines the ds_attrib register |
mv_reg_t_ds_limit | 33 | defines the ds_limit register |
mv_reg_t_ds_base | 34 | defines the ds_base register |
mv_reg_t_fs_selector | 35 | defines the fs_selector register |
mv_reg_t_fs_attrib | 36 | defines the fs_attrib register |
mv_reg_t_fs_limit | 37 | defines the fs_limit register |
mv_reg_t_fs_base | 38 | defines the fs_base register |
mv_reg_t_gs_selector | 39 | defines the gs_selector register |
mv_reg_t_gs_attrib | 40 | defines the gs_attrib register |
mv_reg_t_gs_limit | 41 | defines the gs_limit register |
mv_reg_t_gs_base | 42 | defines the gs_base register |
mv_reg_t_ldtr_selector | 43 | defines the ldtr_selector register |
mv_reg_t_ldtr_attrib | 44 | defines the ldtr_attrib register |
mv_reg_t_ldtr_limit | 45 | defines the ldtr_limit register |
mv_reg_t_ldtr_base | 46 | defines the ldtr_base register |
mv_reg_t_tr_selector | 47 | defines the tr_selector register |
mv_reg_t_tr_attrib | 48 | defines the tr_attrib register |
mv_reg_t_tr_limit | 49 | defines the tr_limit register |
mv_reg_t_tr_base | 50 | defines the tr_base register |
mv_reg_t_gdtr_selector | 51 | defines the gdtr_selector register |
mv_reg_t_gdtr_attrib | 52 | defines the gdtr_attrib register |
mv_reg_t_gdtr_limit | 53 | defines the gdtr_limit register |
mv_reg_t_gdtr_base | 54 | defines the gdtr_base register |
mv_reg_t_idtr_selector | 55 | defines the idtr_selector register |
mv_reg_t_idtr_attrib | 56 | defines the idtr_attrib register |
mv_reg_t_idtr_limit | 57 | defines the idtr_limit register |
mv_reg_t_idtr_base | 58 | defines the idtr_base register |
mv_reg_t_dr0 | 59 | defines the dr0 register |
mv_reg_t_dr1 | 60 | defines the dr1 register |
mv_reg_t_dr2 | 61 | defines the dr2 register |
mv_reg_t_dr3 | 62 | defines the dr3 register |
mv_reg_t_dr6 | 63 | defines the dr6 register |
mv_reg_t_dr7 | 64 | defines the dr7 register |
mv_reg_t_cr0 | 65 | defines the cr0 register |
mv_reg_t_cr2 | 66 | defines the cr2 register |
mv_reg_t_cr3 | 67 | defines the cr3 register |
mv_reg_t_cr4 | 68 | defines the cr4 register |
mv_reg_t_cr8 | 69 | defines the cr8 register |
mv_reg_t_xcr0 | 70 | defines the xcr0 register (Intel Only) |
Defines different bit sizes for address, operands, etc.
enum, int32_t: mv_bit_size_t
Name | Value | Description |
---|---|---|
mv_bit_size_t_8 | 0 | indicates 8 bits |
mv_bit_size_t_16 | 1 | indicates 16 bits |
mv_bit_size_t_32 | 2 | indicates 32 bits |
mv_bit_size_t_64 | 3 | indicates 64 bits |
The permission flags are used to define different permission types.
Bit | Name | Description |
---|---|---|
0 | MV_PERM_READ | Indicates the read permissions |
1 | MV_PERM_WRITE | Indicates the write permissions |
Defines the multiprocessor state of a VS
enum, int32_t: mv_mp_state_t
Name | Value | Description |
---|---|---|
mv_mp_state_t_initial | 0 | the initial state of the VS |
mv_mp_state_t_running | 1 | the VS is running |
mv_mp_state_t_wait | 2 | the VS is waiting for an interrupt |
mv_mp_state_t_init | 3 | the VS is waiting for INIT (x86 only) |
mv_mp_state_t_sipi | 4 | the VS is waiting for SIPI (x86 only) |
A register descriptor list (RDL) describes a list of registers that either need to be read or written. Each RDL consists of a list of entries with each entry describing one register to read/write. Like all structures used in this ABI, the RDL must be placed inside the shared page. Not all registers require 64 bits for either the register index or the value itself. In all cases, unused bits are considered REVI. The meaning of the register and value fields is ABI dependent. For some ABIs, the reg field refers to a mv_reg_t while in other cases it refers to an architecture specific register like MSRs on x86 which have it's index type. The value field for some ABIs is the value read or the value to be written to the requested register. In other cases, it is a boolean, enum or bit field describing attributes about the register such as whether the register is supported, emulated or permissable. Registers 0-7 in the mv_rdl_t are NOT entries, but instead input/output registers for the ABIs that need additional input and output registers. If any of these registers is not used by a specific ABI, it is REVI.
const, uint64_t: MV_RDL_MAX_ENTRIES
Value | Description |
---|---|
250 | Defines the max number of entires in the RDL |
struct: mv_rdl_entry_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
reg | uint64_t | 0x0 | 8 bytes | An mv_reg_t or MSR index |
val | uint64_t | 0x8 | 8 bytes | The value read or to be written |
The format of the RDL as follows:
struct: mv_rdl_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
reg0 | uint64_t | 0x0 | 8 bytes | ABI dependent. REVZ if unused |
reg1 | uint64_t | 0x8 | 8 bytes | ABI dependent. REVZ if unused |
reg2 | uint64_t | 0x10 | 8 bytes | ABI dependent. REVI if unused |
reg3 | uint64_t | 0x18 | 8 bytes | ABI dependent. REVI if unused |
reg4 | uint64_t | 0x20 | 8 bytes | ABI dependent. REVI if unused |
reg5 | uint64_t | 0x28 | 8 bytes | ABI dependent. REVI if unused |
reg6 | uint64_t | 0x30 | 8 bytes | ABI dependent. REVI if unused |
reg7 | uint64_t | 0x38 | 8 bytes | ABI dependent. REVI if unused |
reserved1 | uint64_t | 0x40 | 8 bytes | REVI |
reserved2 | uint64_t | 0x48 | 8 bytes | REVI |
reserved3 | uint64_t | 0x50 | 8 bytes | REVI |
num_entries | uint64_t | 0x58 | 8 bytes | The number of entries in the RDL |
entries | mv_rdl_entry_t[MV_RDL_MAX_ENTRIES] | 0x60 | ABI dependent | Each entry in the RDL |
A memory descriptor list (MDL) describes a discontiguous region of guest physical memory. Each MDL consists of a list of entries with each entry describing one contiguous region of guest physical memory. By combining multiple entries into a list, software is capable of describing both contiguous and discontiguous regions of guest physical memory. Like all structures used in this ABI, the MDL must be placed inside the shared page. The meaning of the dst and src fields is ABI dependent. Both the dst and src fields could be GVAs, GLAs or GPAs (virtual, linear or physical). The bytes field describes the total number of bytes in the contiguous memory region. For some ABIs, this field must be page aligned. The flags field is also ABI dependent. For example, for map hypercalls, this field refers to map flags. Registers 0-7 in the mv_mdl_t are NOT entries, but instead input/output registers for the ABIs that need additional input and output registers. If any of these registers is not used by a specific ABI, it is REVI.
const, uint64_t: MV_MDL_MAX_ENTRIES
Value | Description |
---|---|
125 | Defines the max number of entires in the MDL |
struct: mv_mdl_entry_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
dst | uint64_t | 0x0 | 8 bytes | The GPA to map the memory to |
src | uint64_t | 0x8 | 8 bytes | The GPA to map the memory from |
bytes | uint64_t | 0x8 | 8 bytes | The total number of bytes |
flags | uint64_t | 0x8 | 8 bytes | How to map dst to src |
The format of the MDL as follows:
struct: mv_mdl_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
reg0 | uint64_t | 0x0 | 8 bytes | ABI dependent. REVI if unused |
reg1 | uint64_t | 0x8 | 8 bytes | ABI dependent. REVI if unused |
reg2 | uint64_t | 0x10 | 8 bytes | ABI dependent. REVI if unused |
reg3 | uint64_t | 0x18 | 8 bytes | ABI dependent. REVI if unused |
reg4 | uint64_t | 0x20 | 8 bytes | ABI dependent. REVI if unused |
reg5 | uint64_t | 0x28 | 8 bytes | ABI dependent. REVI if unused |
reg6 | uint64_t | 0x30 | 8 bytes | ABI dependent. REVI if unused |
reg7 | uint64_t | 0x38 | 8 bytes | ABI dependent. REVI if unused |
reserved1 | uint64_t | 0x40 | 8 bytes | REVI |
reserved2 | uint64_t | 0x48 | 8 bytes | REVI |
reserved3 | uint64_t | 0x50 | 8 bytes | REVI |
num_entries | uint64_t | 0x58 | 8 bytes | The number of entries in the MDL |
entries | mv_mdl_entry_t[MV_MDL_MAX_ENTRIES] | 0x60 | ABI dependent | Each entry in the MDL |
A CPUID descriptor list (CDL) describes a list of CPUID leaves that either need to be read or written. Each CDL consists of a list of entries with each entry describing one CPUID leaf to read/write. Like all structures used in this ABI, the CDL must be placed inside the shared page. Registers 0-7 in the mv_cdl_t are NOT entries, but instead input/output registers for the ABIs that need additional input and output registers. If any of these registers is not used by a specific ABI, it is REVI.
const, uint64_t: MV_CDL_MAX_ENTRIES
Value | Description |
---|---|
125 | Defines the max number of entires in the CDL |
enum, int32_t: mv_cpuid_flag_t
Name | Value | Description |
---|---|---|
mv_cpuid_flag_t_reserved | 0 | reserved |
struct: mv_cdl_entry_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
fun | uint32_t | 0x0 | 4 bytes | stores the CPUID function input |
idx | uint32_t | 0x4 | 4 bytes | stores the CPUID index input |
flags | mv_cpuid_flag_t | 0x8 | 4 bytes | stores an MicroV specific flags |
eax | uint32_t | 0xC | 4 bytes | stores the CPUID eax output |
ebx | uint32_t | 0x10 | 4 bytes | stores the CPUID ebx output |
ecx | uint32_t | 0x14 | 4 bytes | stores the CPUID ecx output |
edx | uint32_t | 0x18 | 4 bytes | stores the CPUID edx output |
reserved | uint32_t | 0x1C | 4 bytes | reserved |
The format of the CDL as follows:
struct: mv_cdl_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
reg0 | uint64_t | 0x0 | 8 bytes | ABI dependent. REVZ if unused |
reg1 | uint64_t | 0x8 | 8 bytes | ABI dependent. REVZ if unused |
reg2 | uint64_t | 0x10 | 8 bytes | ABI dependent. REVI if unused |
reg3 | uint64_t | 0x18 | 8 bytes | ABI dependent. REVI if unused |
reg4 | uint64_t | 0x20 | 8 bytes | ABI dependent. REVI if unused |
reg5 | uint64_t | 0x28 | 8 bytes | ABI dependent. REVI if unused |
reg6 | uint64_t | 0x30 | 8 bytes | ABI dependent. REVI if unused |
reg7 | uint64_t | 0x38 | 8 bytes | ABI dependent. REVI if unused |
reserved1 | uint64_t | 0x40 | 8 bytes | REVI |
reserved2 | uint64_t | 0x48 | 8 bytes | REVI |
reserved3 | uint64_t | 0x50 | 8 bytes | REVI |
num_entries | uint64_t | 0x58 | 8 bytes | The number of entries in the CDL |
entries | mv_cdl_entry_t[MV_CDL_MAX_ENTRIES] | 0x60 | ABI dependent | Each entry in the CDL |
The RDL flags are used by some of the hypercalls as both inputs to a hypercall as well as outputs from a hypercall to provide information about how an RDL should be interpreted.
Bit | Name | Description |
---|---|---|
0 | MV_RDL_FLAG_ALL | Indicates a request for all available registers |
The map flags are used by some of the hypercalls as both inputs to a hypercall as well as outputs from a hypercall to provide information about how a memory is or should be mapped.
Bit | Name | Description |
---|---|---|
0 | MV_MAP_FLAG_READ_ACCESS | Indicates the map has read access |
1 | MV_MAP_FLAG_WRITE_ACCESS | Indicates the map has write access |
2 | MV_MAP_FLAG_EXECUTE_ACCESS | Indicates the map has execute access |
3 | MV_MAP_FLAG_USER | Indicates the map has user privileges |
8:4 | revi | REVI |
9 | MV_MAP_FLAG_4K_PAGE | Indicates the map is 4k in size |
10 | MV_MAP_FLAG_2M_PAGE | Indicates the map is 2m in size |
11 | MV_MAP_FLAG_1G_PAGE | Indicates the map is 1g in size |
56:12 | revi | REVI |
57 | MV_MAP_FLAG_UNCACHEABLE | Indicates the map is mapped as UC |
58 | MV_MAP_FLAG_UNCACHEABLE_MINUS | Indicates the map is mapped as UC- |
59 | MV_MAP_FLAG_WRITE_COMBINING | Indicates the map is mapped as WC |
60 | MV_MAP_FLAG_WRITE_COMBINING_PLUS | Indicates the map is mapped as WC+ |
61 | MV_MAP_FLAG_WRITE_THROUGH | Indicates the map is mapped as WT |
62 | MV_MAP_FLAG_WRITE_BACK | Indicates the map is mapped as WB |
63 | MV_MAP_FLAG_WRITE_PROTECTED | Indicates the map is mapped as WP |
The following defines some ID constants.
const, uint16_t: MV_INVALID_ID
Value | Description |
---|---|
0xFFFF | Defines an invalid ID for an extension, VM, VP, VS and PP |
const, uint16_t: MV_SELF_ID
Value | Description |
---|---|
0xFFFE | Defines the ID for "self" |
const, uint16_t: MV_ALL_ID
Value | Description |
---|---|
0xFFFD | Defines the ID for "all" |
const, uint16_t: MV_BS_PPID
Value | Description |
---|---|
0x0 | Defines the bootstrap physical processor ID |
const, uint16_t: MV_ROOT_VMID
Value | Description |
---|---|
0x0 | Defines the root virtual machine ID |
This document only applies to 64bit Intel and AMD systems conforming to the amd64 architecture. As such, this document is limited to little endian.
TBD
A Virtual Machine or VM virtually represents a physical computer and stores the resources that are shared between one or more Virtual Processors called the Virtual Machine State or VMS. MicroV is capable of executing multiple VMs simultaneously on the same physical machine. In some configurations these VMs might share the same physical cores/threads and in other configurations, each VM is given dedicated access to one or more physical cores/threads, and either share the rest of hardware, or the rest of hardware is divided up between VMs using something like an IOMMU (or some combination of the two).
There are different types of VMs. The root VM is the initial VM created by the MicroV Microkernel and executes whatever operating system was executing at the time MicroV was started. In some configurations (early boot), MicroV is started from BIOS/UEFI and demotes BIOS/UEFI into the root VM. From there, BIOS/UEFI might boot an additional operating system such as Windows or Linux inside the root VM. In other configurations (late launch), an operating system such as Windows or Linux has already booted and MicroV is started some time later. In this configuration MicroV demotes the current operating system into the root VM and executes from there.
The early boot configuration of MicroV provides better security as well as early access to memory resources reducing fragmentation and increasing the efficiency of the overall system (reduces shattering of large pages). The late launch configuration of MicroV is easier to develop for.
All additional VMs that are created from the root VM are called guest VMs. Guest VMs are not capable of creating additional guest VMs (VMs can only be created by the root VM). That is, MicroV uses a breath of many, depth of one approach.
A Virtual Processor or VP virtually represents a physical core/thread on the system. It is the "thing" that is scheduled to execute code and contains one or more Virtual Processor States or VSs that store the actual state of the VP and execute the actual code on behalf of a VP. Each time a VP is scheduled for execution, it replaces the state on the physical core/thread with one of the VSs it owns. Once the VP is done executing, the current state of the physical core/thread is saved back to the VS in use, allowing another VP to execute as needed.
There are different types of VPs. The root VPs are created when MicroV is first started and one and only one root VP is created for every physical core/thread on the system. Root VPs are owned by the Root VM. MicroV does not provide the ability to create additional root VPs.
Any additional VPs that are created are called guest VPs which are owned and executed by the root VPs. Guest VPs cannot create additional guest VPs (meaning guest VPs must be created by a root VP). When a root VP executes a guest VP using the mv_vp_run_vp hypercall, it is said to be "donating" its execution time to the guest VP. This allows, for example, applications running in the root VM to execute guest VMs, whose time is billed to the application making the call to mv_vp_run_vp.
Unlike guest VMs who only have a single owning root VM, guest VPs can be owned by a single but different root VP at any given time. When a root VP executes a guest VP, the root VP becomes the parent VP and the guest VP becomes the child VP. During execution of a guest VP the parent/child relationship does not change. Once the guest VP's execution is complete the parent/child relationship is released and the scheduler is free to transfer ownership of a guest VP from one root VP to another. This transfer of ownership usually occurs during VP migration and is due to the fact that a guest VM is not required to have the same number of guest VPs compared to the number of root VPs which reflects the physical number of cores/threads on the system. As a result, the scheduler is free to move guest VPs to different root VPs as needed to optimize performance, resulting in a VP migration.
TBD
The following section defines the hypercall interface used by this specification, and therefore MicroV.
The kernel and userspace can execute hypercalls from 64bit mode. 32bit mode is currently not supported.
Most GPAs are required to be page aligned. When this occurs, the hypercall documentation will state that bits 11:0 are REVZ. If this is not documented, software can safely assume that the lower 12 bits of the GPA are valid and can be provided.
If a hypercall must provide input/output larger than what is supported from a register only hypercall, a structure will be used instead. When this occurs, software must place the structure in a page (that is page aligned) at offset 0 of the page, providing the GPA of the page as input. Hypercalls that accept more than one page use the MDL format listed above.
Every hypercall returns a mv_status_t to indicate the success or failure of a hypercall after execution. The following defines the layout of mv_status_t:
uint64_t: mv_status_t
Bits | Name | Description |
---|---|---|
63:48 | MV_STATUS_SIG | Contains 0x0000 on success, 0xDEAD on failure |
47:16 | MV_STATUS_FLAGS | Contains the flags associated with the mv_status_t |
15:0 | MV_STATUS_VALUE | Contains the value of the mv_status_t |
MV_STATUS_VALUE defines success or which type of error occurred. MV_STATUS_FLAGS provides additional information about why the error occurred.
const, mv_status_t: MV_STATUS_SUCCESS
Value | Description |
---|---|
0x0000000000000000 | Indicates the hypercall returned successfully |
const, mv_status_t: MV_STATUS_FAILURE_UNKNOWN
Value | Description |
---|---|
0xDEAD000000010001 | Indicates an unknown error occurred |
const, mv_status_t: MV_STATUS_FAILURE_UNSUPPORTED
Value | Description |
---|---|
0xDEAD000000020001 | Indicates the hypercall is unsupported |
const, mv_status_t: MV_STATUS_FAILURE_INVALID_HANDLE
Value | Description |
---|---|
0xDEAD000000040001 | Indicates the provided handle is invalid |
const, mv_status_t: MV_STATUS_INVALID_PERM_DENIED
Value | Description |
---|---|
0xDEAD000000010002 | Indicates the policy engine denied the hypercall |
const, mv_status_t: MV_STATUS_INVALID_INPUT_REG0
Value | Description |
---|---|
0xDEAD000000010003 | Indicates input reg0 is invalid |
const, mv_status_t: MV_STATUS_INVALID_INPUT_REG1
Value | Description |
---|---|
0xDEAD000000020003 | Indicates input reg1 is invalid |
const, mv_status_t: MV_STATUS_INVALID_INPUT_REG2
Value | Description |
---|---|
0xDEAD000000040003 | Indicates input reg2 is invalid |
const, mv_status_t: MV_STATUS_INVALID_INPUT_REG3
Value | Description |
---|---|
0xDEAD000000080003 | Indicates input reg3 is invalid |
const, mv_status_t: MV_STATUS_INVALID_OUTPUT_REG0
Value | Description |
---|---|
0xDEAD000000100003 | Indicates output reg0 is invalid |
const, mv_status_t: MV_STATUS_INVALID_OUTPUT_REG1
Value | Description |
---|---|
0xDEAD000000200003 | Indicates output reg1 is invalid |
const, mv_status_t: MV_STATUS_INVALID_OUTPUT_REG2
Value | Description |
---|---|
0xDEAD000000400003 | Indicates output reg2 is invalid |
const, mv_status_t: MV_STATUS_INVALID_OUTPUT_REG3
Value | Description |
---|---|
0xDEAD000000800003 | Indicates output reg3 is invalid |
const, mv_status_t: MV_STATUS_RETRY_CONTINUATION
Value | Description |
---|---|
0xDEAD000000100004 | Indicates software should execute the hypercall again |
const, mv_status_t: MV_STATUS_RETRY_CONTINUATION_SCC
Value | Description |
---|---|
0xDEAD000000200004 | Indicates software should execute the hypercall again when it is ready |
const, mv_status_t: MV_STATUS_EXIT_FAILURE
Value | Description |
---|---|
0xDEAD000000010005 | Indicates that mv_exit_failure_t contains more info |
const, mv_status_t: MV_STATUS_EXIT_UNKNOWN
Value | Description |
---|---|
0xDEAD000000020005 | Indicates that mv_exit_unknown_t contains more info |
Before software can execute a hypercall, it must first open a handle to the hypercall interface by executing the mv_handle_op_open_handle hypercall. This handle must be provided as the first argument to each hypercall in R10 (i.e., REG0) and can be released using the mv_handle_op_close_handle hypercall.
R10: REG_HANDLE
Bits | Name | Description |
---|---|---|
63:0 | MV_HANDLE | The result of mv_handle_op_open_handle |
Every hypercall must provide information about the hypercall by filling out RAX as follows:
RAX: REG_HYPERCALL
Bits | Name | Description |
---|---|---|
63:48 | MV_HYPERCALL_SIG | 0x764D = "Mv" |
47:32 | MV_HYPERCALL_FLAGS | Contains the hypercall's flags |
31:16 | MV_HYPERCALL_OP | Contains the hypercall's opcode |
15:0 | MV_HYPERCALL_IDX | Contains the hypercall's index |
const, uint64_t: MV_HYPERCALL_SIG_VAL
Value | Description |
---|---|
0x764D000000000000 | Defines the MV_HYPERCALL_SIG field for RAX |
const, uint64_t: MV_HYPERCALL_SIG_MASK
Value | Description |
---|---|
0xFFFF000000000000 | Defines a mask for MV_HYPERCALL_SIG |
const, uint64_t: MV_HYPERCALL_FLAGS_MASK
Value | Description |
---|---|
0x0000FFFF00000000 | Defines a mask for MV_HYPERCALL_FLAGS |
const, uint64_t: MV_HYPERCALL_OPCODE_MASK
Value | Description |
---|---|
0xFFFF0000FFFF0000 | Defines a mask for MV_HYPERCALL_OP |
const, uint64_t: MV_HYPERCALL_OPCODE_NOSIG_MASK
Value | Description |
---|---|
0x00000000FFFF0000 | Defines a mask for MV_HYPERCALL_OP (with no signature added) |
const, uint64_t: MV_HYPERCALL_INDEX_MASK
Value | Description |
---|---|
0x000000000000FFFF | Defines a mask for MV_HYPERCALL_IDX |
MV_HYPERCALL_SIG is used to ensure the hypercall is, in fact, a MicroV specific hypercall. MV_HYPERCALL_FLAGS is used to provide additional hypercall options.
MV_HYPERCALL_OP determines which opcode the hypercall belongs to, logically grouping hypercalls based on their function. MV_HYPERCALL_OP is also used internally within MicroV to dispatch the hypercall to the proper handler. MV_HYPERCALL_IDX, when combined with MV_HYPERCALL_OP, uniquely identifies a specific hypercall. This specification tightly packs the values assigned to both MV_HYPERCALL_IDX and MV_HYPERCALL_OP to ensure MicroV (and variants) can use jump tables instead of branch logic.
The following defines the input registers for x64 based systems (i.e., x86_64 and amd64):
Arguments:
Register Name | Description |
---|---|
R10 | Set to the result of mv_handle_op_open_handle |
R11 | Stores the value of REG1 (hypercall specific) |
R12 | Stores the value of REG2 (hypercall specific) |
R13 | Stores the value of REG3 (hypercall specific) |
All unused registers by any hypercall are considered REVI.
const, uint64_t: MV_HYPERCALL_FLAGS_SCC
Value | Description |
---|---|
0x0000000100000000 | Defines the software controlled continuation flag |
After executing a hypercall, a mv_status_t is returned in RAX to indicate if the hypercall succeeded or failed and why.
RAX: REG_RETURN
Bits | Name | Description |
---|---|---|
63:0 | MV_STATUS | Contains the value of mv_status_t |
The following defines the output registers for x64 based systems (i.e., x86_64 and amd64):
Arguments:
Register Name | Description |
---|---|
R10 | Stores the value of REG0 (hypercall specific) |
R11 | Stores the value of REG1 (hypercall specific) |
R12 | Stores the value of REG2 (hypercall specific) |
R13 | Stores the value of REG3 (hypercall specific) |
The following sections define the different opcodes that are supported by this specification. Note that each opcode includes the hypercall signature making it easier to validate if the hypercall is supported or not.
const, uint64_t: MV_ID_OP_VAL
Value | Description |
---|---|
0x764D000000000000 | Defines the hypercall opcode for mv_id_op hypercalls |
const, uint64_t: MV_ID_OP_NOSIG_VAL
Value | Description |
---|---|
0x0000000000000000 | Defines the hypercall opcode for mv_id_op hypercalls with no signature |
const, uint64_t: MV_HANDLE_OP_VAL
Value | Description |
---|---|
0x764D000000010000 | Defines the hypercall opcode for mv_handle_op hypercalls |
const, uint64_t: MV_HANDLE_OP_NOSIG_VAL
Value | Description |
---|---|
0x000000000010000 | Defines the hypercall opcode for mv_handle_op hypercalls with no signature |
const, uint64_t: MV_DEBUG_OP_VAL
Value | Description |
---|---|
0x764D000000020000 | Defines the hypercall opcode for mv_debug_op hypercalls |
const, uint64_t: MV_DEBUG_OP_NOSIG_VAL
Value | Description |
---|---|
0x0000000000020000 | Defines the hypercall opcode for mv_debug_op hypercalls with no signature |
const, uint64_t: MV_PP_OP_VAL
Value | Description |
---|---|
0x764D000000030000 | Defines the hypercall opcode for mv_pp_op hypercalls |
const, uint64_t: MV_PP_OP_NOSIG_VAL
Value | Description |
---|---|
0x0000000000030000 | Defines the hypercall opcode for mv_pp_op hypercalls with no signature |
const, uint64_t: MV_VM_OP
Value | Description |
---|---|
0x764D000000040000 | Defines the hypercall opcode for mv_vm_op hypercalls |
const, uint64_t: MV_VM_OP_NOSIG_VAL
Value | Description |
---|---|
0x0000000000040000 | Defines the hypercall opcode for mv_vm_op hypercalls with no signature |
const, uint64_t: MV_VP_OP_VAL
Value | Description |
---|---|
0x764D000000050000 | Defines the hypercall opcode for mv_vp_op hypercalls |
const, uint64_t: MV_VP_OP_NOSIG_VAL
Value | Description |
---|---|
0x0000000000050000 | Defines the hypercall opcode for mv_vp_op hypercalls with no signature |
const, uint64_t: MV_VS_OP_VAL
Value | Description |
---|---|
0x764D000000060000 | Defines the hypercall opcode for mv_vs_op hypercalls |
const, uint64_t: MV_VS_OP_NOSIG_VAL
Value | Description |
---|---|
0x0000000000060000 | Defines the hypercall opcode for mv_vs_op hypercalls with no signature |
The following defines the specification IDs used when opening a handle. These provide software with a means to define which specification it implements. mv_id_op_version returns which version of this spec MicroV supports. For example, if the returned version is 0x2, it means that it supports version #1 of this spec, in which case, an extension can open a handle with MV_SPEC_ID1_VAL. If the returned version is 0x6, it would mean that an extension could open a handle with MV_SPEC_ID1_VAL or MV_SPEC_ID2_VAL. Likewise, if the returned version is 0x4, it means that MV_SPEC_ID1_VAL is no longer supported, and the extension must open the handle with MV_SPEC_ID2_VAL.
const, uint32_t: MV_SPEC_ID1_VAL
Value | Description |
---|---|
0x3123764D | Defines the ID for version #1 of this spec |
const, uint32_t: MV_SPEC_ID1_MASK
Value | Description |
---|---|
0x2 | Defines the mask for checking support for version #1 of this spec |
const, uint32_t: MV_ALL_SPECS_SUPPORTED_VAL
Value | Description |
---|---|
0x2 | Defines all versions supported |
const, uint32_t: MV_INVALID_VERSION
Value | Description |
---|---|
0x80000000 | Defines an invalid version |
Some hypercalls might take a long time to execute. Since MicroV does not service interrupts, interrupts are disabled while a hypercall is being processed. If a hypercall takes to long, this can have adverse effects on software if interrupts need to perform work while the hypercall is attempting to process.
To prevent this from occurring, long running hypercalls resume software periodically without advancing the instruction pointer. When this is done, MicroV will return MV_STATUS_RETRY_CONTINUATION from the hypercall. This forces the hypercall to be executed again, allowing MicroV to resume its execution.
In some cases, software might want more control on how a continuation is handled. For example, if software needs to perform additional actions above and beyond servicing interrupts. To support this, the MV_HYPERCALL_FLAGS_SCC flag can be set, telling MicroV to advance the instruction pointer and return MV_STATUS_RETRY_CONTINUATION_SCC, indicating to software that a continuation is required and software should retry the hypercall when it is ready.
If MV_STATUS_RETRY_CONTINUATION is returned, software must immediately execute the previous hypercall with the same inputs. Providing different inputs is undefined and may lead to corruption or an error. No other hypercalls are allowed to be called until the hypercall that needs a continuation has completed. Attempting to do so is undefined and may lead to corruption or an error.
If MV_STATUS_RETRY_CONTINUATION_SCC is returned, software is free to execute whatever hypercalls it wants. MicroV will store the inputs associated with the hypercall that needs the continuation. If this same hypercall is made with the same inputs, MicroV will perform the continuation. If the same hypercall is made with different inputs, MicroV will either cancel the previous hypercall and execute the new one, or return an error. Support for cancellations is ABI specific, including how any previously committed state is handled.
Continuations can occur more than once. Continuations can also be mixed. For example, if the MV_HYPERCALL_FLAGS_SCC flag is set, MicroV has the right to return MV_STATUS_RETRY_CONTINUATION, meaning MicroV is not obligated to support this flag, even between continuations. This is needed because in some cases, long running hypercalls might contain moments where MV_STATUS_RETRY_CONTINUATION_SCC can be supported, and moments where it cannot. It is up to MicroV to decide.
This hypercall tells MicroV to return the version of the spec that it supports.
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Returns which versions of the spec MicroV supports |
const, uint64_t: MV_ID_OP_VERSION_IDX_VAL
Value | Description |
---|---|
0x0000000000000000 | Defines the index for mv_id_op_version |
TBD
const, uint64_t: MV_ID_OP_GET_CAPABILITY_IDX_VAL
Value | Description |
---|---|
0x0000000000000001 | Defines the index for mv_id_op_get_capability |
TBD
const, uint64_t: MV_ID_OP_CLR_CAPABILITY_IDX_VAL
Value | Description |
---|---|
0x0000000000000002 | Defines the index for mv_id_op_clr_capability |
TBD
const, uint64_t: MV_ID_OP_SET_CAPABILITY_IDX_VAL
Value | Description |
---|---|
0x0000000000000003 | Defines the index for mv_id_op_set_capability |
Returns MV_STATUS_SUCCESS if the capability is supported. Returns MV_STATUS_FAILURE_UNSUPPORTED if the capability is not supported.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The capability to query |
const, uint64_t: MV_ID_OP_HAS_CAPABILITY_IDX_VAL
Value | Description |
---|---|
0x0000000000000004 | Defines the index for mv_id_op_has_capability |
This hypercall returns the handle that is required to execute the remaining hypercalls.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 31:0 | The version of this spec that software supports |
REG0 | 63:32 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The value to set REG0 to for most other hypercalls |
const, uint64_t: MV_HANDLE_OP_OPEN_HANDLE_IDX_VAL
Value | Description |
---|---|
0x0000000000000000 | Defines the index for mv_handle_op_open_handle |
const, uint64_t: MV_INVALID_HANDLE
Value | Description |
---|---|
0xFFFFFFFFFFFFFFFF | Defines an invalid handle |
This hypercall closes a previously opened handle.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
const, uint64_t: MV_HANDLE_OP_CLOSE_HANDLE_IDX_VAL
Value | Description |
---|---|
0x0000000000000001 | Defines the index for mv_handle_op_close_handle |
This hypercall tells MicroV to output reg0 and reg1 to the console device MicroV is currently using for debugging. The purpose of this hypercall is to provide a simple means for debugging issues with the guest and can be used by a VM from both userspace and the kernel, even when the operating system is not fully bootstrapped or is in a failure state.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The first value to output to MicroV's console |
REG1 | 63:0 | The second value to output to MicroV's console |
const, uint64_t: MV_DEBUG_OP_OUT_IDX_VAL
Value | Description |
---|---|
0x0000000000000000 | Defines the index for mv_debug_op_out |
TBD
This hypercall returns the ID of the PP that executed this hypercall.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting PPID |
REG0 | 63:16 | REVI |
const, uint64_t: MV_PP_OP_PPID_IDX_VAL
Value | Description |
---|---|
0x0000000000000000 | Defines the index for mv_pp_op_ppid |
This hypercall returns the number of online PPs
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting number of online PPs |
REG0 | 63:16 | REVI |
const, uint64_t: MV_PP_OP_ONLINE_PPS_IDX_VAL
Value | Description |
---|---|
0x0000000000000001 | Defines the index for mv_pp_op_online_pps |
This hypercall tells MicroV to clear the GPA of the current PP's shared page.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
const, uint64_t: MV_PP_OP_CLR_SHARED_PAGE_GPA_IDX_VAL
Value | Description |
---|---|
0x0000000000000002 | Defines the index for mv_pp_op_clr_shared_page_gpa |
This hypercall tells MicroV to set the GPA of the current PP's shared page.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 11:0 | REVZ |
REG1 | 63:12 | The GPA to set the requested PP's shared page to |
Output:
Register Name | Bits | Description |
---|
const, uint64_t: MV_PP_OP_SET_SHARED_PAGE_GPA_IDX_VAL
Value | Description |
---|---|
0x0000000000000003 | Defines the index for mv_pp_op_set_shared_page_gpa |
Given the shared page cast as a single mv_cdl_entry_t, with mv_cdl_entry_t.fun and mv_cdl_entry_t.idx set to the requested CPUID leaf, the same mv_cdl_entry_t is returned in the shared page with mv_cdl_entry_t.eax, mv_cdl_entry_t.ebx, mv_cdl_entry_t.ecx and mv_cdl_entry_t.edx set with all supported CPU features set to 1. Any non-feature fields returned by CPUID are returned as 0.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
const, uint64_t: MV_PP_OP_CPUID_GET_SUPPORTED_IDX_VAL
Value | Description |
---|---|
0x0000000000000004 | Defines the index for mv_pp_op_cpuid_get_supported |
Given the shared page cast as a mv_cdl_t, with each entry's mv_cdl_entry_t.fun and mv_cdl_entry_t.idx set to the requested CPUID leaf, the same entries are returned in the shared page with each entry's mv_cdl_entry_t.eax, mv_cdl_entry_t.ebx, mv_cdl_entry_t.ecx and mv_cdl_entry_t.edx set with all supported CPU features set to 1. Any non-feature fields returned by CPUID are returned as 0.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
const, uint64_t: MV_PP_OP_CPUID_GET_SUPPORTED_LIST_IDX_VAL
Value | Description |
---|---|
0x0000000000000005 | Defines the index for mv_pp_op_cpuid_get_supported_list |
Reserved
const, uint64_t: MV_PP_OP_CPUID_GET_PERMISSABLE_IDX_VAL
Value | Description |
---|---|
0x0000000000000006 | Defines the index for mv_pp_op_cpuid_get_permissable |
Reserved
const, uint64_t: MV_PP_OP_CPUID_GET_PERMISSABLE_LIST_IDX_VAL
Value | Description |
---|---|
0x0000000000000007 | Defines the index for mv_pp_op_cpuid_get_permissable_list |
Given the shared page cast as a single mv_cdl_entry_t, with mv_cdl_entry_t.fun and mv_cdl_entry_t.idx set to the requested CPUID leaf, the same mv_cdl_entry_t is returned in the shared page with mv_cdl_entry_t.eax, mv_cdl_entry_t.ebx, mv_cdl_entry_t.ecx and mv_cdl_entry_t.edx set with all emulated CPU features set to 1. Any non-feature fields returned by CPUID are returned as 0. Emulated CPU features are features that are not supported by hardware, but are supported MicroV, meaning the VM is free to use this CPU feature as if hardware support were provided. An example of an emulated CPU feature might be the x2APIC.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
const, uint64_t: MV_PP_OP_CPUID_GET_EMULATED_IDX_VAL
Value | Description |
---|---|
0x0000000000000008 | Defines the index for mv_pp_op_cpuid_get_emulated |
Given the shared page cast as a mv_cdl_t, with each entry's mv_cdl_entry_t.fun and mv_cdl_entry_t.idx set to the requested CPUID leaf, the same entries are returned in the shared page with each entry's mv_cdl_entry_t.eax, mv_cdl_entry_t.ebx, mv_cdl_entry_t.ecx and mv_cdl_entry_t.edx set with all supported CPU features set to 1. Any non-feature fields returned by CPUID are returned as 0. Emulated CPU features are features that are not supported by hardware, but are supported MicroV, meaning the VM is free to use this CPU feature as if hardware support were provided. An example of an emulated CPU feature might be the x2APIC.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
const, uint64_t: MV_PP_OP_CPUID_GET_EMULATED_LIST_IDX_VAL
Value | Description |
---|---|
0x0000000000000009 | Defines the index for mv_pp_op_cpuid_get_emulated_list |
Reserved
const, uint64_t: MV_PP_OP_REG_GET_SUPPORTED_IDX_VAL
Value | Description |
---|---|
0x000000000000000A | Defines the index for mv_pp_op_reg_get_supported |
Reserved
const, uint64_t: MV_PP_OP_REG_GET_SUPPORTED_LIST_IDX_VAL
Value | Description |
---|---|
0x000000000000000B | Defines the index for mv_pp_op_reg_get_supported_list |
Reserved
const, uint64_t: MV_PP_OP_REG_GET_PERMISSABLE_IDX_VAL
Value | Description |
---|---|
0x000000000000000C | Defines the index for mv_pp_op_reg_get_permissable |
Reserved
const, uint64_t: MV_PP_OP_REG_GET_PERMISSABLE_LIST_IDX_VAL
Value | Description |
---|---|
0x000000000000000D | Defines the index for mv_pp_op_reg_get_permissable_list |
Reserved
const, uint64_t: MV_PP_OP_REG_GET_EMULATED_IDX_VAL
Value | Description |
---|---|
0x000000000000000E | Defines the index for mv_pp_op_reg_get_emulated |
Reserved
const, uint64_t: MV_PP_OP_REG_GET_EMULATED_LIST_IDX_VAL
Value | Description |
---|---|
0x000000000000000F | Defines the index for mv_pp_op_reg_get_emulated_list |
Given a requested MSR, a 1 is returned if the MSR is supported, and a 0 is returned if the MSR is not supported.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 31:0 | The requested MSR |
REG1 | 63:32 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The resulting supported value |
const, uint64_t: MV_PP_OP_MSR_GET_SUPPORTED_IDX_VAL
Value | Description |
---|---|
0x0000000000000010 | Defines the index for mv_pp_op_msr_get_supported |
Given the shared page cast as a mv_rdl_t, with each entry's mv_rdl_entry_t.reg set to the requested MSR, the same entries are returned in the shared page with each entry's mv_rdl_entry_t.val set to 1 if the MSR is supported, and 0 if the MSR is not supported.
This hypercall supports flag modifiers in mv_rdl_t.reg0. When MV_RDL_FLAG_ALL is enabled, the entire list of supported MSRs will be returned via the shared page and no entries must be given as input. If the entire list doesn't fit in the shared page, this hypercall will output in mv_rdl_t.reg1 the number of entries that are left allowing to make subsequent continuation calls by providing the current index of entries to resume from in mv_rdl_t.reg1 as input, i.e. mv_rdl_t.reg1 should be incremented by MV_RDL_MAX_ENTRIES.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
const, uint64_t: MV_PP_OP_MSR_GET_SUPPORTED_LIST_IDX_VAL
Value | Description |
---|---|
0x0000000000000011 | Defines the index for mv_pp_op_msr_get_supported_list |
Given a requested MSR, MV_PERM_READ is returned if the calling VM can read from the MSR, and MV_PERM_WRITE is returned if the calling VM can write to the MSR.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 31:0 | The requested MSR |
REG1 | 63:32 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The resulting permissions flags |
const, uint64_t: MV_PP_OP_MSR_GET_PERMISSABLE_IDX_VAL
Value | Description |
---|---|
0x0000000000000012 | Defines the index for mv_pp_op_msr_get_permissable |
Given the shared page cast as a mv_rdl_t, with each entry's mv_rdl_entry_t.reg set to the requested MSR, the same entries are returned in the shared page with each entry's mv_rdl_entry_t.val MV_PERM_READ bit set to 1 if the MSR can be read by the calling VM, and the MV_PERM_WRITE bit set to 1 if the MSR can be written by the calling VM.
This hypercall supports flag modifiers in mv_rdl_t.reg0. When MV_RDL_FLAG_ALL is enabled, the entire list of permissable MSRs will be returned via the shared page and no entries must be given as input. If the entire list doesn't fit in the shared page, this hypercall will output in mv_rdl_t.reg1 the number of entries that are left allowing to make subsequent continuation calls by providing the current index of entries to resume from in mv_rdl_t.reg1 as input, i.e. mv_rdl_t.reg1 should be incremented by MV_RDL_MAX_ENTRIES.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
const, uint64_t: MV_PP_OP_MSR_GET_PERMISSABLE_LIST_IDX_VAL
Value | Description |
---|---|
0x0000000000000013 | Defines the index for mv_pp_op_msr_get_permissable_list |
Reserved
const, uint64_t: MV_PP_OP_MSR_GET_EMULATED_IDX_VAL
Value | Description |
---|---|
0x0000000000000014 | Defines the index for mv_pp_op_msr_get_emulated |
Reserved
const, uint64_t: MV_PP_OP_MSR_GET_EMULATED_LIST_IDX_VAL
Value | Description |
---|---|
0x0000000000000015 | Defines the index for mv_pp_op_msr_get_emulated_list |
Returns the frequency of the PP. If the frequency has not been set, returns 0.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The resulting frequency in KHz |
const, uint64_t: MV_PP_OP_TSC_GET_KHZ_IDX_VAL
Value | Description |
---|---|
0x0000000000000016 | Defines the index for mv_pp_op_tsc_get_khz |
Sets the frequency of the PP. This hypercall must be called before any VS can be created.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 63:0 | The frequency in KHz |
const, uint64_t: MV_PP_OP_TSC_SET_KHZ_IDX_VAL
Value | Description |
---|---|
0x0000000000000017 | Defines the index for mv_pp_op_tsc_set_khz |
TBD
This hypercall tells MicroV to create a VM and return its ID.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting ID of the newly created VM |
REG0 | 63:16 | REVI |
const, uint64_t: MV_VM_OP_CREATE_VM_IDX_VAL
Value | Description |
---|---|
0x0000000000000000 | Defines the index for mv_vm_op_create_vm |
This hypercall tells MicroV to destroy a VM given an ID.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VM to destroy |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VM_OP_DESTROY_VM_IDX_VAL
Value | Description |
---|---|
0x0000000000000001 | Defines the index for mv_vm_op_destroy_vm |
This hypercall returns the ID of the VM that executed this hypercall.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting ID |
REG0 | 63:16 | REVI |
const, uint64_t: MV_VM_OP_VMID_IDX_VAL
Value | Description |
---|---|
0x0000000000000002 | Defines the index for mv_vm_op_vmid |
This hypercall is used to map a range of physically discontiguous guest memory from one VM to another using a Memory Descriptor List (MDL) in the shared page. For this ABI, the dst field in the mv_mdl_entry_t refers to the GPA to map the contiguous memory region described by the entry to. The src field in the mv_mdl_entry_t refers to the GPA to map the contiguous memory region from. The dst and src VMIDs must be different. If the src VMID is not MV_ROOT_VMID, the map is considered a foreign map and is currently not supported (although will be in the future to support device domains). The bytes field in the mv_mdl_entry_t must be page aligned and cannot be 0. The flags field in the mv_mdl_entry_t refers to Map Flags and only apply to the destination (meaning source mappings are not affected by this hypercall). The only flags that are supported by this hypercall are the access/permission flags and the capability flags. Of these flags, MicroV may reject the use of certain flags based on MicroV's configuration and which CPU architecture is in use. mv_id_op_get_capability can be used to determine which specific flags are supported by MicroV. Care should be taken to ensure that both the dst and src memory is mapped with the same cacheability. In general, the safest option is to map MV_MAP_FLAG_WRITE_BACK from the src to MV_MAP_FLAG_WRITE_BACK in the dst. This ABI does not use any of the reg 0-7 fields in the mv_mdl_t. Double maps (i.e., mapping memory that is already mapped) is undefined and may result in MicroV returning an error.
Warning:
This hypercall is slow and may require a Hypercall Continuation. See Hypercall Continuations for more information.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the dst VM to map memory to |
REG1 | 63:16 | REVI |
REG2 | 15:0 | The ID of the src VM to map memory from |
REG2 | 63:16 | REVI |
const, uint64_t: MV_VM_OP_MMIO_MAP_IDX_VAL
Value | Description |
---|---|
0x0000000000000003 | Defines the index for mv_vm_op_mmio_map |
This hypercall is used to unmap a range of physically discontiguous guest memory from a VM. For this ABI, the dst field in the mv_mdl_entry_t refers to the GPA of the contiguous memory region to unmap. The src field is ignored. The bytes field in the mv_mdl_entry_t must be page aligned and cannot be 0. The flags field is ignored. This ABI does not use any of the reg 0-7 fields in the mv_mdl_t. Double unmaps (i.e., unmapping memory that is already unmapped) is undefined and may result in MicroV returning an error. To ensure the unmap is seen by the processor, this hypercall performs a TLB invalidation of all of the memory described in the MDL. MicroV reserves the right to invalidate the entire TLB and cache if needed. If a VM has more than one VP, this hypercall may perform a remote TLB invalidation. How remote TLB invalidations are performed by MicroV is undefined and left to MicroV to determine.
Warning:
This hypercall is slow and may require a Hypercall Continuation. See Hypercall Continuations for more information.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VM to unmap memory from |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VM_OP_MMIO_UNMAP_IDX_VAL
Value | Description |
---|---|
0x0000000000000004 | Defines the index for mv_vm_op_mmio_unmap |
TBD
This hypercall tells MicroV to create a VP given the ID of the VM the VP will be assigned to. Upon success, this hypercall returns the ID of the newly created VP.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VM to assign the newly created VP to |
REG1 | 63:16 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting VPID of the newly created VP |
REG0 | 63:16 | REVI |
const, uint64_t: MV_VP_OP_CREATE_VP_IDX_VAL
Value | Description |
---|---|
0x0000000000000000 | Defines the index for mv_vp_op_create_vp |
This hypercall tells MicroV to destroy a VP given an ID.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VP to destroy |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VP_OP_DESTROY_VP_IDX_VAL
Value | Description |
---|---|
0x0000000000000001 | Defines the index for mv_vp_op_destroy_vp |
This hypercall returns the ID of the VM the requested VP is assigned to.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VP to query |
REG1 | 63:16 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting ID |
REG0 | 63:16 | REVI |
const, uint64_t: MV_VP_OP_VMID_IDX_VAL
Value | Description |
---|---|
0x0000000000000002 | Defines the index for mv_vp_op_vmid |
This hypercall returns the ID of the VP that executed this hypercall.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting VPID |
REG0 | 63:16 | REVI |
const, uint64_t: MV_VP_OP_VPID_IDX_VAL
Value | Description |
---|---|
0x0000000000000003 | Defines the index for mv_vp_op_vpid |
TBD
This hypercall tells MicroV to create a VS given the ID of the VP the VS will be assigned to. Upon success, this hypercall returns the ID of the newly created VS.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VP to assign the newly created VS to |
REG1 | 63:16 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting VSID of the newly created VS |
REG0 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_CREATE_VS_IDX_VAL
Value | Description |
---|---|
0x0000000000000000 | Defines the index for mv_vs_op_create_vs |
This hypercall tells MicroV to destroy a VS given an ID.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to destroy |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_DESTROY_VS_IDX_VAL
Value | Description |
---|---|
0x0000000000000001 | Defines the index for mv_vs_op_destroy_vs |
This hypercall returns the ID of the VM the requested VS is assigned to.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting ID |
REG0 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_VMID_IDX_VAL
Value | Description |
---|---|
0x0000000000000002 | Defines the index for mv_vs_op_vmid |
This hypercall returns the ID of the VP the requested VS is assigned to.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting ID |
REG0 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_VPID_IDX_VAL
Value | Description |
---|---|
0x0000000000000003 | Defines the index for mv_vs_op_vpid |
This hypercall returns the ID of the VS that executed this hypercall.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 15:0 | The resulting ID |
REG0 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_VSID_IDX_VAL
Value | Description |
---|---|
0x0000000000000004 | Defines the index for mv_vs_op_vsid |
Reserved
This is reserved but not supported in this version of the MicroV spec. This hypercall tells MicroV to translate the provided guest virtual address (GVA) to a guest linear address (GLA). To perform this translation, MicroV will use the current state of CR0, CR4, EFER, the GDT and the segment registers. To perform this translation, software must provide the ID of the VS whose state will be used during translation, the segment register to use, and the the GVA to translate. How the translation occurs depends on whether or not the VS is in 16bit real mode, 32bit protected mode, or 64bit long mode. In 16bit real mode, the segment registers are used for the translation. In 32bit protected mode, the segment registers and the GDT are used for the translation. 64bit long mode is the same as 32bit protected mode with the difference being that certain segments will return an error as they are not supported (e.g., ES and DS). If the translation fails for any reason, the resulting GLA is undefined.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to use for the translation |
REG1 | 31:16 | The SSID of the segment to use for the translation |
REG1 | 63:32 | REVI |
REG2 | 63:0 | The GVA to translate |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The translated GLA |
const, uint64_t: MV_VS_OP_GVA_TO_GLA_IDX_VAL
Value | Description |
---|---|
0x0000000000000005 | Defines the index for mv_vs_op_gva_to_gla |
This hypercall tells MicroV to translate the provided guest linear address (GLA) to a guest physical address (GPA). To perform this translation, MicroV will perform a linear to physical address conversion using the current state of CR0, CR3, and CR4. To perform this translation, software must provide the ID of the VS whose state will be used during translation and the the GLA to translate. How the translation occurs depends on whether or not the VS is in 16bit real mode, 32bit protected mode, 32bit protected mode with paging enabled, or 64bit long mode. If the VS is in 16bit real mode or 32bit protected mode with paging disabled, no translation is performed and the provided GLA is returned as the GPA. If the VS is in 32bit protected mode with paging enabled or 64bit long mode, MicroV will walk the guest page tables pointed to by CR3 in the VS and return the resulting GPA and GPA flags used to map the GLA to the GPA (caching flags are not included). If the translation fails for any reason, the resulting GPA is undefined.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to use for the translation |
REG1 | 63:16 | REVI |
REG2 | 11:0 | REVZ |
REG2 | 63:12 | The GLA to translate |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 11:0 | The map flags that are used to map the GLA to the GPA |
REG0 | 63:12 | The translated GPA |
const, uint64_t: MV_VS_OP_GLA_TO_GPA_IDX_VAL
Value | Description |
---|---|
0x0000000000000006 | Defines the index for mv_vs_op_gla_to_gpa |
Reserved
This is reserved but not supported in this version of the MicroV spec. If MicroV where to actually implement this ABI, it would have to either make assumptions as to what to do between the GVA to GLA translation and GLA to GPA translation, or handle all edge cases, which is a lot to sign up too. Trying to make this sort of generic ABI is likely to cause problems that seem simple at first, but come back to haunt you later. It makes more sense to have software make whatever assumptions it wants between each step than to actually support this. Two hypercalls is a small price to pay, especially since most of the time, software can ignore the GVA to GLA translation if it wants.
Internal to MicroV an API like this should never be implemented as a GVA to GLA translation is wildly different from a GLA to GPA conversion. One uses segmentation and translation errors use a segmentation specific exception while the other uses paging and translation errors use a page fault exception. When a translation is done, it must be done in two steps as the inject of an exception will depend on which step fails.
const, uint64_t: MV_VS_OP_GVA_TO_GPA_IDX_VAL
Value | Description |
---|---|
0x0000000000000007 | Defines the index for mv_vs_op_gva_to_gpa |
This hypercall executes a VM's VP using the requested VS. The VM and VP that are executed is determined by which VM and VP were assigned during the creation of the VP and VS. This hypercall does not return until an exit condition occurs, or an error is encountered. The exit condition can be identified using the output REG0 which defines the "exit reason". Whenever mv_vs_op_run is executed, MicroV reads the shared page using a mv_run_t as input. If "reg" is set to a valid mv_reg_t, this register is written before the guest VM is executed. If "reg" is mv_reg_t_unsupported, "reg" is ignored. If "msr" is set to a valid, non-zero MSR, the MSR is written before the guest VM is executed. If "msr" is set to 0, "msr" is ignored. When mv_vs_op_run returns, and no error has occurred, the shared page's contents depends on the exit condition. For some exit conditions, the shared page is ignored. In other cases, a structure specific to the exit condition is returned providing software with the information that it needs to handle the exit.
Warning:
This hypercall is slow and may require a Hypercall Continuation. See Hypercall Continuations for more information.
struct: mv_run_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
reg0 | mv_rdl_entry_t | 0x000 | 16 bytes | An RDL entry containing the contents of a register that should be set |
reg1 | mv_rdl_entry_t | 0x010 | 16 bytes | An RDL entry containing the contents of a register that should be set |
reg2 | mv_rdl_entry_t | 0x020 | 16 bytes | An RDL entry containing the contents of a register that should be set |
reg3 | mv_rdl_entry_t | 0x030 | 16 bytes | An RDL entry containing the contents of a register that should be set |
reg4 | mv_rdl_entry_t | 0x040 | 16 bytes | An RDL entry containing the contents of a register that should be set |
reg5 | mv_rdl_entry_t | 0x050 | 16 bytes | An RDL entry containing the contents of a register that should be set |
reg6 | mv_rdl_entry_t | 0x060 | 16 bytes | An RDL entry containing the contents of a register that should be set |
reg7 | mv_rdl_entry_t | 0x070 | 16 bytes | An RDL entry containing the contents of a register that should be set |
reg8 | mv_rdl_entry_t | 0x080 | 16 bytes | An RDL entry containing the contents of a register that should be set |
reg9 | mv_rdl_entry_t | 0x090 | 16 bytes | An RDL entry containing the contents of a register that should be set |
msr0 | mv_rdl_entry_t | 0x0A0 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
msr1 | mv_rdl_entry_t | 0x0B0 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
msr2 | mv_rdl_entry_t | 0x0C0 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
msr3 | mv_rdl_entry_t | 0x0D0 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
msr4 | mv_rdl_entry_t | 0x0E0 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
msr5 | mv_rdl_entry_t | 0x0F0 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
msr6 | mv_rdl_entry_t | 0x100 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
msr7 | mv_rdl_entry_t | 0x110 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
msr8 | mv_rdl_entry_t | 0x120 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
msr9 | mv_rdl_entry_t | 0x130 | 16 bytes | An RDL entry containing the contents of an MSR that should be set |
enum, int32_t: mv_exit_reason_t
Name | Value | Description |
---|---|---|
mv_exit_reason_t_failure | 0 | returned on error |
mv_exit_reason_t_unknown | 1 | an unknown/unsupported VMExit has occurred |
mv_exit_reason_t_hlt | 2 | a halt event has occurred |
mv_exit_reason_t_io | 3 | a IO event has occurred |
mv_exit_reason_t_mmio | 4 | a MMIO event has occurred |
mv_exit_reason_t_msr | 5 | a MSR event has occurred |
mv_exit_reason_t_interrupt | 6 | an interrupt event has occurred |
mv_exit_reason_t_nmi | 7 | an NMI event has occurred |
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to run |
REG1 | 63:16 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | A mv_exit_reason_t describing the reason for the exit |
const, uint64_t: MV_VS_OP_RUN_IDX_VAL
Value | Description |
---|---|
0x0000000000000008 | Defines the index for mv_vs_op_run |
If mv_vs_op_run returns an error with an exit reason of mv_exit_reason_t_failure, mv_exit_failure_t can be used to determine why the error occurred if MV_STATUS_EXIT_FAILURE is returned.
struct: mv_exit_failure_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
reserved | uint8_t | 0x0 | 4096 bytes | REVI |
If mv_vs_op_run returns an error with an exit reason of mv_exit_reason_t_unknown, mv_exit_unknown_t can be used to determine why the error occurred if MV_STATUS_EXIT_UNKNOWN is returned.
struct: mv_exit_unknown_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
info0 | uint64_t | 0x0 | 8 bytes | architecture specific information |
info1 | uint64_t | 0x0 | 8 bytes | architecture specific information |
info2 | uint64_t | 0x0 | 8 bytes | architecture specific information |
info3 | uint64_t | 0x0 | 8 bytes | architecture specific information |
reserved | uint8_t | 0x0 | 4064 bytes | REVI |
If mv_vs_op_run returns success with an exit reason of mv_exit_reason_t_hlt, it means that the VM has executed a halt event and mv_exit_hlt_t can be used to determine how to handle the event. For example, the VM might have issued a shutdown or reset command. Halt events can also occur when the VM or MicroV encounters a crash. For example, on x86, if a triple fault has occurred, MicroV will return mv_hlt_t_vm_crash. If MicroV itself encounters an error that it cannot recover from, it will return mv_hlt_t_microv_crash.
enum, int32_t: mv_hlt_t
Name | Value | Description |
---|---|---|
mv_hlt_t_shutdown | 0 | shutdown event |
mv_hlt_t_reset | 1 | reset event |
mv_hlt_t_vm_crash | 2 | crash event due to the VM |
mv_hlt_t_microv_crash | 3 | crash event due to MicroV |
struct: mv_exit_hlt_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
reason | mv_hlt_t | 0x0 | 8 bytes | describes the reason for the halt |
reserved | uint8_t | 0x0 | 4088 bytes | REVI |
If mv_vs_op_run returns success with an exit reason of mv_exit_reason_t_io, it means that the VM has executed IO and mv_exit_io_t can be used to determine how to handle the event.
const, uint64_t: MV_EXIT_IO_IN
Value | Description |
---|---|
0x0000000000000000 | The mv_exit_io_t defines an input access |
const, uint64_t: MV_EXIT_IO_OUT
Value | Description |
---|---|
0x0000000000000001 | The mv_exit_io_t defines an output access |
struct: mv_exit_io_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
addr | uint64_t | 0x0 | 8 bytes | The address of the IO register |
data | uint64_t | 0x8 | 8 bytes | The data to read/write |
reps | uint64_t | 0x10 | 8 bytes | The number of repetitions to make |
type | uint64_t | 0x18 | 8 bytes | MV_EXIT_IO flags |
size | mv_bit_size_t | 0x20 | 1 byte | defines the bit size of the IO |
reserved | uint8_t | 0x21 | 4063 bytes | REVI |
If mv_vs_op_run returns success with an exit reason of mv_exit_reason_t_mmio, it means that the VM has executed MMIO that MicroV does not know how to handle. It is up to guest software to determine how to handle the MMIO access. To support the emulation of the instruction that has generated the MMIO event, the raw instruction bytes are returned along with the guest physical address the instruction was attempting to access. In addition, the contents of the CPU's general purpose registers are provided as well. Which general purpose registers are provided depends on MMIO access. Guest software must use this information to decode the instruction and perform whatever emulation is required, but it must not assume that all of general purpose registers will be provided. For example, if the MMIO access is attempting to read the contents of RAX, and write the value to a memory location, MicroV may only provide a valid value to RAX, with the rest of the registers being undefined. It is up to MicroV as to how much state it wishes to share with guest software for any given exit. At a minimum, MicroV will always provide enough state so that guest software can perform emulation as required to produce a valid result, but has the right to withhold any addition state that it believes guest software should have no use for. How this is determined is up to MicroV, but in general, you can only rely on register state that would be needed to emulate the instruction that generated the MMIO access. Any additional register state that might be needed should be read using mv_vs_op_reg_get instead. If a register must be modified as a result of emulation, mv_run_t.reg can be set on the next execution of mv_vs_op_run without the need to execute mv_vs_op_reg_set. Again, MicroV reserves the right to return an error when executing mv_vs_op_run if the register being set does not match what MicroV would expect if the MMIO where being emulated.
Note that the resulting RWE flags are system dependent. On AMD, MV_EXIT_MMIO_READ == always enabled, MV_EXIT_MMIO_WRITE == EXITINFO1.RW, and MV_EXIT_MMIO_EXECUTE == EXITINFO1.ID. On Intel, MV_EXIT_MMIO_READ == EXIT_QUALIFICATION.0, MV_EXIT_MMIO_WRITE == EXIT_QUALIFICATION.1, and MV_EXIT_MMIO_EXECUTE == EXIT_QUALIFICATION.2.
Note that the registers that are returned are not written back. Any changes made to mv_exit_mmio_t will NOT be written back to the VS. Either set mv_run_t.reg.reg and mv_run_t.reg.val, or use mv_vs_op_reg_set. The values of each register on AMD and Intel are reg0 == rax, reg1 == rbx, reg2 == rcx, reg3 == rdx, reg4 == rbp, reg5 == rsi, reg6 == rdi, reg7 == r8, reg8 == r9, reg9 == r10, reg10 == r11, reg11 == r12, reg12 == r13, reg13 == r14, reg14 == r15, reg15 = rsp, reg16 = rip. All other registers are REVI. reg16 (i.e., RIP which is a GVA), should be used by guest software to determine which instruction generated the MMIO access. Since guest software provided the original memory, it should not only be able to easily perform the needed GVA to GLA conversion without the need for MicroV's assistance (i.e., do not use mv_vs_op_gva_to_gpa for this), it should also be able to access this memory to get the instruction's bytes and decode the instruction as needed.
const, uint64_t: MV_EXIT_MMIO_READ
Value | Description |
---|---|
0x0000000000000001 | The mv_exit_mmio_t defines a read access |
const, uint64_t: MV_EXIT_MMIO_WRITE
Value | Description |
---|---|
0x0000000000000002 | The mv_exit_mmio_t defines a write access |
const, uint64_t: MV_EXIT_MMIO_EXECUTE
Value | Description |
---|---|
0x0000000000000004 | The mv_exit_mmio_t defines an execute access |
struct: mv_exit_mmio_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
gpa | uint64_t | 0x0 | 8 bytes | The GPA of the MMIO access |
flags | uint64_t | 0x8 | 8 bytes | The MV_EXIT_MMIO flags |
reserved0 | uint64_t | 0x10 | 8 bytes | reserved |
reserved1 | uint64_t | 0x18 | 8 bytes | reserved |
reg0 | uint64_t | 0x20 | 8 bytes | system dependent register value |
reg1 | uint64_t | 0x28 | 8 bytes | system dependent register value |
reg2 | uint64_t | 0x30 | 8 bytes | system dependent register value |
reg3 | uint64_t | 0x38 | 8 bytes | system dependent register value |
reg4 | uint64_t | 0x40 | 8 bytes | system dependent register value |
reg5 | uint64_t | 0x48 | 8 bytes | system dependent register value |
reg6 | uint64_t | 0x50 | 8 bytes | system dependent register value |
reg7 | uint64_t | 0x58 | 8 bytes | system dependent register value |
reg8 | uint64_t | 0x60 | 8 bytes | system dependent register value |
reg9 | uint64_t | 0x68 | 8 bytes | system dependent register value |
reg10 | uint64_t | 0x70 | 8 bytes | system dependent register value |
reg11 | uint64_t | 0x78 | 8 bytes | system dependent register value |
reg12 | uint64_t | 0x80 | 8 bytes | system dependent register value |
reg13 | uint64_t | 0x88 | 8 bytes | system dependent register value |
reg14 | uint64_t | 0x90 | 8 bytes | system dependent register value |
reg15 | uint64_t | 0x98 | 8 bytes | system dependent register value |
reg16 | uint64_t | 0xA0 | 8 bytes | system dependent register value |
reg17 | uint64_t | 0xA8 | 8 bytes | system dependent register value |
reg18 | uint64_t | 0xB0 | 8 bytes | system dependent register value |
reg19 | uint64_t | 0xB8 | 8 bytes | system dependent register value |
reg20 | uint64_t | 0xC0 | 8 bytes | system dependent register value |
reg21 | uint64_t | 0xC8 | 8 bytes | system dependent register value |
reg22 | uint64_t | 0xD0 | 8 bytes | system dependent register value |
reg23 | uint64_t | 0xD8 | 8 bytes | system dependent register value |
reg24 | uint64_t | 0xE0 | 8 bytes | system dependent register value |
reg25 | uint64_t | 0xE8 | 8 bytes | system dependent register value |
reg26 | uint64_t | 0xF0 | 8 bytes | system dependent register value |
reg27 | uint64_t | 0xF8 | 8 bytes | system dependent register value |
reg28 | uint64_t | 0x100 | 8 bytes | system dependent register value |
reg29 | uint64_t | 0x108 | 8 bytes | system dependent register value |
reg30 | uint64_t | 0x110 | 8 bytes | system dependent register value |
reg31 | uint64_t | 0x118 | 8 bytes | system dependent register value |
If mv_vs_op_run returns success with an exit reason of mv_exit_reason_t_msr, it means that the VM has executed an rdmsr or wrmsr that MicroV does not know how to handle, and the MSR is permissable, meaning guest software is allowed to read/write the value of the MSR.
const, uint64_t: MV_EXIT_MSR_READ
Value | Description |
---|---|
0x0000000000000001 | The mv_exit_msr_t defines a read access |
const, uint64_t: MV_EXIT_MSR_WRITE
Value | Description |
---|---|
0x0000000000000002 | The mv_exit_msr_t defines a write access |
struct: mv_exit_msr_t
Name | Type | Offset | Size | Description |
---|---|---|---|---|
msr | mv_rdl_entry_t | 0x0 | 16 bytes | The MSR and it's value (wrmsr only, REVI for rdmsr) |
flags | uint64_t | 0x10 | 8 bytes | The MV_EXIT_MSR flags |
If mv_vs_op_run returns success with an exit reason of mv_exit_reason_t_interrupt, it means that MicroV needed to inject an interrupt into the VM that executed mv_vs_op_run. There is nothing for software to do other than execute mv_vs_op_run again.
If mv_vs_op_run returns success with an exit reason of mv_exit_reason_t_nmi, it means that MicroV needed to inject an NMI into the VM that executed mv_vs_op_run. There is nothing for software to do other than execute mv_vs_op_run again.
Given the shared page cast as a single mv_cdl_entry_t, with mv_cdl_entry_t.fun and mv_cdl_entry_t.idx set to the requested CPUID leaf, the same mv_cdl_entry_t is returned in the shared page with mv_cdl_entry_t.eax, mv_cdl_entry_t.ebx, mv_cdl_entry_t.ecx and mv_cdl_entry_t.edx set to the value seen by the VS as if CPUID were executed.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_CPUID_GET_IDX_VAL
Value | Description |
---|---|
0x0000000000000009 | Defines the index for mv_vs_op_cpuid_get |
Given the shared page cast as a single mv_cdl_entry_t, with mv_cdl_entry_t.fun and mv_cdl_entry_t.idx set to the requested CPUID leaf, any feature bit in mv_cdl_entry_t.eax, mv_cdl_entry_t.ebx, mv_cdl_entry_t.ecx and mv_cdl_entry_t.edx set to 0 will disable the CPU feature for the requested VS. Any feature bit set to 1 is ignored by MicroV (meaning the CPU feature is left unmodified). Any non-feature bits are ignored. Note that mv_vs_op_cpuid_set can only be used to disabled CPU features. CPU features that are enabled are determined by hardware and MicroV's support for this hardware.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to set |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_CPUID_SET_IDX_VAL
Value | Description |
---|---|
0x000000000000000A | Defines the index for mv_vs_op_cpuid_set |
Given the shared page cast as a mv_cdl_t, with each entry's mv_cdl_entry_t.fun and mv_cdl_entry_t.idx set to the requested CPUID leaf, the same entries are returned in the shared page with each entry's mv_cdl_entry_t.eax, mv_cdl_entry_t.ebx, mv_cdl_entry_t.ecx and mv_cdl_entry_t.edx set to the value seen by the VS as if CPUID were executed.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_CPUID_GET_LIST_IDX_VAL
Value | Description |
---|---|
0x000000000000000B | Defines the index for mv_vs_op_cpuid_get_list |
Given the shared page cast as a mv_cdl_t, with each entry's mv_cdl_entry_t.fun and mv_cdl_entry_t.idx set to the requested CPUID leaf, any feature bit in entry's mv_cdl_entry_t.eax, mv_cdl_entry_t.ebx, mv_cdl_entry_t.ecx and mv_cdl_entry_t.edx set to 0 will disable the CPU feature for the requested VS. Any feature bit set to 1 is ignored by MicroV (meaning the CPU feature is left unmodified). Any non-feature bits are ignored. Note that mv_vs_op_cpuid_set can only be used to disabled CPU features. CPU features that are enabled are determined by hardware and MicroV's support for this hardware.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to set |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_CPUID_SET_LIST_IDX_VAL
Value | Description |
---|---|
0x000000000000000C | Defines the index for mv_vs_op_cpuid_set_list |
This hypercall tells MicroV to return the value of a requested register. Not all registers values require 64 bits. Any unused bits are REVI.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
REG2 | 63:0 | An mv_reg_t describing the register to get |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The value read from the requested register |
const, uint64_t: MV_VS_OP_REG_GET_IDX_VAL
Value | Description |
---|---|
0x000000000000000D | Defines the index for mv_vs_op_reg_get |
This hypercall tells MicroV to set the value of a requested register. Not all registers values require 64 bits. Any unused bits are REVI.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to set |
REG1 | 63:16 | REVI |
REG2 | 63:0 | An mv_reg_t describing the register to set |
REG3 | 63:0 | The value to write to the requested register |
const, uint64_t: MV_VS_OP_REG_SET_IDX_VAL
Value | Description |
---|---|
0x000000000000000E | Defines the index for mv_vs_op_reg_set |
This hypercall tells MicroV to return the values of multiple requested registers using a Register Descriptor List (RDL) in the shared page. For this ABI, the reg field of each mv_rdl_entry_t refers to an mv_reg_t. The val field refers to the returned value of the requested register in that entry. Not all registers values require 64 bits. Any unused bits are REVI. This ABI does not use any of the reg 0-7 fields in the mv_rdl_t.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_REG_GET_LIST_IDX_VAL
Value | Description |
---|---|
0x000000000000000F | Defines the index for mv_vs_op_reg_get_list |
This hypercall tells MicroV to set the values of multiple requested registers using a Register Descriptor List (RDL) in the shared page. For this ABI, the reg field of each mv_rdl_entry_t refers to an mv_reg_t. The val field refers to the value to set the requested register in that entry to. Not all registers values require 64 bits. Any unused bits are REVI. This ABI does not use any of the reg 0-7 fields in the mv_rdl_t.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to set |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_REG_SET_LIST_IDX_VAL
Value | Description |
---|---|
0x0000000000000010 | Defines the index for mv_vs_op_reg_set_list |
This hypercall tells MicroV to return the value of a requested MSR.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
REG2 | 31:0 | The index of the MSR to get |
REG2 | 63:32 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The value read from the MSR |
const, uint64_t: MV_VS_OP_MSR_GET_IDX_VAL
Value | Description |
---|---|
0x0000000000000017 | Defines the index for mv_vs_op_msr_get |
This hypercall tells MicroV to set the value of a requested MSR.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to set |
REG1 | 63:16 | REVI |
REG2 | 31:0 | The index of the MSR to set |
REG2 | 63:32 | REVI |
REG3 | 63:0 | The value to write to the requested MSR |
const, uint64_t: MV_VS_OP_MSR_SET_IDX_VAL
Value | Description |
---|---|
0x0000000000000018 | Defines the index for mv_vs_op_msr_set |
This hypercall tells MicroV to return the values of multiple requested MSRs using a Register Descriptor List (RDL) in the shared page. For this ABI, the reg field of each mv_rdl_entry_t refers to the index of the MSR. The val field refers to the returned value of the requested MSR in that entry. This ABI does not use any of the reg 0-7 fields in the mv_rdl_t.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_MSR_GET_LIST_IDX_VAL
Value | Description |
---|---|
0x0000000000000019 | Defines the index for mv_vs_op_msr_get_list |
This hypercall tells MicroV to set the values of multiple requested MSRs using a Register Descriptor List (RDL) in the shared page. For this ABI, the reg field of each mv_rdl_entry_t refers to the index of the MSR. The val field refers to the value to set the requested MSR in that entry to. This ABI does not use any of the reg 0-7 fields in the mv_rdl_t.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to set |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_MSR_SET_LIST_IDX_VAL
Value | Description |
---|---|
0x000000000000001A | Defines the index for mv_vs_op_msr_set_list |
Reserved
const, uint64_t: MV_VS_OP_FPU_GET_IDX_VAL
Value | Description |
---|---|
0x000000000000001B | Defines the index for mv_vs_op_fpu_get |
Reserved
const, uint64_t: MV_VS_OP_FPU_SET_IDX_VAL
Value | Description |
---|---|
0x000000000000001C | Defines the index for mv_vs_op_fpu_set |
Returns FPU state as seen by the VS in the shared page. The format of the FPU state depends on which mode the VS is currently in.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_FPU_GET_ALL_IDX_VAL
Value | Description |
---|---|
0x000000000000001D | Defines the index for mv_vs_op_fpu_get_all |
Sets the FPU state as seen by the VS in the shared page. The format of the FPU state depends on which mode the VS is currently in.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to set |
REG1 | 63:16 | REVI |
const, uint64_t: MV_VS_OP_FPU_SET_ALL_IDX_VAL
Value | Description |
---|---|
0x000000000000001E | Defines the index for mv_vs_op_fpu_set_all |
Reserved
const, uint64_t: MV_VS_OP_XSAVE_GET_IDX_VAL
Value | Description |
---|---|
0x000000000000001F | Defines the index for mv_vs_op_xsave_get |
Reserved
const, uint64_t: MV_VS_OP_XSAVE_SET_IDX_VAL
Value | Description |
---|---|
0x0000000000000020 | Defines the index for mv_vs_op_xsave_set |
Returns XSAVE state as seen by the VS in the shared page. The format of the XSAVE state depends on which mode the VS is currently in, and which XSAVE features are enabled in the guest as seen by XCR0. If the XSAVE region is larger than one page, REG2 can be used to tell MicroV which page of the xsave region to return.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
REG2 | 63:0 | The index of the page to return |
const, uint64_t: MV_VS_OP_XSAVE_GET_ALL_IDX_VAL
Value | Description |
---|---|
0x0000000000000021 | Defines the index for mv_vs_op_xsave_get_all |
Sets the XSAVE state as seen by the VS in the shared page. The format of the XSAVE state depends on which mode the VS is currently in, and which XSAVE features are enabled in the guest as seen by XCR0. If the XSAVE region is larger than one page, REG2 can be used to tell MicroV which page of the xsave region to set.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
REG2 | 63:0 | The index of the page to set |
const, uint64_t: MV_VS_OP_XSAVE_SET_ALL_IDX_VAL
Value | Description |
---|---|
0x0000000000000022 | Defines the index for mv_vs_op_xsave_set_all |
Returns the mv_mp_state_t of the VS.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The mv_mp_state_t read from the VS |
const, uint64_t: MV_VS_OP_MP_STATE_GET_IDX_VAL
Value | Description |
---|---|
0x0000000000000023 | Defines the index for mv_vs_op_mp_state_get |
Sets the mv_mp_state_t of the VS.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to query |
REG1 | 63:16 | REVI |
REG2 | 63:0 | The mv_mp_state_t to set the VS to |
const, uint64_t: MV_VS_OP_MP_STATE_SET_IDX_VAL
Value | Description |
---|---|
0x0000000000000024 | Defines the index for mv_vs_op_mp_state_set |
Injects an exception into the VS immediately.
On x86, only vectors 0-31 may be injected.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to inject the exception into |
REG1 | 63:16 | REVI |
REG2 | 63:0 | The vector to inject |
const, uint64_t: MV_VS_OP_INJECT_EXCEPTION_IDX_VAL
Value | Description |
---|---|
0x0000000000000025 | Defines the index for mv_vs_op_inject_exception |
Queues an interrupt in the VS for injection. The interrupt will only be injected into the VS once the VS is capable of processing the interrupt.
On x86, only vectors 31-255 may be injected. Interrupts injected using mv_vs_op_queue_interrupt bypass the emulated LAPIC, IOAPIC and PIC. If these emulated devices are in use, interrupts should be injected using these devices instead of the mv_vs_op_queue_interrupt, otherwise the guest's view of these emulated devices will not match the interrupt currently being processed.
Input:*
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
REG1 | 15:0 | The ID of the VS to queue the interrupt into |
REG1 | 63:16 | REVI |
REG2 | 63:0 | The vector to queue |
const, uint64_t: MV_VS_OP_QUEUE_INTERRUPT_IDX_VAL
Value | Description |
---|---|
0x0000000000000026 | Defines the index for mv_vs_op_queue_interrupt |
Returns the frequency of the VS.
Input:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | Set to the result of mv_handle_op_open_handle |
Output:
Register Name | Bits | Description |
---|---|---|
REG0 | 63:0 | The resulting frequency in KHz |
const, uint64_t: MV_VS_OP_TSC_GET_KHZ_IDX_VAL
Value | Description |
---|---|
0x0000000000000027 | Defines the index for mv_vs_op_tsc_get_khz |
Reserved
const, uint64_t: MV_VS_OP_TSC_SET_KHZ_IDX_VAL
Value | Description |
---|---|
0x0000000000000028 | Defines the index for mv_vs_op_tsc_set_khz |