Skip to content

Commit 6a00fba

Browse files
committed
[host/hypervisor/hyperv_linux] brought back mshv driver
Needed to make some modications to hyperv_linux for it to conform to the new SandboxMemorySections API. With that, I also had to add a From impl to sandbox_builder. As an aside, I also modified the signature of get_memory_access_violation to take a borrow of SandboxMemorySections instead of an owned value, which ended up impacting kvm too. Signed-off-by: danbugs <[email protected]>
1 parent 7a2e0da commit 6a00fba

File tree

4 files changed

+106
-102
lines changed

4 files changed

+106
-102
lines changed

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ extern crate mshv_ioctls3 as mshv_ioctls;
2626

2727
use std::fmt::{Debug, Formatter};
2828

29-
use log::LevelFilter;
29+
use log::{error, LevelFilter};
3030
#[cfg(mshv2)]
3131
use mshv_bindings::hv_message;
3232
#[cfg(gdb)]
@@ -62,7 +62,7 @@ use super::{
6262
use crate::hypervisor::hypervisor_handler::HypervisorHandler;
6363
use crate::hypervisor::HyperlightExit;
6464
use crate::mem::ptr::{GuestPtr, RawPtr};
65-
use crate::sandbox::sandbox_builder::SandboxMemorySections;
65+
use crate::sandbox::sandbox_builder::{MemoryRegionFlags, SandboxMemorySections};
6666
#[cfg(gdb)]
6767
use crate::HyperlightError;
6868
use crate::{log_then_return, new_error, Result};
@@ -289,8 +289,6 @@ pub(crate) fn is_hypervisor_present() -> bool {
289289
/// called the Microsoft Hypervisor (MSHV)
290290
pub(super) struct HypervLinuxDriver {
291291
_mshv: Mshv,
292-
// TODO(danbugs:297): remove
293-
#[allow(dead_code)]
294292
vm_fd: VmFd,
295293
vcpu_fd: VcpuFd,
296294
entrypoint: u64,
@@ -379,11 +377,10 @@ impl HypervLinuxDriver {
379377
(None, None)
380378
};
381379

382-
// TODO(danbugs:297): bring back
383-
// mem_sections.iter().try_for_each(|region| {
384-
// let mshv_region = region.to_owned().into();
385-
// vm_fd.map_user_memory(mshv_region)
386-
// })?;
380+
mem_sections.iter().try_for_each(|(_, region)| {
381+
let mshv_region = region.to_owned().into();
382+
vm_fd.map_user_memory(mshv_region)
383+
})?;
387384

388385
Self::setup_initial_sregs(&mut vcpu_fd, pml4_ptr.absolute()?)?;
389386

@@ -476,7 +473,7 @@ impl Hypervisor for HypervLinuxDriver {
476473
let regs = StandardRegisters {
477474
rip: self.entrypoint,
478475
rsp: self.orig_rsp.absolute()?,
479-
rflags: 2, //bit 1 of rlags is required to be set
476+
rflags: 2, //bit 1 of rflags is required to be set
480477

481478
// function args
482479
rcx: hyperlight_peb_guest_memory_region_address,
@@ -496,6 +493,8 @@ impl Hypervisor for HypervLinuxDriver {
496493
dbg_mem_access_fn,
497494
)?;
498495

496+
// TODO(danbugs:297): here, we should update the rsp to what the guest configured.
497+
499498
Ok(())
500499
}
501500

@@ -512,7 +511,7 @@ impl Hypervisor for HypervLinuxDriver {
512511
let regs = StandardRegisters {
513512
rip: dispatch_func_addr.into(),
514513
rsp: self.orig_rsp.absolute()?,
515-
rflags: 2, //bit 1 of rlags is required to be set
514+
rflags: 2, //bit 1 of rflags is required to be set
516515
..Default::default()
517516
};
518517
self.vcpu_fd.set_regs(&regs)?;
@@ -616,24 +615,21 @@ impl Hypervisor for HypervLinuxDriver {
616615
INVALID_GPA_ACCESS_MESSAGE => {
617616
let mimo_message = m.to_memory_info()?;
618617
let gpa = mimo_message.guest_physical_address;
619-
// TODO(danbugs:297): bring back
620-
// let access_info = MemoryRegionFlags::try_from(mimo_message)?;
618+
let access_info = MemoryRegionFlags::try_from(mimo_message)?;
621619
crate::debug!(
622620
"mshv MMIO invalid GPA access -Details: Address: {} \n {:#?}",
623621
gpa,
624622
&self
625623
);
626-
// TODO(danbugs:297): bring back
627-
// match self.get_memory_access_violation(
628-
// gpa as usize,
629-
// &self.mem_regions,
630-
// access_info,
631-
// ) {
632-
// Some(access_info_violation) => access_info_violation,
633-
// None => HyperlightExit::Mmio(gpa),
634-
// }
635-
636-
HyperlightExit::Mmio(gpa)
624+
625+
match self.get_memory_access_violation(
626+
gpa as usize,
627+
&self.mem_sections,
628+
access_info,
629+
) {
630+
Some(access_info_violation) => access_info_violation,
631+
None => HyperlightExit::Mmio(gpa),
632+
}
637633
}
638634
// The only case an intercept exit is expected is when debugging is enabled
639635
// and the intercepts are installed
@@ -719,19 +715,18 @@ impl Hypervisor for HypervLinuxDriver {
719715
}
720716
}
721717

722-
// TODO(danbugs:297): bring back
723-
// impl Drop for HypervLinuxDriver {
724-
// #[instrument(skip_all, parent = Span::current(), level = "Trace")]
725-
// fn drop(&mut self) {
726-
// for region in self.mem_sections.iter() {
727-
// let mshv_region: mshv_user_mem_region = region.to_owned().into();
728-
// match self.vm_fd.unmap_user_memory(mshv_region) {
729-
// Ok(_) => (),
730-
// Err(e) => error!("Failed to unmap user memory in HyperVOnLinux ({:?})", e),
731-
// }
732-
// }
733-
// }
734-
// }
718+
impl Drop for HypervLinuxDriver {
719+
#[instrument(skip_all, parent = Span::current(), level = "Trace")]
720+
fn drop(&mut self) {
721+
for region in self.mem_sections.iter() {
722+
let mshv_region: mshv_bindings::mshv_user_mem_region = region.1.to_owned().into();
723+
match self.vm_fd.unmap_user_memory(mshv_region) {
724+
Ok(_) => (),
725+
Err(e) => error!("Failed to unmap user memory in HyperVOnLinux ({:?})", e),
726+
}
727+
}
728+
}
729+
}
735730

736731
// TODO(danbugs:297): bring back
737732
// #[cfg(test)]

src/hyperlight_host/src/hypervisor/kvm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ impl Hypervisor for KVMDriver {
528528

529529
match self.get_memory_access_violation(
530530
addr as usize,
531-
self.mem_sections.clone(),
531+
&self.mem_sections,
532532
MemoryRegionFlags::READ,
533533
) {
534534
Some(access_violation_exit) => access_violation_exit,
@@ -540,7 +540,7 @@ impl Hypervisor for KVMDriver {
540540

541541
match self.get_memory_access_violation(
542542
addr as usize,
543-
self.mem_sections.clone(),
543+
&self.mem_sections,
544544
MemoryRegionFlags::WRITE,
545545
) {
546546
Some(access_violation_exit) => access_violation_exit,

src/hyperlight_host/src/hypervisor/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ pub(crate) trait Hypervisor: Debug + Sync + Send {
169169
fn get_memory_access_violation(
170170
&self,
171171
gpa: usize,
172-
mem_sections: SandboxMemorySections,
172+
mem_sections: &SandboxMemorySections,
173173
access_info: MemoryRegionFlags,
174174
) -> Option<HyperlightExit> {
175175
// find the region containing the given gpa

src/hyperlight_host/src/sandbox/sandbox_builder.rs

Lines changed: 71 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ use crate::{
1717
log_build_details, log_then_return, new_error, Result, SandboxRunOptions, UninitializedSandbox,
1818
};
1919

20+
#[cfg(mshv2)]
21+
extern crate mshv_bindings2 as mshv_bindings;
22+
23+
#[cfg(mshv2)]
24+
use mshv_bindings::{
25+
HV_MAP_GPA_EXECUTABLE, HV_MAP_GPA_PERMISSIONS_NONE, HV_MAP_GPA_READABLE, HV_MAP_GPA_WRITABLE,
26+
};
27+
28+
#[cfg(mshv3)]
29+
extern crate mshv_bindings3 as mshv_bindings;
30+
31+
#[cfg(mshv3)]
32+
use mshv_bindings::{
33+
MSHV_SET_MEM_BIT_EXECUTABLE, MSHV_SET_MEM_BIT_UNMAP, MSHV_SET_MEM_BIT_WRITABLE,
34+
};
35+
2036
const DEFAULT_GUEST_CODE_SECTION_NAME: &str = "guest code";
2137
const DEFAULT_TMP_STACK_SECTION_NAME: &str = "tmp stack";
2238
const DEFAULT_HYPERLIGHT_PEB_SECTION_NAME: &str = "HyperlightPEB";
@@ -28,7 +44,7 @@ pub(crate) const PD_OFFSET: usize = 0x2000; // this offset is from the PML4 base
2844
pub(crate) const PT_OFFSET: usize = 0x3000; // this offset is from the PML4 base address
2945
const DEFAULT_GUEST_MEMORY_SIZE: usize = 0x200_000; // 2MB
3046

31-
/// TODO: comment
47+
/// Represents a memory section in the sandbox.
3248
#[derive(Debug, Clone)]
3349
pub struct SandboxMemorySection {
3450
/// Name of the memory section
@@ -164,16 +180,6 @@ impl SandboxMemorySections {
164180
}
165181
}
166182

167-
#[cfg(mshv2)]
168-
extern crate mshv_bindings2 as mshv_bindings;
169-
#[cfg(mshv2)]
170-
extern crate mshv_ioctls2 as mshv_ioctls;
171-
172-
#[cfg(mshv3)]
173-
extern crate mshv_bindings3 as mshv_bindings;
174-
#[cfg(mshv3)]
175-
extern crate mshv_ioctls3 as mshv_ioctls;
176-
177183
use bitflags::bitflags;
178184
#[cfg(mshv)]
179185
use mshv_bindings::hv_x64_memory_intercept_message;
@@ -798,6 +804,60 @@ impl SandboxBuilder {
798804
}
799805
}
800806

807+
#[cfg(mshv)]
808+
impl From<SandboxMemorySection> for mshv_bindings::mshv_user_mem_region {
809+
fn from(section: SandboxMemorySection) -> Self {
810+
let size = section.page_aligned_size as u64;
811+
let guest_pfn = (section.page_aligned_guest_offset as u64) >> 12;
812+
let userspace_addr = section.host_address.unwrap_or(0) as u64;
813+
814+
#[cfg(mshv2)]
815+
{
816+
let mut flags = 0;
817+
if section.flags.contains(MemoryRegionFlags::READ) {
818+
flags |= HV_MAP_GPA_READABLE;
819+
}
820+
if section.flags.contains(MemoryRegionFlags::WRITE) {
821+
flags |= HV_MAP_GPA_WRITABLE;
822+
}
823+
if section.flags.contains(MemoryRegionFlags::EXECUTE) {
824+
flags |= HV_MAP_GPA_EXECUTABLE;
825+
}
826+
if section.flags.is_empty() || section.flags.contains(MemoryRegionFlags::NONE) {
827+
flags |= HV_MAP_GPA_PERMISSIONS_NONE;
828+
}
829+
830+
mshv_bindings::mshv_user_mem_region {
831+
guest_pfn,
832+
size,
833+
userspace_addr,
834+
flags,
835+
}
836+
}
837+
#[cfg(mshv3)]
838+
{
839+
let mut flags: u8 = 0;
840+
if section.flags.contains(MemoryRegionFlags::WRITE) {
841+
flags |= 1 << MSHV_SET_MEM_BIT_WRITABLE;
842+
}
843+
if section.flags.contains(MemoryRegionFlags::EXECUTE) {
844+
flags |= 1 << MSHV_SET_MEM_BIT_EXECUTABLE;
845+
}
846+
if section.flags.is_empty() || section.flags.contains(MemoryRegionFlags::NONE) {
847+
flags |= 1 << MSHV_SET_MEM_BIT_UNMAP;
848+
}
849+
850+
mshv_bindings::mshv_user_mem_region {
851+
guest_pfn,
852+
size,
853+
userspace_addr,
854+
flags,
855+
..Default::default()
856+
}
857+
}
858+
}
859+
}
860+
801861
#[cfg(test)]
802862
mod tests {
803863
use std::sync::{Arc, Mutex};
@@ -873,54 +933,3 @@ mod tests {
873933
Ok(())
874934
}
875935
}
876-
877-
// TODO(danbugs:297): impl
878-
// #[cfg(mshv)]
879-
// impl From<MemoryRegion> for mshv_user_mem_region {
880-
// fn from(region: MemoryRegion) -> Self {
881-
// let size = (region.guest_region.end - region.guest_region.start) as u64;
882-
// let guest_pfn = region.guest_region.start as u64 >> 12;
883-
// let userspace_addr = region.host_region.start as u64;
884-
//
885-
// #[cfg(mshv2)]
886-
// {
887-
// let flags = region.flags.iter().fold(0, |acc, flag| {
888-
// let flag_value = match flag {
889-
// MemoryRegionFlags::NONE => HV_MAP_GPA_PERMISSIONS_NONE,
890-
// MemoryRegionFlags::READ => HV_MAP_GPA_READABLE,
891-
// MemoryRegionFlags::WRITE => HV_MAP_GPA_WRITABLE,
892-
// MemoryRegionFlags::EXECUTE => HV_MAP_GPA_EXECUTABLE,
893-
// _ => 0, // ignore any unknown flags
894-
// };
895-
// acc | flag_value
896-
// });
897-
// mshv_user_mem_region {
898-
// guest_pfn,
899-
// size,
900-
// userspace_addr,
901-
// flags,
902-
// }
903-
// }
904-
// #[cfg(mshv3)]
905-
// {
906-
// let flags: u8 = region.flags.iter().fold(0, |acc, flag| {
907-
// let flag_value = match flag {
908-
// MemoryRegionFlags::NONE => 1 << MSHV_SET_MEM_BIT_UNMAP,
909-
// MemoryRegionFlags::READ => 0,
910-
// MemoryRegionFlags::WRITE => 1 << MSHV_SET_MEM_BIT_WRITABLE,
911-
// MemoryRegionFlags::EXECUTE => 1 << MSHV_SET_MEM_BIT_EXECUTABLE,
912-
// _ => 0, // ignore any unknown flags
913-
// };
914-
// acc | flag_value
915-
// });
916-
//
917-
// mshv_user_mem_region {
918-
// guest_pfn,
919-
// size,
920-
// userspace_addr,
921-
// flags,
922-
// ..Default::default()
923-
// }
924-
// }
925-
// }
926-
// }

0 commit comments

Comments
 (0)