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