Skip to content

Commit

Permalink
detect/riscv_linux: Use asm-based syscall on Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Sep 21, 2024
1 parent c95ffe5 commit 71c3afa
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 194 deletions.
1 change: 1 addition & 0 deletions .github/.cspell/project-dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ cxchgweak
DESTDIR
dlsym
DWCAS
ecall
elems
espup
exynos
Expand Down
60 changes: 4 additions & 56 deletions src/cfgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,20 +166,7 @@ mod atomic_32_macros {
feature = "fallback",
not(portable_atomic_no_outline_atomics),
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
),
any(target_os = "linux", target_os = "android"),
),
),
),
Expand Down Expand Up @@ -242,20 +229,7 @@ mod atomic_64_macros {
feature = "fallback",
not(portable_atomic_no_outline_atomics),
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
),
any(target_os = "linux", target_os = "android"),
),
),
),
Expand Down Expand Up @@ -310,20 +284,7 @@ mod atomic_64_macros {
feature = "fallback",
not(portable_atomic_no_outline_atomics),
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
),
any(target_os = "linux", target_os = "android"),
not(any(miri, portable_atomic_sanitize_thread)),
),
),
Expand Down Expand Up @@ -429,20 +390,7 @@ mod atomic_128_macros {
feature = "fallback",
not(portable_atomic_no_outline_atomics),
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
),
any(target_os = "linux", target_os = "android"),
not(any(miri, portable_atomic_sanitize_thread)),
),
),
Expand Down
15 changes: 1 addition & 14 deletions src/imp/atomic128/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,7 @@ pub(super) mod powerpc64;
feature = "fallback",
not(portable_atomic_no_outline_atomics),
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
),
any(target_os = "linux", target_os = "android"),
not(any(miri, portable_atomic_sanitize_thread)),
),
),
Expand Down
14 changes: 1 addition & 13 deletions src/imp/atomic128/riscv64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ include!("macros.rs");
#[path = "../fallback/outline_atomics.rs"]
mod fallback;

// On musl with static linking, it seems that libc is not always available.
// See detect/auxv.rs for more.
#[cfg(not(portable_atomic_no_outline_atomics))]
#[cfg(any(test, portable_atomic_outline_atomics))] // TODO(riscv): currently disabled by default
#[cfg(any(
Expand All @@ -38,17 +36,7 @@ mod fallback;
portable_atomic_target_feature = "experimental-zacas",
)),
))]
#[cfg(any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static")),
portable_atomic_outline_atomics,
),
),
target_os = "android",
))]
#[cfg(any(target_os = "linux", target_os = "android"))]
#[path = "../detect/riscv_linux.rs"]
mod detect;

Expand Down
15 changes: 1 addition & 14 deletions src/imp/atomic64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,7 @@ pub(super) mod arm_linux;
feature = "fallback",
not(portable_atomic_no_outline_atomics),
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
),
any(target_os = "linux", target_os = "android"),
),
),
))]
Expand Down
14 changes: 1 addition & 13 deletions src/imp/atomic64/riscv32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ include!("macros.rs");
#[path = "../fallback/outline_atomics.rs"]
mod fallback;

// On musl with static linking, it seems that libc is not always available.
// See detect/auxv.rs for more.
#[cfg(not(portable_atomic_no_outline_atomics))]
#[cfg(any(test, portable_atomic_outline_atomics))] // TODO(riscv): currently disabled by default
#[cfg(any(
Expand All @@ -40,17 +38,7 @@ mod fallback;
portable_atomic_target_feature = "experimental-zacas",
)),
))]
#[cfg(any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static")),
portable_atomic_outline_atomics,
),
),
target_os = "android",
))]
#[cfg(any(target_os = "linux", target_os = "android"))]
#[path = "../detect/riscv_linux.rs"]
mod detect;

Expand Down
66 changes: 66 additions & 0 deletions src/imp/detect/riscv_linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod ffi {

// https://github.com/torvalds/linux/blob/v6.11/arch/riscv/include/uapi/asm/hwprobe.h
#[derive(Copy, Clone)]
#[cfg_attr(test, derive(Debug, PartialEq))]
#[repr(C)]
pub(crate) struct riscv_hwprobe {
pub(crate) key: i64,
Expand All @@ -34,10 +35,49 @@ mod ffi {
// https://github.com/torvalds/linux/commit/154a3706122978eeb34d8223d49285ed4f3c61fa
pub(crate) const RISCV_HWPROBE_EXT_ZACAS: u64 = 1 << 34;

#[cfg(not(all(
target_os = "linux",
any(target_arch = "riscv32", all(target_arch = "riscv64", target_pointer_width = "64")),
)))]
extern "C" {
// https://man7.org/linux/man-pages/man2/syscall.2.html
pub(crate) fn syscall(number: c_long, ...) -> c_long;
}
// Use asm-based syscall for compatibility with non-libc targets if possible.
#[cfg(all(
target_os = "linux", // https://github.com/bytecodealliance/rustix/issues/1095
any(target_arch = "riscv32", all(target_arch = "riscv64", target_pointer_width = "64")),
))]
#[inline]
pub(crate) unsafe fn syscall(
number: c_long,
a0: *mut riscv_hwprobe,
a1: c_size_t,
a2: c_size_t,
a3: *mut c_ulong,
a4: c_uint,
) -> c_long {
// arguments must be extended to 64-bit if RV64
let a4 = a4 as usize;
let r;
// SAFETY: the caller must uphold the safety contract.
// Refs:
// - https://github.com/bminor/musl/blob/v1.2.5/arch/riscv32/syscall_arch.h
// - https://github.com/bminor/musl/blob/v1.2.5/arch/riscv64/syscall_arch.h
unsafe {
core::arch::asm!(
"ecall",
in("a7") number,
inout("a0") a0 => r,
in("a1") a1,
in("a2") a2,
in("a3") a3,
in("a4") a4,
options(nostack, preserves_flags)
);
}
r
}

// https://github.com/torvalds/linux/blob/v6.11/Documentation/arch/riscv/hwprobe.rst
pub(crate) unsafe fn __riscv_hwprobe(
Expand Down Expand Up @@ -82,6 +122,32 @@ fn _detect(info: &mut CpuInfo) {
mod tests {
use super::*;

// We use asm-based syscall for compatibility with non-libc targets.
// This test tests that our ones and libc::syscall returns the same result.
#[test]
fn test_linux_like() {
use test_helper::libc;
unsafe fn __libc_riscv_hwprobe(
pairs: *mut ffi::riscv_hwprobe,
pair_count: ffi::c_size_t,
cpu_set_size: ffi::c_size_t,
cpus: *mut ffi::c_ulong,
flags: ffi::c_uint,
) -> ffi::c_long {
// SAFETY: the caller must uphold the safety contract.
unsafe {
libc::syscall(ffi::__NR_riscv_hwprobe, pairs, pair_count, cpu_set_size, cpus, flags)
}
}
fn libc_riscv_hwprobe(out: &mut ffi::riscv_hwprobe) -> bool {
unsafe { __libc_riscv_hwprobe(out, 1, 0, ptr::null_mut(), 0) == 0 }
}
let mut out = ffi::riscv_hwprobe { key: ffi::RISCV_HWPROBE_KEY_IMA_EXT_0, value: 0 };
let mut libc_out = ffi::riscv_hwprobe { key: ffi::RISCV_HWPROBE_KEY_IMA_EXT_0, value: 0 };
assert_eq!(riscv_hwprobe(&mut out), libc_riscv_hwprobe(&mut libc_out));
assert_eq!(out, libc_out);
}

// Static assertions for FFI bindings.
// This checks that FFI bindings defined in this crate, FFI bindings defined
// in libc, and FFI bindings generated for the platform's latest header file
Expand Down
30 changes: 2 additions & 28 deletions src/imp/fallback/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,7 @@ type and the value type must be the same.
feature = "fallback",
not(portable_atomic_no_outline_atomics),
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
),
any(target_os = "linux", target_os = "android"),
),
),
),
Expand All @@ -83,20 +70,7 @@ type and the value type must be the same.
feature = "fallback",
not(portable_atomic_no_outline_atomics),
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
any(
all(
target_os = "linux",
any(
target_env = "gnu",
all(
any(target_env = "musl", target_env = "ohos"),
not(target_feature = "crt-static"),
),
portable_atomic_outline_atomics,
),
),
target_os = "android",
),
any(target_os = "linux", target_os = "android"),
not(any(miri, portable_atomic_sanitize_thread)),
),
),
Expand Down
Loading

0 comments on commit 71c3afa

Please sign in to comment.