pub use moto_sys::syscalls::*;
pub use moto_sys::*;
pub fn num_cpus() -> u32 {
moto_sys::num_cpus()
}
use core::alloc::GlobalAlloc;
use core::alloc::Layout;
struct BackEndAllocator {}
unsafe impl Send for BackEndAllocator {}
unsafe impl Sync for BackEndAllocator {}
unsafe impl GlobalAlloc for BackEndAllocator {
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
const PAGE_4K: u64 = 1 << 12;
assert_eq!(SysMem::PAGE_SIZE_SMALL, PAGE_4K);
let alloc_size = align_up(layout.size() as u64, PAGE_4K);
if let Ok(start) = SysMem::alloc(PAGE_4K, alloc_size >> 12) {
start as usize as *mut u8
} else {
core::ptr::null_mut()
}
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: core::alloc::Layout) {
SysMem::free(ptr as usize as u64).unwrap()
}
}
static BACK_END: BackEndAllocator = BackEndAllocator {};
static FRUSA: frusa::Frusa4K = frusa::Frusa4K::new(&BACK_END);
pub unsafe fn alloc(layout: Layout) -> *mut u8 {
FRUSA.alloc(layout)
}
pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
FRUSA.alloc_zeroed(layout)
}
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
FRUSA.dealloc(ptr, layout)
}
pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
FRUSA.realloc(ptr, layout, new_size)
}
#[linkage = "weak"]
#[no_mangle]
pub extern "C" fn moturus_runtime_start() {}
#[cfg(not(test))]
pub fn moturus_start_rt() {
moturus_runtime_start();
if crate::fs::init().is_err() {
crate::util::moturus_log!("Failed to initialize FS. Exiting.");
exit(-1);
}
}
pub fn sys_exit(code: u64) -> ! {
SysCpu::exit(code)
}
pub fn exit(code: i32) -> ! {
let code_u32: u32 = unsafe { core::mem::transmute::<i32, u32>(code) };
sys_exit(code_u32 as u64)
}
#[cfg(not(test))]
use core::panic::PanicInfo;
#[cfg(not(test))]
#[no_mangle]
pub fn moturus_log_panic(info: &PanicInfo<'_>) {
if moturus_log_panics_to_kernel() {
SysMem::log("PANIC").ok(); let msg = alloc::format!("PANIC: {}", info);
SysMem::log(msg.as_str()).ok();
log_backtrace(crate::rt_api::process::binary().unwrap_or("<unknown>"));
} else {
use core::fmt::Write;
let mut stderr = super::stdio::StderrRt::new();
let _ = stderr.write_str("PANIC\n"); let msg = alloc::format!("PANIC: {}\n", info);
let _ = stderr.write_str(msg.as_str());
log_backtrace(crate::rt_api::process::binary().unwrap_or("<unknown>"));
let _ = stderr.flush();
crate::thread::sleep(core::time::Duration::from_millis(10));
}
}
#[cfg(not(test))]
#[panic_handler]
fn _panic(info: &PanicInfo<'_>) -> ! {
moturus_log_panic(info);
sys_exit(u64::MAX)
}
const BT_DEPTH: usize = 64;
fn get_backtrace() -> [u64; BT_DEPTH] {
let mut backtrace: [u64; BT_DEPTH] = [0; BT_DEPTH];
let mut rbp: u64;
unsafe {
core::arch::asm!(
"mov rdx, rbp", out("rdx") rbp, options(nomem, nostack)
)
};
if rbp == 0 {
return backtrace;
}
rbp = unsafe { *(rbp as *mut u64) };
let mut prev = 0_u64;
for idx in 0..BT_DEPTH {
if prev == rbp {
break;
}
if rbp == 0 {
break;
}
if rbp < 1024 * 64 {
break;
}
prev = rbp;
unsafe {
backtrace[idx] = *((rbp + 8) as *mut u64);
rbp = *(rbp as *mut u64);
}
}
backtrace
}
pub fn log_backtrace(binary: &str) {
use core::fmt::Write;
let mut writer = alloc::string::String::with_capacity(256);
let backtrace = get_backtrace();
write!(&mut writer, "backtrace: run \n\naddr2line -e {}", binary).ok();
for addr in backtrace {
if addr == 0 {
break;
}
if addr > (1_u64 << 40) {
break;
}
write!(&mut writer, " \\\n 0x{:x}", addr).ok();
}
let _ = write!(&mut writer, "\n\n");
if moturus_log_panics_to_kernel() {
let _ = SysMem::log(writer.as_str());
} else {
let _ = super::stdio::StderrRt::new().write_str(writer.as_str());
}
}
#[linkage = "weak"]
#[no_mangle]
pub extern "C" fn moturus_log_panics_to_kernel() -> bool {
false
}