hyperlight_guest_bin/
lib.rs1#![no_std]
17
18extern crate alloc;
20
21use core::fmt::Write;
22
23use buddy_system_allocator::LockedHeap;
24#[cfg(target_arch = "x86_64")]
25use exceptions::{gdt::load_gdt, idtr::load_idt};
26use guest_function::call::dispatch_function;
27use guest_function::register::GuestFunctionRegister;
28use guest_logger::init_logger;
29use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
30use hyperlight_common::mem::HyperlightPEB;
31#[cfg(feature = "mem_profile")]
32use hyperlight_common::outb::OutBAction;
33use hyperlight_guest::exit::{halt, write_abort};
34use hyperlight_guest::guest_handle::handle::GuestHandle;
35use hyperlight_guest_tracing::{trace, trace_function};
36use log::LevelFilter;
37use spin::Once;
38
39#[cfg(target_arch = "x86_64")]
41pub mod exceptions {
42 pub(super) mod gdt;
43 pub mod handler;
44 mod idt;
45 pub(super) mod idtr;
46 mod interrupt_entry;
47}
48pub mod guest_err;
49pub mod guest_function {
50 pub(super) mod call;
51 pub mod definition;
52 pub mod register;
53}
54
55pub mod guest_logger;
56pub mod host_comm;
57pub mod memory;
58pub mod paging;
59
60#[cfg(feature = "mem_profile")]
62struct ProfiledLockedHeap<const ORDER: usize>(LockedHeap<ORDER>);
63#[cfg(feature = "mem_profile")]
64unsafe impl<const ORDER: usize> alloc::alloc::GlobalAlloc for ProfiledLockedHeap<ORDER> {
65 unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
66 let addr = unsafe { self.0.alloc(layout) };
67 unsafe {
68 core::arch::asm!("out dx, al",
69 in("dx") OutBAction::TraceMemoryAlloc as u16,
70 in("rax") layout.size() as u64,
71 in("rcx") addr as u64);
72 }
73 addr
74 }
75 unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
76 unsafe {
77 core::arch::asm!("out dx, al",
78 in("dx") OutBAction::TraceMemoryFree as u16,
79 in("rax") layout.size() as u64,
80 in("rcx") ptr as u64);
81 self.0.dealloc(ptr, layout)
82 }
83 }
84 unsafe fn alloc_zeroed(&self, layout: core::alloc::Layout) -> *mut u8 {
85 let addr = unsafe { self.0.alloc_zeroed(layout) };
86 unsafe {
87 core::arch::asm!("out dx, al",
88 in("dx") OutBAction::TraceMemoryAlloc as u16,
89 in("rax") layout.size() as u64,
90 in("rcx") addr as u64);
91 }
92 addr
93 }
94 unsafe fn realloc(
95 &self,
96 ptr: *mut u8,
97 layout: core::alloc::Layout,
98 new_size: usize,
99 ) -> *mut u8 {
100 let new_ptr = unsafe { self.0.realloc(ptr, layout, new_size) };
101 unsafe {
102 core::arch::asm!("out dx, al",
103 in("dx") OutBAction::TraceMemoryFree as u16,
104 in("rax") layout.size() as u64,
105 in("rcx") ptr);
106 core::arch::asm!("out dx, al",
107 in("dx") OutBAction::TraceMemoryAlloc as u16,
108 in("rax") new_size as u64,
109 in("rcx") new_ptr);
110 }
111 new_ptr
112 }
113}
114
115#[cfg(not(feature = "mem_profile"))]
117#[global_allocator]
118pub(crate) static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::empty();
119#[cfg(feature = "mem_profile")]
120#[global_allocator]
121pub(crate) static HEAP_ALLOCATOR: ProfiledLockedHeap<32> =
122 ProfiledLockedHeap(LockedHeap::<32>::empty());
123
124pub(crate) static mut GUEST_HANDLE: GuestHandle = GuestHandle::new();
125pub(crate) static mut REGISTERED_GUEST_FUNCTIONS: GuestFunctionRegister =
126 GuestFunctionRegister::new();
127
128pub static mut MIN_STACK_ADDRESS: u64 = 0;
129
130pub static mut OS_PAGE_SIZE: u32 = 0;
131
132#[cfg_attr(not(test), panic_handler)]
138#[allow(clippy::panic)]
139#[allow(dead_code)]
141fn panic(info: &core::panic::PanicInfo) -> ! {
142 _panic_handler(info)
143}
144
145struct HyperlightAbortWriter;
150impl core::fmt::Write for HyperlightAbortWriter {
151 fn write_str(&mut self, s: &str) -> core::fmt::Result {
152 write_abort(s.as_bytes());
153 Ok(())
154 }
155}
156
157#[inline(always)]
158fn _panic_handler(info: &core::panic::PanicInfo) -> ! {
159 let mut w = HyperlightAbortWriter;
160
161 write_abort(&[ErrorCode::UnknownError as u8]);
163
164 let write_res = write!(w, "{}", info);
165 if write_res.is_err() {
166 write_abort("panic: message format failed".as_bytes());
167 }
168
169 write_abort(&[0xFF]);
172 unreachable!();
173}
174
175unsafe extern "C" {
178 fn hyperlight_main();
179 fn srand(seed: u32);
180}
181
182static INIT: Once = Once::new();
183
184#[unsafe(no_mangle)]
185#[trace_function]
186pub extern "C" fn entrypoint(peb_address: u64, seed: u64, ops: u64, max_log_level: u64) {
187 if peb_address == 0 {
188 panic!("PEB address is null");
189 }
190
191 INIT.call_once(|| {
192 unsafe {
193 GUEST_HANDLE = GuestHandle::init(peb_address as *mut HyperlightPEB);
194 #[allow(static_mut_refs)]
195 let peb_ptr = GUEST_HANDLE.peb().unwrap();
196
197 let srand_seed = (((peb_address << 8) ^ (seed >> 4)) >> 32) as u32;
198
199 srand(srand_seed);
201
202 MIN_STACK_ADDRESS = (*peb_ptr).guest_stack.min_user_stack_address;
206
207 #[cfg(target_arch = "x86_64")]
208 {
209 load_gdt();
211 load_idt();
212 }
213
214 let heap_start = (*peb_ptr).guest_heap.ptr as usize;
215 let heap_size = (*peb_ptr).guest_heap.size as usize;
216 #[cfg(not(feature = "mem_profile"))]
217 let heap_allocator = &HEAP_ALLOCATOR;
218 #[cfg(feature = "mem_profile")]
219 let heap_allocator = &HEAP_ALLOCATOR.0;
220 heap_allocator
221 .try_lock()
222 .expect("Failed to access HEAP_ALLOCATOR")
223 .init(heap_start, heap_size);
224
225 OS_PAGE_SIZE = ops as u32;
226
227 (*peb_ptr).guest_function_dispatch_ptr = dispatch_function as usize as u64;
228
229 let max_log_level = LevelFilter::iter()
231 .nth(max_log_level as usize)
232 .expect("Invalid log level");
233 init_logger(max_log_level);
234
235 trace!("hyperlight_main",
236 hyperlight_main();
237 );
238 }
239 });
240
241 halt();
242}