Skip to content

Commit 1a280b6

Browse files
authored
Let windows decide at which address to map shared memory in surrogate process (#637)
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 30e1ff2 commit 1a280b6

File tree

5 files changed

+29
-46
lines changed

5 files changed

+29
-46
lines changed

src/hyperlight_host/src/hypervisor/hyperv_windows.rs

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

17-
use core::ffi::c_void;
1817
use std::fmt;
1918
use std::fmt::{Debug, Formatter};
2019
use std::string::String;
2120
use std::sync::Arc;
2221
use std::sync::atomic::{AtomicBool, Ordering};
2322

24-
use hyperlight_common::mem::PAGE_SIZE_USIZE;
2523
use log::LevelFilter;
2624
use tracing::{Span, instrument};
2725
use windows::Win32::System::Hypervisor::{
@@ -57,10 +55,8 @@ use crate::{Result, debug, new_error};
5755

5856
/// A Hypervisor driver for HyperV-on-Windows.
5957
pub(crate) struct HypervWindowsDriver {
60-
size: usize, // this is the size of the memory region, excluding the 2 surrounding guard pages
6158
processor: VMProcessor,
6259
_surrogate_process: SurrogateProcess, // we need to keep a reference to the SurrogateProcess for the duration of the driver since otherwise it will dropped and the memory mapping will be unmapped and the surrogate process will be returned to the pool
63-
source_address: *mut c_void, // this points into the first guard page
6460
entrypoint: u64,
6561
orig_rsp: GuestPtr,
6662
mem_regions: Vec<MemoryRegion>,
@@ -82,7 +78,6 @@ impl HypervWindowsDriver {
8278
pub(crate) fn new(
8379
mem_regions: Vec<MemoryRegion>,
8480
raw_size: usize,
85-
raw_source_address: *mut c_void,
8681
pml4_address: u64,
8782
entrypoint: u64,
8883
rsp: u64,
@@ -96,23 +91,18 @@ impl HypervWindowsDriver {
9691
// with guard pages setup
9792
let surrogate_process = {
9893
let mgr = get_surrogate_process_manager()?;
99-
mgr.get_surrogate_process(raw_size, raw_source_address, mmap_file_handle)
94+
mgr.get_surrogate_process(raw_size, mmap_file_handle)
10095
}?;
10196

102-
partition.map_gpa_range(&mem_regions, surrogate_process.process_handle)?;
97+
partition.map_gpa_range(&mem_regions, &surrogate_process)?;
10398

10499
let mut proc = VMProcessor::new(partition)?;
105100
Self::setup_initial_sregs(&mut proc, pml4_address)?;
106101
let partition_handle = proc.get_partition_hdl();
107102

108-
// subtract 2 pages for the guard pages, since when we copy memory to and from surrogate process,
109-
// we don't want to copy the guard pages themselves (that would cause access violation)
110-
let mem_size = raw_size - 2 * PAGE_SIZE_USIZE;
111103
Ok(Self {
112-
size: mem_size,
113104
processor: proc,
114105
_surrogate_process: surrogate_process,
115-
source_address: raw_source_address,
116106
entrypoint,
117107
orig_rsp: GuestPtr::try_from(RawPtr::from(rsp))?,
118108
mem_regions,
@@ -193,9 +183,7 @@ impl Debug for HypervWindowsDriver {
193183
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
194184
let mut fs = f.debug_struct("HyperV Driver");
195185

196-
fs.field("Size", &self.size)
197-
.field("Source Address", &self.source_address)
198-
.field("Entrypoint", &self.entrypoint)
186+
fs.field("Entrypoint", &self.entrypoint)
199187
.field("Original RSP", &self.orig_rsp);
200188

201189
for region in &self.mem_regions {

src/hyperlight_host/src/hypervisor/surrogate_process.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use super::wrappers::HandleWrapper;
3030
#[derive(Debug)]
3131
pub(super) struct SurrogateProcess {
3232
/// The address of memory allocated in the surrogate process to be mapped to the VM.
33+
/// This includes the first guard page
3334
pub(crate) allocated_address: *mut c_void,
3435
/// The handle to the surrogate process.
3536
pub(crate) process_handle: HandleWrapper,

src/hyperlight_host/src/hypervisor/surrogate_process_manager.rs

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ impl SurrogateProcessManager {
144144
pub(super) fn get_surrogate_process(
145145
&self,
146146
raw_size: usize,
147-
raw_source_address: *const c_void,
148147
mmap_file_handle: HandleWrapper,
149148
) -> Result<SurrogateProcess> {
150149
let surrogate_process_handle: HANDLE = self.process_receiver.recv()?.into();
@@ -160,7 +159,7 @@ impl SurrogateProcessManager {
160159
mapping_file_handle,
161160
surrogate_process_handle,
162161
0,
163-
Some(raw_source_address),
162+
None,
164163
raw_size,
165164
0,
166165
PAGE_READWRITE.0,
@@ -171,19 +170,7 @@ impl SurrogateProcessManager {
171170
if allocated_address.Value.is_null() {
172171
// Safety: `MapViewOfFileNuma2` will set the last error code if it fails.
173172
let error = unsafe { windows::Win32::Foundation::GetLastError() };
174-
log_then_return!(
175-
"MapViewOfFileNuma2 failed with error code: {:?} for mem address {:?} ",
176-
error,
177-
raw_source_address
178-
);
179-
}
180-
181-
if allocated_address.Value as *const c_void != raw_source_address {
182-
log_then_return!(
183-
"Address Mismatch Allocated: {:?} Requested: {:?}",
184-
allocated_address.Value,
185-
raw_source_address
186-
);
173+
log_then_return!("MapViewOfFileNuma2 failed with error code: {:?}", error);
187174
}
188175

189176
// set up guard pages
@@ -193,7 +180,7 @@ impl SurrogateProcessManager {
193180
let mut unused_out_old_prot_flags = PAGE_PROTECTION_FLAGS(0);
194181

195182
// the first page of the raw_size is the guard page
196-
let first_guard_page_start = raw_source_address;
183+
let first_guard_page_start = allocated_address.Value;
197184
if let Err(e) = unsafe {
198185
VirtualProtectEx(
199186
surrogate_process_handle,
@@ -207,7 +194,8 @@ impl SurrogateProcessManager {
207194
}
208195

209196
// the last page of the raw_size is the guard page
210-
let last_guard_page_start = unsafe { raw_source_address.add(raw_size - PAGE_SIZE_USIZE) };
197+
let last_guard_page_start =
198+
unsafe { first_guard_page_start.add(raw_size - PAGE_SIZE_USIZE) };
211199
if let Err(e) = unsafe {
212200
VirtualProtectEx(
213201
surrogate_process_handle,
@@ -485,11 +473,8 @@ mod tests {
485473

486474
let timer = Instant::now();
487475
let surrogate_process = {
488-
let res = surrogate_process_manager.get_surrogate_process(
489-
size,
490-
addr.Value,
491-
HandleWrapper::from(handle),
492-
)?;
476+
let res = surrogate_process_manager
477+
.get_surrogate_process(size, HandleWrapper::from(handle))?;
493478
let elapsed = timer.elapsed();
494479
// Print out the time it took to get the process if its greater than 150ms (this is just to allow us to see that threads are blocking on the process queue)
495480
if (elapsed.as_millis() as u64) > 150 {
@@ -579,7 +564,6 @@ mod tests {
579564
let process = mgr
580565
.get_surrogate_process(
581566
mem.raw_mem_size(),
582-
mem.raw_ptr() as *mut c_void,
583567
HandleWrapper::from(mem.get_mmap_file_handle()),
584568
)
585569
.unwrap();

src/hyperlight_host/src/hypervisor/windows_hypervisor_platform.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ limitations under the License.
1616

1717
use core::ffi::c_void;
1818

19+
use hyperlight_common::mem::PAGE_SIZE_USIZE;
1920
use tracing::{Span, instrument};
2021
use windows::Win32::Foundation::{FreeLibrary, HANDLE};
2122
use windows::Win32::System::Hypervisor::*;
2223
use windows::Win32::System::LibraryLoader::*;
2324
use windows::core::s;
2425
use windows_result::HRESULT;
2526

26-
use super::wrappers::HandleWrapper;
27+
use super::surrogate_process::SurrogateProcess;
2728
#[cfg(crashdump)]
2829
use crate::HyperlightError;
2930
use crate::hypervisor::wrappers::{WHvFPURegisters, WHvGeneralRegisters, WHvSpecialRegisters};
@@ -89,9 +90,21 @@ impl VMPartition {
8990
pub(super) fn map_gpa_range(
9091
&mut self,
9192
regions: &[MemoryRegion],
92-
process_handle: HandleWrapper,
93+
surrogate_process: &SurrogateProcess,
9394
) -> Result<()> {
94-
let process_handle: HANDLE = process_handle.into();
95+
let process_handle: HANDLE = surrogate_process.process_handle.into();
96+
// this is the address in the surrogate process where shared memory starts.
97+
// We add page-size because we don't care about the first guard page
98+
let surrogate_address = surrogate_process.allocated_address as usize + PAGE_SIZE_USIZE;
99+
if regions.is_empty() {
100+
return Err(new_error!("No memory regions to map"));
101+
}
102+
// this is the address in the main process where the shared memory starts
103+
let host_address = regions[0].host_region.start;
104+
105+
// offset between the surrogate process and the host process address of start of shared memory
106+
let offset = isize::try_from(surrogate_address)? - isize::try_from(host_address)?;
107+
95108
// The function pointer to WHvMapGpaRange2 is resolved dynamically to allow us to detect
96109
// when we are running on older versions of windows that do not support this API and
97110
// return a more informative error message, rather than failing with an error about a missing entrypoint
@@ -121,9 +134,9 @@ impl VMPartition {
121134
let res = whvmapgparange2_func(
122135
self.0,
123136
process_handle,
124-
region.host_region.start as *const c_void,
137+
(isize::try_from(region.host_region.start)? + offset) as *const c_void,
125138
region.guest_region.start as u64,
126-
(region.guest_region.end - region.guest_region.start) as u64,
139+
region.guest_region.len() as u64,
127140
flags,
128141
);
129142
if res.is_err() {

src/hyperlight_host/src/sandbox/uninitialized_evolve.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,6 @@ pub(crate) fn set_up_hypervisor_partition(
244244

245245
#[cfg(target_os = "windows")]
246246
Some(HypervisorType::Whp) => {
247-
use std::ffi::c_void;
248-
249247
use crate::hypervisor::wrappers::HandleWrapper;
250248

251249
let mmap_file_handle = mgr
@@ -254,7 +252,6 @@ pub(crate) fn set_up_hypervisor_partition(
254252
let hv = crate::hypervisor::hyperv_windows::HypervWindowsDriver::new(
255253
regions,
256254
mgr.shared_mem.raw_mem_size(), // we use raw_* here because windows driver requires 64K aligned addresses,
257-
mgr.shared_mem.raw_ptr() as *mut c_void, // and instead convert it to base_addr where needed in the driver itself
258255
pml4_ptr.absolute()?,
259256
entrypoint_ptr.absolute()?,
260257
rsp_ptr.absolute()?,

0 commit comments

Comments
 (0)