mirror of
https://github.com/NotAShelf/microfetch.git
synced 2026-04-27 10:55:20 +00:00
arch: add s390x support
This commit is contained in:
parent
ce7a8553a8
commit
05fc3d8df9
5 changed files with 214 additions and 6 deletions
1
.github/workflows/rust.yml
vendored
1
.github/workflows/rust.yml
vendored
|
|
@ -21,6 +21,7 @@ jobs:
|
|||
- aarch64-unknown-linux-gnu
|
||||
- riscv64gc-unknown-linux-gnu
|
||||
- loongarch64-unknown-linux-gnu
|
||||
- s390x-unknown-linux-gnu
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
//! What do you mean I wasted two whole hours to make the program only 100µs
|
||||
//! faster?
|
||||
//!
|
||||
//! Supports `x86_64`, `aarch64`, `riscv64`, and `loongarch64` architectures.
|
||||
//! Supports `x86_64`, `aarch64`, `riscv64`, `loongarch64`, and `s390x`
|
||||
//! architectures.
|
||||
|
||||
#![no_std]
|
||||
|
||||
|
|
@ -14,11 +15,12 @@
|
|||
target_arch = "x86_64",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "loongarch64"
|
||||
target_arch = "loongarch64",
|
||||
target_arch = "s390x"
|
||||
)))]
|
||||
compile_error!(
|
||||
"Unsupported architecture: only x86_64, aarch64, riscv64, and loongarch64 \
|
||||
are supported"
|
||||
"Unsupported architecture: only x86_64, aarch64, riscv64, loongarch64, and \
|
||||
s390x are supported"
|
||||
);
|
||||
|
||||
// Per-arch syscall implementations live in their own module files.
|
||||
|
|
@ -34,6 +36,9 @@ mod arch;
|
|||
#[cfg(target_arch = "loongarch64")]
|
||||
#[path = "loongarch64.rs"]
|
||||
mod arch;
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[path = "s390x.rs"]
|
||||
mod arch;
|
||||
|
||||
/// Copies `n` bytes from `src` to `dest`.
|
||||
///
|
||||
|
|
@ -267,6 +272,7 @@ 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(target_arch = "s390x"))]
|
||||
pub struct StatfsBuf {
|
||||
pub f_type: i64,
|
||||
pub f_bsize: i64,
|
||||
|
|
@ -284,6 +290,26 @@ 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],
|
||||
}
|
||||
|
||||
/// Direct `statfs(2)` syscall
|
||||
///
|
||||
/// # Returns
|
||||
|
|
|
|||
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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -140,10 +140,15 @@ fn get_cpu_freq_mhz() -> Option<u32> {
|
|||
}
|
||||
}
|
||||
// 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",
|
||||
] {
|
||||
if let Some(val) = extract_field(data, key) {
|
||||
// Parse integer part of the MHz value (e.g. "5200.00" -> 5200)
|
||||
let mut mhz = 0u32;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,22 @@ unsafe extern "C" fn _start() {
|
|||
);
|
||||
}
|
||||
|
||||
#[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,
|
||||
);
|
||||
}
|
||||
|
||||
// Global allocator
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: BumpAllocator = BumpAllocator::new();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue