Skip to content

Commit 1231cc6

Browse files
committed
Remove dirty_pages from HostMapping struct, remove some unnecessary Options in parameters.
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 24429ee commit 1231cc6

File tree

9 files changed

+115
-212
lines changed

9 files changed

+115
-212
lines changed

src/hyperlight_host/src/hypervisor/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ pub(crate) mod tests {
511511
use super::handlers::{MemAccessHandler, OutBHandler};
512512
#[cfg(gdb)]
513513
use crate::hypervisor::DbgMemAccessHandlerCaller;
514+
use crate::mem::dirty_page_tracking::DirtyPageTracking;
514515
use crate::mem::ptr::RawPtr;
515516
use crate::sandbox::uninitialized::GuestBinary;
516517
#[cfg(any(crashdump, gdb))]
@@ -562,14 +563,15 @@ pub(crate) mod tests {
562563
let rt_cfg: SandboxRuntimeConfig = Default::default();
563564
let sandbox =
564565
UninitializedSandbox::new(GuestBinary::FilePath(filename.clone()), Some(config))?;
565-
let tracker = sandbox.tracker;
566+
let tracker = sandbox.tracker.unwrap();
566567
let (_hshm, mut gshm) = sandbox.mgr.build();
568+
// we need to undo the mprotect(readonly) before mapping memory into vm, and that is done by getting dirty pages
569+
let _ = tracker.get_dirty_pages()?;
567570
let mut vm = set_up_hypervisor_partition(
568571
&mut gshm,
569572
&config,
570573
#[cfg(any(crashdump, gdb))]
571574
&rt_cfg,
572-
tracker,
573575
)?;
574576
vm.initialise(
575577
RawPtr::from(0x230000),

src/hyperlight_host/src/mem/dirty_page_tracking.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::Result;
2525

2626
/// Trait defining the interface for dirty page tracking implementations
2727
pub trait DirtyPageTracking {
28-
fn get_dirty_pages(self) -> Vec<usize>;
28+
fn get_dirty_pages(self) -> Result<Vec<usize>>;
2929
}
3030

3131
/// Cross-platform dirty page tracker that delegates to platform-specific implementations
@@ -43,7 +43,7 @@ impl DirtyPageTracker {
4343
}
4444

4545
impl DirtyPageTracking for DirtyPageTracker {
46-
fn get_dirty_pages(self) -> Vec<usize> {
46+
fn get_dirty_pages(self) -> Result<Vec<usize>> {
4747
self.inner.get_dirty_pages()
4848
}
4949
}

src/hyperlight_host/src/mem/linux_dirty_page_tracker.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,10 @@ impl LinuxDirtyPageTracker {
163163
})
164164
}
165165

166-
/// Get all dirty page indices for this tracker
167-
pub(super) fn get_dirty_pages(self) -> Vec<usize> {
168-
let res = if let Some(tracker_data) = get_trackers().get(&self.id) {
166+
/// Get all dirty page indices for this tracker.
167+
/// NOTE: This is not a bitmap, but a vector of indices where each index corresponds to a page that has been written to.
168+
pub(super) fn get_dirty_pages(self) -> Result<Vec<usize>> {
169+
let res: Vec<usize> = if let Some(tracker_data) = get_trackers().get(&self.id) {
169170
let mut dirty_pages = Vec::new();
170171
let tracker_data = tracker_data.val();
171172
for (idx, dirty) in tracker_data.dirty_pages.iter().enumerate() {
@@ -175,13 +176,15 @@ impl LinuxDirtyPageTracker {
175176
}
176177
dirty_pages
177178
} else {
178-
Vec::new()
179+
return Err(new_error!(
180+
"Tried to get dirty pages from tracker, but no tracker data found"
181+
));
179182
};
180183

181-
// self is dropped here, triggering cleanup
182184
// explicit to document intent
183185
drop(self);
184-
res
186+
187+
Ok(res)
185188
}
186189

187190
#[cfg(test)]
@@ -793,7 +796,7 @@ mod tests {
793796
let addr = memory_ptr as usize;
794797

795798
let tracker = create_test_tracker(addr, memory_size).unwrap();
796-
let dirty_pages = tracker.get_dirty_pages();
799+
let dirty_pages = tracker.get_dirty_pages().unwrap();
797800
assert!(dirty_pages.is_empty());
798801

799802
// tracker is already dropped by get_dirty_pages() call above
@@ -831,7 +834,7 @@ mod tests {
831834
}
832835
}
833836

834-
let dirty_pages = tracker.get_dirty_pages();
837+
let dirty_pages = tracker.get_dirty_pages().unwrap();
835838

836839
println!("Dirty Pages expected: {:?}", pages_to_dirty);
837840
println!("Dirty pages found: {:?}", dirty_pages);
@@ -876,8 +879,8 @@ mod tests {
876879
std::ptr::write_volatile((addr2 + PAGE_SIZE + 200) as *mut u8, 2);
877880
}
878881

879-
let dirty1 = tracker1.get_dirty_pages();
880-
let dirty2 = tracker2.get_dirty_pages();
882+
let dirty1 = tracker1.get_dirty_pages().unwrap();
883+
let dirty2 = tracker2.get_dirty_pages().unwrap();
881884

882885
// Verify each tracker only reports pages that were actually written to
883886
// Tracker1: wrote to offset 100, which is in page 0
@@ -956,7 +959,7 @@ mod tests {
956959
}
957960
}
958961

959-
let dirty_pages = tracker.get_dirty_pages();
962+
let dirty_pages = tracker.get_dirty_pages().unwrap();
960963

961964
// All writes to the same page should result in the same page being dirty
962965
if !dirty_pages.is_empty() {
@@ -1036,7 +1039,7 @@ mod tests {
10361039
}
10371040

10381041
// Final verification: check that ALL pages we wrote to are marked as dirty
1039-
let final_dirty_pages = tracker.get_dirty_pages();
1042+
let final_dirty_pages = tracker.get_dirty_pages().unwrap();
10401043

10411044
// Check that every page we wrote to is marked as dirty
10421045
for &page_idx in &pages_written {
@@ -1198,7 +1201,7 @@ mod tests {
11981201
}
11991202
}
12001203

1201-
let dirty_pages = tracker.get_dirty_pages();
1204+
let dirty_pages = tracker.get_dirty_pages().unwrap();
12021205
println!("Stress test dirty pages: {:?}", dirty_pages);
12031206

12041207
// Verify all page indices are valid

src/hyperlight_host/src/mem/mgr.rs

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use hyperlight_common::flatbuffer_wrappers::function_types::ReturnValue;
2424
use hyperlight_common::flatbuffer_wrappers::guest_error::GuestError;
2525
use hyperlight_common::flatbuffer_wrappers::guest_log_data::GuestLogData;
2626
use hyperlight_common::flatbuffer_wrappers::host_function_details::HostFunctionDetails;
27-
use hyperlight_common::mem::{PAGE_SIZE_USIZE, PAGES_IN_BLOCK};
27+
use hyperlight_common::mem::PAGES_IN_BLOCK;
2828
use tracing::{Span, instrument};
2929

3030
use super::exe::ExeInfo;
@@ -269,7 +269,8 @@ where
269269
/// this function will create an initial snapshot and then create the SnapshotManager
270270
pub(crate) fn create_initial_snapshot(
271271
&mut self,
272-
dirty_bitmap: Option<&Vec<u64>>,
272+
vm_dirty_bitmap: &[u64],
273+
host_dirty_page_idx: &[usize],
273274
layout: &SandboxMemoryLayout,
274275
) -> Result<()> {
275276
let mut existing_snapshot_manager = self
@@ -280,36 +281,21 @@ where
280281
if existing_snapshot_manager.is_some() {
281282
log_then_return!("Snapshot manager already initialized, not creating a new one");
282283
}
283-
let merged_page_map = if let Some(host_dirty_page_map) = self
284-
.shared_mem
285-
.with_exclusivity(|e| e.get_and_clear_host_dirty_page_map())??
286-
{
287-
// covert vec of page indices to vec of blocks
288-
// memory size is the size of the shared memory minus the 2 guard pages
289-
let mut res = new_page_bitmap(self.shared_mem.mem_size() - 2 * PAGE_SIZE_USIZE, false)?;
290-
for page_idx in host_dirty_page_map {
291-
let block_idx = page_idx / PAGES_IN_BLOCK;
292-
let bit_idx = page_idx % PAGES_IN_BLOCK;
293-
res[block_idx] |= 1 << bit_idx;
294-
}
295284

296-
// merge the host dirty page map into the dirty bitmap
297-
let len = res.len();
298-
let merged = bitmap_union(&res, dirty_bitmap.unwrap_or(&vec![0; len]));
299-
Some(merged)
300-
} else {
301-
None
302-
};
285+
// covert vec of page indices to bitmap
286+
let mut res = new_page_bitmap(self.shared_mem.raw_mem_size(), false)?;
287+
for page_idx in host_dirty_page_idx {
288+
let block_idx = page_idx / PAGES_IN_BLOCK;
289+
let bit_idx = page_idx % PAGES_IN_BLOCK;
290+
res[block_idx] |= 1 << bit_idx;
291+
}
303292

304-
let dirty_page_map = if let Some(ref dirty_page_map) = merged_page_map {
305-
Some(dirty_page_map)
306-
} else {
307-
dirty_bitmap
308-
};
293+
// merge the host dirty page map into the dirty bitmap
294+
let merged = bitmap_union(&res, vm_dirty_bitmap);
309295

310296
let snapshot_manager = SharedMemorySnapshotManager::new(
311297
&mut self.shared_mem,
312-
dirty_page_map,
298+
&merged,
313299
layout,
314300
self.mapped_rgns,
315301
)?;
@@ -358,7 +344,7 @@ where
358344
}
359345
}
360346

361-
pub(crate) fn push_state(&mut self, dirty_bitmap: Option<&Vec<u64>>) -> Result<()> {
347+
pub(crate) fn push_state(&mut self, dirty_bitmap: &[u64]) -> Result<()> {
362348
let mut snapshot_manager = self
363349
.snapshot_manager
364350
.try_lock()

src/hyperlight_host/src/mem/shared_mem.rs

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::ffi::c_void;
1919
use std::io::Error;
2020
#[cfg(target_os = "linux")]
2121
use std::ptr::null_mut;
22-
use std::sync::{Arc, Mutex, RwLock};
22+
use std::sync::{Arc, RwLock};
2323

2424
use hyperlight_common::mem::PAGE_SIZE_USIZE;
2525
use tracing::{Span, instrument};
@@ -96,7 +96,6 @@ pub struct HostMapping {
9696
size: usize,
9797
#[cfg(target_os = "windows")]
9898
handle: HANDLE,
99-
dirty_pages: Mutex<Option<Vec<usize>>>,
10099
}
101100

102101
impl Drop for HostMapping {
@@ -385,7 +384,6 @@ impl ExclusiveSharedMemory {
385384
region: Arc::new(HostMapping {
386385
ptr: addr as *mut u8,
387386
size: total_size,
388-
dirty_pages: None.into(),
389387
}),
390388
})
391389
}
@@ -396,37 +394,11 @@ impl ExclusiveSharedMemory {
396394
}
397395

398396
/// Stop tracking dirty pages in the shared memory region.
399-
pub(crate) fn stop_tracking_dirty_pages(&self, tracker: DirtyPageTracker) -> Result<()> {
400-
let dirty_pages = tracker.get_dirty_pages();
401-
let mut existing_dirty_pages = self
402-
.region
403-
.dirty_pages
404-
.lock()
405-
.map_err(|e| new_error!("Failed to lock dirty_pages: {}", e))?;
406-
407-
match existing_dirty_pages.as_mut() {
408-
Some(existing) => {
409-
// merge the new dirty pages with the existing ones
410-
existing.extend(dirty_pages);
411-
existing.sort_unstable();
412-
existing.dedup();
413-
}
414-
None => {
415-
*existing_dirty_pages = Some(dirty_pages);
416-
}
417-
}
418-
419-
Ok(())
420-
}
421-
422-
// Take the dirty pages
423-
pub(super) fn get_and_clear_host_dirty_page_map(&self) -> Result<Option<Vec<usize>>> {
424-
Ok(self
425-
.region
426-
.dirty_pages
427-
.lock()
428-
.map_err(|e| new_error!("Failed to lock dirty_pages: {}", e))?
429-
.take())
397+
pub(crate) fn stop_tracking_dirty_pages(
398+
&self,
399+
tracker: DirtyPageTracker,
400+
) -> Result<Vec<usize>> {
401+
tracker.get_dirty_pages()
430402
}
431403

432404
/// Create a new region of shared memory with the given minimum
@@ -540,7 +512,6 @@ impl ExclusiveSharedMemory {
540512
ptr: addr.Value as *mut u8,
541513
size: total_size,
542514
handle,
543-
dirty_pages: None.into(),
544515
}),
545516
})
546517
}

0 commit comments

Comments
 (0)