mirror of
https://github.com/NotAShelf/microfetch.git
synced 2026-04-26 10:39:54 +00:00
Merge pull request #66 from amaanq/arch
Some checks failed
Rust / Test on aarch64-unknown-linux-gnu (push) Has been cancelled
Rust / Test on armv7-unknown-linux-gnueabihf (push) Has been cancelled
Rust / Test on i686-unknown-linux-gnu (push) Has been cancelled
Rust / Test on loongarch64-unknown-linux-gnu (push) Has been cancelled
Rust / Test on powerpc-unknown-linux-gnu (push) Has been cancelled
Rust / Test on powerpc64-unknown-linux-gnu (push) Has been cancelled
Rust / Test on powerpc64le-unknown-linux-gnu (push) Has been cancelled
Rust / Test on riscv64gc-unknown-linux-gnu (push) Has been cancelled
Rust / Test on s390x-unknown-linux-gnu (push) Has been cancelled
Rust / Test on sparc64-unknown-linux-gnu (push) Has been cancelled
Rust / Test on mips-unknown-linux-gnu (push) Has been cancelled
Rust / Test on mips64-unknown-linux-gnuabi64 (push) Has been cancelled
Rust / Test on riscv32gc-unknown-linux-gnu (push) Has been cancelled
Rust / Test on x86_64-unknown-linux-gnu (push) Has been cancelled
Some checks failed
Rust / Test on aarch64-unknown-linux-gnu (push) Has been cancelled
Rust / Test on armv7-unknown-linux-gnueabihf (push) Has been cancelled
Rust / Test on i686-unknown-linux-gnu (push) Has been cancelled
Rust / Test on loongarch64-unknown-linux-gnu (push) Has been cancelled
Rust / Test on powerpc-unknown-linux-gnu (push) Has been cancelled
Rust / Test on powerpc64-unknown-linux-gnu (push) Has been cancelled
Rust / Test on powerpc64le-unknown-linux-gnu (push) Has been cancelled
Rust / Test on riscv64gc-unknown-linux-gnu (push) Has been cancelled
Rust / Test on s390x-unknown-linux-gnu (push) Has been cancelled
Rust / Test on sparc64-unknown-linux-gnu (push) Has been cancelled
Rust / Test on mips-unknown-linux-gnu (push) Has been cancelled
Rust / Test on mips64-unknown-linux-gnuabi64 (push) Has been cancelled
Rust / Test on riscv32gc-unknown-linux-gnu (push) Has been cancelled
Rust / Test on x86_64-unknown-linux-gnu (push) Has been cancelled
arch: add loongarch64, s390x, powerpc64, powerpc, armv7, riscv32, sparc64, sparc32, mips64, mips32, and i686 support
This commit is contained in:
commit
6c7bc1bee2
20 changed files with 3058 additions and 508 deletions
58
.github/workflows/rust.yml
vendored
58
.github/workflows/rust.yml
vendored
|
|
@ -16,10 +16,47 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- x86_64-unknown-linux-gnu
|
||||
- aarch64-unknown-linux-gnu
|
||||
- riscv64gc-unknown-linux-gnu
|
||||
include:
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
toolchain: stable
|
||||
- target: aarch64-unknown-linux-gnu
|
||||
toolchain: stable
|
||||
- target: riscv64gc-unknown-linux-gnu
|
||||
toolchain: stable
|
||||
- target: loongarch64-unknown-linux-gnu
|
||||
toolchain: stable
|
||||
- target: s390x-unknown-linux-gnu
|
||||
toolchain: stable
|
||||
# powerpc64 uses experimental asm features
|
||||
- target: powerpc64le-unknown-linux-gnu
|
||||
toolchain: nightly
|
||||
- target: powerpc64-unknown-linux-gnu
|
||||
toolchain: nightly
|
||||
- target: armv7-unknown-linux-gnueabihf
|
||||
toolchain: stable
|
||||
# riscv32 is tier-3
|
||||
- target: riscv32gc-unknown-linux-gnu
|
||||
toolchain: nightly
|
||||
components: rust-src
|
||||
build_std: true
|
||||
# sparc64 uses experimental asm features
|
||||
- target: sparc64-unknown-linux-gnu
|
||||
toolchain: nightly
|
||||
# mips64 is tier-3 and uses experimental asm features
|
||||
- target: mips64-unknown-linux-gnuabi64
|
||||
toolchain: nightly
|
||||
components: rust-src
|
||||
build_std: true
|
||||
- target: i686-unknown-linux-gnu
|
||||
toolchain: stable
|
||||
# powerpc uses experimental asm features
|
||||
- target: powerpc-unknown-linux-gnu
|
||||
toolchain: nightly
|
||||
# mips is tier-3 and uses experimental asm features
|
||||
- target: mips-unknown-linux-gnu
|
||||
toolchain: nightly
|
||||
components: rust-src
|
||||
build_std: true
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
|
|
@ -28,9 +65,14 @@ jobs:
|
|||
- name: "Setup Rust toolchain"
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
toolchain: ${{ matrix.toolchain }}
|
||||
components: ${{ matrix.components || '' }}
|
||||
rustflags: ""
|
||||
|
||||
- name: "Add Rust target"
|
||||
if: ${{ !matrix.build_std }}
|
||||
run: rustup target add ${{ matrix.target }}
|
||||
|
||||
- name: "Make Mold the default linker"
|
||||
uses: rui314/setup-mold@v1
|
||||
|
||||
|
|
@ -40,7 +82,9 @@ jobs:
|
|||
target: ${{ matrix.target }}
|
||||
|
||||
- name: "Build"
|
||||
run: cargo build --verbose
|
||||
run: cargo build --verbose --target ${{ matrix.target }} ${{ matrix.build_std && '-Z build-std=core,alloc,panic_abort' || '' }} ${{ matrix.extra_args || '' }}
|
||||
|
||||
# tier-3 targets have no prebuilt std and tests are arch-agnostic, so
|
||||
# run them against the host toolchain instead of the cross target.
|
||||
- name: "Run tests"
|
||||
run: cargo test --workspace --exclude microfetch --verbose
|
||||
run: cargo test --workspace --exclude microfetch --verbose ${{ matrix.build_std && '--target x86_64-unknown-linux-gnu' || '' }}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ resolver = "3"
|
|||
authors = [ "NotAShelf <raf@notashelf.dev>" ]
|
||||
edition = "2024"
|
||||
license = "GPL-3.0"
|
||||
rust-version = "1.92.0"
|
||||
rust-version = "1.95.0"
|
||||
version = "1.1.0"
|
||||
|
||||
[workspace.dependencies]
|
||||
|
|
|
|||
164
crates/asm/src/aarch64.rs
Normal file
164
crates/asm/src/aarch64.rs
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
//! Syscall implementations for `aarch64`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let fd: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 56i64, // SYS_openat
|
||||
in("x0") -100i32, // AT_FDCWD
|
||||
in("x1") path,
|
||||
in("x2") flags,
|
||||
in("x3") 0i32, // mode
|
||||
lateout("x0") fd,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
fd as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 63i64, // SYS_read
|
||||
in("x0") fd,
|
||||
in("x1") buf,
|
||||
in("x2") count,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 64i64, // SYS_write
|
||||
in("x0") fd,
|
||||
in("x1") buf,
|
||||
in("x2") count,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 57i64, // SYS_close
|
||||
in("x0") fd,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 160i64, // SYS_uname
|
||||
in("x0") buf,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 43i64, // SYS_statfs
|
||||
in("x0") path,
|
||||
in("x1") buf,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 179_i64, // __NR_sysinfo
|
||||
in("x0") info,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 123i64, // __NR_sched_getaffinity
|
||||
in("x0") pid,
|
||||
in("x1") mask_size,
|
||||
in("x2") mask,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 93i64, // SYS_exit
|
||||
in("x0") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
140
crates/asm/src/arm.rs
Normal file
140
crates/asm/src/arm.rs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
//! Syscall implementations for `arm`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("r7") 5i32, // SYS_open
|
||||
in("r0") path,
|
||||
in("r1") flags,
|
||||
in("r2") 0i32, // mode
|
||||
lateout("r0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("r7") 3i32, // SYS_read
|
||||
in("r0") fd,
|
||||
in("r1") buf,
|
||||
in("r2") count,
|
||||
lateout("r0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("r7") 4i32, // SYS_write
|
||||
in("r0") fd,
|
||||
in("r1") buf,
|
||||
in("r2") count,
|
||||
lateout("r0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("r7") 6i32, // SYS_close
|
||||
in("r0") fd,
|
||||
lateout("r0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("r7") 122i32, // SYS_newuname
|
||||
in("r0") buf,
|
||||
lateout("r0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("r7") 266i32, // SYS_statfs64
|
||||
in("r0") path,
|
||||
in("r1") core::mem::size_of::<StatfsBuf>(),
|
||||
in("r2") buf,
|
||||
lateout("r0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("r7") 116_i32, // __NR_sysinfo
|
||||
in("r0") info,
|
||||
lateout("r0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
i64::from(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("r7") 242i32, // __NR_sched_getaffinity
|
||||
in("r0") pid,
|
||||
in("r1") mask_size,
|
||||
in("r2") mask,
|
||||
lateout("r0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("r7") 1i32, // SYS_exit
|
||||
in("r0") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,19 +5,39 @@
|
|||
//! What do you mean I wasted two whole hours to make the program only 100µs
|
||||
//! faster?
|
||||
//!
|
||||
//! Supports `x86_64`, `aarch64`, and `riscv64` architectures.
|
||||
//! Supports `x86_64`, `aarch64`, `riscv64`, `loongarch64`, `s390x`,
|
||||
//! `powerpc64`, `arm` (armv7), `riscv32`, `sparc64`, `mips64`, `x86` (i686),
|
||||
//! `powerpc` (ppc32), `sparc` (sparc32), and `mips` (O32) architectures.
|
||||
|
||||
#![no_std]
|
||||
#![cfg_attr(
|
||||
any(
|
||||
target_arch = "sparc64",
|
||||
target_arch = "sparc",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips"
|
||||
),
|
||||
feature(asm_experimental_arch)
|
||||
)]
|
||||
|
||||
// Ensure we're compiling for a supported architecture.
|
||||
#[cfg(not(any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64"
|
||||
)))]
|
||||
compile_error!(
|
||||
"Unsupported architecture: only x86_64, aarch64, and riscv64 are supported"
|
||||
);
|
||||
// Per-arch syscall implementations live in their own module files.
|
||||
core::cfg_select! {
|
||||
target_arch = "x86_64" => { #[path = "x86_64.rs" ] mod arch; }
|
||||
target_arch = "aarch64" => { #[path = "aarch64.rs" ] mod arch; }
|
||||
target_arch = "riscv64" => { #[path = "riscv64.rs" ] mod arch; }
|
||||
target_arch = "loongarch64" => { #[path = "loongarch64.rs"] mod arch; }
|
||||
target_arch = "s390x" => { #[path = "s390x.rs" ] mod arch; }
|
||||
target_arch = "powerpc64" => { #[path = "powerpc64.rs" ] mod arch; }
|
||||
target_arch = "arm" => { #[path = "arm.rs" ] mod arch; }
|
||||
target_arch = "riscv32" => { #[path = "riscv32.rs" ] mod arch; }
|
||||
target_arch = "sparc64" => { #[path = "sparc64.rs" ] mod arch; }
|
||||
target_arch = "mips64" => { #[path = "mips64.rs" ] mod arch; }
|
||||
target_arch = "x86" => { #[path = "x86.rs" ] mod arch; }
|
||||
target_arch = "powerpc" => { #[path = "powerpc.rs" ] mod arch; }
|
||||
target_arch = "sparc" => { #[path = "sparc.rs" ] mod arch; }
|
||||
target_arch = "mips" => { #[path = "mips.rs" ] mod arch; }
|
||||
_ => { compile_error!("Unsupported architecture"); }
|
||||
}
|
||||
|
||||
/// Copies `n` bytes from `src` to `dest`.
|
||||
///
|
||||
|
|
@ -165,62 +185,7 @@ unsafe extern "C" {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
pub unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
let fd: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 2i64, // SYS_open
|
||||
in("rdi") path,
|
||||
in("rsi") flags,
|
||||
in("rdx") 0i32, // mode (not used for reading)
|
||||
lateout("rax") fd,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
fd as i32
|
||||
}
|
||||
}
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
let fd: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 56i64, // SYS_openat
|
||||
in("x0") -100i32, // AT_FDCWD
|
||||
in("x1") path,
|
||||
in("x2") flags,
|
||||
in("x3") 0i32, // mode
|
||||
lateout("x0") fd,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
fd as i32
|
||||
}
|
||||
}
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
let fd: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 56i64, // SYS_openat
|
||||
in("a0") -100i32, // AT_FDCWD
|
||||
in("a1") path,
|
||||
in("a2") flags,
|
||||
in("a3") 0i32, // mode
|
||||
lateout("a0") fd,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
fd as i32
|
||||
}
|
||||
}
|
||||
unsafe { arch::sys_open(path, flags) }
|
||||
}
|
||||
|
||||
/// Direct syscall to read from a file descriptor
|
||||
|
|
@ -237,64 +202,7 @@ pub unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
|||
/// - `fd` is a valid open file descriptor
|
||||
#[inline]
|
||||
pub unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 0i64, // SYS_read
|
||||
in("rdi") fd,
|
||||
in("rsi") buf,
|
||||
in("rdx") count,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 63i64, // SYS_read
|
||||
in("x0") fd,
|
||||
in("x1") buf,
|
||||
in("x2") count,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 63i64, // SYS_read
|
||||
in("a0") fd,
|
||||
in("a1") buf,
|
||||
in("a2") count,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
unsafe { arch::sys_read(fd, buf, count) }
|
||||
}
|
||||
|
||||
/// Direct syscall to write to a file descriptor
|
||||
|
|
@ -312,64 +220,7 @@ pub unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
pub unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 1i64, // SYS_write
|
||||
in("rdi") fd,
|
||||
in("rsi") buf,
|
||||
in("rdx") count,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 64i64, // SYS_write
|
||||
in("x0") fd,
|
||||
in("x1") buf,
|
||||
in("x2") count,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 64i64, // SYS_write
|
||||
in("a0") fd,
|
||||
in("a1") buf,
|
||||
in("a2") count,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
unsafe { arch::sys_write(fd, buf, count) }
|
||||
}
|
||||
|
||||
/// Direct syscall to close a file descriptor
|
||||
|
|
@ -380,55 +231,7 @@ pub unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
pub unsafe fn sys_close(fd: i32) -> i32 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 3i64, // SYS_close
|
||||
in("rdi") fd,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 57i64, // SYS_close
|
||||
in("x0") fd,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 57i64, // SYS_close
|
||||
in("a0") fd,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
unsafe { arch::sys_close(fd) }
|
||||
}
|
||||
|
||||
/// Raw buffer for the `uname(2)` syscall.
|
||||
|
|
@ -459,57 +262,7 @@ pub struct UtsNameBuf {
|
|||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 63i64, // SYS_uname
|
||||
in("rdi") buf,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 160i64, // SYS_uname
|
||||
in("x0") buf,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 160i64, // SYS_uname
|
||||
in("a0") buf,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
unsafe { arch::sys_uname(buf) }
|
||||
}
|
||||
|
||||
/// Raw buffer for the `statfs(2)` syscall.
|
||||
|
|
@ -518,6 +271,16 @@ pub unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
|||
/// offsets on both architectures. Only the fields needed for disk usage are
|
||||
/// declared; the remainder of the 120-byte struct is covered by `_pad`.
|
||||
#[repr(C)]
|
||||
#[cfg(not(any(
|
||||
target_arch = "s390x",
|
||||
target_arch = "arm",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "x86",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "sparc",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips"
|
||||
)))]
|
||||
pub struct StatfsBuf {
|
||||
pub f_type: i64,
|
||||
pub f_bsize: i64,
|
||||
|
|
@ -535,6 +298,96 @@ pub struct StatfsBuf {
|
|||
pub _pad: [i64; 4],
|
||||
}
|
||||
|
||||
/// on s390x `f_type` and `f_bsize` are 32-bit.
|
||||
#[repr(C)]
|
||||
#[cfg(target_arch = "s390x")]
|
||||
pub struct StatfsBuf {
|
||||
pub f_type: u32,
|
||||
pub f_bsize: u32,
|
||||
pub f_blocks: u64,
|
||||
pub f_bfree: u64,
|
||||
pub f_bavail: u64,
|
||||
pub f_files: u64,
|
||||
pub f_ffree: u64,
|
||||
pub f_fsid: [i32; 2],
|
||||
pub f_namelen: u32,
|
||||
pub f_frsize: u32,
|
||||
pub f_flags: u32,
|
||||
|
||||
#[allow(clippy::pub_underscore_fields, reason = "This is not a public API")]
|
||||
pub _pad: [u32; 5],
|
||||
}
|
||||
|
||||
/// on armv7 `statfs64(2)` has 32-bit word fields; see
|
||||
/// https://github.com/torvalds/linux/blob/v6.19/include/uapi/asm-generic/statfs.h
|
||||
#[repr(C)]
|
||||
#[cfg(any(
|
||||
target_arch = "arm",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "x86",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "sparc"
|
||||
))]
|
||||
pub struct StatfsBuf {
|
||||
pub f_type: u32,
|
||||
pub f_bsize: u32,
|
||||
pub f_blocks: u64,
|
||||
pub f_bfree: u64,
|
||||
pub f_bavail: u64,
|
||||
pub f_files: u64,
|
||||
pub f_ffree: u64,
|
||||
pub f_fsid: [i32; 2],
|
||||
pub f_namelen: u32,
|
||||
pub f_frsize: u32,
|
||||
pub f_flags: u32,
|
||||
|
||||
#[allow(clippy::pub_underscore_fields, reason = "This is not a public API")]
|
||||
pub _pad: [u32; 4],
|
||||
}
|
||||
|
||||
/// mips (O32) uses `compat_statfs64`, same reordering with 32-bit words; see
|
||||
/// https://github.com/torvalds/linux/blob/v6.19/arch/mips/include/uapi/asm/statfs.h
|
||||
#[repr(C)]
|
||||
#[cfg(target_arch = "mips")]
|
||||
pub struct StatfsBuf {
|
||||
pub f_type: u32,
|
||||
pub f_bsize: u32,
|
||||
pub f_frsize: u32,
|
||||
_pad: u32,
|
||||
pub f_blocks: u64,
|
||||
pub f_bfree: u64,
|
||||
pub f_files: u64,
|
||||
pub f_ffree: u64,
|
||||
pub f_bavail: u64,
|
||||
pub f_fsid: [i32; 2],
|
||||
pub f_namelen: u32,
|
||||
pub f_flags: u32,
|
||||
|
||||
#[allow(clippy::pub_underscore_fields, reason = "This is not a public API")]
|
||||
pub _pad2: [u32; 5],
|
||||
}
|
||||
|
||||
/// mips reorders fields; see
|
||||
/// https://github.com/torvalds/linux/blob/v6.19/arch/mips/include/uapi/asm/statfs.h
|
||||
#[repr(C)]
|
||||
#[cfg(target_arch = "mips64")]
|
||||
pub struct StatfsBuf {
|
||||
pub f_type: i64,
|
||||
pub f_bsize: i64,
|
||||
pub f_frsize: i64,
|
||||
pub f_blocks: u64,
|
||||
pub f_bfree: u64,
|
||||
pub f_files: u64,
|
||||
pub f_ffree: u64,
|
||||
pub f_bavail: u64,
|
||||
pub f_fsid: [i32; 2],
|
||||
pub f_namelen: i64,
|
||||
pub f_flags: i64,
|
||||
|
||||
#[allow(clippy::pub_underscore_fields, reason = "This is not a public API")]
|
||||
pub _pad: [i64; 5],
|
||||
}
|
||||
|
||||
/// Direct `statfs(2)` syscall
|
||||
///
|
||||
/// # Returns
|
||||
|
|
@ -549,61 +402,7 @@ pub struct StatfsBuf {
|
|||
/// - `buf` points to a valid `StatfsBuf`
|
||||
#[inline]
|
||||
pub unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 137i64, // SYS_statfs
|
||||
in("rdi") path,
|
||||
in("rsi") buf,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 43i64, // SYS_statfs
|
||||
in("x0") path,
|
||||
in("x1") buf,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 43i64, // SYS_statfs
|
||||
in("a0") path,
|
||||
in("a1") buf,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
unsafe { arch::sys_statfs(path, buf) }
|
||||
}
|
||||
|
||||
/// Read entire file using direct syscalls. This avoids libc overhead and can be
|
||||
|
|
@ -658,6 +457,14 @@ pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> Result<usize, i32> {
|
|||
/// The layout matches the kernel's `struct sysinfo` *exactly*:
|
||||
/// `mem_unit` ends at offset 108, then 4 bytes of implicit padding to 112.
|
||||
#[repr(C)]
|
||||
#[cfg(not(any(
|
||||
target_arch = "arm",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "x86",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "sparc",
|
||||
target_arch = "mips"
|
||||
)))]
|
||||
pub struct SysInfo {
|
||||
pub uptime: i64,
|
||||
pub loads: [u64; 3],
|
||||
|
|
@ -678,6 +485,35 @@ pub struct SysInfo {
|
|||
// needed
|
||||
}
|
||||
|
||||
/// on armv7 `__kernel_long_t` is 4 bytes; see
|
||||
/// https://github.com/torvalds/linux/blob/v6.19/include/uapi/linux/sysinfo.h
|
||||
#[repr(C)]
|
||||
#[cfg(any(
|
||||
target_arch = "arm",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "x86",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "sparc",
|
||||
target_arch = "mips"
|
||||
))]
|
||||
pub struct SysInfo {
|
||||
pub uptime: i32,
|
||||
pub loads: [u32; 3],
|
||||
pub totalram: u32,
|
||||
pub freeram: u32,
|
||||
pub sharedram: u32,
|
||||
pub bufferram: u32,
|
||||
pub totalswap: u32,
|
||||
pub freeswap: u32,
|
||||
pub procs: u16,
|
||||
_pad: u16,
|
||||
pub totalhigh: u32,
|
||||
pub freehigh: u32,
|
||||
pub mem_unit: u32,
|
||||
#[allow(clippy::pub_underscore_fields, reason = "This is not a public API")]
|
||||
pub _f: [u8; 8],
|
||||
}
|
||||
|
||||
/// Direct `sysinfo(2)` syscall
|
||||
///
|
||||
/// # Returns
|
||||
|
|
@ -689,46 +525,7 @@ pub struct SysInfo {
|
|||
/// The caller must ensure that `info` points to a valid `SysInfo` buffer.
|
||||
#[inline]
|
||||
pub unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 99_i64, // __NR_sysinfo
|
||||
in("rdi") info,
|
||||
out("rcx") _,
|
||||
out("r11") _,
|
||||
lateout("rax") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 179_i64, // __NR_sysinfo
|
||||
in("x0") info,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 179_i64, // __NR_sysinfo
|
||||
in("a0") info,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
unsafe { arch::sys_sysinfo(info) }
|
||||
}
|
||||
|
||||
/// Direct `sched_getaffinity(2)` syscall
|
||||
|
|
@ -748,61 +545,7 @@ pub unsafe fn sys_sched_getaffinity(
|
|||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 204i64, // __NR_sched_getaffinity
|
||||
in("rdi") pid,
|
||||
in("rsi") mask_size,
|
||||
in("rdx") mask,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 123i64, // __NR_sched_getaffinity
|
||||
in("x0") pid,
|
||||
in("x1") mask_size,
|
||||
in("x2") mask,
|
||||
lateout("x0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 123i64, // __NR_sched_getaffinity
|
||||
in("a0") pid,
|
||||
in("a1") mask_size,
|
||||
in("a2") mask,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
unsafe { arch::sys_sched_getaffinity(pid, mask_size, mask) }
|
||||
}
|
||||
|
||||
/// Direct syscall to exit the process
|
||||
|
|
@ -812,33 +555,5 @@ pub unsafe fn sys_sched_getaffinity(
|
|||
/// This syscall never returns. The process will terminate immediately.
|
||||
#[inline]
|
||||
pub unsafe fn sys_exit(code: i32) -> ! {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 60i64, // SYS_exit
|
||||
in("rdi") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"svc #0",
|
||||
in("x8") 93i64, // SYS_exit
|
||||
in("x0") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 93i64, // SYS_exit
|
||||
in("a0") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
unsafe { arch::sys_exit(code) }
|
||||
}
|
||||
|
|
|
|||
161
crates/asm/src/loongarch64.rs
Normal file
161
crates/asm/src/loongarch64.rs
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
//! Syscall implementations for `loongarch64`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let fd: i64;
|
||||
core::arch::asm!(
|
||||
"syscall 0",
|
||||
in("$a7") 56i64, // SYS_openat
|
||||
in("$a0") -100i32, // AT_FDCWD
|
||||
in("$a1") path,
|
||||
in("$a2") flags,
|
||||
in("$a3") 0i32, // mode
|
||||
lateout("$a0") fd,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
fd as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall 0",
|
||||
in("$a7") 63i64, // SYS_read
|
||||
in("$a0") fd,
|
||||
in("$a1") buf,
|
||||
in("$a2") count,
|
||||
lateout("$a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall 0",
|
||||
in("$a7") 64i64, // SYS_write
|
||||
in("$a0") fd,
|
||||
in("$a1") buf,
|
||||
in("$a2") count,
|
||||
lateout("$a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall 0",
|
||||
in("$a7") 57i64, // SYS_close
|
||||
in("$a0") fd,
|
||||
lateout("$a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall 0",
|
||||
in("$a7") 160i64, // SYS_uname
|
||||
in("$a0") buf,
|
||||
lateout("$a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall 0",
|
||||
in("$a7") 43i64, // SYS_statfs
|
||||
in("$a0") path,
|
||||
in("$a1") buf,
|
||||
lateout("$a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall 0",
|
||||
in("$a7") 179_i64, // __NR_sysinfo
|
||||
in("$a0") info,
|
||||
lateout("$a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall 0",
|
||||
in("$a7") 123i64, // __NR_sched_getaffinity
|
||||
in("$a0") pid,
|
||||
in("$a1") mask_size,
|
||||
in("$a2") mask,
|
||||
lateout("$a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"syscall 0",
|
||||
in("$a7") 93i64, // SYS_exit
|
||||
in("$a0") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
196
crates/asm/src/mips.rs
Normal file
196
crates/asm/src/mips.rs
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
//! Syscall implementations for `mips`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"subu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 4000i32 + 5 => ret, // SYS_open
|
||||
in("$4") path,
|
||||
in("$5") flags,
|
||||
in("$6") 0i32, // mode
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"subu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 4000i32 + 3 => ret, // SYS_read
|
||||
in("$4") fd,
|
||||
in("$5") buf,
|
||||
in("$6") count,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"subu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 4000i32 + 4 => ret, // SYS_write
|
||||
in("$4") fd,
|
||||
in("$5") buf,
|
||||
in("$6") count,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"subu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 4000i32 + 6 => ret, // SYS_close
|
||||
in("$4") fd,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"subu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 4000i32 + 122 => ret, // SYS_newuname
|
||||
in("$4") buf,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"subu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 4000i32 + 255 => ret, // SYS_statfs64
|
||||
in("$4") path,
|
||||
in("$5") core::mem::size_of::<StatfsBuf>(),
|
||||
in("$6") buf,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"subu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 4000_i32 + 116 => ret, // __NR_sysinfo
|
||||
in("$4") info,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
i64::from(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"subu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 4000i32 + 240 => ret, // __NR_sched_getaffinity
|
||||
in("$4") pid,
|
||||
in("$5") mask_size,
|
||||
in("$6") mask,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("$2") 4000i32 + 1, // SYS_exit
|
||||
in("$4") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
206
crates/asm/src/mips64.rs
Normal file
206
crates/asm/src/mips64.rs
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
//! Syscall implementations for `mips64`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"dsubu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 5000i64 + 2 => ret, // SYS_open
|
||||
in("$4") path,
|
||||
in("$5") flags,
|
||||
in("$6") 0i32, // mode
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"dsubu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 5000i64 + 0 => ret, // SYS_read
|
||||
in("$4") fd,
|
||||
in("$5") buf,
|
||||
in("$6") count,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"dsubu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 5000i64 + 1 => ret, // SYS_write
|
||||
in("$4") fd,
|
||||
in("$5") buf,
|
||||
in("$6") count,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"dsubu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 5000i64 + 3 => ret, // SYS_close
|
||||
in("$4") fd,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"dsubu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 5000i64 + 61 => ret, // SYS_newuname
|
||||
in("$4") buf,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"dsubu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 5000i64 + 134 => ret, // SYS_statfs
|
||||
in("$4") path,
|
||||
in("$5") buf,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
"beqz $7, 1f",
|
||||
"nop",
|
||||
"dsubu $2, $0, $2",
|
||||
"1:",
|
||||
inlateout("$2") 5000_i64 + 97 => ret, // SYS_sysinfo
|
||||
in("$4") info,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
inlateout("$2") 5000i64 + 196 => ret, // __NR_sched_getaffinity
|
||||
in("$4") pid,
|
||||
in("$5") mask_size,
|
||||
in("$6") mask,
|
||||
lateout("$7") _,
|
||||
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
|
||||
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
|
||||
lateout("$24") _, lateout("$25") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("$2") 5000i64 + 58, // SYS_exit
|
||||
in("$4") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
180
crates/asm/src/powerpc.rs
Normal file
180
crates/asm/src/powerpc.rs
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
//! Syscall implementations for `powerpc`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 5i32 => _, // SYS_open
|
||||
inlateout("r3") path => ret,
|
||||
inlateout("r4") flags => _,
|
||||
inlateout("r5") 0i32 => _,
|
||||
out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 3i32 => _, // SYS_read
|
||||
inlateout("r3") fd => ret,
|
||||
inlateout("r4") buf => _,
|
||||
inlateout("r5") count => _,
|
||||
out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 4i32 => _, // SYS_write
|
||||
inlateout("r3") fd => ret,
|
||||
inlateout("r4") buf => _,
|
||||
inlateout("r5") count => _,
|
||||
out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 6i32 => _, // SYS_close
|
||||
inlateout("r3") fd => ret,
|
||||
out("r4") _, out("r5") _, out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 122i32 => _, // SYS_newuname
|
||||
inlateout("r3") buf => ret,
|
||||
out("r4") _, out("r5") _, out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 252i32 => _, // SYS_statfs64
|
||||
inlateout("r3") path => ret,
|
||||
inlateout("r4") core::mem::size_of::<StatfsBuf>() => _,
|
||||
inlateout("r5") buf => _,
|
||||
out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 116_i32 => _, // __NR_sysinfo
|
||||
inlateout("r3") info => ret,
|
||||
out("r4") _, out("r5") _, out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
i64::from(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 223i32 => _, // __NR_sched_getaffinity
|
||||
inlateout("r3") pid => ret,
|
||||
inlateout("r4") mask_size => _,
|
||||
inlateout("r5") mask => _,
|
||||
out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"li 0, 1", // SYS_exit
|
||||
"sc",
|
||||
in("r3") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
200
crates/asm/src/powerpc64.rs
Normal file
200
crates/asm/src/powerpc64.rs
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
//! Syscall implementations for `powerpc64`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 5i64 => _, // SYS_open
|
||||
inlateout("r3") path => ret,
|
||||
inlateout("r4") flags => _,
|
||||
inlateout("r5") 0i32 => _, // mode
|
||||
out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 3i64 => _, // SYS_read
|
||||
inlateout("r3") fd as i64 => ret,
|
||||
inlateout("r4") buf => _,
|
||||
inlateout("r5") count => _,
|
||||
out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 4i64 => _, // SYS_write
|
||||
inlateout("r3") fd as i64 => ret,
|
||||
inlateout("r4") buf => _,
|
||||
inlateout("r5") count => _,
|
||||
out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 6i64 => _, // SYS_close
|
||||
inlateout("r3") fd as i64 => ret,
|
||||
out("r4") _, out("r5") _, out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 122i64 => _, // SYS_uname
|
||||
inlateout("r3") buf => ret,
|
||||
out("r4") _, out("r5") _, out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 99i64 => _, // SYS_statfs
|
||||
inlateout("r3") path => ret,
|
||||
inlateout("r4") buf => _,
|
||||
out("r5") _, out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 116_i64 => _, // __NR_sysinfo
|
||||
inlateout("r3") info => ret,
|
||||
out("r4") _, out("r5") _, out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"sc",
|
||||
"bns+ 2f",
|
||||
"neg 3, 3",
|
||||
"2:",
|
||||
inlateout("r0") 223i64 => _, // __NR_sched_getaffinity
|
||||
inlateout("r3") pid as i64 => ret,
|
||||
inlateout("r4") mask_size => _,
|
||||
inlateout("r5") mask => _,
|
||||
out("r6") _, out("r7") _, out("r8") _,
|
||||
out("r9") _, out("r10") _, out("r11") _, out("r12") _,
|
||||
out("cr0") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"li 0, 1", // SYS_exit
|
||||
"sc",
|
||||
in("r3") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
142
crates/asm/src/riscv32.rs
Normal file
142
crates/asm/src/riscv32.rs
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
//! Syscall implementations for `riscv32`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 56i32, // SYS_openat
|
||||
in("a0") -100i32, // AT_FDCWD
|
||||
in("a1") path,
|
||||
in("a2") flags,
|
||||
in("a3") 0i32, // mode
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 63i32, // SYS_read
|
||||
in("a0") fd,
|
||||
in("a1") buf,
|
||||
in("a2") count,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 64i32, // SYS_write
|
||||
in("a0") fd,
|
||||
in("a1") buf,
|
||||
in("a2") count,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 57i32, // SYS_close
|
||||
in("a0") fd,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 160i32, // SYS_uname
|
||||
in("a0") buf,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
// asm-generic __NR_statfs routes to sys_statfs64 on 32-bit: 3-arg form.
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 43i32, // __NR_statfs
|
||||
in("a0") path,
|
||||
in("a1") core::mem::size_of::<StatfsBuf>(),
|
||||
in("a2") buf,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 179_i32, // __NR_sysinfo
|
||||
in("a0") info,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
i64::from(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 123i32, // __NR_sched_getaffinity
|
||||
in("a0") pid,
|
||||
in("a1") mask_size,
|
||||
in("a2") mask,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 93i32, // SYS_exit
|
||||
in("a0") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
166
crates/asm/src/riscv64.rs
Normal file
166
crates/asm/src/riscv64.rs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
//! Syscall implementations for `riscv64`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let fd: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 56i64, // SYS_openat
|
||||
in("a0") -100i32, // AT_FDCWD
|
||||
in("a1") path,
|
||||
in("a2") flags,
|
||||
in("a3") 0i32, // mode
|
||||
lateout("a0") fd,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
fd as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 63i64, // SYS_read
|
||||
in("a0") fd,
|
||||
in("a1") buf,
|
||||
in("a2") count,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 64i64, // SYS_write
|
||||
in("a0") fd,
|
||||
in("a1") buf,
|
||||
in("a2") count,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 57i64, // SYS_close
|
||||
in("a0") fd,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 160i64, // SYS_uname
|
||||
in("a0") buf,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 43i64, // SYS_statfs
|
||||
in("a0") path,
|
||||
in("a1") buf,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 179_i64, // __NR_sysinfo
|
||||
in("a0") info,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 123i64, // __NR_sched_getaffinity
|
||||
in("a0") pid,
|
||||
in("a1") mask_size,
|
||||
in("a2") mask,
|
||||
lateout("a0") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a7") 93i64, // SYS_exit
|
||||
in("a0") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
160
crates/asm/src/s390x.rs
Normal file
160
crates/asm/src/s390x.rs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
//! Syscall implementations for `s390x`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let fd: i64;
|
||||
core::arch::asm!(
|
||||
"svc 0",
|
||||
in("r1") 5i64, // SYS_open
|
||||
in("r2") path,
|
||||
in("r3") flags,
|
||||
in("r4") 0i32, // mode
|
||||
lateout("r2") fd,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
fd as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc 0",
|
||||
in("r1") 3i64, // SYS_read
|
||||
in("r2") fd,
|
||||
in("r3") buf,
|
||||
in("r4") count,
|
||||
lateout("r2") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc 0",
|
||||
in("r1") 4i64, // SYS_write
|
||||
in("r2") fd,
|
||||
in("r3") buf,
|
||||
in("r4") count,
|
||||
lateout("r2") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc 0",
|
||||
in("r1") 6i64, // SYS_close
|
||||
in("r2") fd,
|
||||
lateout("r2") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc 0",
|
||||
in("r1") 122i64, // SYS_uname
|
||||
in("r2") buf,
|
||||
lateout("r2") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc 0",
|
||||
in("r1") 99i64, // SYS_statfs
|
||||
in("r2") path,
|
||||
in("r3") buf,
|
||||
lateout("r2") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc 0",
|
||||
in("r1") 116_i64, // __NR_sysinfo
|
||||
in("r2") info,
|
||||
lateout("r2") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"svc 0",
|
||||
in("r1") 240i64, // __NR_sched_getaffinity
|
||||
in("r2") pid,
|
||||
in("r3") mask_size,
|
||||
in("r4") mask,
|
||||
lateout("r2") ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"svc 0",
|
||||
in("r1") 1i64, // SYS_exit
|
||||
in("r2") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
165
crates/asm/src/sparc.rs
Normal file
165
crates/asm/src/sparc.rs
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
//! Syscall implementations for `sparc`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"ta 0x10",
|
||||
"bcs,a 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 5i32, // SYS_open
|
||||
inlateout("o0") path => ret,
|
||||
in("o1") flags,
|
||||
in("o2") 0i32, // mode
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"ta 0x10",
|
||||
"bcs,a 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 3i32, // SYS_read
|
||||
inlateout("o0") fd => ret,
|
||||
in("o1") buf,
|
||||
in("o2") count,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"ta 0x10",
|
||||
"bcs,a 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 4i32, // SYS_write
|
||||
inlateout("o0") fd => ret,
|
||||
in("o1") buf,
|
||||
in("o2") count,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"ta 0x10",
|
||||
"bcs,a 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 6i32, // SYS_close
|
||||
inlateout("o0") fd => ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"ta 0x10",
|
||||
"bcs,a 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 189i32, // SYS_newuname
|
||||
inlateout("o0") buf => ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"ta 0x10",
|
||||
"bcs,a 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 234i32, // SYS_statfs64
|
||||
inlateout("o0") path => ret,
|
||||
in("o1") core::mem::size_of::<StatfsBuf>(),
|
||||
in("o2") buf,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"ta 0x10",
|
||||
"bcs,a 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 214_i32, // __NR_sysinfo
|
||||
inlateout("o0") info => ret,
|
||||
options(nostack)
|
||||
);
|
||||
i64::from(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"ta 0x10",
|
||||
"bcs,a 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 260i32, // __NR_sched_getaffinity
|
||||
inlateout("o0") pid => ret,
|
||||
in("o1") mask_size,
|
||||
in("o2") mask,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"ta 0x10",
|
||||
nr = in(reg) 1i32, // SYS_exit
|
||||
in("o0") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
179
crates/asm/src/sparc64.rs
Normal file
179
crates/asm/src/sparc64.rs
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
//! Syscall implementations for `sparc64`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"t 0x6d",
|
||||
"bcs,a %xcc, 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 5i64, // SYS_open
|
||||
inlateout("o0") path => ret,
|
||||
in("o1") flags,
|
||||
in("o2") 0i32, // mode
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"t 0x6d",
|
||||
"bcs,a %xcc, 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 3i64, // SYS_read
|
||||
inlateout("o0") fd as i64 => ret,
|
||||
in("o1") buf,
|
||||
in("o2") count,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"t 0x6d",
|
||||
"bcs,a %xcc, 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 4i64, // SYS_write
|
||||
inlateout("o0") fd as i64 => ret,
|
||||
in("o1") buf,
|
||||
in("o2") count,
|
||||
options(nostack)
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"t 0x6d",
|
||||
"bcs,a %xcc, 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 6i64, // SYS_close
|
||||
inlateout("o0") fd as i64 => ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"t 0x6d",
|
||||
"bcs,a %xcc, 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 189i64, // SYS_newuname
|
||||
inlateout("o0") buf => ret,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"t 0x6d",
|
||||
"bcs,a %xcc, 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 157i64, // SYS_statfs
|
||||
inlateout("o0") path => ret,
|
||||
in("o1") buf,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"t 0x6d",
|
||||
"bcs,a %xcc, 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 214_i64, // __NR_sysinfo
|
||||
inlateout("o0") info => ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"t 0x6d",
|
||||
"bcs,a %xcc, 1f",
|
||||
"sub %g0, %o0, %o0",
|
||||
"1:",
|
||||
nr = in(reg) 260i64, // __NR_sched_getaffinity
|
||||
inlateout("o0") pid as i64 => ret,
|
||||
in("o1") mask_size,
|
||||
in("o2") mask,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"mov {nr}, %g1",
|
||||
"t 0x6d",
|
||||
nr = in(reg) 1i64, // SYS_exit
|
||||
in("o0") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
149
crates/asm/src/x86.rs
Normal file
149
crates/asm/src/x86.rs
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
//! Syscall implementations for `x86`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"push ebx",
|
||||
"mov ebx, {arg1:e}",
|
||||
"int 0x80",
|
||||
"pop ebx",
|
||||
arg1 = in(reg) path,
|
||||
inlateout("eax") 5i32 => ret, // SYS_open
|
||||
in("ecx") flags,
|
||||
in("edx") 0i32, // mode
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"push ebx",
|
||||
"mov ebx, {arg1:e}",
|
||||
"int 0x80",
|
||||
"pop ebx",
|
||||
arg1 = in(reg) fd,
|
||||
inlateout("eax") 3i32 => ret, // SYS_read
|
||||
in("ecx") buf,
|
||||
in("edx") count,
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"push ebx",
|
||||
"mov ebx, {arg1:e}",
|
||||
"int 0x80",
|
||||
"pop ebx",
|
||||
arg1 = in(reg) fd,
|
||||
inlateout("eax") 4i32 => ret, // SYS_write
|
||||
in("ecx") buf,
|
||||
in("edx") count,
|
||||
);
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"push ebx",
|
||||
"mov ebx, {arg1:e}",
|
||||
"int 0x80",
|
||||
"pop ebx",
|
||||
arg1 = in(reg) fd,
|
||||
inlateout("eax") 6i32 => ret, // SYS_close
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"push ebx",
|
||||
"mov ebx, {arg1:e}",
|
||||
"int 0x80",
|
||||
"pop ebx",
|
||||
arg1 = in(reg) buf,
|
||||
inlateout("eax") 122i32 => ret, // SYS_newuname
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"push ebx",
|
||||
"mov ebx, {arg1:e}",
|
||||
"int 0x80",
|
||||
"pop ebx",
|
||||
arg1 = in(reg) path,
|
||||
inlateout("eax") 268i32 => ret, // SYS_statfs64
|
||||
in("ecx") core::mem::size_of::<StatfsBuf>(),
|
||||
in("edx") buf,
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"push ebx",
|
||||
"mov ebx, {arg1:e}",
|
||||
"int 0x80",
|
||||
"pop ebx",
|
||||
arg1 = in(reg) info,
|
||||
inlateout("eax") 116_i32 => ret, // __NR_sysinfo
|
||||
);
|
||||
i64::from(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i32;
|
||||
core::arch::asm!(
|
||||
"push ebx",
|
||||
"mov ebx, {arg1:e}",
|
||||
"int 0x80",
|
||||
"pop ebx",
|
||||
arg1 = in(reg) pid,
|
||||
inlateout("eax") 242i32 => ret, // __NR_sched_getaffinity
|
||||
in("ecx") mask_size,
|
||||
in("edx") mask,
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"mov ebx, {code:e}",
|
||||
"int 0x80",
|
||||
code = in(reg) code,
|
||||
in("eax") 1i32, // SYS_exit
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
}
|
||||
180
crates/asm/src/x86_64.rs
Normal file
180
crates/asm/src/x86_64.rs
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
//! Syscall implementations for `x86_64`.
|
||||
|
||||
use super::{StatfsBuf, SysInfo, UtsNameBuf};
|
||||
|
||||
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
|
||||
unsafe {
|
||||
let fd: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 2i64, // SYS_open
|
||||
in("rdi") path,
|
||||
in("rsi") flags,
|
||||
in("rdx") 0i32, // mode (not used for reading)
|
||||
lateout("rax") fd,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
fd as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 0i64, // SYS_read
|
||||
in("rdi") fd,
|
||||
in("rsi") buf,
|
||||
in("rdx") count,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 1i64, // SYS_write
|
||||
in("rdi") fd,
|
||||
in("rsi") buf,
|
||||
in("rdx") count,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 3i64, // SYS_close
|
||||
in("rdi") fd,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 63i64, // SYS_uname
|
||||
in("rdi") buf,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 137i64, // SYS_statfs
|
||||
in("rdi") path,
|
||||
in("rsi") buf,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 99_i64, // __NR_sysinfo
|
||||
in("rdi") info,
|
||||
out("rcx") _,
|
||||
out("r11") _,
|
||||
lateout("rax") ret,
|
||||
options(nostack)
|
||||
);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_sched_getaffinity(
|
||||
pid: i32,
|
||||
mask_size: usize,
|
||||
mask: *mut u8,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
let ret: i64;
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 204i64, // __NR_sched_getaffinity
|
||||
in("rdi") pid,
|
||||
in("rsi") mask_size,
|
||||
in("rdx") mask,
|
||||
lateout("rax") ret,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
{
|
||||
ret as i32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn sys_exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"syscall",
|
||||
in("rax") 60i64, // SYS_exit
|
||||
in("rdi") code,
|
||||
options(noreturn, nostack)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -121,29 +121,78 @@ fn parse_num(data: &[u8], i: &mut usize) -> u32 {
|
|||
n
|
||||
}
|
||||
|
||||
/// Build `/sys/devices/system/cpu/cpu{n}/cpufreq/cpuinfo_max_freq` into buf,
|
||||
/// returning the byte length written.
|
||||
fn format_cpufreq_path(buf: &mut [u8; 64], cpu: u32) -> usize {
|
||||
const PREFIX: &[u8] = b"/sys/devices/system/cpu/cpu";
|
||||
const SUFFIX: &[u8] = b"/cpufreq/cpuinfo_max_freq";
|
||||
buf[..PREFIX.len()].copy_from_slice(PREFIX);
|
||||
let mut i = PREFIX.len();
|
||||
let mut tmp = [0u8; 3];
|
||||
let mut n = cpu;
|
||||
let mut digits = 0;
|
||||
loop {
|
||||
tmp[digits] = b'0' + (n % 10) as u8;
|
||||
digits += 1;
|
||||
n /= 10;
|
||||
if n == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while digits > 0 {
|
||||
digits -= 1;
|
||||
buf[i] = tmp[digits];
|
||||
i += 1;
|
||||
}
|
||||
buf[i..i + SUFFIX.len()].copy_from_slice(SUFFIX);
|
||||
i + SUFFIX.len()
|
||||
}
|
||||
|
||||
/// Read CPU frequency in MHz. Tries sysfs first, then cpuinfo fields.
|
||||
fn get_cpu_freq_mhz() -> Option<u32> {
|
||||
// Try sysfs cpuinfo_max_freq (in kHz)
|
||||
let mut buf = [0u8; 32];
|
||||
if let Ok(n) = read_file_fast(
|
||||
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
|
||||
&mut buf,
|
||||
) {
|
||||
// Read cpuinfo_max_freq across all CPUs (in kHz) and take the max so
|
||||
// heterogeneous (big.LITTLE) topologies report the performance cluster.
|
||||
let mut max_khz = 0u32;
|
||||
let mut path = [0u8; 64];
|
||||
for cpu in 0u32..64 {
|
||||
let n = format_cpufreq_path(&mut path, cpu);
|
||||
let p = match core::str::from_utf8(&path[..n]) {
|
||||
Ok(s) => s,
|
||||
Err(_) => continue,
|
||||
};
|
||||
let mut buf = [0u8; 32];
|
||||
let Ok(m) = read_file_fast(p, &mut buf) else {
|
||||
if cpu == 0 {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
};
|
||||
let mut khz = 0u32;
|
||||
for &b in &buf[..n] {
|
||||
for &b in &buf[..m] {
|
||||
if b.is_ascii_digit() {
|
||||
khz = khz * 10 + u32::from(b - b'0');
|
||||
}
|
||||
}
|
||||
if khz > 0 {
|
||||
return Some(khz / 1000);
|
||||
if khz > max_khz {
|
||||
max_khz = khz;
|
||||
}
|
||||
}
|
||||
if max_khz > 0 {
|
||||
return Some(max_khz / 1000);
|
||||
}
|
||||
// Fall back to cpuinfo fields
|
||||
let mut buf2 = [0u8; 2048];
|
||||
let mut buf2 = [0u8; 4096];
|
||||
let n = read_file_fast("/proc/cpuinfo", &mut buf2).ok()?;
|
||||
let data = &buf2[..n];
|
||||
for key in &[b"cpu MHz" as &[u8], b"cpu MHz dynamic", b"CPU MHz"] {
|
||||
for key in &[
|
||||
b"cpu MHz" as &[u8],
|
||||
b"cpu MHz dynamic",
|
||||
b"cpu MHz static",
|
||||
b"CPU MHz",
|
||||
b"clock",
|
||||
// BogoMIPS on MIPS is calibrated to the clock frequency (unlike x86).
|
||||
b"BogoMIPS",
|
||||
] {
|
||||
if let Some(val) = extract_field(data, key) {
|
||||
// Parse integer part of the MHz value (e.g. "5200.00" -> 5200)
|
||||
let mut mhz = 0u32;
|
||||
|
|
@ -160,6 +209,32 @@ fn get_cpu_freq_mhz() -> Option<u32> {
|
|||
}
|
||||
}
|
||||
}
|
||||
// SPARC exposes its clock as `Cpu0ClkTck : <hex>`,
|
||||
// which signifies ticks per second in hex.
|
||||
if let Some(val) = extract_field(data, b"Cpu0ClkTck") {
|
||||
let mut hz = 0u64;
|
||||
let mut seen = false;
|
||||
for &b in val.as_bytes() {
|
||||
let d = match b {
|
||||
b'0'..=b'9' => Some(u64::from(b - b'0')),
|
||||
b'a'..=b'f' => Some(u64::from(b - b'a' + 10)),
|
||||
b'A'..=b'F' => Some(u64::from(b - b'A' + 10)),
|
||||
_ => None,
|
||||
};
|
||||
match d {
|
||||
Some(d) => {
|
||||
hz = hz * 16 + d;
|
||||
seen = true;
|
||||
},
|
||||
None if seen => break,
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
if hz > 0 {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
return Some((hz / 1_000_000) as u32);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
|
|
@ -169,10 +244,35 @@ fn get_model_name() -> Option<String> {
|
|||
let n = read_file_fast("/proc/cpuinfo", &mut buf).ok()?;
|
||||
let data = &buf[..n];
|
||||
|
||||
let base = extract_name(data)?;
|
||||
let mut name = base;
|
||||
if let Some(mhz) = get_cpu_freq_mhz() {
|
||||
name.push_str(" @ ");
|
||||
// Round to nearest 0.01 GHz, then split so carries (e.g. 1999 MHz)
|
||||
// roll into the integer part instead of overflowing the fraction.
|
||||
let rounded_centesimal = (mhz + 5) / 10;
|
||||
let ghz_int = rounded_centesimal / 100;
|
||||
let ghz_frac = rounded_centesimal % 100;
|
||||
write_u64(&mut name, u64::from(ghz_int));
|
||||
name.push('.');
|
||||
if ghz_frac < 10 {
|
||||
name.push('0');
|
||||
}
|
||||
write_u64(&mut name, u64::from(ghz_frac));
|
||||
name.push_str(" GHz");
|
||||
}
|
||||
Some(name)
|
||||
}
|
||||
|
||||
/// Extract a human-readable CPU name. Tries cpuinfo fields first, then
|
||||
/// falls back to the device-tree `compatible` string on SoCs that don't
|
||||
/// expose a model through cpuinfo.
|
||||
fn extract_name(data: &[u8]) -> Option<String> {
|
||||
for key in &[
|
||||
b"model name" as &[u8],
|
||||
b"Model Name",
|
||||
b"uarch",
|
||||
b"cpu model",
|
||||
b"isa",
|
||||
b"cpu",
|
||||
b"machine",
|
||||
|
|
@ -181,28 +281,34 @@ fn get_model_name() -> Option<String> {
|
|||
if let Some(val) = extract_field(data, key) {
|
||||
let trimmed = trim(val);
|
||||
if !trimmed.is_empty() {
|
||||
let mut name = String::from(trimmed);
|
||||
if let Some(mhz) = get_cpu_freq_mhz() {
|
||||
name.push_str(" @ ");
|
||||
// Round to nearest 0.01 GHz, then split so carries (e.g. 1999 MHz)
|
||||
// roll into the integer part instead of overflowing the fraction.
|
||||
let rounded_centesimal = (mhz + 5) / 10;
|
||||
let ghz_int = rounded_centesimal / 100;
|
||||
let ghz_frac = rounded_centesimal % 100;
|
||||
write_u64(&mut name, u64::from(ghz_int));
|
||||
name.push('.');
|
||||
if ghz_frac < 10 {
|
||||
name.push('0');
|
||||
}
|
||||
write_u64(&mut name, u64::from(ghz_frac));
|
||||
name.push_str(" GHz");
|
||||
}
|
||||
return Some(name);
|
||||
return Some(String::from(trimmed));
|
||||
}
|
||||
}
|
||||
}
|
||||
parse_dt_compatible()
|
||||
}
|
||||
|
||||
None
|
||||
/// Parse the SoC name from `/sys/firmware/devicetree/base/compatible`.
|
||||
/// The file holds NUL-separated `vendor,model` strings from most-specific
|
||||
/// (board) to most-generic (SoC); we take the last entry and return just
|
||||
/// the model portion after the comma.
|
||||
fn parse_dt_compatible() -> Option<String> {
|
||||
let mut buf = [0u8; 256];
|
||||
let n = read_file_fast("/sys/firmware/devicetree/base/compatible", &mut buf)
|
||||
.ok()?;
|
||||
// Drop the terminating NUL so the rposition below locates the entry
|
||||
// separator rather than the end-of-string marker.
|
||||
let end = if n > 0 && buf[n - 1] == 0 { n - 1 } else { n };
|
||||
let data = &buf[..end];
|
||||
let start = data.iter().rposition(|&b| b == 0).map_or(0, |p| p + 1);
|
||||
let entry = &data[start..];
|
||||
let comma = entry.iter().position(|&b| b == b',')?;
|
||||
let model = core::str::from_utf8(&entry[comma + 1..]).ok()?;
|
||||
if model.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(String::from(model))
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract value of first occurrence of `key` in cpuinfo.
|
||||
|
|
|
|||
|
|
@ -401,7 +401,13 @@ fn print_system_info(fields: &Fields) -> Result<(), Error> {
|
|||
// Row format mirrors the default logo path exactly.
|
||||
let rows: [(&str, &str, &str, &str, &str); 11] = [
|
||||
("", "", user_info.as_str(), " ", " ~"),
|
||||
("\u{F313} ", "System", os_name.as_str(), " \u{E621} ", ""),
|
||||
(
|
||||
"\u{F313} ",
|
||||
"System",
|
||||
os_name.as_str(),
|
||||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
(
|
||||
"\u{E712} ",
|
||||
"Kernel",
|
||||
|
|
@ -409,11 +415,41 @@ fn print_system_info(fields: &Fields) -> Result<(), Error> {
|
|||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
("\u{F2DB} ", "CPU", cpu_name.as_str(), " \u{E621} ", ""),
|
||||
("\u{F4BC} ", "Topology", cpu_cores.as_str(), " \u{E621} ", ""),
|
||||
("\u{E795} ", "Shell", shell.as_str(), " \u{E621} ", ""),
|
||||
("\u{F017} ", "Uptime", uptime.as_str(), " \u{E621} ", ""),
|
||||
("\u{F2D2} ", "Desktop", desktop.as_str(), " \u{E621} ", ""),
|
||||
(
|
||||
"\u{F2DB} ",
|
||||
"CPU",
|
||||
cpu_name.as_str(),
|
||||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
(
|
||||
"\u{F4BC} ",
|
||||
"Topology",
|
||||
cpu_cores.as_str(),
|
||||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
(
|
||||
"\u{E795} ",
|
||||
"Shell",
|
||||
shell.as_str(),
|
||||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
(
|
||||
"\u{F017} ",
|
||||
"Uptime",
|
||||
uptime.as_str(),
|
||||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
(
|
||||
"\u{F2D2} ",
|
||||
"Desktop",
|
||||
desktop.as_str(),
|
||||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
(
|
||||
"\u{F035B} ",
|
||||
"Memory",
|
||||
|
|
@ -421,8 +457,20 @@ fn print_system_info(fields: &Fields) -> Result<(), Error> {
|
|||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
("\u{F194E} ", "Storage (/)", storage.as_str(), " \u{E621} ", ""),
|
||||
("\u{E22B} ", "Colors", colors.as_str(), " \u{E621} ", ""),
|
||||
(
|
||||
"\u{F194E} ",
|
||||
"Storage (/)",
|
||||
storage.as_str(),
|
||||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
(
|
||||
"\u{E22B} ",
|
||||
"Colors",
|
||||
colors.as_str(),
|
||||
" \u{E621} ",
|
||||
"",
|
||||
),
|
||||
];
|
||||
|
||||
core::fmt::write(&mut w, format_args!("\n")).ok();
|
||||
|
|
|
|||
|
|
@ -1,14 +1,23 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
#![cfg_attr(
|
||||
any(
|
||||
target_arch = "sparc64",
|
||||
target_arch = "sparc",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips"
|
||||
),
|
||||
feature(asm_experimental_arch)
|
||||
)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use core::{arch::naked_asm, panic::PanicInfo};
|
||||
|
||||
use microfetch_alloc::BumpAllocator;
|
||||
use microfetch_asm::{entry_rust, sys_exit, sys_write};
|
||||
// Re-export libc replacement functions from asm crate
|
||||
pub use microfetch_asm::{memcpy, memset, strlen};
|
||||
use microfetch_asm::{entry_rust, sys_exit, sys_write};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[unsafe(no_mangle)]
|
||||
|
|
@ -25,6 +34,23 @@ unsafe extern "C" fn _start() {
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
"mov eax, esp", // save original sp (argc/argv)
|
||||
"and esp, -16", // align stack to 16 bytes
|
||||
"sub esp, 12", // leave room so that the one-arg push keeps alignment
|
||||
"push eax", // arg: initial stack pointer
|
||||
"call {entry_rust}",
|
||||
"mov ebx, eax", // exit code -> first syscall arg
|
||||
"mov eax, 1", // SYS_exit
|
||||
"int 0x80",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
|
|
@ -57,6 +83,218 @@ unsafe extern "C" fn _start() {
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "loongarch64")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
"or $a0, $sp, $zero",
|
||||
"bstrins.d $sp, $zero, 3, 0",
|
||||
"bl {entry_rust}",
|
||||
"or $a0, $a0, $zero",
|
||||
"li.w $a7, 93",
|
||||
"syscall 0",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
"lgr %r2, %r15", // save original sp (argc/argv) as arg
|
||||
"aghi %r15, -160", // allocate s390x mandatory stack frame
|
||||
"lghi %r0, -16",
|
||||
"ngr %r15, %r0", // align stack to 16 bytes
|
||||
"brasl %r14, {entry_rust}",
|
||||
"lghi %r1, 1", // SYS_exit
|
||||
"svc 0",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
// ELFv2 (ppc64le / new BE): entry point is code directly, no function
|
||||
// descriptor needed.
|
||||
#[cfg(all(target_arch = "powerpc64", target_abi = "elfv2"))]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
// Set up TOC (r2) for ELFv2 by computing from current PC
|
||||
"bl 0f",
|
||||
"0: mflr 12",
|
||||
"addis 2, 12, .TOC. - 0b@ha",
|
||||
"addi 2, 2, .TOC. - 0b@l",
|
||||
// Save sp as first arg, set up stack frame
|
||||
"mr 3, 1",
|
||||
"clrrdi 1, 1, 4",
|
||||
"stdu 1, -64(1)",
|
||||
"bl {entry_rust}",
|
||||
"nop",
|
||||
"li 0, 1",
|
||||
"sc",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
// ppc32 has no function descriptors; entry is direct code like ELFv2.
|
||||
#[cfg(target_arch = "powerpc")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
"mr 3, 1", // first arg = initial sp (argc/argv)
|
||||
"clrrwi 1, 1, 4", // align sp to 16 bytes
|
||||
"stwu 1, -64(1)", // reserve a frame with back-chain
|
||||
"bl {entry_rust}",
|
||||
"li 0, 1", // SYS_exit
|
||||
"sc",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
// On ELFv1, the ELF entry point must be a function descriptor
|
||||
// in .opd whose first word is the real code address. We emit both manually via
|
||||
// `global_asm` so the kernel reads the descriptor and jumps into `_start_impl`.
|
||||
#[cfg(all(target_arch = "powerpc64", target_abi = "elfv1"))]
|
||||
core::arch::global_asm!(
|
||||
".section .opd, \"aw\"",
|
||||
".balign 8",
|
||||
".globl _start",
|
||||
".type _start, @object",
|
||||
".size _start, 24",
|
||||
"_start:",
|
||||
" .quad _start_impl",
|
||||
" .quad .TOC.@tocbase",
|
||||
" .quad 0",
|
||||
".previous",
|
||||
".text",
|
||||
".type _start_impl, @function",
|
||||
"_start_impl:",
|
||||
" mr 3, 1",
|
||||
" clrrdi 1, 1, 4",
|
||||
" stdu 1, -64(1)",
|
||||
" bl entry_rust",
|
||||
" nop",
|
||||
" li 0, 1",
|
||||
" sc",
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "arm")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
"mov r0, sp", // first arg = original sp (argc/argv)
|
||||
"bic sp, sp, #7", // align sp to 8 bytes (AAPCS)
|
||||
"bl {entry_rust}",
|
||||
"mov r7, #1", // SYS_exit
|
||||
"svc #0",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
"mv a0, sp", // first arg = original sp (argc/argv)
|
||||
"andi sp, sp, -16", // align sp to 16 bytes
|
||||
"call {entry_rust}",
|
||||
"li a7, 93", // SYS_exit
|
||||
"ecall",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "sparc64")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
// SPARC v9: kernel sets %sp biased by -2047; argc is at
|
||||
// %sp + 2047 + 128 (bias + 128-byte register save area).
|
||||
// See glibc sysdeps/sparc/sparc64/start.S.
|
||||
"mov %g0, %fp",
|
||||
"add %sp, 2047+128, %o0", // first arg = &argc
|
||||
"add %sp, 2047, %sp", // unbias
|
||||
"sub %sp, 176, %sp", // reserve register save area
|
||||
"and %sp, -16, %sp", // align
|
||||
"sub %sp, 2047, %sp", // rebias
|
||||
"call {entry_rust}",
|
||||
"nop", // delay slot
|
||||
"mov 1, %g1", // SYS_exit
|
||||
"t 0x6d",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "mips64")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
"move $a0, $sp", // first arg = original sp (argc/argv)
|
||||
"daddiu $sp, $sp, -16",// reserve + keep 16-byte alignment (N64 ABI)
|
||||
"jal {entry_rust}",
|
||||
"nop", // delay slot
|
||||
"move $a0, $v0", // exit code = entry_rust return value
|
||||
"li $v0, 5058", // SYS_exit (5000 + 58)
|
||||
"syscall",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "sparc")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
"mov %g0, %fp",
|
||||
"add %sp, 64, %o0", // first arg = &argc (past the 64-byte window save)
|
||||
"and %sp, -16, %sp", // align sp to 16 bytes
|
||||
"sub %sp, 64, %sp", // reserve window save area
|
||||
"call {entry_rust}",
|
||||
"nop", // delay slot
|
||||
"mov 1, %g1", // SYS_exit (code already in %o0)
|
||||
"ta 0x10",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
// SPARC V8 has no 1-byte CAS, so rustc emits calls to libatomic for byte
|
||||
// atomics. We're single-threaded with panic=abort, so a plain load/store is
|
||||
// already correct.
|
||||
#[cfg(all(not(test), target_arch = "sparc"))]
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn __atomic_load_1(ptr: *const u8, _order: i32) -> u8 {
|
||||
unsafe { core::ptr::read_volatile(ptr) }
|
||||
}
|
||||
|
||||
#[cfg(all(not(test), target_arch = "sparc"))]
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn __atomic_store_1(ptr: *mut u8, val: u8, _order: i32) {
|
||||
unsafe { core::ptr::write_volatile(ptr, val) }
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "mips")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
"move $a0, $sp", // first arg = original sp (argc/argv)
|
||||
"addiu $sp, $sp, -24", // reserve 16-byte O32 shadow space + align
|
||||
"jal {entry_rust}",
|
||||
"nop", // delay slot
|
||||
"move $a0, $v0", // exit code = entry_rust return value
|
||||
"li $v0, 4001", // SYS_exit (4000 + 1)
|
||||
"syscall",
|
||||
entry_rust = sym entry_rust,
|
||||
);
|
||||
}
|
||||
|
||||
// Global allocator
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: BumpAllocator = BumpAllocator::new();
|
||||
|
|
@ -110,3 +348,14 @@ const extern "C" fn rust_eh_personality() {}
|
|||
extern "C" fn _Unwind_Resume() -> ! {
|
||||
unsafe { sys_exit(1) }
|
||||
}
|
||||
|
||||
// compiler_builtins emits `.ARM.exidx` entries that reference these even
|
||||
// with panic=abort. libgcc/libunwind would normally resolve them; we're
|
||||
// nostdlib, so we stub them. They're never called.
|
||||
#[cfg(all(not(test), target_arch = "arm"))]
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn __aeabi_unwind_cpp_pr0() {}
|
||||
|
||||
#[cfg(all(not(test), target_arch = "arm"))]
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn __aeabi_unwind_cpp_pr1() {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue