Skip to content

Commit 40a8091

Browse files
committed
[host/hypervisor_handler,host/mem/{layout,mgr},docs/paging] moved guest code to start at 0x0
instead of after paging sections This is the first step in moving memory sections around to provide a more generic layout. After this, I'll move continue moving sections to fulfill the layout shown in the description for PR #297. Changes: - removed no longer applicable checks in hypervisor_handler - changed the way we build memory in get_memory_regions - added functions to get the offsets/addresses to paging sections as they are no longer static from 0x0 and are now relative to code size - updated code docs - changed set_up_shared_memory to properly place paging sections - updated paging docs Signed-off-by: danbugs <[email protected]>
1 parent ee38c6f commit 40a8091

File tree

4 files changed

+66
-70
lines changed

4 files changed

+66
-70
lines changed

Diff for: docs/paging-development-notes.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ The following page table structs are set up in memory before running a Hyperligh
2929
### PML4 (Page Map Level 4) Table
3030

3131
The PML4 table is located at physical address specified in CR3. In Hyperlight we set
32-
`CR3=0x0`, which means the PML4 table is located at physical address `0x0`. The PML4
33-
table comprises 512 64-bit entries.
32+
`CR3=pml4_address` (i.e., i.e., base address (0x0) + aligned guest code size), which
33+
means the PML4 table is located at physical address `0x0`. The PML4 table comprises
34+
512 64-bit entries.
3435

35-
In Hyperlight, we only initialize the first entry (at address `0x0`), with value
36-
`0x1_000`, implying that we only have a single PDPT.
36+
In Hyperlight, we only initialize the first entry, with value `0x1_000`, implying that
37+
we only have a single PDPT.
3738

3839
### PDPT (Page-directory-pointer Table)
3940

@@ -63,7 +64,7 @@ created to cover the size of memory mapped into the VM.
6364
Given a 64-bit virtual address X, the corresponding physical address is obtained as
6465
follows:
6566

66-
1. PML4 table's physical address is located using CR3 (CR3 is `0x0`).
67+
1. PML4 table's physical address is located using CR3.
6768
2. Bits 47:39 of X are used to index into PML4, giving us the address of the PDPT.
6869
3. Bits 38:30 of X are used to index into PDPT, giving us the address of the PD.
6970
4. Bits 29:21 of X are used to index into PD, giving us the address of the PT.

Diff for: src/hyperlight_host/src/hypervisor/hypervisor_handler.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ use crate::hypervisor::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper};
4545
#[cfg(target_os = "windows")]
4646
use crate::hypervisor::wrappers::HandleWrapper;
4747
use crate::hypervisor::Hypervisor;
48-
use crate::mem::layout::SandboxMemoryLayout;
4948
use crate::mem::mgr::SandboxMemoryManager;
5049
use crate::mem::ptr::{GuestPtr, RawPtr};
5150
use crate::mem::ptr_offset::Offset;
@@ -859,28 +858,14 @@ fn set_up_hypervisor_partition(
859858
}?;
860859
let base_ptr = GuestPtr::try_from(Offset::from(0))?;
861860
let pml4_ptr = {
862-
let pml4_offset_u64 = u64::try_from(SandboxMemoryLayout::PML4_OFFSET)?;
861+
let pml4_offset_u64 = u64::try_from(mgr.layout.get_pml4_offset())?;
863862
base_ptr + Offset::from(pml4_offset_u64)
864863
};
865864
let entrypoint_ptr = {
866865
let entrypoint_total_offset = mgr.load_addr.clone() + mgr.entrypoint_offset;
867866
GuestPtr::try_from(entrypoint_total_offset)
868867
}?;
869868

870-
if base_ptr != pml4_ptr {
871-
log_then_return!(
872-
"Error: base_ptr ({:#?}) does not equal pml4_ptr ({:#?})",
873-
base_ptr,
874-
pml4_ptr
875-
);
876-
}
877-
if entrypoint_ptr <= pml4_ptr {
878-
log_then_return!(
879-
"Error: entrypoint_ptr ({:#?}) is not greater than pml4_ptr ({:#?})",
880-
entrypoint_ptr,
881-
pml4_ptr
882-
);
883-
}
884869
if mgr.is_in_process() {
885870
cfg_if::cfg_if! {
886871
if #[cfg(inprocess)] {

Diff for: src/hyperlight_host/src/mem/layout.rs

+51-41
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,16 @@ use crate::{log_then_return, new_error, Result};
6161
// +-------------------------------------------+
6262
// | PEB Struct (0x98) |
6363
// +-------------------------------------------+
64-
// | Guest Code |
65-
// +-------------------------------------------+
6664
// | PT |
67-
// +-------------------------------------------+ 0x3_000
65+
// +-------------------------------------------+ guest_code_offset + 0x3_000
6866
// | PD |
69-
// +-------------------------------------------+ 0x2_000
67+
// +-------------------------------------------+ guest_code_offset + 0x2_000
7068
// | PDPT |
71-
// +-------------------------------------------+ 0x1_000
69+
// +-------------------------------------------+ guest_code_offset + 0x1_000
7270
// | PML4 |
73-
// +-------------------------------------------+ 0x0_000
71+
// +-------------------------------------------+ guest_code_offset
72+
// | Guest Code |
73+
// +-------------------------------------------+ 0x0
7474

7575
///
7676
/// - `HostDefinitions` - the length of this is the `HostFunctionDefinitionSize`
@@ -160,6 +160,8 @@ pub(crate) struct SandboxMemoryLayout {
160160
total_page_table_size: usize,
161161
// The offset in the sandbox memory where the code starts
162162
guest_code_offset: usize,
163+
// The offset in the sandbox memory where the PML4 Table is located
164+
paging_sections_offset: usize,
163165
}
164166

165167
impl Debug for SandboxMemoryLayout {
@@ -283,24 +285,13 @@ impl Debug for SandboxMemoryLayout {
283285
}
284286

285287
impl SandboxMemoryLayout {
286-
/// The offset into the sandbox's memory where the PML4 Table is located.
287-
/// See https://www.pagetable.com/?p=14 for more information.
288-
pub(crate) const PML4_OFFSET: usize = 0x0000;
289-
/// The offset into the sandbox's memory where the Page Directory Pointer
290-
/// Table starts.
291-
pub(super) const PDPT_OFFSET: usize = 0x1000;
288+
/// The offset from the start of the paging section region into the sandbox's memory where the
289+
/// Page Directory Pointer Table starts.
290+
const PDPT_OFFSET: usize = 0x1000;
292291
/// The offset into the sandbox's memory where the Page Directory starts.
293-
pub(super) const PD_OFFSET: usize = 0x2000;
292+
const PD_OFFSET: usize = 0x2000;
294293
/// The offset into the sandbox's memory where the Page Tables start.
295-
pub(super) const PT_OFFSET: usize = 0x3000;
296-
/// The address (not the offset) to the start of the page directory
297-
pub(super) const PD_GUEST_ADDRESS: usize = Self::BASE_ADDRESS + Self::PD_OFFSET;
298-
/// The address (not the offset) into sandbox memory where the Page
299-
/// Directory Pointer Table starts
300-
pub(super) const PDPT_GUEST_ADDRESS: usize = Self::BASE_ADDRESS + Self::PDPT_OFFSET;
301-
/// The address (not the offset) into sandbox memory where the Page
302-
/// Tables start
303-
pub(super) const PT_GUEST_ADDRESS: usize = Self::BASE_ADDRESS + Self::PT_OFFSET;
294+
const PT_OFFSET: usize = 0x3000;
304295
/// The maximum amount of memory a single sandbox will be allowed.
305296
/// The addressable virtual memory with current paging setup is virtual address 0x0 - 0x40000000,
306297
/// excluding the memory up to BASE_ADDRESS (which is 0 by default).
@@ -321,9 +312,9 @@ impl SandboxMemoryLayout {
321312
stack_size: usize,
322313
heap_size: usize,
323314
) -> Result<Self> {
324-
let total_page_table_size =
325-
Self::get_total_page_table_size(cfg, code_size, stack_size, heap_size);
326-
let guest_code_offset = total_page_table_size;
315+
let guest_code_offset = 0x0;
316+
let total_page_table_size = Self::get_total_page_table_size(cfg, code_size, stack_size, heap_size);
317+
let paging_sections_offset = guest_code_offset + round_up_to(code_size, PAGE_SIZE_USIZE);
327318
// The following offsets are to the fields of the PEB struct itself!
328319
let peb_offset = total_page_table_size + round_up_to(code_size, PAGE_SIZE_USIZE);
329320
let peb_security_cookie_seed_offset =
@@ -424,9 +415,34 @@ impl SandboxMemoryLayout {
424415
kernel_stack_guard_page_offset,
425416
kernel_stack_size_rounded,
426417
boot_stack_buffer_offset,
418+
paging_sections_offset,
427419
})
428420
}
429421

422+
/// Gets the PML4 offset
423+
/// (i.e., the `paging_sections_offset` == aligned code size)
424+
pub fn get_pml4_offset(&self) -> usize {
425+
self.paging_sections_offset
426+
}
427+
428+
/// Gets the PDPT offset
429+
/// (i.e., the `paging_sections_offset` + 0x1000)
430+
pub fn get_pdpt_offset(&self) -> usize {
431+
self.paging_sections_offset + Self::PDPT_OFFSET
432+
}
433+
434+
/// Gets the PD offset
435+
/// (i.e., the `paging_sections_offset` + 0x2000)
436+
pub fn get_pd_offset(&self) -> usize {
437+
self.paging_sections_offset + Self::PD_OFFSET
438+
}
439+
440+
/// Gets the PT offset
441+
/// (i.e., the `paging_sections_offset` + 0x3000)
442+
pub fn get_pt_offset(&self) -> usize {
443+
self.paging_sections_offset + Self::PT_OFFSET
444+
}
445+
430446
/// Gets the offset in guest memory to the RunMode field in the PEB struct.
431447
pub fn get_run_mode_offset(&self) -> usize {
432448
self.peb_runmode_offset
@@ -778,28 +794,22 @@ impl SandboxMemoryLayout {
778794
pub fn get_memory_regions(&self, shared_mem: &GuestSharedMemory) -> Result<Vec<MemoryRegion>> {
779795
let mut builder = MemoryRegionVecBuilder::new(Self::BASE_ADDRESS, shared_mem.base_addr());
780796

781-
// PML4, PDPT, PD
782-
let code_offset = builder.push_page_aligned(
783-
self.total_page_table_size,
784-
MemoryRegionFlags::READ | MemoryRegionFlags::WRITE,
785-
PageTables,
786-
);
787-
788-
if code_offset != self.guest_code_offset {
789-
return Err(new_error!(
790-
"Code offset does not match expected code offset expected: {}, actual: {}",
791-
self.guest_code_offset,
792-
code_offset
793-
));
794-
}
797+
assert_eq!(self.guest_code_offset, 0x0);
795798

796-
// code
797-
let peb_offset = builder.push_page_aligned(
799+
// Code
800+
builder.push_page_aligned(
798801
self.code_size,
799802
MemoryRegionFlags::READ | MemoryRegionFlags::WRITE | MemoryRegionFlags::EXECUTE,
800803
Code,
801804
);
802805

806+
// PML4, PDPT, PD
807+
let peb_offset = builder.push_page_aligned(
808+
self.total_page_table_size,
809+
MemoryRegionFlags::READ | MemoryRegionFlags::WRITE,
810+
PageTables,
811+
);
812+
803813
let expected_peb_offset = TryInto::<usize>::try_into(self.peb_offset)?;
804814

805815
if peb_offset != expected_peb_offset {

Diff for: src/hyperlight_host/src/mem/mgr.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -152,21 +152,21 @@ where
152152
- 0x28;
153153

154154
self.shared_mem.with_exclusivity(|shared_mem| {
155-
// Create PDL4 table with only 1 PML4E
155+
// Create PML4 table with only 1 PML4E
156156
shared_mem.write_u64(
157-
SandboxMemoryLayout::PML4_OFFSET,
158-
SandboxMemoryLayout::PDPT_GUEST_ADDRESS as u64 | PAGE_PRESENT | PAGE_RW,
157+
self.layout.get_pml4_offset(),
158+
self.layout.get_pdpt_offset() as u64 | PAGE_PRESENT | PAGE_RW,
159159
)?;
160160

161161
// Create PDPT with only 1 PDPTE
162162
shared_mem.write_u64(
163-
SandboxMemoryLayout::PDPT_OFFSET,
164-
SandboxMemoryLayout::PD_GUEST_ADDRESS as u64 | PAGE_PRESENT | PAGE_RW,
163+
self.layout.get_pdpt_offset(),
164+
self.layout.get_pd_offset() as u64 | PAGE_PRESENT | PAGE_RW,
165165
)?;
166166

167167
for i in 0..512 {
168-
let offset = SandboxMemoryLayout::PD_OFFSET + (i * 8);
169-
let val_to_write: u64 = (SandboxMemoryLayout::PT_GUEST_ADDRESS as u64
168+
let offset = self.layout.get_pd_offset() + (i * 8);
169+
let val_to_write: u64 = (self.layout.get_pt_offset() as u64
170170
+ (i * 4096) as u64)
171171
| PAGE_PRESENT
172172
| PAGE_RW;
@@ -186,7 +186,7 @@ where
186186
// Create num_pages PT with 512 PTEs
187187
for p in 0..num_pages {
188188
for i in 0..512 {
189-
let offset = SandboxMemoryLayout::PT_OFFSET + (p * 4096) + (i * 8);
189+
let offset = self.layout.get_pt_offset() + (p * 4096) + (i * 8);
190190
// Each PTE maps a 4KB page
191191
let val_to_write = {
192192
let flags = match Self::get_page_flags(p, i, regions) {

0 commit comments

Comments
 (0)