Skip to content

Commit 807fa5b

Browse files
committed
cpufeatures: add support for avx10.1, avx10.2, avx10.1-512 and evex512
1 parent 03a330e commit 807fa5b

3 files changed

Lines changed: 175 additions & 1 deletion

File tree

cpufeatures/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ Target features:
101101
- `adx`
102102
- `aes`
103103
- `avx`
104+
- `avx10.1`*
105+
- `avx10.2`*
106+
- `avx10.1-512`*
107+
- `evex512`*
104108
- `avx2`
105109
- `avx512bw`*
106110
- `avx512cd`*

cpufeatures/src/x86.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ macro_rules! __detect_target_features {
4747
}
4848

4949
let cr = unsafe {
50-
[cpuid(1), cpuid_count(7, 0), cpuid_count(7, 1)]
50+
[
51+
cpuid(1),
52+
cpuid_count(7, 0),
53+
cpuid_count(7, 1),
54+
cpuid(0),
55+
cpuid_count(0x24, 0),
56+
]
5157
};
5258

5359
$($crate::check!(cr, $tf) & )+ true
@@ -81,6 +87,34 @@ macro_rules! __expand_check_macro {
8187
#[macro_export]
8288
#[doc(hidden)]
8389
macro_rules! check {
90+
($cr:expr, "avx10.1") => {{
91+
$crate::__xgetbv!($cr, 0b110)
92+
& ($cr[3].eax >= 0x24)
93+
& ($cr[2].edx & (1 << 19) != 0)
94+
& (($cr[4].ebx & 0xff) >= 1)
95+
& (($cr[4].ebx & ((1 << 17) | (1 << 18))) != 0)
96+
}};
97+
($cr:expr, "avx10.2") => {{
98+
$crate::__xgetbv!($cr, 0b110)
99+
& ($cr[3].eax >= 0x24)
100+
& ($cr[2].edx & (1 << 19) != 0)
101+
& (($cr[4].ebx & 0xff) >= 2)
102+
& (($cr[4].ebx & ((1 << 17) | (1 << 18))) != 0)
103+
}};
104+
($cr:expr, "evex512") => {{
105+
$crate::__xgetbv!($cr, 0b1110_0110)
106+
& ($cr[3].eax >= 0x24)
107+
& ($cr[2].edx & (1 << 19) != 0)
108+
& (($cr[4].ebx & 0xff) >= 1)
109+
& (($cr[4].ebx & (1 << 18)) != 0)
110+
}};
111+
($cr:expr, "avx10.1-512") => {{
112+
$crate::__xgetbv!($cr, 0b1110_0110)
113+
& ($cr[3].eax >= 0x24)
114+
& ($cr[2].edx & (1 << 19) != 0)
115+
& (($cr[4].ebx & 0xff) >= 1)
116+
& (($cr[4].ebx & (1 << 18)) != 0)
117+
}};
84118
$(
85119
($cr:expr, $name) => {{
86120
// Register bits are listed here:

cpufeatures/tests/x86.rs

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
44

55
cpufeatures::new!(cpuid, "aes", "sha");
6+
cpufeatures::new!(cpuid_avx10, "avx10.1", "avx10.2");
67

78
#[test]
89
fn init() {
@@ -15,3 +16,138 @@ fn init_get() {
1516
let (token, val) = cpuid::init_get();
1617
assert_eq!(val, token.get());
1718
}
19+
20+
#[test]
21+
fn avx10_probe_does_not_fault() {
22+
let (token, val) = cpuid_avx10::init_get();
23+
assert_eq!(val, token.get());
24+
let _ = cpuid_avx10::get();
25+
}
26+
27+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
28+
mod avx10_logic {
29+
#[cfg(target_arch = "x86")]
30+
use core::arch::x86::{__cpuid, __cpuid_count, CpuidResult};
31+
#[cfg(target_arch = "x86_64")]
32+
use core::arch::x86_64::{__cpuid, __cpuid_count, CpuidResult};
33+
34+
fn leaf1() -> CpuidResult {
35+
CpuidResult {
36+
eax: 0,
37+
ebx: 0,
38+
ecx: 0b11 << 26,
39+
edx: 0,
40+
}
41+
}
42+
43+
fn blank() -> CpuidResult {
44+
CpuidResult {
45+
eax: 0,
46+
ebx: 0,
47+
ecx: 0,
48+
edx: 0,
49+
}
50+
}
51+
52+
#[test]
53+
fn version_zero_is_disabled() {
54+
let cr = [
55+
leaf1(),
56+
blank(),
57+
CpuidResult {
58+
eax: 0,
59+
ebx: 0,
60+
ecx: 0,
61+
edx: 1 << 19,
62+
},
63+
CpuidResult {
64+
eax: 0x24,
65+
ebx: 0,
66+
ecx: 0,
67+
edx: 0,
68+
},
69+
CpuidResult {
70+
eax: 0,
71+
ebx: (1 << 17) | (1 << 18),
72+
ecx: 0,
73+
edx: 0,
74+
},
75+
];
76+
assert!(!cpufeatures::check!(cr, "avx10.1"));
77+
assert!(!cpufeatures::check!(cr, "avx10.2"));
78+
assert!(!cpufeatures::check!(cr, "avx10.1-512"));
79+
assert!(!cpufeatures::check!(cr, "evex512"));
80+
}
81+
82+
#[test]
83+
fn max_leaf_guard_holds() {
84+
let cr = [
85+
leaf1(),
86+
blank(),
87+
CpuidResult {
88+
eax: 0,
89+
ebx: 0,
90+
ecx: 0,
91+
edx: 1 << 19,
92+
},
93+
CpuidResult {
94+
eax: 0x16,
95+
ebx: 0,
96+
ecx: 0,
97+
edx: 0,
98+
},
99+
CpuidResult {
100+
eax: 0,
101+
ebx: 1 | (1 << 17) | (1 << 18),
102+
ecx: 0,
103+
edx: 0,
104+
},
105+
];
106+
assert!(!cpufeatures::check!(cr, "avx10.1"));
107+
assert!(!cpufeatures::check!(cr, "avx10.2"));
108+
assert!(!cpufeatures::check!(cr, "avx10.1-512"));
109+
assert!(!cpufeatures::check!(cr, "evex512"));
110+
}
111+
112+
#[test]
113+
fn presence_bit_required() {
114+
let cr = [
115+
leaf1(),
116+
blank(),
117+
blank(),
118+
CpuidResult {
119+
eax: 0x24,
120+
ebx: 0,
121+
ecx: 0,
122+
edx: 0,
123+
},
124+
CpuidResult {
125+
eax: 0,
126+
ebx: 1 | (1 << 17) | (1 << 18),
127+
ecx: 0,
128+
edx: 0,
129+
},
130+
];
131+
assert!(!cpufeatures::check!(cr, "avx10.1"));
132+
assert!(!cpufeatures::check!(cr, "avx10.2"));
133+
assert!(!cpufeatures::check!(cr, "avx10.1-512"));
134+
assert!(!cpufeatures::check!(cr, "evex512"));
135+
}
136+
137+
#[test]
138+
fn tier_512_implies_avx10_1_on_real_host() {
139+
let cr = [
140+
__cpuid(1),
141+
__cpuid_count(7, 0),
142+
__cpuid_count(7, 1),
143+
__cpuid(0),
144+
__cpuid_count(0x24, 0),
145+
];
146+
if cpufeatures::check!(cr, "avx10.1-512") {
147+
assert!(cpufeatures::check!(cr, "avx10.1"));
148+
}
149+
if cpufeatures::check!(cr, "evex512") {
150+
assert!(cpufeatures::check!(cr, "avx10.1"));
151+
}
152+
}
153+
}

0 commit comments

Comments
 (0)