ostd/arch/x86/cpu/
extension.rs1use core::arch::x86_64::CpuidResult;
6
7use bitflags::bitflags;
8use spin::Once;
9
10use super::cpuid::cpuid;
11
12pub(in crate::arch) fn init() {
14 let mut global_isa_extensions = IsaExtensions::empty();
15
16 for ext_leaf in EXTENSION_TABLE.iter() {
17 let Some(CpuidResult { ebx, ecx, edx, .. }) = cpuid(ext_leaf.leaf, ext_leaf.subleaf) else {
18 continue;
19 };
20
21 for ext_data in ext_leaf.data.iter() {
22 let bits = match ext_data.reg {
23 Reg::Ebx => ebx,
24 Reg::Ecx => ecx,
25 Reg::Edx => edx,
26 };
27 if bits & (1 << ext_data.bit) != 0 {
28 global_isa_extensions |= ext_data.flag;
29 }
30 }
31 }
32
33 log::info!("Detected ISA extensions: {:?}", global_isa_extensions);
34
35 GLOBAL_ISA_EXTENSIONS.call_once(|| global_isa_extensions);
36}
37
38pub fn has_extensions(required: IsaExtensions) -> bool {
40 GLOBAL_ISA_EXTENSIONS.get().unwrap().contains(required)
41}
42
43static GLOBAL_ISA_EXTENSIONS: Once<IsaExtensions> = Once::new();
44
45macro_rules! define_isa_extensions {
46 { $(leaf $leaf:literal, subleaf $subleaf:literal => {
47 $($name:ident, $reg:ident ($bit:literal), $doc:literal; )*
48 })* } => {
49 define_isa_extension_type! {
50 $($($name, $doc;)*)*
51 }
52
53 const EXTENSION_TABLE: &[ExtensionLeaf] = &[
54 $(ExtensionLeaf {
55 leaf: $leaf,
56 subleaf: $subleaf,
57 data: &[
58 $(ExtensionData {
59 reg: Reg::$reg,
60 bit: $bit,
61 flag: IsaExtensions::$name,
62 },)*
63 ]
64 },)*
65 ];
66 };
67}
68
69macro_rules! define_isa_extension_type {
70 { $($name:ident, $doc:literal;)* } => {
71 bitflags! {
72 pub struct IsaExtensions: u128 {
74 $(
75 #[doc = $doc]
76 const $name = 1u128 << ${index()};
77 )*
78 }
79 }
80 };
81}
82
83struct ExtensionLeaf {
85 leaf: u32,
86 subleaf: u32,
87 data: &'static [ExtensionData],
88}
89
90struct ExtensionData {
92 reg: Reg,
93 bit: u32,
94 flag: IsaExtensions,
95}
96
97enum Reg {
98 Ebx,
99 Ecx,
100 Edx,
101}
102
103define_isa_extensions! {
104 leaf 1, subleaf 0 => {
105 X2APIC, Ecx(21), "The processor supports x2APIC feature.";
106 TSC_DEADLINE, Ecx(24), "The processor's local APIC timer supports \
107 one-shot operation using a TSC deadline value.";
108 XSAVE, Ecx(26), "The processor supports the XSAVE/XRSTOR \
109 processor extended states feature, \
110 the XSETBV/XGETBV instructions, and XCR0.";
111 AVX, Ecx(28), "The processor supports the AVX instruction extensions.";
112 RDRAND, Ecx(30), "The processor supports RDRAND instruction.";
113
114 XAPIC, Edx( 9), "APIC On-Chip.";
115 }
116
117 leaf 7, subleaf 0 => {
118 FSGSBASE, Ebx( 0), "Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE.";
119 AVX512F, Ebx(16), "Supports the AVX512F instruction extensions.";
120 }
121}