Skip to content

Commit 04344df

Browse files
committed
mshv works
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 5f14d7a commit 04344df

File tree

5 files changed

+99
-47
lines changed

5 files changed

+99
-47
lines changed

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ extern crate mshv_bindings3 as mshv_bindings;
2525
extern crate mshv_ioctls3 as mshv_ioctls;
2626

2727
use std::fmt::{Debug, Formatter};
28+
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
29+
use std::sync::Arc;
2830

2931
use log::{error, LevelFilter};
3032
#[cfg(mshv2)]
@@ -56,8 +58,9 @@ use super::gdb::{DebugCommChannel, DebugMsg, DebugResponse, GuestDebug, MshvDebu
5658
use super::handlers::DbgMemAccessHandlerWrapper;
5759
use super::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper};
5860
use super::{
59-
Hypervisor, VirtualCPU, CR0_AM, CR0_ET, CR0_MP, CR0_NE, CR0_PE, CR0_PG, CR0_WP, CR4_OSFXSR,
60-
CR4_OSXMMEXCPT, CR4_PAE, EFER_LMA, EFER_LME, EFER_NX, EFER_SCE,
61+
Hypervisor, InterruptHandle, LinuxInterruptHandle, VirtualCPU, CR0_AM, CR0_ET, CR0_MP, CR0_NE,
62+
CR0_PE, CR0_PG, CR0_WP, CR4_OSFXSR, CR4_OSXMMEXCPT, CR4_PAE, EFER_LMA, EFER_LME, EFER_NX,
63+
EFER_SCE,
6164
};
6265
use crate::hypervisor::HyperlightExit;
6366
use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
@@ -292,6 +295,7 @@ pub(crate) struct HypervLinuxDriver {
292295
entrypoint: u64,
293296
mem_regions: Vec<MemoryRegion>,
294297
orig_rsp: GuestPtr,
298+
interrupt_handle: Arc<LinuxInterruptHandle>,
295299

296300
#[cfg(gdb)]
297301
debug: Option<MshvDebug>,
@@ -389,6 +393,11 @@ impl HypervLinuxDriver {
389393
mem_regions,
390394
entrypoint: entrypoint_ptr.absolute()?,
391395
orig_rsp: rsp_ptr,
396+
interrupt_handle: Arc::new(LinuxInterruptHandle {
397+
running: AtomicBool::new(false),
398+
tid: AtomicU64::new(unsafe { libc::pthread_self() }),
399+
dropped: AtomicBool::new(false),
400+
}),
392401

393402
#[cfg(gdb)]
394403
debug,
@@ -572,13 +581,38 @@ impl Hypervisor for HypervLinuxDriver {
572581
#[cfg(gdb)]
573582
const EXCEPTION_INTERCEPT: hv_message_type = hv_message_type_HVMSG_X64_EXCEPTION_INTERCEPT;
574583

584+
self.interrupt_handle
585+
.tid
586+
.store(unsafe { libc::pthread_self() as u64 }, Ordering::Relaxed);
587+
// Note: if a `InterruptHandle::kill()` signal is delivered to this thread **here**
588+
// - before we've set the running to true,
589+
// Then the signal does not have any effect, because the signal handler is a no-op.
590+
self.interrupt_handle.running.store(true, Ordering::Relaxed);
591+
// Note: if a `InterruptHandle::kill()` signal is delivered to this thread **here**
592+
// - after we've set the running to true,
593+
// - before we've called `VcpuFd::run()`
594+
// Then the individual signal is lost, because the signal is only processed after we've left userspace.
595+
// However, for this reason, we keep sending the signal again and again until we see that the atomic `running` is set to false.
575596
#[cfg(mshv2)]
576597
let run_result = {
577598
let hv_message: hv_message = Default::default();
578-
&self.vcpu_fd.run(hv_message)
599+
self.vcpu_fd.run(hv_message)
579600
};
580601
#[cfg(mshv3)]
581-
let run_result = &self.vcpu_fd.run();
602+
let run_result = self.vcpu_fd.run();
603+
// Note: if a `InterruptHandle::kill()` signal is delivered to this thread **here**
604+
// - after we've called `VcpuFd::run()`
605+
// - before we've set the running to false
606+
// Then this is fine because the call to `VcpuFd::run()` is already finished,
607+
// the signal handler itself is a no-op, and the signals will stop being sent
608+
// once we've set the `running` to false.
609+
self.interrupt_handle
610+
.running
611+
.store(false, Ordering::Relaxed);
612+
// Note: if a `InterruptHandle::kill()` signal is delivered to this thread **here**
613+
// - after we've set the running to true,
614+
// Then the signal does not have any effect, because the signal handler is a no-op.
615+
// This is fine since we are already done with the `VcpuFd::run()` call.
582616

583617
let result = match run_result {
584618
Ok(m) => match m.header.message_type {
@@ -673,6 +707,10 @@ impl Hypervisor for HypervLinuxDriver {
673707
self as &mut dyn Hypervisor
674708
}
675709

710+
fn interrupt_handle(&self) -> Arc<dyn InterruptHandle> {
711+
self.interrupt_handle.clone()
712+
}
713+
676714
#[cfg(crashdump)]
677715
fn get_memory_regions(&self) -> &[MemoryRegion] {
678716
&self.mem_regions
@@ -722,10 +760,6 @@ impl Hypervisor for HypervLinuxDriver {
722760

723761
Ok(())
724762
}
725-
726-
fn interrupt_handle(&self) -> std::sync::Arc<dyn super::InterruptHandle> {
727-
todo!()
728-
}
729763
}
730764

731765
impl Drop for HypervLinuxDriver {

src/hyperlight_host/src/hypervisor/kvm.rs

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ use super::gdb::{DebugCommChannel, DebugMsg, DebugResponse, GuestDebug, KvmDebug
3434
use super::handlers::DbgMemAccessHandlerWrapper;
3535
use super::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper};
3636
use super::{
37-
HyperlightExit, Hypervisor, InterruptHandle, VirtualCPU, CR0_AM, CR0_ET, CR0_MP, CR0_NE,
38-
CR0_PE, CR0_PG, CR0_WP, CR4_OSFXSR, CR4_OSXMMEXCPT, CR4_PAE, EFER_LMA, EFER_LME, EFER_NX,
39-
EFER_SCE,
37+
HyperlightExit, Hypervisor, InterruptHandle, LinuxInterruptHandle, VirtualCPU, CR0_AM, CR0_ET,
38+
CR0_MP, CR0_NE, CR0_PE, CR0_PG, CR0_WP, CR4_OSFXSR, CR4_OSXMMEXCPT, CR4_PAE, EFER_LMA,
39+
EFER_LME, EFER_NX, EFER_SCE,
4040
};
4141
use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
4242
use crate::mem::ptr::{GuestPtr, RawPtr};
@@ -283,24 +283,14 @@ pub(crate) struct KVMDriver {
283283
entrypoint: u64,
284284
orig_rsp: GuestPtr,
285285
mem_regions: Vec<MemoryRegion>,
286-
interrupt_handle: Arc<KvmInterruptHandle>,
286+
interrupt_handle: Arc<LinuxInterruptHandle>,
287287

288288
#[cfg(gdb)]
289289
debug: Option<KvmDebug>,
290290
#[cfg(gdb)]
291291
gdb_conn: Option<DebugCommChannel<DebugResponse, DebugMsg>>,
292292
}
293293

294-
#[derive(Debug)]
295-
pub(super) struct KvmInterruptHandle {
296-
/// True when the vcpu is currently running and blocking the thread
297-
running: AtomicBool,
298-
/// The thread id on which the vcpu was most recently run on or is currently running on
299-
tid: AtomicU64,
300-
/// Whether the corresponding vm is dropped
301-
dropped: AtomicBool,
302-
}
303-
304294
impl KVMDriver {
305295
/// Create a new instance of a `KVMDriver`, with only control registers
306296
/// set. Standard registers will not be set, and `initialise` must
@@ -358,7 +348,7 @@ impl KVMDriver {
358348
entrypoint,
359349
orig_rsp: rsp_gp,
360350
mem_regions,
361-
interrupt_handle: Arc::new(KvmInterruptHandle {
351+
interrupt_handle: Arc::new(LinuxInterruptHandle {
362352
running: AtomicBool::new(false),
363353
tid: AtomicU64::new(unsafe { libc::pthread_self() }),
364354
dropped: AtomicBool::new(false),
@@ -681,23 +671,3 @@ impl Drop for KVMDriver {
681671
self.interrupt_handle.dropped.store(true, Ordering::Relaxed);
682672
}
683673
}
684-
685-
impl InterruptHandle for KvmInterruptHandle {
686-
fn kill(&self) -> bool {
687-
let sigrtmin = libc::SIGRTMIN();
688-
let mut sent_signal = false;
689-
690-
while self.running.load(Ordering::Relaxed) {
691-
sent_signal = true;
692-
unsafe {
693-
libc::pthread_kill(self.tid.load(Ordering::Relaxed) as _, sigrtmin);
694-
}
695-
std::thread::sleep(std::time::Duration::from_micros(50));
696-
}
697-
698-
sent_signal
699-
}
700-
fn dropped(&self) -> bool {
701-
self.dropped.load(Ordering::Relaxed)
702-
}
703-
}

src/hyperlight_host/src/hypervisor/mod.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub(crate) mod hyperv_windows;
3636

3737
/// GDB debugging support
3838
#[cfg(gdb)]
39-
mod gdb;
39+
pub(crate) mod gdb;
4040

4141
#[cfg(kvm)]
4242
/// Functionality to manipulate KVM-based virtual machines
@@ -59,6 +59,7 @@ pub(crate) mod crashdump;
5959

6060
use std::fmt::Debug;
6161
use std::str::FromStr;
62+
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
6263
use std::sync::{Arc, Mutex};
6364

6465
#[cfg(gdb)]
@@ -335,3 +336,33 @@ pub trait InterruptHandle: Send + Sync {
335336
/// Returns true iff the corresponding sandbox has been dropped
336337
fn dropped(&self) -> bool;
337338
}
339+
340+
#[derive(Debug)]
341+
pub(super) struct LinuxInterruptHandle {
342+
/// True when the vcpu is currently running and blocking the thread
343+
running: AtomicBool,
344+
/// The thread id on which the vcpu was most recently run on or is currently running on
345+
tid: AtomicU64,
346+
/// Whether the corresponding vm is dropped
347+
dropped: AtomicBool,
348+
}
349+
350+
impl InterruptHandle for LinuxInterruptHandle {
351+
fn kill(&self) -> bool {
352+
let sigrtmin = libc::SIGRTMIN();
353+
let mut sent_signal = false;
354+
355+
while self.running.load(Ordering::Relaxed) {
356+
sent_signal = true;
357+
unsafe {
358+
libc::pthread_kill(self.tid.load(Ordering::Relaxed) as _, sigrtmin);
359+
}
360+
std::thread::sleep(std::time::Duration::from_micros(50));
361+
}
362+
363+
sent_signal
364+
}
365+
fn dropped(&self) -> bool {
366+
self.dropped.load(Ordering::Relaxed)
367+
}
368+
}

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ use super::host_funcs::FunctionRegistry;
2626
use super::{MemMgrWrapper, WrapperGetter};
2727
use crate::func::call_ctx::MultiUseGuestCallContext;
2828
use crate::func::guest_err::check_for_guest_error;
29+
#[cfg(gdb)]
30+
use crate::hypervisor::handlers::DbgMemAccessHandlerWrapper;
2931
use crate::hypervisor::handlers::{MemAccessHandlerCaller, OutBHandlerCaller};
3032
use crate::hypervisor::{Hypervisor, InterruptHandle};
3133
use crate::mem::ptr::RawPtr;
@@ -51,6 +53,8 @@ pub struct MultiUseSandbox {
5153
out_hdl: Arc<Mutex<dyn OutBHandlerCaller>>,
5254
mem_hdl: Arc<Mutex<dyn MemAccessHandlerCaller>>,
5355
dispatch_ptr: RawPtr,
56+
#[cfg(gdb)]
57+
dbg_mem_access_fn: DbgMemAccessHandlerWrapper,
5458
}
5559

5660
impl MultiUseSandbox {
@@ -67,6 +71,7 @@ impl MultiUseSandbox {
6771
out_hdl: Arc<Mutex<dyn OutBHandlerCaller>>,
6872
mem_hdl: Arc<Mutex<dyn MemAccessHandlerCaller>>,
6973
dispatch_ptr: RawPtr,
74+
#[cfg(gdb)] dbg_mem_access_fn: DbgMemAccessHandlerWrapper,
7075
) -> MultiUseSandbox {
7176
Self {
7277
_host_funcs: host_funcs,
@@ -75,6 +80,8 @@ impl MultiUseSandbox {
7580
out_hdl,
7681
mem_hdl,
7782
dispatch_ptr,
83+
#[cfg(gdb)]
84+
dbg_mem_access_fn,
7885
}
7986
}
8087

@@ -194,6 +201,7 @@ impl MultiUseSandbox {
194201
self.dispatch_ptr.clone(),
195202
self.out_hdl.clone(),
196203
self.mem_hdl.clone(),
204+
self.dbg_mem_access_fn.clone(),
197205
)?;
198206

199207
self.check_stack_guard()?;

src/hyperlight_host/src/sandbox/uninitialized_evolve.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,13 @@ where
6767
) -> Result<ResSandbox>,
6868
{
6969
let (hshm, mut gshm) = u_sbox.mgr.build();
70-
let mut vm = set_up_hypervisor_partition(&mut gshm)?;
70+
let mut vm = set_up_hypervisor_partition(
71+
&mut gshm,
72+
#[cfg(gdb)]
73+
&u_sbox.debug_info,
74+
)?;
7175
let outb_hdl = outb_handler_wrapper(hshm.clone(), u_sbox.host_funcs.clone());
76+
7277
let seed = {
7378
let mut rng = rand::rng();
7479
rng.random::<u64>()
@@ -94,7 +99,7 @@ where
9499
mem_access_hdl.clone(),
95100
u_sbox.max_guest_log_level,
96101
#[cfg(gdb)]
97-
u_sbox.debug_info,
102+
dbg_mem_access_hdl,
98103
)?;
99104

100105
let dispatch_function_addr = hshm.as_ref().get_pointer_to_dispatch_function()?;
@@ -122,11 +127,13 @@ pub(super) fn evolve_impl_multi_use(u_sbox: UninitializedSandbox) -> Result<Mult
122127
}
123128
Ok(MultiUseSandbox::from_uninit(
124129
hf,
125-
hshm,
130+
hshm.clone(),
126131
vm,
127132
out_hdl,
128133
mem_hdl,
129134
dispatch_ptr,
135+
#[cfg(gdb)]
136+
dbg_mem_access_handler_wrapper(hshm),
130137
))
131138
},
132139
)
@@ -171,6 +178,8 @@ fn set_up_hypervisor_partition(
171178
// Create gdb thread if gdb is enabled and the configuration is provided
172179
#[cfg(gdb)]
173180
let gdb_conn = if let Some(DebugInfo { port }) = debug_info {
181+
use crate::hypervisor::gdb::create_gdb_thread;
182+
174183
let gdb_conn = create_gdb_thread(*port, unsafe { libc::pthread_self() });
175184

176185
// in case the gdb thread creation fails, we still want to continue

0 commit comments

Comments
 (0)