Skip to content

Commit 68cc2d8

Browse files
authored
cpufeatures: Add support for LoongArch64 (#955)
1 parent 7d6927b commit 68cc2d8

File tree

6 files changed

+189
-10
lines changed

6 files changed

+189
-10
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cpufeatures/Cargo.toml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
name = "cpufeatures"
33
version = "0.2.9"
44
description = """
5-
Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with
6-
no_std support and support for mobile targets including Android and iOS
5+
Lightweight runtime CPU feature detection for aarch64, loongarch64, and x86/x86_64 targets,
6+
with no_std support and support for mobile targets including Android and iOS
77
"""
88
authors = ["RustCrypto Developers"]
99
license = "MIT OR Apache-2.0"
@@ -15,10 +15,13 @@ edition = "2018"
1515
readme = "README.md"
1616

1717
[target.'cfg(all(target_arch = "aarch64", target_vendor = "apple"))'.dependencies]
18-
libc = "0.2.95"
18+
libc = "0.2.149"
1919

2020
[target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'.dependencies]
21-
libc = "0.2.95"
21+
libc = "0.2.149"
22+
23+
[target.'cfg(all(target_arch = "loongarch64", target_os = "linux"))'.dependencies]
24+
libc = "0.2.149"
2225

2326
[target.aarch64-linux-android.dependencies]
24-
libc = "0.2.95"
27+
libc = "0.2.149"

cpufeatures/README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[![Project Chat][chat-image]][chat-link]
88
[![Build Status][build-image]][build-link]
99

10-
Lightweight and efficient runtime CPU feature detection for `aarch64` and
10+
Lightweight and efficient runtime CPU feature detection for `aarch64`, `loongarch64`, and
1111
`x86`/`x86_64` targets.
1212

1313
Supports `no_std` as well as mobile targets including iOS and Android,
@@ -31,6 +31,26 @@ Target features:
3131
- `sha2`*
3232
- `sha3`*
3333

34+
## `loongarch64`
35+
36+
Linux only (LoongArch64 does not support OS-independent feature detection)
37+
38+
Target features:
39+
40+
- `lam`*
41+
- `ual`*
42+
- `fpu`*
43+
- `lsx`*
44+
- `lasx`*
45+
- `crc32`*
46+
- `complex`*
47+
- `crypto`*
48+
- `lvz`*
49+
- `lbt.x86`*
50+
- `lbt.arm`*
51+
- `lbt.mips`*
52+
- `ptw`*
53+
3454
## `x86`/`x86_64`
3555

3656
OS independent and `no_std`-friendly

cpufeatures/src/lib.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@
1818
//! - `sha2`*
1919
//! - `sha3`*
2020
//!
21+
//! ## `loongarch64`
22+
//!
23+
//! Linux only (LoongArch64 does not support OS-independent feature detection)
24+
//!
25+
//! Target features:
26+
//!
27+
//! - `lam`*
28+
//! - `ual`*
29+
//! - `fpu`*
30+
//! - `lsx`*
31+
//! - `lasx`*
32+
//! - `crc32`*
33+
//! - `complex`*
34+
//! - `crypto`*
35+
//! - `lvz`*
36+
//! - `lbt.x86`*
37+
//! - `lbt.arm`*
38+
//! - `lbt.mips`*
39+
//! - `ptw`*
40+
//!
2141
//! ## `x86`/`x86_64`
2242
//!
2343
//! OS independent and `no_std`-friendly
@@ -107,15 +127,25 @@
107127
#[doc(hidden)]
108128
pub mod aarch64;
109129

130+
#[cfg(not(miri))]
131+
#[cfg(target_arch = "loongarch64")]
132+
#[doc(hidden)]
133+
pub mod loongarch64;
134+
110135
#[cfg(not(miri))]
111136
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
112137
mod x86;
113138

114139
#[cfg(miri)]
115140
mod miri;
116141

117-
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")))]
118-
compile_error!("This crate works only on `aarch64`, `x86`, and `x86-64` targets.");
142+
#[cfg(not(any(
143+
target_arch = "aarch64",
144+
target_arch = "loongarch64",
145+
target_arch = "x86",
146+
target_arch = "x86_64"
147+
)))]
148+
compile_error!("This crate works only on `aarch64`, `loongarch64`, `x86`, and `x86-64` targets.");
119149

120150
/// Create module with CPU feature detection code.
121151
#[macro_export]

cpufeatures/src/loongarch64.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//! LoongArch64 CPU feature detection support.
2+
//!
3+
//! This implementation relies on OS-specific APIs for feature detection.
4+
5+
// Evaluate the given `$body` expression any of the supplied target features
6+
// are not enabled. Otherwise returns true.
7+
#[macro_export]
8+
#[doc(hidden)]
9+
macro_rules! __unless_target_features {
10+
($($tf:tt),+ => $body:expr ) => {
11+
{
12+
#[cfg(not(all($(target_feature=$tf,)*)))]
13+
$body
14+
15+
#[cfg(all($(target_feature=$tf,)*))]
16+
true
17+
}
18+
};
19+
}
20+
21+
// Linux runtime detection of target CPU features using `getauxval`.
22+
#[cfg(target_os = "linux")]
23+
#[macro_export]
24+
#[doc(hidden)]
25+
macro_rules! __detect_target_features {
26+
($($tf:tt),+) => {{
27+
let hwcaps = $crate::loongarch64::getauxval_hwcap();
28+
$($crate::check!(hwcaps, $tf) & )+ true
29+
}};
30+
}
31+
32+
/// Linux helper function for calling `getauxval` to get `AT_HWCAP`.
33+
#[cfg(target_os = "linux")]
34+
pub fn getauxval_hwcap() -> u64 {
35+
unsafe { libc::getauxval(libc::AT_HWCAP) }
36+
}
37+
38+
// Linux `expand_check_macro`
39+
#[cfg(target_os = "linux")]
40+
macro_rules! __expand_check_macro {
41+
($(($name:tt, $hwcap:ident)),* $(,)?) => {
42+
#[macro_export]
43+
#[doc(hidden)]
44+
macro_rules! check {
45+
$(
46+
($hwcaps:expr, $name) => {
47+
(($hwcaps & $crate::loongarch64::hwcaps::$hwcap) != 0)
48+
};
49+
)*
50+
}
51+
};
52+
}
53+
54+
// Linux `expand_check_macro`
55+
#[cfg(target_os = "linux")]
56+
__expand_check_macro! {
57+
("cpucfg", CPUCFG), // Enable CPUCFG support.
58+
("lam", LAM), // Enable LAM support.
59+
("ual", UAL), // Enable UAL support.
60+
("fpu", FPU), // Enable FPU support.
61+
("lsx", LSX), // Enable LSX support.
62+
("lasx", LASX), // Enable LASX support.
63+
("crc32", CRC32), // Enable CRC32 support.
64+
("complex", COMPLEX), // Enable COMPLEX support.
65+
("crypto", CRYPTO), // Enable CRYPTO support.
66+
("lvz", LVZ), // Enable LVZ support.
67+
("lbt.x86", LBT_X86), // Enable LBT_X86 support.
68+
("lbt.arm", LBT_ARM), // Enable LBT_ARM support.
69+
("lbt.mips", LBT_MIPS), // Enable LBT_MIPS support.
70+
("ptw", PTW), // Enable PTW support.
71+
}
72+
73+
/// Linux hardware capabilities mapped to target features.
74+
///
75+
/// Note that LLVM target features are coarser grained than what Linux supports
76+
/// and imply more capabilities under each feature. This module attempts to
77+
/// provide that mapping accordingly.
78+
#[cfg(target_os = "linux")]
79+
pub mod hwcaps {
80+
use libc::c_ulong;
81+
82+
pub const CPUCFG: c_ulong = libc::HWCAP_CPUCFG;
83+
pub const LAM: c_ulong = libc::HWCAP_LAM;
84+
pub const UAL: c_ulong = libc::HWCAP_UAL;
85+
pub const FPU: c_ulong = libc::HWCAP_FPU;
86+
pub const LSX: c_ulong = libc::HWCAP_LSX;
87+
pub const LASX: c_ulong = libc::HWCAP_LASX;
88+
pub const CRC32: c_ulong = libc::HWCAP_CRC32;
89+
pub const COMPLEX: c_ulong = libc::HWCAP_COMPLEX;
90+
pub const CRYPTO: c_ulong = libc::HWCAP_CRYPTO;
91+
pub const LVZ: c_ulong = libc::HWCAP_LVZ;
92+
pub const LBT_X86: c_ulong = libc::HWCAP_LBT_X86;
93+
pub const LBT_ARM: c_ulong = libc::HWCAP_LBT_ARM;
94+
pub const LBT_MIPS: c_ulong = libc::HWCAP_LBT_MIPS;
95+
pub const PTW: c_ulong = libc::HWCAP_PTW;
96+
}
97+
98+
// On other targets, runtime CPU feature detection is unavailable
99+
#[cfg(not(target_os = "linux"))]
100+
#[macro_export]
101+
#[doc(hidden)]
102+
macro_rules! __detect_target_features {
103+
($($tf:tt),+) => {
104+
false
105+
};
106+
}

cpufeatures/tests/loongarch64.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//! LoongArch64 tests
2+
3+
#![cfg(target_arch = "loongarch64")]
4+
5+
cpufeatures::new!(
6+
lacaps, "cpucfg", "lam", "ual", "fpu", "lsx", "lasx", "crc32", "complex", "crypto", "lvz",
7+
"lbt.x86", "lbt.arm", "lbt.mips", "ptw"
8+
);
9+
10+
#[test]
11+
fn init() {
12+
let token: lacaps::InitToken = lacaps::init();
13+
assert_eq!(token.get(), lacaps::get());
14+
}
15+
16+
#[test]
17+
fn init_get() {
18+
let (token, val) = lacaps::init_get();
19+
assert_eq!(val, token.get());
20+
}

0 commit comments

Comments
 (0)