hyperlight-guest-tracing 0.16.0

Provides the tracing functionality for the hyperlight guest.
Documentation
/*
Copyright 2025  The Hyperlight Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/// Module for checking invariant TSC support and reading the timestamp counter
use core::arch::x86_64::{__cpuid, _rdtsc};

/// Check if the processor supports invariant TSC
///
/// Returns true if CPUID.80000007H:EDX[8] is set, indicating invariant TSC support
// TODO: Remove this when MSRV is raised above 1.89.
// On Rust 1.89, __cpuid requires `unsafe`; on newer compilers it is safe and
// clippy flags these blocks as unnecessary.
#[allow(unused_unsafe)]
pub fn has_invariant_tsc() -> bool {
    // Check if extended CPUID functions are available
    let max_extended = unsafe { __cpuid(0x80000000) };
    if max_extended.eax < 0x80000007 {
        return false;
    }

    // Query CPUID.80000007H for invariant TSC support
    let cpuid_result = unsafe { __cpuid(0x80000007) };

    // Check bit 8 of EDX register for invariant TSC support
    (cpuid_result.edx & (1 << 8)) != 0
}

/// Read the timestamp counter
///
/// This function provides a high-performance timestamp by reading the TSC.
/// Should only be used when invariant TSC is supported for reliable timing.
///
/// # Safety
/// This function uses unsafe assembly instructions but is safe to call.
/// However, the resulting timestamp is only meaningful if invariant TSC is supported.
pub fn read_tsc() -> u64 {
    unsafe { _rdtsc() }
}