Skip to content

Commit 0fa71f9

Browse files
committed
[trace-guest] update guest crates to add trace instrumentation
- conditionally handle logs either through tracing or the dedicated VM exit based on whether tracing is initialized on the guest - modify `test_with_small_stack_and_heap` to 18kB because the `#[intrument]` attributes use more stack. Signed-off-by: Doru Blânzeanu <[email protected]>
1 parent 1a371d1 commit 0fa71f9

File tree

13 files changed

+78
-21
lines changed

13 files changed

+78
-21
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/hyperlight_guest/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
1717
hyperlight-common = { workspace = true }
1818
hyperlight-guest-tracing = { workspace = true, default-features = false }
1919
flatbuffers = { version= "25.9.23", default-features = false }
20+
tracing = { version = "0.1.41", default-features = false, features = ["attributes"] }
2021

2122
[features]
2223
default = []

src/hyperlight_guest/src/exit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ use core::arch::asm;
1818
use core::ffi::{CStr, c_char};
1919

2020
use hyperlight_common::outb::OutBAction;
21+
use tracing::instrument;
2122

2223
/// Halt the execution of the guest and returns control to the host.
2324
#[inline(never)]
25+
#[instrument(skip_all, level = "Trace")]
2426
pub fn halt() {
2527
#[cfg(feature = "trace_guest")]
2628
{
@@ -121,6 +123,7 @@ pub(crate) fn outb(port: u16, data: &[u8]) {
121123
}
122124

123125
/// OUT function for sending a 32-bit value to the host.
126+
#[instrument(skip_all, level = "Trace")]
124127
pub(crate) unsafe fn out32(port: u16, val: u32) {
125128
#[cfg(feature = "trace_guest")]
126129
{

src/hyperlight_guest/src/guest_handle/host_comm.rs

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ use hyperlight_common::flatbuffer_wrappers::guest_log_level::LogLevel;
3030
use hyperlight_common::flatbuffer_wrappers::host_function_details::HostFunctionDetails;
3131
use hyperlight_common::flatbuffer_wrappers::util::estimate_flatbuffer_capacity;
3232
use hyperlight_common::outb::OutBAction;
33+
use tracing::instrument;
3334

3435
use super::handle::GuestHandle;
3536
use crate::error::{HyperlightGuestError, Result};
3637
use crate::exit::out32;
3738

3839
impl GuestHandle {
3940
/// Get user memory region as bytes.
41+
#[instrument(skip_all, level = "Trace")]
4042
pub fn read_n_bytes_from_user_memory(&self, num: u64) -> Result<Vec<u8>> {
4143
let peb_ptr = self.peb().unwrap();
4244
let user_memory_region_ptr = unsafe { (*peb_ptr).init_data.ptr as *mut u8 };
@@ -124,6 +126,7 @@ impl GuestHandle {
124126
/// sends it to the host, and then retrieves the return value.
125127
///
126128
/// The return value is deserialized into the specified type `T`.
129+
#[instrument(skip_all, level = "Trace")]
127130
pub fn call_host_function<T: TryFrom<ReturnValue>>(
128131
&self,
129132
function_name: &str,
@@ -134,6 +137,7 @@ impl GuestHandle {
134137
self.get_host_return_value::<T>()
135138
}
136139

140+
#[instrument(skip_all, level = "Trace")]
137141
pub fn get_host_function_details(&self) -> HostFunctionDetails {
138142
let peb_ptr = self.peb().unwrap();
139143
let host_function_details_buffer =
@@ -159,24 +163,46 @@ impl GuestHandle {
159163
source_file: &str,
160164
line: u32,
161165
) {
162-
let guest_log_data = GuestLogData::new(
163-
message.to_string(),
164-
source.to_string(),
165-
log_level,
166-
caller.to_string(),
167-
source_file.to_string(),
168-
line,
169-
);
170-
171-
let bytes: Vec<u8> = guest_log_data
172-
.try_into()
173-
.expect("Failed to convert GuestLogData to bytes");
174-
175-
self.push_shared_output_data(&bytes)
176-
.expect("Unable to push log data to shared output data");
177-
178-
unsafe {
179-
out32(OutBAction::Log as u16, 0);
166+
// Closure to send log message to host
167+
let send_to_host = || {
168+
let guest_log_data = GuestLogData::new(
169+
message.to_string(),
170+
source.to_string(),
171+
log_level,
172+
caller.to_string(),
173+
source_file.to_string(),
174+
line,
175+
);
176+
177+
let bytes: Vec<u8> = guest_log_data
178+
.try_into()
179+
.expect("Failed to convert GuestLogData to bytes");
180+
181+
self.push_shared_output_data(&bytes)
182+
.expect("Unable to push log data to shared output data");
183+
184+
unsafe {
185+
out32(OutBAction::Log as u16, 0);
186+
}
187+
};
188+
189+
#[cfg(feature = "trace_guest")]
190+
if hyperlight_guest_tracing::is_trace_enabled() {
191+
// If the "trace_guest" feature is enabled and tracing is initialized, log using tracing
192+
tracing::trace!(
193+
event = message,
194+
level = ?log_level,
195+
code.filepath = source,
196+
caller = caller,
197+
source_file = source_file,
198+
code.lineno = line,
199+
);
200+
} else {
201+
send_to_host();
202+
}
203+
#[cfg(not(feature = "trace_guest"))]
204+
{
205+
send_to_host();
180206
}
181207
}
182208
}

src/hyperlight_guest/src/guest_handle/io.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ use core::any::type_name;
2020
use core::slice::from_raw_parts_mut;
2121

2222
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
23+
use tracing::{Span, instrument};
2324

2425
use super::handle::GuestHandle;
2526
use crate::error::{HyperlightGuestError, Result};
2627

2728
impl GuestHandle {
2829
/// Pops the top element from the shared input data buffer and returns it as a T
30+
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
2931
pub fn try_pop_shared_input_data_into<T>(&self) -> Result<T>
3032
where
3133
T: for<'a> TryFrom<&'a [u8]>,
@@ -87,6 +89,7 @@ impl GuestHandle {
8789
}
8890

8991
/// Pushes the given data onto the shared output data buffer.
92+
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
9093
pub fn push_shared_output_data(&self, data: &[u8]) -> Result<()> {
9194
let peb_ptr = self.peb().unwrap();
9295
let output_stack_size = unsafe { (*peb_ptr).output_stack.size as usize };

src/hyperlight_guest_bin/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ buddy_system_allocator = "0.11.0"
2828
log = { version = "0.4", default-features = false }
2929
spin = "0.10.0"
3030
flatbuffers = { version = "25.2.10", default-features = false }
31-
31+
tracing = { version = "0.1.41", default-features = false, features = ["attributes"] }
3232

3333
[lints]
3434
workspace = true

src/hyperlight_guest_bin/src/guest_function/call.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ use hyperlight_common::flatbuffer_wrappers::function_types::{FunctionCallResult,
2323
use hyperlight_common::flatbuffer_wrappers::guest_error::{ErrorCode, GuestError};
2424
use hyperlight_guest::error::{HyperlightGuestError, Result};
2525
use hyperlight_guest::exit::halt;
26+
use tracing::{Span, instrument};
2627

2728
use crate::{GUEST_HANDLE, REGISTERED_GUEST_FUNCTIONS};
2829

2930
type GuestFunc = fn(&FunctionCall) -> Result<Vec<u8>>;
3031

32+
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
3133
pub(crate) fn call_guest_function(function_call: FunctionCall) -> Result<Vec<u8>> {
3234
// Validate this is a Guest Function Call
3335
if function_call.function_call_type() != FunctionCallType::Guest {
@@ -83,6 +85,7 @@ pub(crate) fn call_guest_function(function_call: FunctionCall) -> Result<Vec<u8>
8385
// This function may panic, as we have no other ways of dealing with errors at this level
8486
#[unsafe(no_mangle)]
8587
#[inline(never)]
88+
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
8689
fn internal_dispatch_function() {
8790
let handle = unsafe { GUEST_HANDLE };
8891

@@ -116,6 +119,7 @@ fn internal_dispatch_function() {
116119
// This is implemented as a separate function to make sure that epilogue in the internal_dispatch_function is called before the halt()
117120
// which if it were included in the internal_dispatch_function cause the epilogue to not be called because the halt() would not return
118121
// when running in the hypervisor.
122+
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
119123
pub(crate) extern "C" fn dispatch_function() {
120124
// The hyperlight host likes to use one partition and reset it in
121125
// various ways; if that has happened, there might stale TLB

src/hyperlight_guest_bin/src/paging.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
use alloc::alloc::Layout;
1818
use core::arch::asm;
1919

20+
use tracing::{Span, instrument};
21+
2022
use crate::OS_PAGE_SIZE;
2123

2224
/// Convert a physical address in main memory to a virtual address
@@ -61,6 +63,7 @@ struct MapResponse {
6163
/// as such do not use concurrently with any other page table operations
6264
/// - TLB invalidation is not performed,
6365
/// if previously-unmapped ranges are not being mapped, TLB invalidation may need to be performed afterwards.
66+
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
6467
pub unsafe fn map_region(phys_base: u64, virt_base: *mut u8, len: u64) {
6568
let mut pml4_base: u64;
6669
unsafe {

src/hyperlight_guest_tracing/src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ mod visitor;
3838
pub use state::TraceBatchInfo;
3939
#[cfg(feature = "trace")]
4040
pub use trace::{
41-
clean_trace_state, end_trace, guest_trace_info, init_guest_tracing, set_start_tsc,
41+
clean_trace_state, end_trace, guest_trace_info, init_guest_tracing, is_trace_enabled,
42+
set_start_tsc,
4243
};
4344

4445
/// Maximum number of spans that the guest can store
@@ -212,4 +213,12 @@ mod trace {
212213
}
213214
res
214215
}
216+
217+
/// Returns true if tracing is enabled (the guest tracing state is initialized).
218+
pub fn is_trace_enabled() -> bool {
219+
GUEST_STATE
220+
.get()
221+
.map(|w| w.upgrade().is_some())
222+
.unwrap_or(false)
223+
}
215224
}

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ mod tests {
602602
fn test_with_small_stack_and_heap() {
603603
let mut cfg = SandboxConfiguration::default();
604604
cfg.set_heap_size(20 * 1024);
605-
cfg.set_stack_size(16 * 1024);
605+
cfg.set_stack_size(18 * 1024);
606606

607607
let mut sbox1: MultiUseSandbox = {
608608
let path = simple_guest_as_string().unwrap();

0 commit comments

Comments
 (0)