use core::ffi::{CStr, c_char};
use hyperlight_common::outb::OutBAction;
#[cfg_attr(target_arch = "x86_64", path = "arch/amd64/exit.rs")]
#[cfg_attr(target_arch = "x86", path = "arch/amd64/exit.rs")]
#[cfg_attr(target_arch = "aarch64", path = "arch/aarch64/exit.rs")]
mod arch;
pub(crate) use arch::out32;
#[unsafe(no_mangle)]
pub extern "C" fn abort() -> ! {
abort_with_code(&[0, 0xFF])
}
pub fn abort_with_code(code: &[u8]) -> ! {
#[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
hyperlight_guest_tracing::end_trace();
outb(OutBAction::Abort as u16, code);
outb(OutBAction::Abort as u16, &[0xFF]); unreachable!()
}
pub unsafe fn abort_with_code_and_message(code: &[u8], message_ptr: *const c_char) -> ! {
#[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
hyperlight_guest_tracing::end_trace();
unsafe {
outb(OutBAction::Abort as u16, code);
let message_bytes = CStr::from_ptr(message_ptr).to_bytes();
outb(OutBAction::Abort as u16, message_bytes);
outb(OutBAction::Abort as u16, &[0xFF]);
unreachable!()
}
}
pub fn write_abort(code: &[u8]) {
outb(OutBAction::Abort as u16, code);
}
pub(crate) fn outb(port: u16, data: &[u8]) {
unsafe {
let mut i = 0;
while i < data.len() {
let remaining = data.len() - i;
let chunk_len = remaining.min(3);
let mut chunk = [0u8; 4];
chunk[0] = chunk_len as u8;
chunk[1..1 + chunk_len].copy_from_slice(&data[i..i + chunk_len]);
let val = u32::from_le_bytes(chunk);
out32(port, val);
i += chunk_len;
}
}
}
pub fn debug_print(msg: &str) {
for byte in msg.bytes() {
unsafe {
out32(OutBAction::DebugPrint as u16, byte as u32);
}
}
}