Skip to content

Commit 4a56fcf

Browse files
committed
[performance] Move set_up_hypervisor_partition to inside the hv handler thread
As per KVM docs, vCPU ioctls should be issued from the same thread that was used to create the vCPU. In accordance to that, this PR moves set_up_hypervisor_partition to inside the hv handler thread, which manages vCPU interactions like init and dispatching guest funciton calls. Signed-off-by: danbugs <[email protected]>
1 parent 6d4c3a8 commit 4a56fcf

File tree

1 file changed

+31
-19
lines changed

1 file changed

+31
-19
lines changed

src/hyperlight_host/src/hypervisor/hypervisor_handler.rs

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ limitations under the License.
1616

1717
#[cfg(target_os = "windows")]
1818
use core::ffi::c_void;
19+
use std::ops::DerefMut;
1920
use std::sync::atomic::{AtomicBool, Ordering};
2021
use std::sync::{Arc, Mutex};
2122
use std::thread;
@@ -125,7 +126,7 @@ impl HvHandlerExecVars {
125126
.thread_id
126127
.try_lock()
127128
.map_err(|_| new_error!("Failed to get_thread_id"))?)
128-
.ok_or_else(|| new_error!("thread_id not set"))
129+
.ok_or_else(|| new_error!("thread_id not set"))
129130
}
130131

131132
#[cfg(target_os = "windows")]
@@ -228,15 +229,11 @@ impl HypervisorHandler {
228229
#[instrument(err(Debug), skip_all, parent = Span::current(), level = "Trace")]
229230
pub(crate) fn start_hypervisor_handler(
230231
&mut self,
231-
mut sandbox_memory_manager: SandboxMemoryManager<GuestSharedMemory>,
232+
sandbox_memory_manager: SandboxMemoryManager<GuestSharedMemory>,
232233
) -> Result<()> {
233234
let configuration = self.configuration.clone();
234-
let mut hv = set_up_hypervisor_partition(
235-
&mut sandbox_memory_manager,
236-
configuration.outb_handler.clone(),
237-
)?;
238235
#[cfg(target_os = "windows")]
239-
let in_process = sandbox_memory_manager.is_in_process();
236+
let in_process = sandbox_memory_manager.is_in_process();
240237

241238
*self.execution_variables.shm.try_lock().unwrap() = Some(sandbox_memory_manager);
242239

@@ -267,18 +264,8 @@ impl HypervisorHandler {
267264
#[cfg(target_os = "linux")]
268265
self.execution_variables.run_cancelled.store(false);
269266

270-
#[cfg(target_os = "windows")]
271-
if !in_process {
272-
self.execution_variables
273-
.set_partition_handle(hv.get_partition_handle())?;
274-
}
275-
276267
let to_handler_rx = self.communication_channels.to_handler_rx.clone();
277-
#[cfg(target_os = "windows")]
278-
let execution_variables = self.execution_variables.clone();
279-
#[cfg(target_os = "linux")]
280268
let mut execution_variables = self.execution_variables.clone();
281-
// ^^^ this needs to be mut on linux to set_thread_id
282269
let from_handler_tx = self.communication_channels.from_handler_tx.clone();
283270
let hv_handler_clone = self.clone();
284271

@@ -295,9 +282,24 @@ impl HypervisorHandler {
295282
thread::Builder::new()
296283
.name("Hypervisor Handler".to_string())
297284
.spawn(move || -> Result<()> {
285+
let mut hv: Option<Box<dyn Hypervisor>> = None;
298286
for action in to_handler_rx {
299287
match action {
300288
HypervisorHandlerAction::Initialise => {
289+
{
290+
hv = Some(set_up_hypervisor_partition(
291+
execution_variables.shm.try_lock().unwrap().deref_mut().as_mut().unwrap(),
292+
configuration.outb_handler.clone(),
293+
)?);
294+
}
295+
let hv = hv.as_mut().unwrap();
296+
297+
#[cfg(target_os = "windows")]
298+
if !in_process {
299+
execution_variables
300+
.set_partition_handle(hv.get_partition_handle())?;
301+
}
302+
301303
#[cfg(target_os = "linux")]
302304
{
303305
// We cannot use the Killable trait, so we get the `pthread_t` via a libc
@@ -328,6 +330,7 @@ impl HypervisorHandler {
328330
.shared_mem
329331
.lock
330332
.try_read();
333+
331334
let res = hv.initialise(
332335
configuration.peb_addr.clone(),
333336
configuration.seed,
@@ -362,6 +365,8 @@ impl HypervisorHandler {
362365
}
363366
}
364367
HypervisorHandlerAction::DispatchCallFromHost(function_name) => {
368+
let hv = hv.as_mut().unwrap();
369+
365370
// Lock to indicate an action is being performed in the hypervisor
366371
execution_variables.running.store(true, Ordering::SeqCst);
367372

@@ -735,7 +740,7 @@ impl HypervisorHandler {
735740
0,
736741
0,
737742
)
738-
.map_err(|e| new_error!("Failed to cancel guest execution {:?}", e))?;
743+
.map_err(|e| new_error!("Failed to cancel guest execution {:?}", e))?;
739744
}
740745
}
741746
// if running in-process on windows, we currently have no way of cancelling the execution
@@ -911,7 +916,7 @@ mod tests {
911916
None,
912917
None,
913918
)
914-
.unwrap();
919+
.unwrap();
915920

916921
usbox.evolve(Noop::default()).unwrap()
917922
}
@@ -944,6 +949,13 @@ mod tests {
944949
}
945950
}
946951

952+
#[test]
953+
fn create_10_sandboxes() {
954+
for _ in 0..10 {
955+
create_multi_use_sandbox();
956+
}
957+
}
958+
947959
#[test]
948960
fn hello_world() -> Result<()> {
949961
let mut sandbox = create_multi_use_sandbox();

0 commit comments

Comments
 (0)