#![allow(dead_code)]
pub trait Syscalls {
unsafe fn syscall0(n: i64) -> i64;
unsafe fn syscall1(n: i64, a1: i64) -> i64;
unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64;
unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64;
unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64;
unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64;
unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64;
unsafe fn syscall_noreturn1(n: i64, a1: i64) -> !;
}
pub struct X86_64;
#[cfg(target_arch = "x86_64")]
impl Syscalls for X86_64 {
#[inline]
unsafe fn syscall0(n: i64) -> i64 {
let result: i64;
unsafe {
core::arch::asm!(
"syscall",
inlateout("rax") n => result,
lateout("rcx") _,
lateout("r11") _,
);
}
result
}
#[inline]
unsafe fn syscall1(n: i64, a1: i64) -> i64 {
let result: i64;
unsafe {
core::arch::asm!(
"syscall",
inlateout("rax") n => result,
in("rdi") a1,
lateout("rcx") _,
lateout("r11") _,
);
}
result
}
#[inline]
unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
let result: i64;
unsafe {
core::arch::asm!(
"syscall",
inlateout("rax") n => result,
in("rdi") a1,
in("rsi") a2,
lateout("rcx") _,
lateout("r11") _,
);
}
result
}
#[inline]
unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
let result: i64;
unsafe {
core::arch::asm!(
"syscall",
inlateout("rax") n => result,
in("rdi") a1,
in("rsi") a2,
in("rdx") a3,
lateout("rcx") _,
lateout("r11") _,
);
}
result
}
#[inline]
unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
let result: i64;
unsafe {
core::arch::asm!(
"syscall",
inlateout("rax") n => result,
in("rdi") a1,
in("rsi") a2,
in("rdx") a3,
in("r10") a4,
lateout("rcx") _,
lateout("r11") _,
);
}
result
}
#[inline]
unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
let result: i64;
unsafe {
core::arch::asm!(
"syscall",
inlateout("rax") n => result,
in("rdi") a1,
in("rsi") a2,
in("rdx") a3,
in("r10") a4,
in("r8") a5,
lateout("rcx") _,
lateout("r11") _,
);
}
result
}
#[inline]
unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
let result: i64;
unsafe {
core::arch::asm!(
"syscall",
inlateout("rax") n => result,
in("rdi") a1,
in("rsi") a2,
in("rdx") a3,
in("r10") a4,
in("r8") a5,
in("r9") a6,
lateout("rcx") _,
lateout("r11") _,
);
}
result
}
#[inline]
unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
unsafe {
core::arch::asm!(
"syscall",
in("rax") n,
in("rdi") a1,
options(noreturn)
);
}
}
}
pub struct Aarch64;
#[cfg(target_arch = "aarch64")]
impl Syscalls for Aarch64 {
#[inline(always)]
unsafe fn syscall0(n: i64) -> i64 {
let result: i64;
core::arch::asm!(
"svc #0",
inlateout("x8") n => _,
lateout("x0") result,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall1(n: i64, a1: i64) -> i64 {
let result: i64;
core::arch::asm!(
"svc #0",
inlateout("x8") n => _,
inlateout("x0") a1 => result,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
let result: i64;
core::arch::asm!(
"svc #0",
inlateout("x8") n => _,
inlateout("x0") a1 => result,
inlateout("x1") a2 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
let result: i64;
core::arch::asm!(
"svc #0",
inlateout("x8") n => _,
inlateout("x0") a1 => result,
inlateout("x1") a2 => _,
inlateout("x2") a3 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
let result: i64;
core::arch::asm!(
"svc #0",
inlateout("x8") n => _,
inlateout("x0") a1 => result,
inlateout("x1") a2 => _,
inlateout("x2") a3 => _,
inlateout("x3") a4 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
let result: i64;
core::arch::asm!(
"svc #0",
inlateout("x8") n => _,
inlateout("x0") a1 => result,
inlateout("x1") a2 => _,
inlateout("x2") a3 => _,
inlateout("x3") a4 => _,
inlateout("x4") a5 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
let result: i64;
core::arch::asm!(
"svc #0",
inlateout("x8") n => _,
inlateout("x0") a1 => result,
inlateout("x1") a2 => _,
inlateout("x2") a3 => _,
inlateout("x3") a4 => _,
inlateout("x4") a5 => _,
inlateout("x5") a6 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
core::arch::asm!(
"svc #0",
in("x8") n,
in("x0") a1,
options(noreturn, nostack),
);
}
}
pub struct Riscv64;
#[cfg(target_arch = "riscv64")]
impl Syscalls for Riscv64 {
#[inline(always)]
unsafe fn syscall0(n: i64) -> i64 {
let result: i64;
core::arch::asm!(
"ecall",
inlateout("a7") n => _,
lateout("a0") result,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall1(n: i64, a1: i64) -> i64 {
let result: i64;
core::arch::asm!(
"ecall",
inlateout("a7") n => _,
inlateout("a0") a1 => result,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
let result: i64;
core::arch::asm!(
"ecall",
inlateout("a7") n => _,
inlateout("a0") a1 => result,
inlateout("a1") a2 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
let result: i64;
core::arch::asm!(
"ecall",
inlateout("a7") n => _,
inlateout("a0") a1 => result,
inlateout("a1") a2 => _,
inlateout("a2") a3 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
let result: i64;
core::arch::asm!(
"ecall",
inlateout("a7") n => _,
inlateout("a0") a1 => result,
inlateout("a1") a2 => _,
inlateout("a2") a3 => _,
inlateout("a3") a4 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
let result: i64;
core::arch::asm!(
"ecall",
inlateout("a7") n => _,
inlateout("a0") a1 => result,
inlateout("a1") a2 => _,
inlateout("a2") a3 => _,
inlateout("a3") a4 => _,
inlateout("a4") a5 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
let result: i64;
core::arch::asm!(
"ecall",
inlateout("a7") n => _,
inlateout("a0") a1 => result,
inlateout("a1") a2 => _,
inlateout("a2") a3 => _,
inlateout("a3") a4 => _,
inlateout("a4") a5 => _,
inlateout("a5") a6 => _,
options(nostack),
);
result
}
#[inline(always)]
unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
core::arch::asm!(
"ecall",
in("a7") n,
in("a0") a1,
options(noreturn, nostack),
);
}
}
#[cfg(target_arch = "x86_64")]
pub type Arch = X86_64;
#[cfg(target_arch = "aarch64")]
pub type Arch = Aarch64;
#[cfg(target_arch = "riscv64")]
pub type Arch = Riscv64;
#[cfg(target_arch = "x86_64")]
mod sysnr {
pub const SYS_MMAP: i64 = 9;
}
#[cfg(target_arch = "aarch64")]
mod sysnr {
pub const SYS_MMAP: i64 = 222;
}
#[cfg(target_arch = "riscv64")]
mod sysnr {
pub const SYS_MMAP: i64 = 222;
}
pub use sysnr::*;
#[inline]
pub unsafe fn clear_thread_pointer() {
#[cfg(target_arch = "x86_64")]
unsafe {
const SYS_ARCH_PRCTL: i64 = 158;
const ARCH_SET_FS: i64 = 0x1002;
let _ = <Arch as Syscalls>::syscall2(SYS_ARCH_PRCTL, ARCH_SET_FS, 0);
}
#[cfg(target_arch = "aarch64")]
unsafe {
core::arch::asm!("msr tpidr_el0, {}", in(reg) 0usize, options(nostack));
}
#[cfg(target_arch = "riscv64")]
unsafe {
core::arch::asm!("mv tp, {}", in(reg) 0usize, options(nostack));
}
}
#[inline]
pub unsafe fn sys_mmap(
addr: *mut u8,
length: usize,
prot: i32,
flags: i32,
fd: i32,
offset: i64,
) -> *mut u8 {
unsafe {
<Arch as Syscalls>::syscall6(
SYS_MMAP,
addr as i64,
length as i64,
prot as i64,
flags as i64,
fd as i64,
offset,
) as *mut u8
}
}