Skip to content

Commit a9d6744

Browse files
committed
more updates
Signed-off-by: Simon Davies <[email protected]>
1 parent c89a998 commit a9d6744

File tree

9 files changed

+292
-354
lines changed

9 files changed

+292
-354
lines changed

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use std::sync::Arc;
2929
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
3030

3131
use log::{LevelFilter, error};
32+
#[cfg(mshv3)]
33+
use mshv_bindings::MSHV_GPAP_ACCESS_OP_CLEAR;
3234
#[cfg(mshv2)]
3335
use mshv_bindings::hv_message;
3436
use mshv_bindings::{
@@ -79,9 +81,6 @@ use crate::{Result, log_then_return, new_error};
7981
#[cfg(mshv2)]
8082
const CLEAR_DIRTY_BIT_FLAG: u64 = 0b100;
8183

82-
#[cfg(mshv3)]
83-
const CLEAR_DIRTY_BIT_FLAG: u8 = 0b100;
84-
8584
#[cfg(gdb)]
8685
mod debug {
8786
use std::sync::{Arc, Mutex};
@@ -397,12 +396,30 @@ impl HypervLinuxDriver {
397396
(None, None)
398397
};
399398

399+
let mut base_pfn = u64::MAX;
400+
let mut total_size: usize = 0;
401+
400402
mem_regions.iter().try_for_each(|region| {
401-
let mshv_region = region.to_owned().into();
403+
let mshv_region: mshv_user_mem_region = region.to_owned().into();
404+
if base_pfn == u64::MAX {
405+
base_pfn = mshv_region.guest_pfn;
406+
}
407+
total_size += mshv_region.size as usize;
402408
vm_fd.map_user_memory(mshv_region)
403409
})?;
404410

405411
Self::setup_initial_sregs(&mut vcpu_fd, pml4_ptr.absolute()?)?;
412+
413+
// get/clear the dirty page bitmap, mshv sets all the bit dirty at initialization
414+
// if we dont clear them then we end up taking a complete snapsot of memory page by page which gets
415+
// progressively slower as the sandbox size increases
416+
// the downside of doing this here is that the call to get_dirty_log will takes longer as the number of pages increase
417+
// but for larger sandboxes its easily cheaper than copying all the pages
418+
419+
#[cfg(mshv2)]
420+
vm_fd.get_dirty_log(base_pfn, total_size, CLEAR_DIRTY_BIT_FLAG)?;
421+
#[cfg(mshv3)]
422+
vm_fd.get_dirty_log(base_pfn, total_size, MSHV_GPAP_ACCESS_OP_CLEAR as u8)?;
406423

407424
let interrupt_handle = Arc::new(LinuxInterruptHandle {
408425
running: AtomicU64::new(0),
@@ -427,7 +444,7 @@ impl HypervLinuxDriver {
427444
sig_rt_min_offset: config.get_interrupt_vcpu_sigrtmin_offset(),
428445
dropped: AtomicBool::new(false),
429446
});
430-
447+
431448
#[allow(unused_mut)]
432449
let mut hv = Self {
433450
_mshv: mshv,
@@ -846,7 +863,10 @@ impl Hypervisor for HypervLinuxDriver {
846863
let res = self.vm_fd.get_dirty_log(
847864
first_mshv_region.guest_pfn,
848865
total_size,
866+
#[cfg(mshv2)]
849867
CLEAR_DIRTY_BIT_FLAG,
868+
#[cfg(mshv3)]
869+
(MSHV_GPAP_ACCESS_OP_CLEAR as u8),
850870
)?;
851871
Ok(res)
852872
}

src/hyperlight_host/src/hypervisor/hyperv_windows.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ use super::{
5555
use super::{HyperlightExit, Hypervisor, InterruptHandle, VirtualCPU};
5656
use crate::hypervisor::fpu::FP_CONTROL_WORD_DEFAULT;
5757
use crate::hypervisor::wrappers::WHvGeneralRegisters;
58+
use crate::mem::bitmap::new_page_bitmap;
5859
use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
5960
use crate::mem::ptr::{GuestPtr, RawPtr};
6061
#[cfg(crashdump)]
@@ -606,6 +607,12 @@ impl Hypervisor for HypervWindowsDriver {
606607
Ok(())
607608
}
608609

610+
fn get_and_clear_dirty_pages(&mut self) -> Result<Vec<u64>> {
611+
// For now we just mark all pages dirty which is the equivalent of taking a full snapshot
612+
let total_size = self.mem_regions.iter().map(|r| r.guest_region.len()).sum();
613+
new_page_bitmap(total_size, true)
614+
}
615+
609616
#[instrument(err(Debug), skip_all, parent = Span::current(), level = "Trace")]
610617
fn dispatch_call_from_host(
611618
&mut self,

src/hyperlight_host/src/mem/bitmap.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub fn new_page_bitmap(size_in_bytes: usize, init_dirty: bool) -> Result<Vec<u64
2020
let mut bitmap = vec![!0u64; num_blocks]; // all pages are dirty
2121
let num_unused_bits = num_blocks * PAGES_IN_BLOCK - num_pages;
2222
// set the unused bits to 0, could cause problems otherwise
23+
#[allow(clippy::unwrap_used)]
2324
let last_block = bitmap.last_mut().unwrap(); // unwrap is safe since size_in_bytes>0
2425
*last_block >>= num_unused_bits;
2526
Ok(bitmap)

src/hyperlight_host/src/mem/dirty_page_tracking.rs

Lines changed: 2 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -14,47 +14,16 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
#![allow(dead_code, unused_variables, unused_imports)]
18-
use std::sync::Arc;
19-
2017
use tracing::{Span, instrument};
2118

22-
#[cfg(target_os = "windows")]
23-
pub use super::WindowsDirtyPageTracker as PlatformDirtyPageTracker;
2419
#[cfg(target_os = "linux")]
2520
pub use super::linux_dirty_page_tracker::LinuxDirtyPageTracker as PlatformDirtyPageTracker;
21+
#[cfg(target_os = "windows")]
22+
pub use super::windows_dirty_page_tracker::WindowsDirtyPageTracker as PlatformDirtyPageTracker;
2623
use crate::Result;
2724

2825
/// Trait defining the interface for dirty page tracking implementations
2926
pub trait DirtyPageTracking {
30-
// /// Start tracking dirty pages
31-
// fn start_tracking(&self) -> Result<()>;
32-
33-
// /// Stop tracking dirty pages
34-
// fn stop_tracking(&self) -> Result<()>;
35-
36-
// /// Take a snapshot of only the dirty pages
37-
// fn take_new_snapshot(&self) -> Result<()>;
38-
39-
// /// Restore memory from the snapshot of dirty pages
40-
// fn restore_from_snapshot(&self) -> Result<()>;
41-
42-
// /// Check if tracking is currently active
43-
// fn is_tracking_active(&self) -> bool;
44-
45-
// /// Get the base address of the tracked region
46-
// fn base_addr(&self) -> usize;
47-
48-
// /// Get the size of the tracked region
49-
// fn size(&self) -> usize;
50-
51-
// /// Get the number of pages in the tracked region
52-
// fn num_pages(&self) -> usize;
53-
54-
// /// Add pages to the last snapshot
55-
// /// This is used to update the snapshot with new dirty pages from hypervisor dirty page tracking
56-
// fn add_pages_to_last_snapshot(&self, pages: &[usize]) -> Result<()>;
57-
5827
fn get_dirty_pages(self) -> Vec<usize>;
5928
}
6029

@@ -66,61 +35,13 @@ pub struct DirtyPageTracker {
6635
impl DirtyPageTracker {
6736
/// Create a new dirty page tracker for the given memory region
6837
#[instrument(skip_all, parent = Span::current(), level = "Trace")]
69-
#[cfg(target_os = "linux")]
7038
pub fn new(base_addr: usize, size: usize) -> Result<Self> {
7139
let inner = PlatformDirtyPageTracker::new(base_addr, size)?;
7240
Ok(Self { inner })
7341
}
74-
75-
/// Create a new tracker with a Windows file mapping handle (Windows only)
76-
#[cfg(target_os = "windows")]
77-
#[instrument(skip_all, parent = Span::current(), level = "Trace")]
78-
pub fn new_with_handle(
79-
base_addr: usize,
80-
size: usize,
81-
handle: windows::Win32::Foundation::HANDLE,
82-
) -> Result<Arc<Self>> {
83-
let inner = PlatformDirtyPageTracker::new_with_handle(base_addr, size, handle)?;
84-
Ok(Arc::new(Self { inner }))
85-
}
8642
}
8743

8844
impl DirtyPageTracking for DirtyPageTracker {
89-
// fn start_tracking(&self) -> Result<()> {
90-
// self.inner.start_tracking()
91-
// }
92-
93-
// fn stop_tracking(&self) -> Result<()> {
94-
// self.inner.stop_tracking()
95-
// }
96-
97-
// fn take_new_snapshot(&self) -> Result<()> {
98-
// self.inner.take_new_snapshot()
99-
// }
100-
101-
// fn restore_from_snapshot(&self) -> Result<()> {
102-
// self.inner.restore_from_snapshot()
103-
// }
104-
105-
// fn is_tracking_active(&self) -> bool {
106-
// self.inner.is_tracking_active()
107-
// }
108-
109-
// fn base_addr(&self) -> usize {
110-
// self.inner.base_addr()
111-
// }
112-
113-
// fn size(&self) -> usize {
114-
// self.inner.size()
115-
// }
116-
117-
// fn num_pages(&self) -> usize {
118-
// self.inner.num_pages()
119-
// }
120-
121-
// fn add_pages_to_last_snapshot(&self, pages: &[usize]) -> Result<()> {
122-
// self.inner.add_pages_to_last_snapshot(pages)
123-
// }
12445
fn get_dirty_pages(self) -> Vec<usize> {
12546
self.inner.get_dirty_pages()
12647
}

0 commit comments

Comments
 (0)