Skip to content

Commit f0f7825

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 <dblnz@pm.me>
1 parent b50d37a commit f0f7825

File tree

8 files changed

+376
-369
lines changed

8 files changed

+376
-369
lines changed

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ use crate::mem::mgr::SandboxMemoryManager;
6868
use crate::mem::ptr::{GuestPtr, RawPtr};
6969
use crate::mem::shared_mem::HostSharedMemory;
7070
use crate::sandbox::SandboxConfiguration;
71-
#[cfg(feature = "trace_guest")]
72-
use crate::sandbox::TraceInfo;
7371
use crate::sandbox::host_funcs::FunctionRegistry;
7472
use crate::sandbox::outb::handle_outb;
73+
#[cfg(feature = "trace_guest")]
74+
use crate::sandbox::trace::TraceInfo;
7575
#[cfg(crashdump)]
7676
use crate::sandbox::uninitialized::SandboxRuntimeConfig;
7777
use crate::{Result, log_then_return, new_error};
@@ -1095,11 +1095,7 @@ impl Hypervisor for HypervLinuxDriver {
10951095
}
10961096

10971097
#[cfg(feature = "trace_guest")]
1098-
fn trace_info_as_ref(&self) -> &TraceInfo {
1099-
&self.trace_info
1100-
}
1101-
#[cfg(feature = "trace_guest")]
1102-
fn trace_info_as_mut(&mut self) -> &mut TraceInfo {
1098+
fn trace_info_mut(&mut self) -> &mut TraceInfo {
11031099
&mut self.trace_info
11041100
}
11051101
}

src/hyperlight_host/src/hypervisor/hyperv_windows.rs

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

943943
#[cfg(feature = "trace_guest")]
944-
fn trace_info_as_ref(&self) -> &TraceInfo {
945-
&self.trace_info
946-
}
947-
#[cfg(feature = "trace_guest")]
948-
fn trace_info_as_mut(&mut self) -> &mut TraceInfo {
944+
fn trace_info_mut(&mut self) -> &mut TraceInfo {
949945
&mut self.trace_info
950946
}
951947
}

src/hyperlight_host/src/hypervisor/kvm.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ use crate::mem::mgr::SandboxMemoryManager;
4141
use crate::mem::ptr::{GuestPtr, RawPtr};
4242
use crate::mem::shared_mem::HostSharedMemory;
4343
use crate::sandbox::SandboxConfiguration;
44-
#[cfg(feature = "trace_guest")]
45-
use crate::sandbox::TraceInfo;
4644
use crate::sandbox::host_funcs::FunctionRegistry;
4745
use crate::sandbox::outb::handle_outb;
46+
#[cfg(feature = "trace_guest")]
47+
use crate::sandbox::trace::TraceInfo;
4848
#[cfg(crashdump)]
4949
use crate::sandbox::uninitialized::SandboxRuntimeConfig;
5050
use crate::{Result, log_then_return, new_error};
@@ -1031,11 +1031,7 @@ impl Hypervisor for KVMDriver {
10311031
}
10321032

10331033
#[cfg(feature = "trace_guest")]
1034-
fn trace_info_as_ref(&self) -> &TraceInfo {
1035-
&self.trace_info
1036-
}
1037-
#[cfg(feature = "trace_guest")]
1038-
fn trace_info_as_mut(&mut self) -> &mut TraceInfo {
1034+
fn trace_info_mut(&mut self) -> &mut TraceInfo {
10391035
&mut self.trace_info
10401036
}
10411037
}

src/hyperlight_host/src/hypervisor/mod.rs

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

3131
/// HyperV-on-linux functionality
@@ -313,12 +313,9 @@ pub(crate) trait Hypervisor: Debug + Send {
313313
/// Check stack guard to see if the stack is still valid
314314
fn check_stack_guard(&self) -> Result<bool>;
315315

316-
/// Get a reference of the trace info for the guest
317-
#[cfg(feature = "trace_guest")]
318-
fn trace_info_as_ref(&self) -> &TraceInfo;
319316
/// Get a mutable reference of the trace info for the guest
320317
#[cfg(feature = "trace_guest")]
321-
fn trace_info_as_mut(&mut self) -> &mut TraceInfo;
318+
fn trace_info_mut(&mut self) -> &mut TraceInfo;
322319
}
323320

324321
/// 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
@@ -37,17 +37,14 @@ pub mod snapshot;
3737
/// Trait used by the macros to paper over the differences between hyperlight and hyperlight-wasm
3838
mod callable;
3939

40-
#[cfg(feature = "mem_profile")]
41-
use std::io::Write;
40+
/// Module for tracing guest execution
4241
#[cfg(feature = "trace_guest")]
43-
use std::sync::{Arc, Mutex};
42+
pub(crate) mod trace;
4443

4544
/// Trait used by the macros to paper over the differences between hyperlight and hyperlight-wasm
4645
pub use callable::Callable;
4746
/// Re-export for `SandboxConfiguration` type
4847
pub use config::SandboxConfiguration;
49-
#[cfg(feature = "mem_profile")]
50-
use framehop::Unwinder;
5148
/// Re-export for the `MultiUseSandbox` type
5249
pub use initialized_multi_use::MultiUseSandbox;
5350
use tracing::{Span, instrument};
@@ -88,140 +85,6 @@ pub fn is_hypervisor_present() -> bool {
8885
hypervisor::get_available_hypervisor().is_some()
8986
}
9087

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

0 commit comments

Comments
 (0)