Skip to content

Commit

Permalink
cpufeatures: Add support for LoongArch64
Browse files Browse the repository at this point in the history
  • Loading branch information
heiher committed Oct 7, 2023
1 parent c19c5cc commit 93955ea
Show file tree
Hide file tree
Showing 6 changed files with 187 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 x86/x86_64/aarch64 and loongarch64
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"
21 changes: 20 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,25 @@ 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`

## `x86`/`x86_64`

OS independent and `no_std`-friendly
Expand Down
33 changes: 31 additions & 2 deletions cpufeatures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,25 @@
//! - `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`
//!
//! ## `x86`/`x86_64`
//!
//! OS independent and `no_std`-friendly
Expand Down Expand Up @@ -107,15 +126,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 93955ea

Please sign in to comment.