Skip to content

Latest commit

 

History

History
2280 lines (1751 loc) · 113 KB

MicroV Hypercall Specification.md

File metadata and controls

2280 lines (1751 loc) · 113 KB

Table of Contents

1. Introduction

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.

1.1. Reserved Values

Name Description
REVZ reserved zero, meaning the value must be set to 0
REVI reserved ignore, meaning the value is ignored

1.2. Document Revision

Version Description
Mv#1 The initial version of this specification

1.3. Glossary

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

1.4. Constants, Structures, Enumerations and Bit Fields

1.4.1. Register Type

Defines which register a hypercall is requesting.

1.4.1.1. Intel/AMD

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)

1.4.2. Bit Size Type

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

1.4.3. Permission Flags

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

1.4.4. Multiprocessor State

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)

1.4.5. Register Descriptor Lists

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

1.4.6. Memory Descriptor Lists

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

1.4.7. CPUID Descriptor Lists

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

1.4.8. RDL Flags

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

1.4.9. Map Flags

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

1.5. ID Constants

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

1.6. Endianness

This document only applies to 64bit Intel and AMD systems conforming to the amd64 architecture. As such, this document is limited to little endian.

1.7. Physical Processor (PP)

TBD

1.8. Virtual Machine (VM)

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.

1.9. Virtual Processor (VP)

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.

1.10. Virtual Processor State (VS)

TBD

2. Hypercall Interface

The following section defines the hypercall interface used by this specification, and therefore MicroV.

2.1. Legal Hypercall Environments

The kernel and userspace can execute hypercalls from 64bit mode. 32bit mode is currently not supported.

2.2. Alignment Requirements

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.

2.3. Hypercall Status Codes

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.

2.3.1. MV_STATUS_SUCCESS, VALUE=0

const, mv_status_t: MV_STATUS_SUCCESS

Value Description
0x0000000000000000 Indicates the hypercall returned successfully

2.3.2. MV_STATUS_FAILURE, VALUE=1

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

2.3.3. MV_STATUS_INVALID_PERM, VALUE=2

const, mv_status_t: MV_STATUS_INVALID_PERM_DENIED

Value Description
0xDEAD000000010002 Indicates the policy engine denied the hypercall

2.3.4. MV_STATUS_INVALID_PARAMS, VALUE=3

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

2.3.5. MV_STATUS_RETRY, VALUE=0x6

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

2.3.6. MV_STATUS_EXIT, VALUE=0x6

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

2.4. Hypercall Inputs

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

2.5. Hypercall Outputs

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)

2.6. Hypercall Opcodes

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.

2.6.1. ID Support

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

2.6.2. Handle Support

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

2.6.3. Debug Support

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

2.6.4. Physical Processors

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

2.6.5. Virtual Machines

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

2.6.6. Virtual Processors

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

2.6.7. Virtual Processor State

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

2.7. Hypercall Specification IDs

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

2.8. Hypercall Continuation

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.

2.9. ID Hypercalls

2.9.1. mv_id_op_version, OP=0x0, IDX=0x0

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

2.9.2. mv_id_op_get_capability, OP=0x0, IDX=0x1

TBD

const, uint64_t: MV_ID_OP_GET_CAPABILITY_IDX_VAL

Value Description
0x0000000000000001 Defines the index for mv_id_op_get_capability

2.9.3. mv_id_op_clr_capability, OP=0x0, IDX=0x2

TBD

const, uint64_t: MV_ID_OP_CLR_CAPABILITY_IDX_VAL

Value Description
0x0000000000000002 Defines the index for mv_id_op_clr_capability

2.9.4. mv_id_op_set_capability, OP=0x0, IDX=0x3

TBD

const, uint64_t: MV_ID_OP_SET_CAPABILITY_IDX_VAL

Value Description
0x0000000000000003 Defines the index for mv_id_op_set_capability

2.9.5. mv_id_op_has_capability, OP=0x0, IDX=0x4

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

2.10. Handle Hypercalls

2.10.1. mv_handle_op_open_handle, OP=0x1, IDX=0x0

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

2.10.2. mv_handle_op_close_handle, OP=0x1, IDX=0x1

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

2.11. Debug Hypercalls

2.11.1. mv_debug_op_out, OP=0x2, IDX=0x0

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

2.12. Physical Processor Hypercalls

TBD

2.12.1. mv_pp_op_ppid, OP=0x3, IDX=0x0

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

2.12.2. mv_pp_op_online_pps, OP=0x3, IDX=0x1

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

2.12.3. mv_pp_op_clr_shared_page_gpa, OP=0x3, IDX=0x2

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

2.12.4. mv_pp_op_set_shared_page_gpa, OP=0x3, IDX=0x3

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

2.12.5. mv_pp_op_cpuid_get_supported, OP=0x3, IDX=0x4

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

2.12.6. mv_pp_op_cpuid_get_supported_list, OP=0x3, IDX=0x5

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

2.12.7. mv_pp_op_cpuid_get_permissable, OP=0x3, IDX=0x6

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

2.12.8. mv_pp_op_cpuid_get_permissable_list, OP=0x3, IDX=0x7

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

2.12.9. mv_pp_op_cpuid_get_emulated, OP=0x3, IDX=0x8

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

2.12.10. mv_pp_op_cpuid_get_emulated_list, OP=0x3, IDX=0x9

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

2.12.11. mv_pp_op_reg_get_supported, OP=0x3, IDX=0xA

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

2.12.12. mv_pp_op_reg_get_supported_list, OP=0x3, IDX=0xB

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

2.12.13. mv_pp_op_reg_get_permissable, OP=0x3, IDX=0xC

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

2.12.14. mv_pp_op_reg_get_permissable_list, OP=0x3, IDX=0xD

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

2.12.15. mv_pp_op_reg_get_emulated, OP=0x3, IDX=0xE

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

2.12.16. mv_pp_op_reg_get_emulated_list, OP=0x3, IDX=0xF

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

2.12.17. mv_pp_op_msr_get_supported, OP=0x3, IDX=010

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

2.12.18. mv_pp_op_msr_get_supported_list, OP=0x3, IDX=0x11

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

2.12.19. mv_pp_op_msr_get_permissable, OP=0x3, IDX=0x12

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

2.12.20. mv_pp_op_msr_get_permissable_list, OP=0x3, IDX=0x13

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

2.12.21. mv_pp_op_msr_get_emulated, OP=0x3, IDX=0x14

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

2.12.22. mv_pp_op_msr_get_emulated_list, OP=0x3, IDX=0x15

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

2.12.23. mv_pp_op_tsc_get_khz, OP=0x3, IDX=0x16

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

2.12.24. mv_pp_op_tsc_set_khz, OP=0x3, IDX=0x17

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

2.13. Virtual Machine Hypercalls

TBD

2.13.1. mv_vm_op_create_vm, OP=0x4, IDX=0x0

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

2.13.2. mv_vm_op_destroy_vm, OP=0x4, IDX=0x1

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

2.13.3. mv_vm_op_vmid, OP=0x4, IDX=0x2

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

2.13.4. mv_vm_op_mmio_map, OP=0x4, IDX=0x3

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

2.13.5. mv_vm_op_mmio_unmap, OP=0x4, IDX=0x4

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

2.14. Virtual Processor Hypercalls

TBD

2.14.1. mv_vp_op_create_vp, OP=0x5, IDX=0x0

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

2.14.2. mv_vp_op_destroy_vp, OP=0x5, IDX=0x1

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

2.14.3. mv_vp_op_vmid, OP=0x5, IDX=0x2

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

2.14.4. mv_vp_op_vpid, OP=0x5, IDX=0x3

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

2.15. Virtual Processor State Hypercalls

TBD

2.15.1. mv_vs_op_create_vs, OP=0x6, IDX=0x0

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

2.15.2. mv_vs_op_destroy_vs, OP=0x6, IDX=0x1

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

2.15.3. mv_vs_op_vmid, OP=0x6, IDX=0x2

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

2.15.4. mv_vs_op_vpid, OP=0x6, IDX=0x3

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

2.15.5. mv_vs_op_vsid, OP=0x6, IDX=0x4

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

2.15.6. mv_vs_op_gva_to_gla, OP=0x6, IDX=0x5

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

2.15.7. mv_vs_op_gla_to_gpa, OP=0x6, IDX=0x6

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

2.15.8. mv_vs_op_gva_to_gpa, OP=0x6, IDX=0x7

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

2.15.9. mv_vs_op_run, OP=0x6, IDX=0x8

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

2.15.9.1. mv_exit_reason_t_failure

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

2.15.9.2. mv_exit_reason_t_unknown

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

2.15.9.3. mv_exit_reason_t_hlt

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

2.15.9.4. mv_exit_reason_t_io

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

2.15.9.5. mv_exit_reason_t_mmio

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

2.15.9.5. mv_exit_reason_t_msr

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

2.15.9.5. mv_exit_reason_t_interrupt

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.

2.15.9.5. mv_exit_reason_t_nmi

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.

2.15.10. mv_vs_op_cpuid_get, OP=0x6, IDX=0x9

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

2.15.11. mv_vs_op_cpuid_set, OP=0x6, IDX=0xA

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

2.15.12. mv_vs_op_cpuid_get_list, OP=0x6, IDX=0xB

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

2.15.13. mv_vs_op_cpuid_set_list, OP=0x6, IDX=0xC

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

2.15.14. mv_vs_op_reg_get, OP=0x6, IDX=0xD

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

2.15.15. mv_vs_op_reg_set, OP=0x6, IDX=0xE

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

2.15.16. mv_vs_op_reg_get_list, OP=0x6, IDX=0xF

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

2.15.17. mv_vs_op_reg_set_list, OP=0x6, IDX=0x10

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

2.15.18. mv_vs_op_msr_get, OP=0x6, IDX=0x17

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

2.15.19. mv_vs_op_msr_set, OP=0x6, IDX=0x18

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

2.15.20. mv_vs_op_msr_get_list, OP=0x6, IDX=0x19

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

2.15.21. mv_vs_op_msr_set_list, OP=0x6, IDX=0x1A

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

2.15.22. mv_vs_op_fpu_get, OP=0x6, IDX=0x1B

Reserved

const, uint64_t: MV_VS_OP_FPU_GET_IDX_VAL

Value Description
0x000000000000001B Defines the index for mv_vs_op_fpu_get

2.15.23. mv_vs_op_fpu_set, OP=0x6, IDX=0x1C

Reserved

const, uint64_t: MV_VS_OP_FPU_SET_IDX_VAL

Value Description
0x000000000000001C Defines the index for mv_vs_op_fpu_set

2.15.24. mv_vs_op_fpu_get_all, OP=0x6, IDX=0x1D

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

2.15.25. mv_vs_op_fpu_set_all, OP=0x6, IDX=0x1E

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

2.15.26. mv_vs_op_xsave_get, OP=0x6, IDX=0x1F

Reserved

const, uint64_t: MV_VS_OP_XSAVE_GET_IDX_VAL

Value Description
0x000000000000001F Defines the index for mv_vs_op_xsave_get

2.15.27. mv_vs_op_xsave_set, OP=0x6, IDX=0x20

Reserved

const, uint64_t: MV_VS_OP_XSAVE_SET_IDX_VAL

Value Description
0x0000000000000020 Defines the index for mv_vs_op_xsave_set

2.15.28. mv_vs_op_xsave_get_all, OP=0x6, IDX=0x21

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

2.15.29. mv_vs_op_xsave_set_all, OP=0x6, IDX=0x22

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

2.15.30. mv_vs_op_mp_state_get, OP=0x6, IDX=0x23

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

2.15.31. mv_vs_op_mp_state_set, OP=0x6, IDX=0x24

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

2.15.32. mv_vs_op_inject_exception, OP=0x6, IDX=0x25

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

2.15.33. mv_vs_op_queue_interrupt, OP=0x6, IDX=0x26

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

2.12.23. mv_vs_op_tsc_get_khz, OP=0x3, IDX=0x27

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

2.12.24. mv_vs_op_tsc_set_khz, OP=0x3, IDX=0x28

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