Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions hermit-builtins/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions hermit-builtins/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,25 @@ edition = "2024"
[dependencies]
libm = "0.2"

#! ## MASOS dependencies
align-address = { version = "0.4", optional = true }
libc = { package = "hermit-abi", version = "0.5", optional = true }
spinning_top = { version = "0.3", optional = true }
talc = { version = "5", default-features = false, optional = true }

[lib]
crate-type = ["staticlib"]
harness = false

[features]
default = []
masos = [
"dep:align-address",
"dep:libc",
"dep:spinning_top",
"dep:talc",
]

[profile.dist]
inherits = "release"
lto = "thin"
Expand Down
7 changes: 7 additions & 0 deletions hermit-builtins/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
#![no_std]
#![no_main]
#![feature(linkage)]
#![cfg_attr(feature = "masos", feature(macro_metavar_expr_concat))]
#![cfg_attr(feature = "masos", feature(thread_local))]

#[cfg(feature = "masos")]
extern crate alloc;

#[cfg(feature = "masos")]
mod masos;
pub mod math;

#[panic_handler]
Expand Down
100 changes: 100 additions & 0 deletions hermit-builtins/src/masos/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use alloc::alloc::{alloc, alloc_zeroed, dealloc, realloc};
use core::alloc::Layout;
use core::ptr::NonNull;

use align_address::Align;
use spinning_top::RawSpinlock;
use talc::TalcLock;
use talc::base::Talc;
use talc::base::binning::Binning;
use talc::source::Source;

#[global_allocator]
static TALC: TalcLock<RawSpinlock, Malloc> = TalcLock::new(Malloc::new());

#[derive(Debug)]
struct Malloc {
heap_end: Option<NonNull<u8>>,
}

impl Malloc {
// From dlmalloc-rs. Also the size of a Wasm page.
const GRANULARITY: usize = 64 * 1024;

const fn new() -> Self {
Self { heap_end: None }
}
}

unsafe impl Send for Malloc {}

unsafe impl Source for Malloc {
fn acquire<B: Binning>(talc: &mut Talc<Self, B>, layout: Layout) -> Result<(), ()> {
let size = layout.size().align_up(Self::GRANULARITY);
let mut base = talc
.source
.heap_end
.map(NonNull::as_ptr)
.unwrap_or_default();

let ret = unsafe { super::sys_mmap(size, libc::PROT_READ | libc::PROT_WRITE, &mut base) };
if ret != 0 {
return Err(());
}

let top = unsafe { base.add(size) };
let new_end = match talc.source.heap_end {
None => unsafe { talc.claim(base, size) },
Some(heap_end) => unsafe { Some(talc.extend(heap_end, top)) },
};
assert_eq!(new_end, NonNull::new(top));
talc.source.heap_end = new_end;

Ok(())
}
}

#[unsafe(no_mangle)]
unsafe extern "C" fn sys_alloc(size: usize, align: usize) -> *mut u8 {
unsafe { alloc(layout_from_size_align(size, align)) }
}

#[unsafe(no_mangle)]
unsafe extern "C" fn sys_dealloc(ptr: *mut u8, size: usize, align: usize) {
unsafe { dealloc(ptr, layout_from_size_align(size, align)) }
}

#[unsafe(no_mangle)]
unsafe extern "C" fn sys_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
unsafe { alloc_zeroed(layout_from_size_align(size, align)) }
}

#[unsafe(no_mangle)]
unsafe extern "C" fn sys_realloc(
ptr: *mut u8,
size: usize,
align: usize,
new_size: usize,
) -> *mut u8 {
unsafe { realloc(ptr, layout_from_size_align(size, align), new_size) }
}

/// Deprecated
#[unsafe(no_mangle)]
unsafe extern "C" fn sys_malloc(size: usize, align: usize) -> *mut u8 {
unsafe { alloc(layout_from_size_align(size, align)) }
}

/// Deprecated
#[unsafe(no_mangle)]
unsafe extern "C" fn sys_free(ptr: *mut u8, size: usize, align: usize) {
unsafe { dealloc(ptr, layout_from_size_align(size, align)) }
}

unsafe fn layout_from_size_align(size: usize, align: usize) -> Layout {
if cfg!(debug_assertions) {
Layout::from_size_align(size, align).unwrap()
} else {
unsafe { Layout::from_size_align_unchecked(size, align) }
}
}
122 changes: 122 additions & 0 deletions hermit-builtins/src/masos/arch/aarch64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use core::arch::asm;

#[inline]
pub(crate) unsafe fn syscall0(nr: usize) -> usize {
let r0;
unsafe {
asm!(
"svc 0",
in("x8") nr,
lateout("x0") r0,
options(preserves_flags),
);
}
r0
}

#[inline]
pub(crate) unsafe fn syscall1(nr: usize, a0: usize) -> usize {
let r0;
unsafe {
asm!(
"svc 0",
in("x8") nr,
inlateout("x0") a0 => r0,
options(preserves_flags),
);
}
r0
}

#[inline]
pub(crate) unsafe fn syscall2(nr: usize, a0: usize, a1: usize) -> usize {
let r0;
unsafe {
asm!(
"svc 0",
in("x8") nr,
inlateout("x0") a0 => r0,
in("x1") a1,
options(preserves_flags),
);
}
r0
}

#[inline]
pub(crate) unsafe fn syscall3(nr: usize, a0: usize, a1: usize, a2: usize) -> usize {
let r0;
unsafe {
asm!(
"svc 0",
in("x8") nr,
inlateout("x0") a0 => r0,
in("x1") a1,
in("x2") a2,
options(preserves_flags),
);
}
r0
}

#[inline]
pub(crate) unsafe fn syscall4(nr: usize, a0: usize, a1: usize, a2: usize, a3: usize) -> usize {
let r0;
unsafe {
asm!(
"svc 0",
in("x8") nr,
inlateout("x0") a0 => r0,
in("x1") a1,
in("x2") a2,
in("x3") a3,
options(preserves_flags),
);
}
r0
}

#[inline]
pub(crate) unsafe fn syscall5(nr: usize, a0: usize, a1: usize, a2: usize, a3: usize, a4: usize) -> usize {
let r0;
unsafe {
asm!(
"svc 0",
in("x8") nr,
inlateout("x0") a0 => r0,
in("x1") a1,
in("x2") a2,
in("x3") a3,
in("x4") a4,
options(preserves_flags),
);
}
r0
}

#[inline]
pub(crate) unsafe fn syscall6(
nr: usize,
a0: usize,
a1: usize,
a2: usize,
a3: usize,
a4: usize,
a5: usize,
) -> usize {
let r0;
unsafe {
asm!(
"svc 0",
in("x8") nr,
inlateout("x0") a0 => r0,
in("x1") a1,
in("x2") a2,
in("x3") a3,
in("x4") a4,
in("x5") a5,
options(preserves_flags),
);
}
r0
}
62 changes: 62 additions & 0 deletions hermit-builtins/src/masos/arch/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
cfg_select! {
target_arch = "aarch64" => {
mod aarch64;
pub(crate) use aarch64::*;
}
target_arch = "x86_64" => {
mod x86_64;
pub(crate) use x86_64::*;
}
_ => {}
}

macro_rules! syscall {
($nr:expr $(,)?) => {
$crate::masos::arch::syscall0($nr as usize)
};

($nr:expr, $a0:expr $(,)?) => {
$crate::masos::arch::syscall1($nr as usize, $a0 as usize)
};

($nr:expr, $a0:expr, $a1:expr $(,)?) => {
$crate::masos::arch::syscall2($nr as usize, $a0 as usize, $a1 as usize)
};

($nr:expr, $a0:expr, $a1:expr, $a2:expr $(,)?) => {
$crate::masos::arch::syscall3($nr as usize, $a0 as usize, $a1 as usize, $a2 as usize)
};

($nr:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr $(,)?) => {
$crate::masos::arch::syscall4(
$nr as usize,
$a0 as usize,
$a1 as usize,
$a2 as usize,
$a3 as usize,
)
};

($nr:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr $(,)?) => {
$crate::masos::arch::syscall5(
$nr as usize,
$a0 as usize,
$a1 as usize,
$a2 as usize,
$a3 as usize,
$a4 as usize,
)
};

($nr:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr $(,)?) => {
$crate::masos::arch::syscall6(
$nr as usize,
$a0 as usize,
$a1 as usize,
$a2 as usize,
$a3 as usize,
$a4 as usize,
$a5 as usize,
)
};
}
Loading
Loading