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")]
37mod arch;
38#[cfg(target_arch = "x86_64")]
42pub mod exception;
43pub mod guest_function {
44 pub(super) mod call;
45 pub mod definition;
46 pub mod register;
47}
48
49pub mod guest_logger;
50pub mod host_comm;
51pub mod memory;
52pub mod paging;
53
54#[cfg(feature = "mem_profile")]
56struct ProfiledLockedHeap<const ORDER: usize>(LockedHeap<ORDER>);
57#[cfg(feature = "mem_profile")]
58unsafe impl<const ORDER: usize> alloc::alloc::GlobalAlloc for ProfiledLockedHeap<ORDER> {
59 unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
60 let addr = unsafe { self.0.alloc(layout) };
61 unsafe {
62 core::arch::asm!("out dx, al",
63 in("dx") OutBAction::TraceMemoryAlloc as u16,
64 in("rax") layout.size() as u64,
65 in("rcx") addr as u64);
66 }
67 addr
68 }
69 unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
70 unsafe {
71 core::arch::asm!("out dx, al",
72 in("dx") OutBAction::TraceMemoryFree as u16,
73 in("rax") layout.size() as u64,
74 in("rcx") ptr as u64);
75 self.0.dealloc(ptr, layout)
76 }
77 }
78 unsafe fn alloc_zeroed(&self, layout: core::alloc::Layout) -> *mut u8 {
79 let addr = unsafe { self.0.alloc_zeroed(layout) };
80 unsafe {
81 core::arch::asm!("out dx, al",
82 in("dx") OutBAction::TraceMemoryAlloc as u16,
83 in("rax") layout.size() as u64,
84 in("rcx") addr as u64);
85 }
86 addr
87 }
88 unsafe fn realloc(
89 &self,
90 ptr: *mut u8,
91 layout: core::alloc::Layout,
92 new_size: usize,
93 ) -> *mut u8 {
94 let new_ptr = unsafe { self.0.realloc(ptr, layout, new_size) };
95 unsafe {
96 core::arch::asm!("out dx, al",
97 in("dx") OutBAction::TraceMemoryFree as u16,
98 in("rax") layout.size() as u64,
99 in("rcx") ptr);
100 core::arch::asm!("out dx, al",
101 in("dx") OutBAction::TraceMemoryAlloc as u16,
102 in("rax") new_size as u64,
103 in("rcx") new_ptr);
104 }
105 new_ptr
106 }
107}
108
109#[cfg(not(feature = "mem_profile"))]
111#[global_allocator]
112pub(crate) static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::empty();
113#[cfg(feature = "mem_profile")]
114#[global_allocator]
115pub(crate) static HEAP_ALLOCATOR: ProfiledLockedHeap<32> =
116 ProfiledLockedHeap(LockedHeap::<32>::empty());
117
118pub static mut GUEST_HANDLE: GuestHandle = GuestHandle::new();
119pub(crate) static mut REGISTERED_GUEST_FUNCTIONS: GuestFunctionRegister<GuestFunc> =
120 GuestFunctionRegister::new();
121
122pub static mut OS_PAGE_SIZE: u32 = 0;
127
128#[cfg_attr(not(test), panic_handler)]
134#[allow(clippy::panic)]
135#[allow(dead_code)]
137fn panic(info: &core::panic::PanicInfo) -> ! {
138 _panic_handler(info)
139}
140
141struct HyperlightAbortWriter;
146impl core::fmt::Write for HyperlightAbortWriter {
147 fn write_str(&mut self, s: &str) -> core::fmt::Result {
148 write_abort(s.as_bytes());
149 Ok(())
150 }
151}
152
153#[inline(always)]
154fn _panic_handler(info: &core::panic::PanicInfo) -> ! {
155 let mut w = HyperlightAbortWriter;
156
157 write_abort(&[ErrorCode::UnknownError as u8]);
159
160 let write_res = write!(w, "{}", info);
161 if write_res.is_err() {
162 write_abort("panic: message format failed".as_bytes());
163 }
164
165 write_abort(&[0xFF]);
168 unreachable!();
169}
170
171unsafe extern "C" {
174 fn hyperlight_main();
175 fn srand(seed: u32);
176}
177
178pub(crate) extern "C" fn generic_init(
182 peb_address: u64,
183 seed: u64,
184 ops: u64,
185 max_log_level: u64,
186) -> u64 {
187 unsafe {
188 GUEST_HANDLE = GuestHandle::init(peb_address as *mut HyperlightPEB);
189 #[allow(static_mut_refs)]
190 let peb_ptr = GUEST_HANDLE.peb().unwrap();
191
192 let heap_start = (*peb_ptr).guest_heap.ptr as usize;
193 let heap_size = (*peb_ptr).guest_heap.size as usize;
194 #[cfg(not(feature = "mem_profile"))]
195 let heap_allocator = &HEAP_ALLOCATOR;
196 #[cfg(feature = "mem_profile")]
197 let heap_allocator = &HEAP_ALLOCATOR.0;
198 heap_allocator
199 .try_lock()
200 .expect("Failed to access HEAP_ALLOCATOR")
201 .init(heap_start, heap_size);
202 peb_ptr
203 };
204
205 #[cfg(feature = "trace_guest")]
207 let guest_start_tsc = hyperlight_guest_tracing::invariant_tsc::read_tsc();
208
209 unsafe {
210 let srand_seed = (((peb_address << 8) ^ (seed >> 4)) >> 32) as u32;
211 srand(srand_seed);
213
214 OS_PAGE_SIZE = ops as u32;
215 }
216
217 let guest_log_level_filter =
219 GuestLogFilter::try_from(max_log_level).expect("Invalid log level");
220 init_logger(guest_log_level_filter.into());
221
222 #[cfg(feature = "trace_guest")]
224 if guest_log_level_filter != GuestLogFilter::Off {
225 hyperlight_guest_tracing::init_guest_tracing(
226 guest_start_tsc,
227 guest_log_level_filter.into(),
228 );
229 }
230
231 #[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
235 let _entered = tracing::span!(tracing::Level::INFO, "generic_init").entered();
236
237 #[cfg(feature = "macros")]
238 for registration in __private::GUEST_FUNCTION_INIT {
239 registration();
240 }
241
242 unsafe {
243 hyperlight_main();
244 }
245
246 #[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
249 {
250 _entered.exit();
255
256 hyperlight_guest_tracing::flush();
259 }
260
261 dispatch_function as usize as u64
262}
263
264#[cfg(feature = "macros")]
265#[doc(hidden)]
266pub mod __private {
267 pub use hyperlight_common::func::ResultType;
268 pub use hyperlight_guest::error::HyperlightGuestError;
269 pub use linkme;
270
271 #[linkme::distributed_slice]
272 pub static GUEST_FUNCTION_INIT: [fn()];
273
274 pub trait FromResult {
275 type Output;
276 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self;
277 }
278
279 use alloc::string::String;
280 use alloc::vec::Vec;
281
282 use hyperlight_common::for_each_return_type;
283
284 macro_rules! impl_maybe_unwrap {
285 ($ty:ty, $enum:ident) => {
286 impl FromResult for $ty {
287 type Output = Self;
288 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self {
289 res.unwrap()
292 }
293 }
294
295 impl FromResult for Result<$ty, HyperlightGuestError> {
296 type Output = $ty;
297 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self {
298 res
299 }
300 }
301 };
302 }
303
304 for_each_return_type!(impl_maybe_unwrap);
305}
306
307#[cfg(feature = "macros")]
308pub use hyperlight_guest_macro::{guest_function, host_function};
309
310pub use crate::guest_function::definition::GuestFunc;