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]]
name = "mshv-bindings"
version = "0.2.0"
source = "git+https://github.com/rust-vmm/mshv?tag=v0.2.0#dd0a9f5ab9c32673e88d6de200af788dbfca6a72"
version = "0.3.0"
source = "git+https://github.com/rust-vmm/mshv?tag=v0.3.0#fda05380ea4c68b807996299d5ffb2854ca6d01d"
dependencies = [
"libc",
"num_enum",
@ -1267,8 +1267,8 @@ dependencies = [
[[package]]
name = "mshv-ioctls"
version = "0.2.0"
source = "git+https://github.com/rust-vmm/mshv?tag=v0.2.0#dd0a9f5ab9c32673e88d6de200af788dbfca6a72"
version = "0.3.0"
source = "git+https://github.com/rust-vmm/mshv?tag=v0.3.0#fda05380ea4c68b807996299d5ffb2854ca6d01d"
dependencies = [
"libc",
"mshv-bindings",
@ -2225,7 +2225,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "vfio-bindings"
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 = [
"vmm-sys-util",
]
@ -2233,7 +2233,7 @@ dependencies = [
[[package]]
name = "vfio-ioctls"
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 = [
"byteorder",
"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 }
libc = "0.2.158"
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",
"with-serde",
], 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_with = { version = "3.9.0", default-features = false, features = [
"macros",

View File

@ -186,7 +186,7 @@ pub enum IrqRoutingEntry {
#[cfg(feature = "kvm")]
Kvm(kvm_bindings::kvm_irq_routing_entry),
#[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)]

View File

@ -46,9 +46,6 @@ pub use x86_64::*;
#[cfg(target_arch = "x86_64")]
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
///
@ -61,19 +58,13 @@ pub const PAGE_SHIFT: usize = 12;
impl From<mshv_user_mem_region> for UserMemoryRegion {
fn from(region: mshv_user_mem_region) -> Self {
let mut flags: u32 = 0;
if region.flags & HV_MAP_GPA_READABLE != 0 {
flags |= USER_MEMORY_REGION_READ;
}
if region.flags & HV_MAP_GPA_WRITABLE != 0 {
let mut flags: u32 = USER_MEMORY_REGION_READ | USER_MEMORY_REGION_ADJUSTABLE;
if region.flags & (1 << MSHV_SET_MEM_BIT_WRITABLE) != 0 {
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;
}
if region.flags & HV_MAP_GPA_ADJUSTABLE != 0 {
flags |= USER_MEMORY_REGION_ADJUSTABLE;
}
UserMemoryRegion {
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 {
fn from(region: UserMemoryRegion) -> Self {
let mut flags: u32 = 0;
if region.flags & USER_MEMORY_REGION_READ != 0 {
flags |= HV_MAP_GPA_READABLE;
}
let mut flags: u8 = 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 {
flags |= HV_MAP_GPA_EXECUTABLE;
}
if region.flags & USER_MEMORY_REGION_ADJUSTABLE != 0 {
flags |= HV_MAP_GPA_ADJUSTABLE;
flags |= 1 << MSHV_SET_MEM_BIT_EXECUTABLE;
}
mshv_user_mem_region {
@ -126,6 +111,7 @@ impl From<UserMemoryRegion> for mshv_user_mem_region {
size: region.memory_size,
userspace_addr: region.userspace_addr,
flags,
..Default::default()
}
}
}
@ -182,13 +168,13 @@ impl From<crate::StandardRegisters> for mshv_bindings::StandardRegisters {
}
}
impl From<mshv_msi_routing_entry> for IrqRoutingEntry {
fn from(s: mshv_msi_routing_entry) -> Self {
impl From<mshv_user_irq_entry> for IrqRoutingEntry {
fn from(s: mshv_user_irq_entry) -> Self {
IrqRoutingEntry::Mshv(s)
}
}
impl From<IrqRoutingEntry> for mshv_msi_routing_entry {
impl From<IrqRoutingEntry> for mshv_user_irq_entry {
fn from(e: IrqRoutingEntry) -> Self {
match e {
IrqRoutingEntry::Mshv(e) => e,
@ -556,8 +542,7 @@ impl cpu::Vcpu for MshvVcpu {
#[allow(non_upper_case_globals)]
fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> {
let hv_message: hv_message = hv_message::default();
match self.fd.run(hv_message) {
match self.fd.run() {
Ok(x) => match x.header.message_type {
hv_message_type_HVMSG_X64_HALT => {
debug!("HALT");
@ -724,16 +709,21 @@ impl cpu::Vcpu for MshvVcpu {
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].host_access = host_vis;
gpa_list[0].acquire = 0;
gpa_list[0].page_count = gpas.len() as u64;
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
// gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold
// everything from gpas.
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());
}
@ -1777,9 +1767,9 @@ impl vm::Vm for MshvVm {
readonly: bool,
_log_dirty_pages: bool,
) -> 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 {
flags |= HV_MAP_GPA_WRITABLE;
flags |= 1 << MSHV_SET_MEM_BIT_WRITABLE;
}
mshv_user_mem_region {
@ -1787,6 +1777,7 @@ impl vm::Vm for MshvVm {
guest_pfn: guest_phys_addr >> PAGE_SHIFT,
size: memory_size,
userspace_addr,
..Default::default()
}
.into()
}
@ -1807,7 +1798,7 @@ impl vm::Vm for MshvVm {
///
fn make_routing_entry(&self, gsi: u32, config: &InterruptSourceConfig) -> IrqRoutingEntry {
match config {
InterruptSourceConfig::MsiIrq(cfg) => mshv_msi_routing_entry {
InterruptSourceConfig::MsiIrq(cfg) => mshv_user_irq_entry {
gsi,
address_lo: cfg.low_addr,
address_hi: cfg.high_addr,
@ -1822,10 +1813,10 @@ impl vm::Vm for MshvVm {
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> vm::Result<()> {
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;
let entries: Vec<mshv_msi_routing_entry> = entries
let entries: Vec<mshv_user_irq_entry> = entries
.iter()
.map(|entry| match entry {
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
// everything from entries.
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());
entries_slice.copy_from_slice(&entries);
}
@ -1867,7 +1858,11 @@ impl vm::Vm for MshvVm {
// This is a requirement from Microsoft Hypervisor
for (_, s) in dirty_log_slots.iter() {
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()))?;
}
self.fd
@ -1884,7 +1879,7 @@ impl vm::Vm for MshvVm {
.get_dirty_log(
base_gpa >> PAGE_SHIFT,
memory_size as usize,
DIRTY_BITMAP_CLEAR_DIRTY,
MSHV_GPAP_ACCESS_OP_CLEAR as u8,
)
.map_err(|e| vm::HypervisorVmError::GetDirtyLog(e.into()))
}
@ -1937,20 +1932,20 @@ impl vm::Vm for MshvVm {
page_size: u32,
pages: &[u64],
) -> vm::Result<()> {
debug_assert!(page_size == hv_isolated_page_size_HV_ISOLATED_PAGE_SIZE_4KB);
if pages.is_empty() {
return Ok(());
}
let mut isolated_pages =
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;
isolated_pages[0].page_size = page_size;
isolated_pages[0].page_type = page_type as u8;
isolated_pages[0].page_count = pages.len() as u64;
// 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
// everything from pages.
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);
}
self.fd
@ -2054,6 +2049,8 @@ impl vm::Vm for MshvVm {
#[cfg(feature = "sev_snp")]
fn gain_page_access(&self, gpa: u64, size: u32) -> vm::Result<()> {
use mshv_ioctls::set_bits;
if !self.sev_snp_enabled {
return Ok(());
}
@ -2065,16 +2062,19 @@ impl vm::Vm for MshvVm {
if !gpas.is_empty() {
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].host_access = HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE;
gpa_list[0].acquire = 1;
gpa_list[0].flags = 0;
gpa_list[0].page_count = gpas.len() as u64;
gpa_list[0].flags = set_bits!(
u8,
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
// gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold
// everything from gpas.
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());
}

View File

@ -17,7 +17,7 @@ epoll = "4.3.3"
event_monitor = { path = "../event_monitor" }
libc = "0.2.158"
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_util = { path = "../net_util" }
pci = { path = "../pci" }

View File

@ -51,7 +51,7 @@ libc = "0.2.158"
linux-loader = { version = "0.11.0", features = ["bzimage", "elf", "pe"] }
log = "0.4.22"
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",
"with-serde",
], 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> {
Ok(or![
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_CREATE_PARTITION())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_MAP_GUEST_MEMORY())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_UNMAP_GUEST_MEMORY())?],
and![Cond::new(
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_IRQFD())?],
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,
ArgLen::Dword,
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(
@ -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_GET_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_UNMAP_GUEST_MEMORY())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_SET_GUEST_MEMORY())?],
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(