Skip to content

Commit eb9f57a

Browse files
committed
Add debugging function for visualizing dirty pages in a specific layout
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
1 parent cdf8b02 commit eb9f57a

File tree

2 files changed

+105
-2
lines changed

2 files changed

+105
-2
lines changed

src/hyperlight_host/src/mem/bitmap.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ limitations under the License.
1616
use std::cmp::Ordering;
1717

1818
use hyperlight_common::mem::{PAGE_SIZE_USIZE, PAGES_IN_BLOCK};
19+
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
1920

21+
use super::layout::SandboxMemoryLayout;
2022
use crate::{Result, log_then_return};
2123

2224
// Contains various helper functions for dealing with bitmaps.
@@ -103,6 +105,107 @@ impl Iterator for SetBitIndices<'_> {
103105
}
104106
}
105107

108+
// Unused but useful for debugging
109+
// Prints the dirty bitmap in a human-readable format, coloring each page according to its region
110+
// NOTE: Might need to be updated if the memory layout changes
111+
#[allow(dead_code)]
112+
pub(crate) fn print_dirty_bitmap(bitmap: &[u64], layout: &SandboxMemoryLayout) {
113+
let mut stdout = StandardStream::stdout(ColorChoice::Auto);
114+
115+
// Helper function to determine which memory region a page belongs to
116+
fn get_region_info(page_index: usize, layout: &SandboxMemoryLayout) -> (&'static str, Color) {
117+
let page_offset = page_index * PAGE_SIZE_USIZE;
118+
119+
// Check each memory region in order, using available methods and approximations
120+
if page_offset >= layout.init_data_offset {
121+
("INIT_DATA", Color::Ansi256(129)) // Purple
122+
} else if page_offset >= layout.get_top_of_user_stack_offset() {
123+
("STACK", Color::Ansi256(208)) // Orange
124+
} else if page_offset >= layout.get_guard_page_offset() {
125+
("GUARD_PAGE", Color::White)
126+
} else if page_offset >= layout.guest_heap_buffer_offset {
127+
("HEAP", Color::Red)
128+
} else if page_offset >= layout.output_data_buffer_offset {
129+
("OUTPUT_DATA", Color::Green)
130+
} else if page_offset >= layout.input_data_buffer_offset {
131+
("INPUT_DATA", Color::Blue)
132+
} else if page_offset >= layout.host_function_definitions_buffer_offset {
133+
("HOST_FUNC_DEF", Color::Cyan)
134+
} else if page_offset >= layout.peb_address {
135+
("PEB", Color::Magenta)
136+
} else if page_offset >= layout.get_guest_code_offset() {
137+
("CODE", Color::Yellow)
138+
} else {
139+
// Everything up to and including guest code should be PAGE_TABLES
140+
("PAGE_TABLES", Color::Ansi256(14)) // Bright cyan
141+
}
142+
}
143+
144+
let mut num_dirty_pages = 0;
145+
for &block in bitmap.iter() {
146+
num_dirty_pages += block.count_ones() as usize;
147+
}
148+
149+
for (i, &block) in bitmap.iter().enumerate() {
150+
if block != 0 {
151+
print!("Block {:3}: ", i);
152+
153+
// Print each bit in the block with appropriate color
154+
for bit_pos in 0..64 {
155+
let bit_mask = 1u64 << bit_pos;
156+
let page_index = i * 64 + bit_pos;
157+
let (_region_name, color) = get_region_info(page_index, layout);
158+
159+
let mut color_spec = ColorSpec::new();
160+
color_spec.set_fg(Some(color));
161+
162+
if block & bit_mask != 0 {
163+
// Make 1s bold with dark background to stand out from 0s
164+
color_spec.set_bold(true).set_bg(Some(Color::Black));
165+
let _ = stdout.set_color(&color_spec);
166+
print!("1");
167+
} else {
168+
// 0s are colored but not bold, no background
169+
let _ = stdout.set_color(&color_spec);
170+
print!("0");
171+
}
172+
let _ = stdout.reset();
173+
}
174+
175+
// Print a legend for this block showing which regions are represented
176+
let mut regions_in_block = std::collections::HashMap::new();
177+
for bit_pos in 0..64 {
178+
let bit_mask = 1u64 << bit_pos;
179+
if block & bit_mask != 0 {
180+
let page_index = i * 64 + bit_pos;
181+
let (region_name, color) = get_region_info(page_index, layout);
182+
regions_in_block.insert(region_name, color);
183+
}
184+
}
185+
186+
if !regions_in_block.is_empty() {
187+
print!(" [");
188+
let mut sorted_regions: Vec<_> = regions_in_block.iter().collect();
189+
sorted_regions.sort_by_key(|(name, _)| *name);
190+
for (i, (region_name, color)) in sorted_regions.iter().enumerate() {
191+
if i > 0 {
192+
print!(", ");
193+
}
194+
let mut color_spec = ColorSpec::new();
195+
color_spec.set_fg(Some(**color)).set_bold(true);
196+
let _ = stdout.set_color(&color_spec);
197+
print!("{}", region_name);
198+
let _ = stdout.reset();
199+
}
200+
print!("]");
201+
}
202+
println!();
203+
}
204+
}
205+
// Print the total number of dirty pages
206+
println!("Total dirty pages: {}", num_dirty_pages);
207+
}
208+
106209
#[cfg(test)]
107210
mod tests {
108211
use hyperlight_common::mem::PAGE_SIZE_USIZE;

src/hyperlight_host/src/mem/layout.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ pub(crate) struct SandboxMemoryLayout {
111111
pub(crate) host_function_definitions_buffer_offset: usize,
112112
pub(super) input_data_buffer_offset: usize,
113113
pub(super) output_data_buffer_offset: usize,
114-
guest_heap_buffer_offset: usize,
114+
pub(super) guest_heap_buffer_offset: usize,
115115
guard_page_offset: usize,
116116
guest_user_stack_buffer_offset: usize, // the lowest address of the user stack
117-
init_data_offset: usize,
117+
pub(super) init_data_offset: usize,
118118

119119
// other
120120
pub(crate) peb_address: usize,

0 commit comments

Comments
 (0)