Skip to content

Commit

Permalink
cpufeatures: Add support for LoongArch64 (#955)
Browse files Browse the repository at this point in the history
  • Loading branch information
heiher authored Oct 20, 2023
1 parent 7d6927b commit 68cc2d8
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 10 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions cpufeatures/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
22 changes: 21 additions & 1 deletion cpufeatures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down
34 changes: 32 additions & 2 deletions cpufeatures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -107,15 +127,25 @@
#[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;

#[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]
Expand Down
106 changes: 106 additions & 0 deletions cpufeatures/src/loongarch64.rs
Original file line number Diff line number Diff line change
@@ -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
};
}
20 changes: 20 additions & 0 deletions cpufeatures/tests/loongarch64.rs
Original file line number Diff line number Diff line change
@@ -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());
}

0 comments on commit 68cc2d8

Please sign in to comment.