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
122const VERSION_STR: &str = env!("CARGO_PKG_VERSION");
123
124#[used]
127#[unsafe(link_section = ".note.hyperlight-version")]
128static HYPERLIGHT_VERSION_NOTE: hyperlight_common::version_note::ElfNote<
129 {
130 hyperlight_common::version_note::padded_name_size(
131 hyperlight_common::version_note::HYPERLIGHT_NOTE_NAME.len() + 1,
132 )
133 },
134 { hyperlight_common::version_note::padded_desc_size(VERSION_STR.len() + 1) },
135> = hyperlight_common::version_note::ElfNote::new(
136 hyperlight_common::version_note::HYPERLIGHT_NOTE_NAME,
137 VERSION_STR,
138 hyperlight_common::version_note::HYPERLIGHT_NOTE_TYPE,
139);
140
141pub static mut OS_PAGE_SIZE: u32 = 0;
146
147#[cfg_attr(not(test), panic_handler)]
153#[allow(clippy::panic)]
154#[allow(dead_code)]
156fn panic(info: &core::panic::PanicInfo) -> ! {
157 _panic_handler(info)
158}
159
160struct HyperlightAbortWriter;
165impl core::fmt::Write for HyperlightAbortWriter {
166 fn write_str(&mut self, s: &str) -> core::fmt::Result {
167 write_abort(s.as_bytes());
168 Ok(())
169 }
170}
171
172#[inline(always)]
173fn _panic_handler(info: &core::panic::PanicInfo) -> ! {
174 let mut w = HyperlightAbortWriter;
175
176 write_abort(&[ErrorCode::UnknownError as u8]);
178
179 let write_res = write!(w, "{}", info);
180 if write_res.is_err() {
181 write_abort("panic: message format failed".as_bytes());
182 }
183
184 write_abort(&[0xFF]);
187 unreachable!();
188}
189
190unsafe extern "C" {
193 fn hyperlight_main();
194 fn srand(seed: u32);
195}
196
197pub(crate) extern "C" fn generic_init(
201 peb_address: u64,
202 seed: u64,
203 ops: u64,
204 max_log_level: u64,
205) -> u64 {
206 unsafe {
207 GUEST_HANDLE = GuestHandle::init(peb_address as *mut HyperlightPEB);
208 #[allow(static_mut_refs)]
209 let peb_ptr = GUEST_HANDLE.peb().unwrap();
210
211 let heap_start = (*peb_ptr).guest_heap.ptr as usize;
212 let heap_size = (*peb_ptr).guest_heap.size as usize;
213 #[cfg(not(feature = "mem_profile"))]
214 let heap_allocator = &HEAP_ALLOCATOR;
215 #[cfg(feature = "mem_profile")]
216 let heap_allocator = &HEAP_ALLOCATOR.0;
217 heap_allocator
218 .try_lock()
219 .expect("Failed to access HEAP_ALLOCATOR")
220 .init(heap_start, heap_size);
221 peb_ptr
222 };
223
224 #[cfg(feature = "trace_guest")]
226 let guest_start_tsc = hyperlight_guest_tracing::invariant_tsc::read_tsc();
227
228 unsafe {
229 let srand_seed = (((peb_address << 8) ^ (seed >> 4)) >> 32) as u32;
230 srand(srand_seed);
232
233 OS_PAGE_SIZE = ops as u32;
234 }
235
236 let guest_log_level_filter =
238 GuestLogFilter::try_from(max_log_level).expect("Invalid log level");
239 init_logger(guest_log_level_filter.into());
240
241 #[cfg(feature = "trace_guest")]
243 if guest_log_level_filter != GuestLogFilter::Off {
244 hyperlight_guest_tracing::init_guest_tracing(
245 guest_start_tsc,
246 guest_log_level_filter.into(),
247 );
248 }
249
250 #[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
254 let _entered = tracing::span!(tracing::Level::INFO, "generic_init").entered();
255
256 #[cfg(feature = "macros")]
257 for registration in __private::GUEST_FUNCTION_INIT {
258 registration();
259 }
260
261 unsafe {
262 hyperlight_main();
263 }
264
265 #[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
268 {
269 _entered.exit();
274
275 hyperlight_guest_tracing::flush();
278 }
279
280 dispatch_function as usize as u64
281}
282
283#[cfg(feature = "macros")]
284#[doc(hidden)]
285pub mod __private {
286 pub use hyperlight_common::func::ResultType;
287 pub use hyperlight_guest::error::HyperlightGuestError;
288 pub use linkme;
289
290 #[linkme::distributed_slice]
291 pub static GUEST_FUNCTION_INIT: [fn()];
292
293 pub trait FromResult {
294 type Output;
295 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self;
296 }
297
298 use alloc::string::String;
299 use alloc::vec::Vec;
300
301 use hyperlight_common::for_each_return_type;
302
303 macro_rules! impl_maybe_unwrap {
304 ($ty:ty, $enum:ident) => {
305 impl FromResult for $ty {
306 type Output = Self;
307 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self {
308 res.unwrap()
311 }
312 }
313
314 impl FromResult for Result<$ty, HyperlightGuestError> {
315 type Output = $ty;
316 fn from_result(res: Result<Self::Output, HyperlightGuestError>) -> Self {
317 res
318 }
319 }
320 };
321 }
322
323 for_each_return_type!(impl_maybe_unwrap);
324}
325
326#[cfg(feature = "macros")]
327pub use hyperlight_guest_macro::{guest_function, host_function};
328
329pub use crate::guest_function::definition::GuestFunc;