Skip to content

Commit 2dd3e1b

Browse files
committed
[trace-host] move trace related logic to separate module
- This helps with keeping code separate and easily gating it out Signed-off-by: Doru Blânzeanu <[email protected]>
1 parent 9c14144 commit 2dd3e1b

File tree

8 files changed

+375
-358
lines changed

8 files changed

+375
-358
lines changed

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
7373
use crate::mem::ptr::{GuestPtr, RawPtr};
7474
use crate::mem::shared_mem::HostSharedMemory;
7575
use crate::sandbox::SandboxConfiguration;
76-
#[cfg(feature = "trace_guest")]
77-
use crate::sandbox::TraceInfo;
7876
use crate::sandbox::host_funcs::FunctionRegistry;
7977
use crate::sandbox::mem_mgr::MemMgrWrapper;
8078
use crate::sandbox::outb::handle_outb;
79+
#[cfg(feature = "trace_guest")]
80+
use crate::sandbox::trace::TraceInfo;
8181
#[cfg(crashdump)]
8282
use crate::sandbox::uninitialized::SandboxRuntimeConfig;
8383
use crate::{Result, log_then_return, new_error};
@@ -1149,11 +1149,7 @@ impl Hypervisor for HypervLinuxDriver {
11491149
}
11501150

11511151
#[cfg(feature = "trace_guest")]
1152-
fn trace_info_as_ref(&self) -> &TraceInfo {
1153-
&self.trace_info
1154-
}
1155-
#[cfg(feature = "trace_guest")]
1156-
fn trace_info_as_mut(&mut self) -> &mut TraceInfo {
1152+
fn trace_info_mut(&mut self) -> &mut TraceInfo {
11571153
&mut self.trace_info
11581154
}
11591155
}

src/hyperlight_host/src/hypervisor/hyperv_windows.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,11 +1101,7 @@ impl Hypervisor for HypervWindowsDriver {
11011101
}
11021102

11031103
#[cfg(feature = "trace_guest")]
1104-
fn trace_info_as_ref(&self) -> &TraceInfo {
1105-
&self.trace_info
1106-
}
1107-
#[cfg(feature = "trace_guest")]
1108-
fn trace_info_as_mut(&mut self) -> &mut TraceInfo {
1104+
fn trace_info_mut(&mut self) -> &mut TraceInfo {
11091105
&mut self.trace_info
11101106
}
11111107
}

src/hyperlight_host/src/hypervisor/kvm.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
4545
use crate::mem::ptr::{GuestPtr, RawPtr};
4646
use crate::mem::shared_mem::HostSharedMemory;
4747
use crate::sandbox::SandboxConfiguration;
48-
#[cfg(feature = "trace_guest")]
49-
use crate::sandbox::TraceInfo;
5048
use crate::sandbox::host_funcs::FunctionRegistry;
5149
use crate::sandbox::mem_mgr::MemMgrWrapper;
5250
use crate::sandbox::outb::handle_outb;
51+
#[cfg(feature = "trace_guest")]
52+
use crate::sandbox::trace::TraceInfo;
5353
#[cfg(crashdump)]
5454
use crate::sandbox::uninitialized::SandboxRuntimeConfig;
5555
use crate::{Result, log_then_return, new_error};
@@ -1042,11 +1042,7 @@ impl Hypervisor for KVMDriver {
10421042
}
10431043

10441044
#[cfg(feature = "trace_guest")]
1045-
fn trace_info_as_ref(&self) -> &TraceInfo {
1046-
&self.trace_info
1047-
}
1048-
#[cfg(feature = "trace_guest")]
1049-
fn trace_info_as_mut(&mut self) -> &mut TraceInfo {
1045+
fn trace_info_mut(&mut self) -> &mut TraceInfo {
10501046
&mut self.trace_info
10511047
}
10521048
}

src/hyperlight_host/src/hypervisor/mod.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::error::HyperlightError::ExecutionCanceledByHost;
2222
use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
2323
use crate::metrics::METRIC_GUEST_CANCELLATION;
2424
#[cfg(feature = "trace_guest")]
25-
use crate::sandbox::TraceInfo;
25+
use crate::sandbox::trace::TraceInfo;
2626
use crate::{HyperlightError, Result, log_then_return};
2727

2828
/// Architecture-specific code for the hypervisor.
@@ -236,12 +236,9 @@ pub(crate) trait Hypervisor: Debug + Send {
236236
#[cfg(feature = "trace_guest")]
237237
fn read_regs(&self) -> Result<arch::X86_64Regs>;
238238

239-
/// Get a reference of the trace info for the guest
240-
#[cfg(feature = "trace_guest")]
241-
fn trace_info_as_ref(&self) -> &TraceInfo;
242239
/// Get a mutable reference of the trace info for the guest
243240
#[cfg(feature = "trace_guest")]
244-
fn trace_info_as_mut(&mut self) -> &mut TraceInfo;
241+
fn trace_info_mut(&mut self) -> &mut TraceInfo;
245242
}
246243

247244
/// Returns a Some(HyperlightExit::AccessViolation(..)) if the given gpa doesn't have

src/hyperlight_host/src/sandbox/mod.rs

Lines changed: 2 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,14 @@ pub mod snapshot;
4040
/// Trait used by the macros to paper over the differences between hyperlight and hyperlight-wasm
4141
mod callable;
4242

43-
#[cfg(feature = "mem_profile")]
44-
use std::io::Write;
43+
/// Module for tracing guest execution
4544
#[cfg(feature = "trace_guest")]
46-
use std::sync::{Arc, Mutex};
45+
pub(crate) mod trace;
4746

4847
/// Trait used by the macros to paper over the differences between hyperlight and hyperlight-wasm
4948
pub use callable::Callable;
5049
/// Re-export for `SandboxConfiguration` type
5150
pub use config::SandboxConfiguration;
52-
#[cfg(feature = "mem_profile")]
53-
use framehop::Unwinder;
5451
/// Re-export for the `MultiUseSandbox` type
5552
pub use initialized_multi_use::MultiUseSandbox;
5653
use tracing::{Span, instrument};
@@ -93,140 +90,6 @@ pub fn is_hypervisor_present() -> bool {
9390
hypervisor::get_available_hypervisor().is_some()
9491
}
9592

96-
/// The information that trace collection requires in order to write
97-
/// an accurate trace.
98-
#[derive(Clone)]
99-
#[cfg(feature = "trace_guest")]
100-
pub(crate) struct TraceInfo {
101-
/// The epoch against which trace events are timed; at least as
102-
/// early as the creation of the sandbox being traced.
103-
pub epoch: std::time::Instant,
104-
/// The frequency of the timestamp counter.
105-
pub tsc_freq: Option<u64>,
106-
/// The epoch at which the guest started, if it has started.
107-
/// This is used to calculate the time spent in the guest relative to the
108-
/// time when the host started.
109-
pub guest_start_epoch: Option<std::time::Instant>,
110-
/// The start guest time, in TSC cycles, for the current guest has a double purpose.
111-
/// This field is used in two ways:
112-
/// 1. It contains the TSC value recorded on the host when the guest started.
113-
/// This is used to calculate the TSC frequency which is the same on the host and guest.
114-
/// The TSC frequency is used to convert TSC values to timestamps in the trace.
115-
/// **NOTE**: This is only used until the TSC frequency is calculated, when the first
116-
/// records are received.
117-
/// 2. To store the TSC value at recorded on the guest when the guest started (first record
118-
/// received)
119-
/// This is used to calculate the records timestamps relative to when guest started.
120-
pub guest_start_tsc: Option<u64>,
121-
/// The file to which the trace is being written
122-
#[allow(dead_code)]
123-
pub file: Arc<Mutex<std::fs::File>>,
124-
/// The unwind information for the current guest
125-
#[allow(dead_code)]
126-
#[cfg(feature = "mem_profile")]
127-
pub unwind_module: Arc<dyn crate::mem::exe::UnwindInfo>,
128-
/// The framehop unwinder for the current guest
129-
#[cfg(feature = "mem_profile")]
130-
pub unwinder: framehop::x86_64::UnwinderX86_64<Vec<u8>>,
131-
/// The framehop cache
132-
#[cfg(feature = "mem_profile")]
133-
pub unwind_cache: Arc<Mutex<framehop::x86_64::CacheX86_64>>,
134-
}
135-
#[cfg(feature = "trace_guest")]
136-
impl TraceInfo {
137-
/// Create a new TraceInfo by saving the current time as the epoch
138-
/// and generating a random filename.
139-
pub fn new(
140-
#[cfg(feature = "mem_profile")] unwind_module: Arc<dyn crate::mem::exe::UnwindInfo>,
141-
) -> crate::Result<Self> {
142-
let mut path = std::env::current_dir()?;
143-
path.push("trace");
144-
145-
// create directory if it does not exist
146-
if !path.exists() {
147-
std::fs::create_dir(&path)?;
148-
}
149-
path.push(uuid::Uuid::new_v4().to_string());
150-
path.set_extension("trace");
151-
152-
log::info!("Creating trace file at: {}", path.display());
153-
println!("Creating trace file at: {}", path.display());
154-
155-
#[cfg(feature = "mem_profile")]
156-
let hash = unwind_module.hash();
157-
#[cfg(feature = "mem_profile")]
158-
let (unwinder, unwind_cache) = {
159-
let mut unwinder = framehop::x86_64::UnwinderX86_64::new();
160-
unwinder.add_module(unwind_module.clone().as_module());
161-
let cache = framehop::x86_64::CacheX86_64::new();
162-
(unwinder, Arc::new(Mutex::new(cache)))
163-
};
164-
if !hyperlight_guest_tracing::invariant_tsc::has_invariant_tsc() {
165-
// If the platform does not support invariant TSC, warn the user.
166-
// On Azure nested virtualization, the TSC invariant bit is not correctly reported, this is a known issue.
167-
log::warn!(
168-
"Invariant TSC is not supported on this platform, trace timestamps may be inaccurate"
169-
);
170-
}
171-
172-
let ret = Self {
173-
epoch: std::time::Instant::now(),
174-
tsc_freq: None,
175-
guest_start_epoch: None,
176-
guest_start_tsc: None,
177-
file: Arc::new(Mutex::new(std::fs::File::create_new(path)?)),
178-
#[cfg(feature = "mem_profile")]
179-
unwind_module,
180-
#[cfg(feature = "mem_profile")]
181-
unwinder,
182-
#[cfg(feature = "mem_profile")]
183-
unwind_cache,
184-
};
185-
/* write a frame identifying the binary */
186-
#[cfg(feature = "mem_profile")]
187-
self::outb::record_trace_frame(&ret, 0, |f| {
188-
let _ = f.write_all(hash.as_bytes());
189-
})?;
190-
Ok(ret)
191-
}
192-
193-
/// Calculate the TSC frequency based on the RDTSC instruction on the host.
194-
fn calculate_tsc_freq(&mut self) -> crate::Result<()> {
195-
let (start, start_time) = match (
196-
self.guest_start_tsc.as_ref(),
197-
self.guest_start_epoch.as_ref(),
198-
) {
199-
(Some(start), Some(start_time)) => (*start, *start_time),
200-
_ => {
201-
// If the guest start TSC and time are not set, we use the current time and TSC.
202-
// This is not ideal, but it allows us to calculate the TSC frequency without
203-
// failing.
204-
// This is a fallback mechanism to ensure that we can still calculate, however it
205-
// should be noted that this may lead to inaccuracies in the TSC frequency.
206-
// The start time should be already set before running the guest for each sandbox.
207-
log::error!(
208-
"Guest start TSC and time are not set. Calculating TSC frequency will use current time and TSC."
209-
);
210-
(
211-
hyperlight_guest_tracing::invariant_tsc::read_tsc(),
212-
std::time::Instant::now(),
213-
)
214-
}
215-
};
216-
217-
let end_time = std::time::Instant::now();
218-
let end = hyperlight_guest_tracing::invariant_tsc::read_tsc();
219-
220-
let elapsed = end_time.duration_since(start_time).as_secs_f64();
221-
let tsc_freq = ((end - start) as f64 / elapsed) as u64;
222-
223-
log::info!("Calculated TSC frequency: {} Hz", tsc_freq);
224-
self.tsc_freq = Some(tsc_freq);
225-
226-
Ok(())
227-
}
228-
}
229-
23093
pub(crate) trait WrapperGetter {
23194
#[allow(dead_code)]
23295
fn get_mgr_wrapper(&self) -> &MemMgrWrapper<HostSharedMemory>;

0 commit comments

Comments
 (0)