diff --git a/Cargo.lock b/Cargo.lock index dddc5b2f..4950d81b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,9 +115,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "opaque-debug" diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index 20ff471d..73e90b8e 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -2,8 +2,8 @@ name = "cpufeatures" version = "0.2.9" description = """ -Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with -no_std support and support for mobile targets including Android and iOS +Lightweight runtime CPU feature detection for aarch64, loongarch64, and x86/x86_64 targets, +with no_std support and support for mobile targets including Android and iOS """ authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -15,10 +15,13 @@ edition = "2018" readme = "README.md" [target.'cfg(all(target_arch = "aarch64", target_vendor = "apple"))'.dependencies] -libc = "0.2.95" +libc = "0.2.149" [target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'.dependencies] -libc = "0.2.95" +libc = "0.2.149" + +[target.'cfg(all(target_arch = "loongarch64", target_os = "linux"))'.dependencies] +libc = "0.2.149" [target.aarch64-linux-android.dependencies] -libc = "0.2.95" +libc = "0.2.149" diff --git a/cpufeatures/README.md b/cpufeatures/README.md index c8d89b08..f199636a 100644 --- a/cpufeatures/README.md +++ b/cpufeatures/README.md @@ -7,7 +7,7 @@ [![Project Chat][chat-image]][chat-link] [![Build Status][build-image]][build-link] -Lightweight and efficient runtime CPU feature detection for `aarch64` and +Lightweight and efficient runtime CPU feature detection for `aarch64`, `loongarch64`, and `x86`/`x86_64` targets. Supports `no_std` as well as mobile targets including iOS and Android, @@ -31,6 +31,26 @@ Target features: - `sha2`* - `sha3`* +## `loongarch64` + +Linux only (LoongArch64 does not support OS-independent feature detection) + +Target features: + +- `lam`* +- `ual`* +- `fpu`* +- `lsx`* +- `lasx`* +- `crc32`* +- `complex`* +- `crypto`* +- `lvz`* +- `lbt.x86`* +- `lbt.arm`* +- `lbt.mips`* +- `ptw`* + ## `x86`/`x86_64` OS independent and `no_std`-friendly diff --git a/cpufeatures/src/lib.rs b/cpufeatures/src/lib.rs index 18bdc7e3..4c916f45 100644 --- a/cpufeatures/src/lib.rs +++ b/cpufeatures/src/lib.rs @@ -18,6 +18,26 @@ //! - `sha2`* //! - `sha3`* //! +//! ## `loongarch64` +//! +//! Linux only (LoongArch64 does not support OS-independent feature detection) +//! +//! Target features: +//! +//! - `lam`* +//! - `ual`* +//! - `fpu`* +//! - `lsx`* +//! - `lasx`* +//! - `crc32`* +//! - `complex`* +//! - `crypto`* +//! - `lvz`* +//! - `lbt.x86`* +//! - `lbt.arm`* +//! - `lbt.mips`* +//! - `ptw`* +//! //! ## `x86`/`x86_64` //! //! OS independent and `no_std`-friendly @@ -107,6 +127,11 @@ #[doc(hidden)] pub mod aarch64; +#[cfg(not(miri))] +#[cfg(target_arch = "loongarch64")] +#[doc(hidden)] +pub mod loongarch64; + #[cfg(not(miri))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod x86; @@ -114,8 +139,13 @@ mod x86; #[cfg(miri)] mod miri; -#[cfg(not(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")))] -compile_error!("This crate works only on `aarch64`, `x86`, and `x86-64` targets."); +#[cfg(not(any( + target_arch = "aarch64", + target_arch = "loongarch64", + target_arch = "x86", + target_arch = "x86_64" +)))] +compile_error!("This crate works only on `aarch64`, `loongarch64`, `x86`, and `x86-64` targets."); /// Create module with CPU feature detection code. #[macro_export] diff --git a/cpufeatures/src/loongarch64.rs b/cpufeatures/src/loongarch64.rs new file mode 100644 index 00000000..51398d74 --- /dev/null +++ b/cpufeatures/src/loongarch64.rs @@ -0,0 +1,106 @@ +//! LoongArch64 CPU feature detection support. +//! +//! This implementation relies on OS-specific APIs for feature detection. + +// Evaluate the given `$body` expression any of the supplied target features +// are not enabled. Otherwise returns true. +#[macro_export] +#[doc(hidden)] +macro_rules! __unless_target_features { + ($($tf:tt),+ => $body:expr ) => { + { + #[cfg(not(all($(target_feature=$tf,)*)))] + $body + + #[cfg(all($(target_feature=$tf,)*))] + true + } + }; +} + +// Linux runtime detection of target CPU features using `getauxval`. +#[cfg(target_os = "linux")] +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => {{ + let hwcaps = $crate::loongarch64::getauxval_hwcap(); + $($crate::check!(hwcaps, $tf) & )+ true + }}; +} + +/// Linux helper function for calling `getauxval` to get `AT_HWCAP`. +#[cfg(target_os = "linux")] +pub fn getauxval_hwcap() -> u64 { + unsafe { libc::getauxval(libc::AT_HWCAP) } +} + +// Linux `expand_check_macro` +#[cfg(target_os = "linux")] +macro_rules! __expand_check_macro { + ($(($name:tt, $hwcap:ident)),* $(,)?) => { + #[macro_export] + #[doc(hidden)] + macro_rules! check { + $( + ($hwcaps:expr, $name) => { + (($hwcaps & $crate::loongarch64::hwcaps::$hwcap) != 0) + }; + )* + } + }; +} + +// Linux `expand_check_macro` +#[cfg(target_os = "linux")] +__expand_check_macro! { + ("cpucfg", CPUCFG), // Enable CPUCFG support. + ("lam", LAM), // Enable LAM support. + ("ual", UAL), // Enable UAL support. + ("fpu", FPU), // Enable FPU support. + ("lsx", LSX), // Enable LSX support. + ("lasx", LASX), // Enable LASX support. + ("crc32", CRC32), // Enable CRC32 support. + ("complex", COMPLEX), // Enable COMPLEX support. + ("crypto", CRYPTO), // Enable CRYPTO support. + ("lvz", LVZ), // Enable LVZ support. + ("lbt.x86", LBT_X86), // Enable LBT_X86 support. + ("lbt.arm", LBT_ARM), // Enable LBT_ARM support. + ("lbt.mips", LBT_MIPS), // Enable LBT_MIPS support. + ("ptw", PTW), // Enable PTW support. +} + +/// Linux hardware capabilities mapped to target features. +/// +/// Note that LLVM target features are coarser grained than what Linux supports +/// and imply more capabilities under each feature. This module attempts to +/// provide that mapping accordingly. +#[cfg(target_os = "linux")] +pub mod hwcaps { + use libc::c_ulong; + + pub const CPUCFG: c_ulong = libc::HWCAP_CPUCFG; + pub const LAM: c_ulong = libc::HWCAP_LAM; + pub const UAL: c_ulong = libc::HWCAP_UAL; + pub const FPU: c_ulong = libc::HWCAP_FPU; + pub const LSX: c_ulong = libc::HWCAP_LSX; + pub const LASX: c_ulong = libc::HWCAP_LASX; + pub const CRC32: c_ulong = libc::HWCAP_CRC32; + pub const COMPLEX: c_ulong = libc::HWCAP_COMPLEX; + pub const CRYPTO: c_ulong = libc::HWCAP_CRYPTO; + pub const LVZ: c_ulong = libc::HWCAP_LVZ; + pub const LBT_X86: c_ulong = libc::HWCAP_LBT_X86; + pub const LBT_ARM: c_ulong = libc::HWCAP_LBT_ARM; + pub const LBT_MIPS: c_ulong = libc::HWCAP_LBT_MIPS; + pub const PTW: c_ulong = libc::HWCAP_PTW; +} + +// On other targets, runtime CPU feature detection is unavailable +#[cfg(not(target_os = "linux"))] +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => { + false + }; +} diff --git a/cpufeatures/tests/loongarch64.rs b/cpufeatures/tests/loongarch64.rs new file mode 100644 index 00000000..fbcbe9d3 --- /dev/null +++ b/cpufeatures/tests/loongarch64.rs @@ -0,0 +1,20 @@ +//! LoongArch64 tests + +#![cfg(target_arch = "loongarch64")] + +cpufeatures::new!( + lacaps, "cpucfg", "lam", "ual", "fpu", "lsx", "lasx", "crc32", "complex", "crypto", "lvz", + "lbt.x86", "lbt.arm", "lbt.mips", "ptw" +); + +#[test] +fn init() { + let token: lacaps::InitToken = lacaps::init(); + assert_eq!(token.get(), lacaps::get()); +} + +#[test] +fn init_get() { + let (token, val) = lacaps::init_get(); + assert_eq!(val, token.get()); +}