hypervisor: mshv: Update mshv crates to v0.3.0

And modify to code to use the updated interfaces.

Arguments for map_guest_memory, get_dirty_bitmap, vp.run(),
import_isolated_pages, modify_gpa_host_access have changed.
Update these to use the new interfaces, including new MSHV_*
definitions, and remove some redundant arguments.

Update seccomp IOCTLs to reflect interface changes.

Fix irq-related definitions naming.

Bump vfio-ioctls to support mshv v0.3.0.

Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
This commit is contained in:
Nuno Das Neves 2024-04-30 18:39:21 +00:00 committed by Rob Bradford
parent d9ee760f3b
commit 9f08aa6dc2
7 changed files with 67 additions and 63 deletions

12
Cargo.lock generated
View File

@ -1254,8 +1254,8 @@ checksum = "9bec4598fddb13cc7b528819e697852653252b760f1228b7642679bf2ff2cd07"
[[package]] [[package]]
name = "mshv-bindings" name = "mshv-bindings"
version = "0.2.0" version = "0.3.0"
source = "git+https://github.com/rust-vmm/mshv?tag=v0.2.0#dd0a9f5ab9c32673e88d6de200af788dbfca6a72" source = "git+https://github.com/rust-vmm/mshv?tag=v0.3.0#fda05380ea4c68b807996299d5ffb2854ca6d01d"
dependencies = [ dependencies = [
"libc", "libc",
"num_enum", "num_enum",
@ -1267,8 +1267,8 @@ dependencies = [
[[package]] [[package]]
name = "mshv-ioctls" name = "mshv-ioctls"
version = "0.2.0" version = "0.3.0"
source = "git+https://github.com/rust-vmm/mshv?tag=v0.2.0#dd0a9f5ab9c32673e88d6de200af788dbfca6a72" source = "git+https://github.com/rust-vmm/mshv?tag=v0.3.0#fda05380ea4c68b807996299d5ffb2854ca6d01d"
dependencies = [ dependencies = [
"libc", "libc",
"mshv-bindings", "mshv-bindings",
@ -2225,7 +2225,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "vfio-bindings" name = "vfio-bindings"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#94bec9fa2a94a29e11d83766a992cb85496fcb7c" source = "git+https://github.com/rust-vmm/vfio?branch=main#09c6b193d6b5a339f6a3ec3f44095046c519baaa"
dependencies = [ dependencies = [
"vmm-sys-util", "vmm-sys-util",
] ]
@ -2233,7 +2233,7 @@ dependencies = [
[[package]] [[package]]
name = "vfio-ioctls" name = "vfio-ioctls"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#94bec9fa2a94a29e11d83766a992cb85496fcb7c" source = "git+https://github.com/rust-vmm/vfio?branch=main#09c6b193d6b5a339f6a3ec3f44095046c519baaa"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"kvm-bindings", "kvm-bindings",

View File

@ -22,11 +22,11 @@ kvm-bindings = { version = "0.9.1", optional = true, features = ["serde"] }
kvm-ioctls = { version = "0.18.0", optional = true } kvm-ioctls = { version = "0.18.0", optional = true }
libc = "0.2.158" libc = "0.2.158"
log = "0.4.22" log = "0.4.22"
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", tag = "v0.2.0", features = [ mshv-bindings = { git = "https://github.com/rust-vmm/mshv", tag = "v0.3.0", features = [
"fam-wrappers", "fam-wrappers",
"with-serde", "with-serde",
], optional = true } ], optional = true }
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", tag = "v0.2.0", optional = true } mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", tag = "v0.3.0", optional = true }
serde = { version = "1.0.208", features = ["derive", "rc"] } serde = { version = "1.0.208", features = ["derive", "rc"] }
serde_with = { version = "3.9.0", default-features = false, features = [ serde_with = { version = "3.9.0", default-features = false, features = [
"macros", "macros",

View File

@ -186,7 +186,7 @@ pub enum IrqRoutingEntry {
#[cfg(feature = "kvm")] #[cfg(feature = "kvm")]
Kvm(kvm_bindings::kvm_irq_routing_entry), Kvm(kvm_bindings::kvm_irq_routing_entry),
#[cfg(feature = "mshv")] #[cfg(feature = "mshv")]
Mshv(mshv_bindings::mshv_msi_routing_entry), Mshv(mshv_bindings::mshv_user_irq_entry),
} }
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]

View File

@ -46,9 +46,6 @@ pub use x86_64::*;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use x86_64::{emulator, VcpuMshvState}; pub use x86_64::{emulator, VcpuMshvState};
const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4;
const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8;
/// ///
/// Export generically-named wrappers of mshv-bindings for Unix-based platforms /// Export generically-named wrappers of mshv-bindings for Unix-based platforms
/// ///
@ -61,19 +58,13 @@ pub const PAGE_SHIFT: usize = 12;
impl From<mshv_user_mem_region> for UserMemoryRegion { impl From<mshv_user_mem_region> for UserMemoryRegion {
fn from(region: mshv_user_mem_region) -> Self { fn from(region: mshv_user_mem_region) -> Self {
let mut flags: u32 = 0; let mut flags: u32 = USER_MEMORY_REGION_READ | USER_MEMORY_REGION_ADJUSTABLE;
if region.flags & HV_MAP_GPA_READABLE != 0 { if region.flags & (1 << MSHV_SET_MEM_BIT_WRITABLE) != 0 {
flags |= USER_MEMORY_REGION_READ;
}
if region.flags & HV_MAP_GPA_WRITABLE != 0 {
flags |= USER_MEMORY_REGION_WRITE; flags |= USER_MEMORY_REGION_WRITE;
} }
if region.flags & HV_MAP_GPA_EXECUTABLE != 0 { if region.flags & (1 << MSHV_SET_MEM_BIT_EXECUTABLE) != 0 {
flags |= USER_MEMORY_REGION_EXECUTE; flags |= USER_MEMORY_REGION_EXECUTE;
} }
if region.flags & HV_MAP_GPA_ADJUSTABLE != 0 {
flags |= USER_MEMORY_REGION_ADJUSTABLE;
}
UserMemoryRegion { UserMemoryRegion {
guest_phys_addr: (region.guest_pfn << PAGE_SHIFT as u64) guest_phys_addr: (region.guest_pfn << PAGE_SHIFT as u64)
@ -107,18 +98,12 @@ impl From<ClockData> for MshvClockData {
impl From<UserMemoryRegion> for mshv_user_mem_region { impl From<UserMemoryRegion> for mshv_user_mem_region {
fn from(region: UserMemoryRegion) -> Self { fn from(region: UserMemoryRegion) -> Self {
let mut flags: u32 = 0; let mut flags: u8 = 0;
if region.flags & USER_MEMORY_REGION_READ != 0 {
flags |= HV_MAP_GPA_READABLE;
}
if region.flags & USER_MEMORY_REGION_WRITE != 0 { if region.flags & USER_MEMORY_REGION_WRITE != 0 {
flags |= HV_MAP_GPA_WRITABLE; flags |= 1 << MSHV_SET_MEM_BIT_WRITABLE;
} }
if region.flags & USER_MEMORY_REGION_EXECUTE != 0 { if region.flags & USER_MEMORY_REGION_EXECUTE != 0 {
flags |= HV_MAP_GPA_EXECUTABLE; flags |= 1 << MSHV_SET_MEM_BIT_EXECUTABLE;
}
if region.flags & USER_MEMORY_REGION_ADJUSTABLE != 0 {
flags |= HV_MAP_GPA_ADJUSTABLE;
} }
mshv_user_mem_region { mshv_user_mem_region {
@ -126,6 +111,7 @@ impl From<UserMemoryRegion> for mshv_user_mem_region {
size: region.memory_size, size: region.memory_size,
userspace_addr: region.userspace_addr, userspace_addr: region.userspace_addr,
flags, flags,
..Default::default()
} }
} }
} }
@ -182,13 +168,13 @@ impl From<crate::StandardRegisters> for mshv_bindings::StandardRegisters {
} }
} }
impl From<mshv_msi_routing_entry> for IrqRoutingEntry { impl From<mshv_user_irq_entry> for IrqRoutingEntry {
fn from(s: mshv_msi_routing_entry) -> Self { fn from(s: mshv_user_irq_entry) -> Self {
IrqRoutingEntry::Mshv(s) IrqRoutingEntry::Mshv(s)
} }
} }
impl From<IrqRoutingEntry> for mshv_msi_routing_entry { impl From<IrqRoutingEntry> for mshv_user_irq_entry {
fn from(e: IrqRoutingEntry) -> Self { fn from(e: IrqRoutingEntry) -> Self {
match e { match e {
IrqRoutingEntry::Mshv(e) => e, IrqRoutingEntry::Mshv(e) => e,
@ -556,8 +542,7 @@ impl cpu::Vcpu for MshvVcpu {
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> { fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> {
let hv_message: hv_message = hv_message::default(); match self.fd.run() {
match self.fd.run(hv_message) {
Ok(x) => match x.header.message_type { Ok(x) => match x.header.message_type {
hv_message_type_HVMSG_X64_HALT => { hv_message_type_HVMSG_X64_HALT => {
debug!("HALT"); debug!("HALT");
@ -724,16 +709,21 @@ impl cpu::Vcpu for MshvVcpu {
let mut gpa_list = let mut gpa_list =
vec_with_array_field::<mshv_modify_gpa_host_access, u64>(gpas.len()); vec_with_array_field::<mshv_modify_gpa_host_access, u64>(gpas.len());
gpa_list[0].gpa_list_size = gpas.len() as u64; gpa_list[0].page_count = gpas.len() as u64;
gpa_list[0].host_access = host_vis;
gpa_list[0].acquire = 0;
gpa_list[0].flags = 0; gpa_list[0].flags = 0;
if host_vis & HV_MAP_GPA_READABLE != 0 {
gpa_list[0].flags |= 1 << MSHV_GPA_HOST_ACCESS_BIT_READABLE;
}
if host_vis & HV_MAP_GPA_WRITABLE != 0 {
gpa_list[0].flags |= 1 << MSHV_GPA_HOST_ACCESS_BIT_WRITABLE;
}
// SAFETY: gpa_list initialized with gpas.len() and now it is being turned into // SAFETY: gpa_list initialized with gpas.len() and now it is being turned into
// gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold // gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold
// everything from gpas. // everything from gpas.
unsafe { unsafe {
let gpas_slice: &mut [u64] = gpa_list[0].gpa_list.as_mut_slice(gpas.len()); let gpas_slice: &mut [u64] =
gpa_list[0].guest_pfns.as_mut_slice(gpas.len());
gpas_slice.copy_from_slice(gpas.as_slice()); gpas_slice.copy_from_slice(gpas.as_slice());
} }
@ -1777,9 +1767,9 @@ impl vm::Vm for MshvVm {
readonly: bool, readonly: bool,
_log_dirty_pages: bool, _log_dirty_pages: bool,
) -> UserMemoryRegion { ) -> UserMemoryRegion {
let mut flags = HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_ADJUSTABLE; let mut flags = 1 << MSHV_SET_MEM_BIT_EXECUTABLE;
if !readonly { if !readonly {
flags |= HV_MAP_GPA_WRITABLE; flags |= 1 << MSHV_SET_MEM_BIT_WRITABLE;
} }
mshv_user_mem_region { mshv_user_mem_region {
@ -1787,6 +1777,7 @@ impl vm::Vm for MshvVm {
guest_pfn: guest_phys_addr >> PAGE_SHIFT, guest_pfn: guest_phys_addr >> PAGE_SHIFT,
size: memory_size, size: memory_size,
userspace_addr, userspace_addr,
..Default::default()
} }
.into() .into()
} }
@ -1807,7 +1798,7 @@ impl vm::Vm for MshvVm {
/// ///
fn make_routing_entry(&self, gsi: u32, config: &InterruptSourceConfig) -> IrqRoutingEntry { fn make_routing_entry(&self, gsi: u32, config: &InterruptSourceConfig) -> IrqRoutingEntry {
match config { match config {
InterruptSourceConfig::MsiIrq(cfg) => mshv_msi_routing_entry { InterruptSourceConfig::MsiIrq(cfg) => mshv_user_irq_entry {
gsi, gsi,
address_lo: cfg.low_addr, address_lo: cfg.low_addr,
address_hi: cfg.high_addr, address_hi: cfg.high_addr,
@ -1822,10 +1813,10 @@ impl vm::Vm for MshvVm {
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> vm::Result<()> { fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> vm::Result<()> {
let mut msi_routing = let mut msi_routing =
vec_with_array_field::<mshv_msi_routing, mshv_msi_routing_entry>(entries.len()); vec_with_array_field::<mshv_user_irq_table, mshv_user_irq_entry>(entries.len());
msi_routing[0].nr = entries.len() as u32; msi_routing[0].nr = entries.len() as u32;
let entries: Vec<mshv_msi_routing_entry> = entries let entries: Vec<mshv_user_irq_entry> = entries
.iter() .iter()
.map(|entry| match entry { .map(|entry| match entry {
IrqRoutingEntry::Mshv(e) => *e, IrqRoutingEntry::Mshv(e) => *e,
@ -1838,7 +1829,7 @@ impl vm::Vm for MshvVm {
// entries_slice with entries.len() again. It is guaranteed to be large enough to hold // entries_slice with entries.len() again. It is guaranteed to be large enough to hold
// everything from entries. // everything from entries.
unsafe { unsafe {
let entries_slice: &mut [mshv_msi_routing_entry] = let entries_slice: &mut [mshv_user_irq_entry] =
msi_routing[0].entries.as_mut_slice(entries.len()); msi_routing[0].entries.as_mut_slice(entries.len());
entries_slice.copy_from_slice(&entries); entries_slice.copy_from_slice(&entries);
} }
@ -1867,7 +1858,11 @@ impl vm::Vm for MshvVm {
// This is a requirement from Microsoft Hypervisor // This is a requirement from Microsoft Hypervisor
for (_, s) in dirty_log_slots.iter() { for (_, s) in dirty_log_slots.iter() {
self.fd self.fd
.get_dirty_log(s.guest_pfn, s.memory_size as usize, DIRTY_BITMAP_SET_DIRTY) .get_dirty_log(
s.guest_pfn,
s.memory_size as usize,
MSHV_GPAP_ACCESS_OP_SET as u8,
)
.map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into()))?; .map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into()))?;
} }
self.fd self.fd
@ -1884,7 +1879,7 @@ impl vm::Vm for MshvVm {
.get_dirty_log( .get_dirty_log(
base_gpa >> PAGE_SHIFT, base_gpa >> PAGE_SHIFT,
memory_size as usize, memory_size as usize,
DIRTY_BITMAP_CLEAR_DIRTY, MSHV_GPAP_ACCESS_OP_CLEAR as u8,
) )
.map_err(|e| vm::HypervisorVmError::GetDirtyLog(e.into())) .map_err(|e| vm::HypervisorVmError::GetDirtyLog(e.into()))
} }
@ -1937,20 +1932,20 @@ impl vm::Vm for MshvVm {
page_size: u32, page_size: u32,
pages: &[u64], pages: &[u64],
) -> vm::Result<()> { ) -> vm::Result<()> {
debug_assert!(page_size == hv_isolated_page_size_HV_ISOLATED_PAGE_SIZE_4KB);
if pages.is_empty() { if pages.is_empty() {
return Ok(()); return Ok(());
} }
let mut isolated_pages = let mut isolated_pages =
vec_with_array_field::<mshv_import_isolated_pages, u64>(pages.len()); vec_with_array_field::<mshv_import_isolated_pages, u64>(pages.len());
isolated_pages[0].num_pages = pages.len() as u64; isolated_pages[0].page_type = page_type as u8;
isolated_pages[0].page_type = page_type; isolated_pages[0].page_count = pages.len() as u64;
isolated_pages[0].page_size = page_size;
// SAFETY: isolated_pages initialized with pages.len() and now it is being turned into // SAFETY: isolated_pages initialized with pages.len() and now it is being turned into
// pages_slice with pages.len() again. It is guaranteed to be large enough to hold // pages_slice with pages.len() again. It is guaranteed to be large enough to hold
// everything from pages. // everything from pages.
unsafe { unsafe {
let pages_slice: &mut [u64] = isolated_pages[0].page_number.as_mut_slice(pages.len()); let pages_slice: &mut [u64] = isolated_pages[0].guest_pfns.as_mut_slice(pages.len());
pages_slice.copy_from_slice(pages); pages_slice.copy_from_slice(pages);
} }
self.fd self.fd
@ -2054,6 +2049,8 @@ impl vm::Vm for MshvVm {
#[cfg(feature = "sev_snp")] #[cfg(feature = "sev_snp")]
fn gain_page_access(&self, gpa: u64, size: u32) -> vm::Result<()> { fn gain_page_access(&self, gpa: u64, size: u32) -> vm::Result<()> {
use mshv_ioctls::set_bits;
if !self.sev_snp_enabled { if !self.sev_snp_enabled {
return Ok(()); return Ok(());
} }
@ -2065,16 +2062,19 @@ impl vm::Vm for MshvVm {
if !gpas.is_empty() { if !gpas.is_empty() {
let mut gpa_list = vec_with_array_field::<mshv_modify_gpa_host_access, u64>(gpas.len()); let mut gpa_list = vec_with_array_field::<mshv_modify_gpa_host_access, u64>(gpas.len());
gpa_list[0].gpa_list_size = gpas.len() as u64; gpa_list[0].page_count = gpas.len() as u64;
gpa_list[0].host_access = HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE; gpa_list[0].flags = set_bits!(
gpa_list[0].acquire = 1; u8,
gpa_list[0].flags = 0; MSHV_GPA_HOST_ACCESS_BIT_ACQUIRE,
MSHV_GPA_HOST_ACCESS_BIT_READABLE,
MSHV_GPA_HOST_ACCESS_BIT_WRITABLE
);
// SAFETY: gpa_list initialized with gpas.len() and now it is being turned into // SAFETY: gpa_list initialized with gpas.len() and now it is being turned into
// gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold // gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold
// everything from gpas. // everything from gpas.
unsafe { unsafe {
let gpas_slice: &mut [u64] = gpa_list[0].gpa_list.as_mut_slice(gpas.len()); let gpas_slice: &mut [u64] = gpa_list[0].guest_pfns.as_mut_slice(gpas.len());
gpas_slice.copy_from_slice(gpas.as_slice()); gpas_slice.copy_from_slice(gpas.as_slice());
} }

View File

@ -17,7 +17,7 @@ epoll = "4.3.3"
event_monitor = { path = "../event_monitor" } event_monitor = { path = "../event_monitor" }
libc = "0.2.158" libc = "0.2.158"
log = "0.4.22" log = "0.4.22"
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", tag = "v0.2.0", optional = true } mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", tag = "v0.3.0", optional = true }
net_gen = { path = "../net_gen" } net_gen = { path = "../net_gen" }
net_util = { path = "../net_util" } net_util = { path = "../net_util" }
pci = { path = "../pci" } pci = { path = "../pci" }

View File

@ -51,7 +51,7 @@ libc = "0.2.158"
linux-loader = { version = "0.11.0", features = ["bzimage", "elf", "pe"] } linux-loader = { version = "0.11.0", features = ["bzimage", "elf", "pe"] }
log = "0.4.22" log = "0.4.22"
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" } micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", tag = "v0.2.0", features = [ mshv-bindings = { git = "https://github.com/rust-vmm/mshv", tag = "v0.3.0", features = [
"fam-wrappers", "fam-wrappers",
"with-serde", "with-serde",
], optional = true } ], optional = true }

View File

@ -159,8 +159,13 @@ use hypervisor::mshv::mshv_ioctls::*;
fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result<Vec<SeccompRule>, BackendError> { fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result<Vec<SeccompRule>, BackendError> {
Ok(or![ Ok(or![
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_CREATE_PARTITION())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_CREATE_PARTITION())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_MAP_GUEST_MEMORY())?], and![Cond::new(
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_UNMAP_GUEST_MEMORY())?], 1,
ArgLen::Dword,
Eq,
MSHV_INITIALIZE_PARTITION()
)?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_SET_GUEST_MEMORY())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_CREATE_VP())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_CREATE_VP())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_IRQFD())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_IRQFD())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_IOEVENTFD())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_IOEVENTFD())?],
@ -186,7 +191,7 @@ fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result<Vec<SeccompRule>, Backe
1, 1,
ArgLen::Dword, ArgLen::Dword,
Eq, Eq,
MSHV_GET_GPA_ACCESS_STATES() MSHV_GET_GPAP_ACCESS_BITMAP()
)?], )?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_VP_TRANSLATE_GVA())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_VP_TRANSLATE_GVA())?],
and![Cond::new( and![Cond::new(
@ -700,8 +705,7 @@ fn create_vcpu_ioctl_seccomp_rule_mshv() -> Result<Vec<SeccompRule>, BackendErro
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_RUN_VP())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_RUN_VP())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_GET_VP_REGISTERS())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_GET_VP_REGISTERS())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_SET_VP_REGISTERS())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_SET_VP_REGISTERS())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_MAP_GUEST_MEMORY())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_SET_GUEST_MEMORY())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_UNMAP_GUEST_MEMORY())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_VP_TRANSLATE_GVA())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_VP_TRANSLATE_GVA())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_GET_VP_CPUID_VALUES())?], and![Cond::new(1, ArgLen::Dword, Eq, MSHV_GET_VP_CPUID_VALUES())?],
and![Cond::new( and![Cond::new(