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;
54#[cfg(target_arch = "x86_64")]
55pub mod paging;
56
57#[cfg(feature = "libc")]
60mod libc_stubs;
61
62#[cfg(feature = "libc")]
64pub use hyperlight_libc as libc;
65
66#[cfg(all(feature = "mem_profile", target_arch = "x86_64"))]
68struct ProfiledLockedHeap<const ORDER: usize>(LockedHeap<ORDER>);
69#[cfg(all(feature = "mem_profile", target_arch = "x86_64"))]
70unsafe impl<const ORDER: usize> alloc::alloc::GlobalAlloc for ProfiledLockedHeap<ORDER> {
71 unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
72 let addr = unsafe { self.0.alloc(layout) };
73 unsafe {
74 core::arch::asm!("out dx, al",
75 in("dx") OutBAction::TraceMemoryAlloc as u16,
76 in("rax") layout.size() as u64,
77 in("rcx") addr as u64);
78 }
79 addr
80 }
81 unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
82 unsafe {
83 core::arch::asm!("out dx, al",
84 in("dx") OutBAction::TraceMemoryFree as u16,
85 in("rax") layout.size() as u64,
86 in("rcx") ptr as u64);
87 self.0.dealloc(ptr, layout)
88 }
89 }
90 unsafe fn alloc_zeroed(&self, layout: core::alloc::Layout) -> *mut u8 {
91 let addr = unsafe { self.0.alloc_zeroed(layout) };
92 unsafe {
93 core::arch::asm!("out dx, al",
94 in("dx") OutBAction::TraceMemoryAlloc as u16,
95 in("rax") layout.size() as u64,
96 in("rcx") addr as u64);
97 }
98 addr
99 }
100 unsafe fn realloc(
101 &self,
102 ptr: *mut u8,
103 layout: core::alloc::Layout,
104 new_size: usize,
105 ) -> *mut u8 {
106 let new_ptr = unsafe { self.0.realloc(ptr, layout, new_size) };
107 unsafe {
108 core::arch::asm!("out dx, al",
109 in("dx") OutBAction::TraceMemoryFree as u16,
110 in("rax") layout.size() as u64,
111 in("rcx") ptr);
112 core::arch::asm!("out dx, al",
113 in("dx") OutBAction::TraceMemoryAlloc as u16,
114 in("rax") new_size as u64,
115 in("rcx") new_ptr);
116 }
117 new_ptr
118 }
119}
120
121#[cfg(not(all(feature = "mem_profile", target_arch = "x86_64")))]
123#[global_allocator]
124pub(crate) static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::empty();
125#[cfg(all(feature = "mem_profile", target_arch = "x86_64"))]
126#[global_allocator]
127pub(crate) static HEAP_ALLOCATOR: ProfiledLockedHeap<32> =
128 ProfiledLockedHeap(LockedHeap::<32>::empty());
129
130pub static mut GUEST_HANDLE: GuestHandle = GuestHandle::new();
131pub(crate) static mut REGISTERED_GUEST_FUNCTIONS: GuestFunctionRegister<GuestFunc> =
132 GuestFunctionRegister::new();
133
134const VERSION_STR: &str = env!("CARGO_PKG_VERSION");
135
136#[used]
139#[unsafe(link_section = ".note.hyperlight-version")]
140static HYPERLIGHT_VERSION_NOTE: hyperlight_common::version_note::ElfNote<
141 {
142 hyperlight_common::version_note::padded_name_size(
143 hyperlight_common::version_note::HYPERLIGHT_NOTE_NAME.len() + 1,
144 )
145 },
146 { hyperlight_common::version_note::padded_desc_size(VERSION_STR.len() + 1) },
147> = hyperlight_common::version_note::ElfNote::new(
148 hyperlight_common::version_note::HYPERLIGHT_NOTE_NAME,
149 VERSION_STR,
150 hyperlight_common::version_note::HYPERLIGHT_NOTE_TYPE,
151);
152
153pub static mut OS_PAGE_SIZE: u32 = 0;
158
159#[cfg_attr(not(test), panic_handler)]
165#[allow(clippy::panic)]
166#[allow(dead_code)]
168fn panic(info: &core::panic::PanicInfo) -> ! {
169 _panic_handler(info)
170}
171
172struct HyperlightAbortWriter;
177impl core::fmt::Write for HyperlightAbortWriter {
178 fn write_str(&mut self, s: &str) -> core::fmt::Result {
179 write_abort(s.as_bytes());
180 Ok(())
181 }
182}
183
184#[inline(always)]
185fn _panic_handler(info: &core::panic::PanicInfo) -> ! {
186 let mut w = HyperlightAbortWriter;
187
188 write_abort(&[ErrorCode::UnknownError as u8]);
190
191 let write_res = write!(w, "{}", info);
192 if write_res.is_err() {
193 write_abort("panic: message format failed".as_bytes());
194 }
195
196 write_abort(&[0xFF]);
199 unreachable!();
200}
201
202unsafe extern "C" {
205 fn hyperlight_main();
206 fn srand(seed: u32);
207}
208
209#[tracing::instrument(skip_all, parent = tracing::Span::current(), level= "Trace")]
210extern "C" fn hyperlight_main_default() {
211 }
213
214core::arch::global_asm!(
215 ".weak hyperlight_main",
216 ".set hyperlight_main, {}",
217 sym hyperlight_main_default,
218);
219
220pub(crate) extern "C" fn generic_init(
224 peb_address: u64,
225 seed: u64,
226 ops: u64,
227 max_log_level: u64,
228) -> u64 {
229 unsafe {
230 GUEST_HANDLE = GuestHandle::init(peb_address as *mut HyperlightPEB);
231 #[allow(static_mut_refs)]
232 let peb_ptr = GUEST_HANDLE.peb().unwrap();
233
234 let heap_start = (*peb_ptr).guest_heap.ptr as usize;
235 let heap_size = (*peb_ptr).guest_heap.size as usize;
236 #[cfg(not(all(feature = "mem_profile", target_arch = "x86_64")))]
237 let heap_allocator = &HEAP_ALLOCATOR;
238 #[cfg(all(feature = "mem_profile", target_arch = "x86_64"))]
239 let heap_allocator = &HEAP_ALLOCATOR.0;
240 heap_allocator
241 .try_lock()
242 .expect("Failed to access HEAP_ALLOCATOR")
243 .init(heap_start, heap_size);
244 peb_ptr
245 };
246
247 #[cfg(feature = "trace_guest")]
249 let guest_start_tsc = hyperlight_guest_tracing::invariant_tsc::read_tsc();
250
251 unsafe {
252 let srand_seed = (((peb_address << 8) ^ (seed >> 4)) >> 32) as u32;
253 srand(srand_seed);
255
256 OS_PAGE_SIZE = ops as u32;
257 }
258
259 let guest_log_level_filter =
261 GuestLogFilter::try_from(max_log_level).expect("Invalid log level");
262 init_logger(guest_log_level_filter.into());
263
264 #[cfg(feature = "trace_guest")]
266 if guest_log_level_filter != GuestLogFilter::Off {
267 hyperlight_guest_tracing::init_guest_tracing(
268 guest_start_tsc,
269 guest_log_level_filter.into(),
270 );
271 }
272
273 #[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
277 let _entered = tracing::span!(tracing::Level::INFO, "generic_init").entered();
278
279 #[cfg(feature = "macros")]
280 for registration in __private::GUEST_FUNCTION_INIT {
281 registration();
282 }
283
284 unsafe {
285 hyperlight_main();
286 }
287
288 #[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
291 {
292 _entered.exit();
297
298 hyperlight_guest_tracing::flush();
301 }
302
303 dispatch_function as usize as u64
304}
305
306#[cfg(feature = "macros")]
307#[doc(hidden)]
308pub mod __private {
309 pub use alloc::vec::Vec;
310
311 pub use hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall;
312 pub use hyperlight_common::func::ResultType;
313 pub use hyperlight_guest::error::HyperlightGuestError;
314 pub use linkme;
315
316 #[linkme::distributed_slice]
317 pub static GUEST_FUNCTION_INIT: [fn()];
318
319 pub trait FromResult {
320 type Output;
321 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self;
322 }
323
324 use alloc::string::String;
325
326 use hyperlight_common::for_each_return_type;
327
328 macro_rules! impl_maybe_unwrap {
329 ($ty:ty, $enum:ident) => {
330 impl FromResult for $ty {
331 type Output = Self;
332 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self {
333 res.unwrap()
336 }
337 }
338
339 impl FromResult for Result<$ty, HyperlightGuestError> {
340 type Output = $ty;
341 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self {
342 res
343 }
344 }
345 };
346 }
347
348 for_each_return_type!(impl_maybe_unwrap);
349}
350
351#[cfg(feature = "macros")]
352pub use hyperlight_guest_macro::{dispatch, guest_function, host_function, main};
353
354pub use crate::guest_function::definition::GuestFunc;