hyperlight_guest_bin/
lib.rs1#![no_std]
17
18extern crate alloc;
20
21use core::fmt::Write;
22
23use arch::dispatch::dispatch_function;
24use buddy_system_allocator::LockedHeap;
25use guest_function::register::GuestFunctionRegister;
26use guest_logger::init_logger;
27use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
28use hyperlight_common::log_level::GuestLogFilter;
29use hyperlight_common::mem::HyperlightPEB;
30#[cfg(feature = "mem_profile")]
31use hyperlight_common::outb::OutBAction;
32use hyperlight_guest::exit::write_abort;
33use hyperlight_guest::guest_handle::handle::GuestHandle;
34
35#[cfg_attr(target_arch = "x86_64", path = "arch/amd64/mod.rs")]
37#[cfg_attr(target_arch = "aarch64", path = "arch/aarch64/mod.rs")]
38mod arch;
39#[cfg(target_arch = "x86_64")]
43pub mod exception;
44pub mod guest_function {
45 pub(super) mod call;
46 pub mod definition;
47 pub mod register;
48}
49
50pub mod error;
51pub mod guest_logger;
52pub mod host_comm;
53pub mod memory;
54pub mod paging;
55
56#[cfg(feature = "libc")]
59mod libc_stubs;
60
61mod init;
63
64#[cfg(feature = "libc")]
66pub use hyperlight_libc as libc;
67
68#[cfg(all(feature = "mem_profile", target_arch = "x86_64"))]
70struct ProfiledLockedHeap<const ORDER: usize>(LockedHeap<ORDER>);
71#[cfg(all(feature = "mem_profile", target_arch = "x86_64"))]
72unsafe impl<const ORDER: usize> alloc::alloc::GlobalAlloc for ProfiledLockedHeap<ORDER> {
73 unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
74 let addr = unsafe { self.0.alloc(layout) };
75 unsafe {
76 core::arch::asm!("out dx, al",
77 in("dx") OutBAction::TraceMemoryAlloc as u16,
78 in("rax") layout.size() as u64,
79 in("rcx") addr as u64);
80 }
81 addr
82 }
83 unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
84 unsafe {
85 core::arch::asm!("out dx, al",
86 in("dx") OutBAction::TraceMemoryFree as u16,
87 in("rax") layout.size() as u64,
88 in("rcx") ptr as u64);
89 self.0.dealloc(ptr, layout)
90 }
91 }
92 unsafe fn alloc_zeroed(&self, layout: core::alloc::Layout) -> *mut u8 {
93 let addr = unsafe { self.0.alloc_zeroed(layout) };
94 unsafe {
95 core::arch::asm!("out dx, al",
96 in("dx") OutBAction::TraceMemoryAlloc as u16,
97 in("rax") layout.size() as u64,
98 in("rcx") addr as u64);
99 }
100 addr
101 }
102 unsafe fn realloc(
103 &self,
104 ptr: *mut u8,
105 layout: core::alloc::Layout,
106 new_size: usize,
107 ) -> *mut u8 {
108 let new_ptr = unsafe { self.0.realloc(ptr, layout, new_size) };
109 unsafe {
110 core::arch::asm!("out dx, al",
111 in("dx") OutBAction::TraceMemoryFree as u16,
112 in("rax") layout.size() as u64,
113 in("rcx") ptr);
114 core::arch::asm!("out dx, al",
115 in("dx") OutBAction::TraceMemoryAlloc as u16,
116 in("rax") new_size as u64,
117 in("rcx") new_ptr);
118 }
119 new_ptr
120 }
121}
122
123#[cfg(not(all(feature = "mem_profile", target_arch = "x86_64")))]
125#[global_allocator]
126pub(crate) static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::empty();
127#[cfg(all(feature = "mem_profile", target_arch = "x86_64"))]
128#[global_allocator]
129pub(crate) static HEAP_ALLOCATOR: ProfiledLockedHeap<32> =
130 ProfiledLockedHeap(LockedHeap::<32>::empty());
131
132pub static mut GUEST_HANDLE: GuestHandle = GuestHandle::new();
133pub(crate) static mut REGISTERED_GUEST_FUNCTIONS: GuestFunctionRegister<GuestFunc> =
134 GuestFunctionRegister::new();
135
136const VERSION_STR: &str = env!("CARGO_PKG_VERSION");
137
138#[used]
141#[unsafe(link_section = ".note.hyperlight-version")]
142static HYPERLIGHT_VERSION_NOTE: hyperlight_common::version_note::ElfNote<
143 {
144 hyperlight_common::version_note::padded_name_size(
145 hyperlight_common::version_note::HYPERLIGHT_NOTE_NAME.len() + 1,
146 )
147 },
148 { hyperlight_common::version_note::padded_desc_size(VERSION_STR.len() + 1) },
149> = hyperlight_common::version_note::ElfNote::new(
150 hyperlight_common::version_note::HYPERLIGHT_NOTE_NAME,
151 VERSION_STR,
152 hyperlight_common::version_note::HYPERLIGHT_NOTE_TYPE,
153);
154
155pub static mut OS_PAGE_SIZE: u32 = 0;
160
161#[cfg_attr(not(test), panic_handler)]
167#[allow(clippy::panic)]
168#[allow(dead_code)]
170fn panic(info: &core::panic::PanicInfo) -> ! {
171 _panic_handler(info)
172}
173
174struct HyperlightAbortWriter;
179impl core::fmt::Write for HyperlightAbortWriter {
180 fn write_str(&mut self, s: &str) -> core::fmt::Result {
181 write_abort(s.as_bytes());
182 Ok(())
183 }
184}
185
186#[inline(always)]
187fn _panic_handler(info: &core::panic::PanicInfo) -> ! {
188 let mut w = HyperlightAbortWriter;
189
190 write_abort(&[ErrorCode::UnknownError as u8]);
192
193 let write_res = write!(w, "{}", info);
194 if write_res.is_err() {
195 write_abort("panic: message format failed".as_bytes());
196 }
197
198 write_abort(&[0xFF]);
201 unreachable!();
202}
203
204unsafe extern "C" {
207 fn hyperlight_main();
208
209 #[cfg(feature = "libc")]
210 fn srand(seed: u32);
211}
212
213#[tracing::instrument(skip_all, parent = tracing::Span::current(), level= "Trace")]
214extern "C" fn hyperlight_main_default() {
215 }
217
218core::arch::global_asm!(
219 ".weak hyperlight_main",
220 ".set hyperlight_main, {}",
221 sym hyperlight_main_default,
222);
223
224pub(crate) extern "C" fn generic_init(
228 peb_address: u64,
229 _seed: u64,
230 ops: u64,
231 max_log_level: u64,
232) -> u64 {
233 unsafe {
234 GUEST_HANDLE = GuestHandle::init(peb_address as *mut HyperlightPEB);
235 #[allow(static_mut_refs)]
236 let peb_ptr = GUEST_HANDLE.peb().unwrap();
237
238 let heap_start = (*peb_ptr).guest_heap.ptr as usize;
239 let heap_size = (*peb_ptr).guest_heap.size as usize;
240 #[cfg(not(all(feature = "mem_profile", target_arch = "x86_64")))]
241 let heap_allocator = &HEAP_ALLOCATOR;
242 #[cfg(all(feature = "mem_profile", target_arch = "x86_64"))]
243 let heap_allocator = &HEAP_ALLOCATOR.0;
244 heap_allocator
245 .try_lock()
246 .expect("Failed to access HEAP_ALLOCATOR")
247 .init(heap_start, heap_size);
248 peb_ptr
249 };
250
251 #[cfg(feature = "trace_guest")]
253 let guest_start_tsc = hyperlight_guest_tracing::invariant_tsc::read_tsc();
254
255 #[cfg(feature = "libc")]
256 unsafe {
257 let srand_seed = (((peb_address << 8) ^ (_seed >> 4)) >> 32) as u32;
258 srand(srand_seed);
259 }
260
261 unsafe {
262 OS_PAGE_SIZE = ops as u32;
263 }
264
265 let guest_log_level_filter =
267 GuestLogFilter::try_from(max_log_level).expect("Invalid log level");
268 init_logger(guest_log_level_filter.into());
269
270 #[cfg(feature = "trace_guest")]
272 if guest_log_level_filter != GuestLogFilter::Off {
273 hyperlight_guest_tracing::init_guest_tracing(
274 guest_start_tsc,
275 guest_log_level_filter.into(),
276 );
277 }
278
279 #[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
283 let _entered = tracing::span!(tracing::Level::INFO, "generic_init").entered();
284
285 #[cfg(feature = "macros")]
286 for registration in __private::GUEST_FUNCTION_INIT {
287 registration();
288 }
289
290 unsafe {
291 hyperlight_main();
292 }
293
294 #[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
297 {
298 _entered.exit();
303
304 hyperlight_guest_tracing::flush();
307 }
308
309 dispatch_function as *const () as usize as u64
310}
311
312#[cfg(feature = "macros")]
313#[doc(hidden)]
314pub mod __private {
315 pub use alloc::vec::Vec;
316
317 pub use hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall;
318 pub use hyperlight_common::func::ResultType;
319 pub use hyperlight_guest::error::HyperlightGuestError;
320 pub use linkme;
321
322 #[linkme::distributed_slice]
323 pub static GUEST_FUNCTION_INIT: [fn()];
324
325 pub trait FromResult {
326 type Output;
327 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self;
328 }
329
330 use alloc::string::String;
331
332 use hyperlight_common::for_each_return_type;
333
334 macro_rules! impl_maybe_unwrap {
335 ($ty:ty, $enum:ident) => {
336 impl FromResult for $ty {
337 type Output = Self;
338 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self {
339 res.unwrap()
342 }
343 }
344
345 impl FromResult for Result<$ty, HyperlightGuestError> {
346 type Output = $ty;
347 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self {
348 res
349 }
350 }
351 };
352 }
353
354 for_each_return_type!(impl_maybe_unwrap);
355}
356
357#[cfg(feature = "macros")]
358pub use hyperlight_guest_macro::{dispatch, guest_function, host_function, main};
359
360pub use crate::guest_function::definition::GuestFunc;