Skip to content

Commit b926470

Browse files
authored
feat: add unmap page api
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
1 parent 302175d commit b926470

7 files changed

Lines changed: 94 additions & 3 deletions

File tree

‎src/hyperlight_common/src/arch/aarch64/layout.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
pub const SCRATCH_TOP_GVA: usize = 0x0000_ffff_ffff_dfff;
77
pub const SNAPSHOT_PT_GVA_MIN: usize = 0x0000_8000_0000_0000;
88
pub const SNAPSHOT_PT_GVA_MAX: usize = 0x0000_80ff_ffff_ffff;
9+
pub const VIRTQ_BUFFER_GVA_START: u64 = 0x0000_fc00_0000_0000;
10+
pub const VIRTQ_BUFFER_GVA_END: u64 = 0x0000_fd00_0000_0000;
911
pub const SCRATCH_TOP_GPA: usize = 0x0000_000f_ffff_bfff;
1012

1113
pub const IO_PAGE_GVA: u64 = 0x0000_ffff_ffff_e000;

‎src/hyperlight_common/src/arch/amd64/layout.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
pub const SCRATCH_TOP_GVA: usize = 0xffff_ffff_ffff_efff;
1212
pub const SNAPSHOT_PT_GVA_MIN: usize = 0xffff_8000_0000_0000;
1313
pub const SNAPSHOT_PT_GVA_MAX: usize = 0xffff_80ff_ffff_ffff;
14+
pub const VIRTQ_BUFFER_GVA_START: u64 = 0xffff_fc00_0000_0000;
15+
pub const VIRTQ_BUFFER_GVA_END: u64 = 0xffff_fd00_0000_0000;
1416

1517
/// We assume 36-bit IPAs for now, since every amd64 processor
1618
/// supports at least 36 bits. Almost all of them support at least 40

‎src/hyperlight_common/src/layout.rs‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use core::num::{NonZeroU16, NonZeroUsize};
99
mod arch;
1010

1111
pub use arch::{
12-
SCRATCH_TOP_GPA, SCRATCH_TOP_GVA, SNAPSHOT_PT_GVA_MAX, SNAPSHOT_PT_GVA_MIN, io_page,
12+
SCRATCH_TOP_GPA, SCRATCH_TOP_GVA, SNAPSHOT_PT_GVA_MAX, SNAPSHOT_PT_GVA_MIN,
13+
VIRTQ_BUFFER_GVA_END, VIRTQ_BUFFER_GVA_START, io_page,
1314
};
1415

1516
use crate::virtq;
@@ -100,6 +101,21 @@ const _: () = {
100101
assert!(SCRATCH_TOP_H2G_POOL_PAGES_OFFSET == 0x60);
101102
assert!(SCRATCH_TOP_H2G_BUFFER_SIZE_OFFSET == 0x68);
102103
assert!(SCRATCH_TOP_EXN_STACK_OFFSET == 0x70);
104+
105+
assert!(VIRTQ_BUFFER_GVA_START < VIRTQ_BUFFER_GVA_END);
106+
assert!((VIRTQ_BUFFER_GVA_START as usize).is_multiple_of(crate::vmem::PAGE_SIZE));
107+
assert!((VIRTQ_BUFFER_GVA_END as usize).is_multiple_of(crate::vmem::PAGE_SIZE));
108+
assert!(VIRTQ_BUFFER_GVA_START > SNAPSHOT_PT_GVA_MAX as u64);
109+
110+
#[cfg(target_arch = "x86_64")]
111+
assert!(VIRTQ_BUFFER_GVA_START >> 47 == 0x1ffff);
112+
#[cfg(target_arch = "x86_64")]
113+
assert!((VIRTQ_BUFFER_GVA_END - 1) >> 47 == 0x1ffff);
114+
#[cfg(target_arch = "aarch64")]
115+
assert!(VIRTQ_BUFFER_GVA_END <= 1 << 48);
116+
117+
assert!(VIRTQ_BUFFER_GVA_END < scratch_base_gva(16 * 1024 * 1024 * 1024));
118+
assert!((SCRATCH_TOP_GPA as u64) < VIRTQ_BUFFER_GVA_END - VIRTQ_BUFFER_GVA_START);
103119
};
104120

105121
/// Exclusive upper GPA boundary for dynamic scratch allocations.
@@ -110,7 +126,7 @@ pub const fn scratch_allocator_limit_gpa() -> u64 {
110126
pub fn scratch_base_gpa(size: usize) -> u64 {
111127
(SCRATCH_TOP_GPA - size + 1) as u64
112128
}
113-
pub fn scratch_base_gva(size: usize) -> u64 {
129+
pub const fn scratch_base_gva(size: usize) -> u64 {
114130
(SCRATCH_TOP_GVA - size + 1) as u64
115131
}
116132

‎src/hyperlight_guest/src/arch/aarch64/paging.rs‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,33 @@ pub unsafe fn modify_mapping(
129129
}
130130
}
131131

132+
/// Unmap one page and invalidate its translations.
133+
/// An absent page is skipped without allocating page tables.
134+
///
135+
/// # Safety
136+
/// `virt` must name an aligned 4 KiB page with no live views.
137+
/// Use initialized guest tables without contiguous hints and serialize table access.
138+
/// Keep paging controls stable. Every root accessing the page must share its leaf.
139+
pub unsafe fn unmap_page(virt: *mut u8) {
140+
if virt_to_phys(virt as u64).next().is_none() {
141+
return;
142+
}
143+
144+
// SAFETY: The caller permits removing this present leaf across all accessing roots.
145+
unsafe {
146+
map_region(0, virt, vmem::PAGE_SIZE as u64, vmem::MappingKind::Unmapped);
147+
148+
core::arch::asm!(
149+
"dsb ishst",
150+
"tlbi vaae1is, {}",
151+
"dsb ish",
152+
"isb",
153+
in(reg) (virt as u64 >> 12),
154+
options(nostack, preserves_flags),
155+
);
156+
}
157+
}
158+
132159
pub fn virt_to_phys(gva: vmem::VirtAddr) -> impl Iterator<Item = vmem::Mapping> {
133160
unsafe { vmem::virt_to_phys::<_>(GuestMappingOperations::new(), gva, 1) }
134161
}

‎src/hyperlight_guest/src/arch/amd64/paging.rs‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,45 @@ pub unsafe fn modify_mapping(
144144
}
145145
}
146146

147+
/// Unmap one page and invalidate its translations.
148+
/// An absent page is skipped without allocating page tables.
149+
///
150+
/// # Safety
151+
/// `virt` must name an aligned 4 KiB page with no live views.
152+
/// Use initialized four-level guest tables and serialize all page-table access.
153+
/// Keep paging controls stable. Every root accessing the page must share its leaf.
154+
pub unsafe fn unmap_page(virt: *mut u8) {
155+
if virt_to_phys(virt as u64).next().is_none() {
156+
return;
157+
}
158+
159+
// SAFETY: The caller permits removing this present leaf.
160+
unsafe { map_region(0, virt, vmem::PAGE_SIZE as u64, vmem::MappingKind::Unmapped) };
161+
162+
let cr4: u64;
163+
164+
// SAFETY: The initialized guest runs at CPL0 with stable paging controls.
165+
unsafe { asm!("mov {}, cr4", out(reg) cr4, options(nostack, preserves_flags)) };
166+
167+
if cr4 & (1 << 17) == 0 {
168+
// SAFETY: INVLPG invalidates the page without dereferencing its address.
169+
unsafe { asm!("invlpg [{}]", in(reg) virt, options(nostack, preserves_flags)) };
170+
} else {
171+
// A PGE transition invalidates all PCIDs and globals.
172+
// Intel SDM 5.10.4.1 and AMD APM 5.5.3 specify this.
173+
// SAFETY: Only PGE changes, and CR4 is restored before guest code resumes.
174+
unsafe {
175+
asm!(
176+
"mov cr4, {toggled}",
177+
"mov cr4, {original}",
178+
toggled = in(reg) (cr4 ^ (1 << 7)),
179+
original = in(reg) cr4,
180+
options(nostack, preserves_flags),
181+
);
182+
}
183+
}
184+
}
185+
147186
pub fn virt_to_phys(gva: vmem::VirtAddr) -> impl Iterator<Item = vmem::Mapping> {
148187
unsafe { vmem::virt_to_phys::<_>(GuestMappingOperations::new(), gva, 1) }
149188
}

‎src/hyperlight_guest/src/paging.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#[cfg_attr(target_arch = "aarch64", path = "arch/aarch64/paging.rs")]
88
mod arch;
99

10-
pub use arch::{map_region, modify_mapping, phys_to_virt, virt_to_phys};
10+
pub use arch::{map_region, modify_mapping, phys_to_virt, unmap_page, virt_to_phys};
1111
/// Barriers that other code may need to use when updating page tables
1212
pub mod barrier {
1313
/// Call this function when a virtual address has had its

‎src/hyperlight_guest_bin/src/arch/amd64/layout.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@
1010
/// a VA that will survive the snapshot process. Since we don't have a
1111
/// useful virtual allocator yet, we just put them here...
1212
pub const PROC_CONTROL_GVA: u64 = 0xffff_fd00_0000_0000;
13+
14+
const _: () = assert!(
15+
hyperlight_common::layout::VIRTQ_BUFFER_GVA_END <= PROC_CONTROL_GVA,
16+
"transport aliases overlap processor control"
17+
);

0 commit comments

Comments
 (0)