mac_sys_info/structs/
cpu_features_info.rs

1/*
2MIT License
3
4Copyright (c) 2020 Philipp Schuster
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25//! CPU-Features info. More detailed/in-depth functionality about the CPU
26//! like specific instructions like AVX on x86.
27
28use derive_more::Display as DeriveMoreDisplay;
29use serde::{Serialize};
30use std::collections::BTreeMap;
31use crate::error::MacSysInfoError;
32use crate::parse::{parse_sysctl_value, ParseAsType};
33use crate::generated_sysctl_keys::SysctlKey;
34use crate::structs::CpuArchitectureInfo;
35
36/// Encapsulates the CPU features for the current processor.
37#[derive(Debug, Serialize, DeriveMoreDisplay)]
38#[allow(non_camel_case_types)]
39pub enum CpuFeaturesInfo {
40    /// Apple Silicon
41    // #[display(fmt = "AppleSi(\n{}\n)", _0)]
42    AppleSi(AppleSiCpuFeaturesInfo),
43    // #[display(fmt = "X86(\n{}\n)", _0)]
44    /// x86_64
45    x86_64(X86_64CpuFeaturesInfo),
46}
47
48impl CpuFeaturesInfo {
49
50    /// Constructor.
51    pub(crate) fn new(sysinfo: &BTreeMap<String, String>) -> Result<Self, MacSysInfoError> {
52        let arch = CpuArchitectureInfo::determine_architecture(sysinfo)?;
53        if arch.is_x86_64() {
54            Ok(
55                CpuFeaturesInfo::x86_64(
56                    X86_64CpuFeaturesInfo::new(sysinfo)?
57                )
58            )
59        } else {
60            Ok(
61                CpuFeaturesInfo::AppleSi(
62                    AppleSiCpuFeaturesInfo::new(sysinfo)?
63                )
64            )
65        }
66    }
67
68    /// Unwraps the cpu features of the Apple Silicon CPU.
69    pub fn get_apple_si_features(self) -> AppleSiCpuFeaturesInfo {
70        if let CpuFeaturesInfo::AppleSi(val) = self {
71            val
72        } else {
73            panic!("Not Apple Silicon!")
74        }
75    }
76
77    /// Unwraps the cpu features of the x86_64 CPU.
78    pub fn get_x86_features(self) -> X86_64CpuFeaturesInfo {
79        if let CpuFeaturesInfo::x86_64(val) = self {
80            val
81        } else {
82            panic!("Not x86!")
83        }
84    }
85}
86
87/// Apple silicon specific CPU features.
88#[derive(Debug, Serialize, DeriveMoreDisplay)]
89pub struct AppleSiCpuFeaturesInfo {
90    // TODO, I need a M1 Macbook to check this :)
91}
92
93impl AppleSiCpuFeaturesInfo {
94
95    /// Constructor.
96    pub(crate) fn new(_sysinfo: &BTreeMap<String, String>) -> Result<Self, MacSysInfoError> {
97        Ok(AppleSiCpuFeaturesInfo {})
98    }
99}
100
101/// x86 specific CPU features, like AVX.
102#[derive(Debug, Serialize, DeriveMoreDisplay)]
103#[display(fmt = "X86CpuFeatures (\n\
104\x20    mmx: {},\n\
105\x20    sse: {},\n\
106\x20    sse2: {},\n\
107\x20    sse3: {},\n\
108\x20    sse4_1: {},\n\
109\x20    sse4_2: {},\n\
110\x20    aes: {},\n\
111\x20    avx1_0: {},\n\
112\x20    avx2_0: {},\n\
113\x20    avx512f: {},\n\
114\x20    avx512cd: {},\n\
115\x20    avx512dq: {},\n\
116\x20    avx512bw: {},\n\
117\x20    avx512vl: {},\n\
118\x20    avx512ifma: {},\n\
119\x20    avx512vbmi: {},\n\
120)", mmx, sse, sse2, sse3, sse4_1, sse4_2, aes, avx1_0, avx2_0, avx512f, avx512cd, avx512dq, avx512bw, avx512vl, avx512ifma, avx512vbmi)]
121#[allow(non_camel_case_types)]
122pub struct X86_64CpuFeaturesInfo {
123    mmx: bool,
124    sse: bool,
125    sse2: bool,
126    sse3: bool,
127    sse4_1: bool,
128    sse4_2: bool,
129    aes: bool,
130    avx1_0: bool,
131    avx2_0: bool,
132    avx512f: bool,
133    avx512cd: bool,
134    avx512dq: bool,
135    avx512bw: bool,
136    avx512vl: bool,
137    avx512ifma: bool,
138    avx512vbmi: bool,
139}
140
141impl X86_64CpuFeaturesInfo {
142
143    /// Constructor.
144    pub(crate) fn new(sysinfo: &BTreeMap<String, String>) -> Result<Self, MacSysInfoError> {
145        let x = X86_64CpuFeaturesInfo {
146            mmx: parse_sysctl_value(
147                "mmx",
148                SysctlKey::HwOptionalMmx,
149                sysinfo,
150                ParseAsType::Bool)?
151                .get_bool(),
152            sse: parse_sysctl_value(
153                "sse",
154                SysctlKey::HwOptionalSse,
155                sysinfo,
156                ParseAsType::Bool)?
157                .get_bool(),
158            sse2: parse_sysctl_value(
159                "sse2",
160                SysctlKey::HwOptionalSse2,
161                sysinfo,
162                ParseAsType::Bool)?
163                .get_bool(),
164            sse3: parse_sysctl_value(
165                "sse3",
166                SysctlKey::HwOptionalSse3,
167                sysinfo,
168                ParseAsType::Bool)?
169                .get_bool(),
170            sse4_1: parse_sysctl_value(
171                "sse4_1",
172                SysctlKey::HwOptionalSse4_1,
173                sysinfo,
174                ParseAsType::Bool)?
175                .get_bool(),
176            sse4_2: parse_sysctl_value(
177                "sse4_2",
178                SysctlKey::HwOptionalSse4_2,
179                sysinfo,
180                ParseAsType::Bool)?
181                .get_bool(),
182            aes: parse_sysctl_value(
183                "aes",
184                SysctlKey::HwOptionalAes,
185                sysinfo,
186                ParseAsType::Bool)?
187                .get_bool(),
188            avx1_0: parse_sysctl_value(
189                "avx1_0",
190                SysctlKey::HwOptionalAvx1_0,
191                sysinfo,
192                ParseAsType::Bool)?
193                .get_bool(),
194            avx2_0: parse_sysctl_value(
195                "avx2_0",
196                SysctlKey::HwOptionalAvx2_0,
197                sysinfo,
198                ParseAsType::Bool)?
199                .get_bool(),
200            avx512f: parse_sysctl_value(
201                "avx512f",
202                SysctlKey::HwOptionalAvx512f,
203                sysinfo,
204                ParseAsType::Bool)?
205                .get_bool(),
206            avx512cd: parse_sysctl_value(
207                "avx512cd",
208                SysctlKey::HwOptionalAvx512cd,
209                sysinfo,
210                ParseAsType::Bool)?
211                .get_bool(),
212            avx512dq: parse_sysctl_value(
213                "avx512dq",
214                SysctlKey::HwOptionalAvx512dq,
215                sysinfo,
216                ParseAsType::Bool)?
217                .get_bool(),
218            avx512bw: parse_sysctl_value(
219                "avx512bw",
220                SysctlKey::HwOptionalAvx512bw,
221                sysinfo,
222                ParseAsType::Bool)?
223                .get_bool(),
224            avx512vl: parse_sysctl_value(
225                "avx512vl",
226                SysctlKey::HwOptionalAvx512vl,
227                sysinfo,
228                ParseAsType::Bool)?
229                .get_bool(),
230            avx512ifma: parse_sysctl_value(
231                "avx512ifma",
232                SysctlKey::HwOptionalAvx512ifma,
233                sysinfo,
234                ParseAsType::Bool)?
235                .get_bool(),
236            avx512vbmi: parse_sysctl_value(
237                "avx512vbmi",
238                SysctlKey::HwOptionalAvx512vbmi,
239                sysinfo,
240                ParseAsType::Bool)?
241                .get_bool(),
242        };
243        Ok(x)
244    }
245
246    /// Getter for the x86_64 CPU feature `mmx`.
247    pub fn mmx(&self) -> bool {
248        self.mmx
249    }
250    /// Getter for the x86_64 CPU feature `sse`.
251    pub fn sse(&self) -> bool {
252        self.sse
253    }
254    /// Getter for the x86_64 CPU feature `sse2`.
255    pub fn sse2(&self) -> bool {
256        self.sse2
257    }
258    /// Getter for the x86_64 CPU feature `sse3`.
259    pub fn sse3(&self) -> bool {
260        self.sse3
261    }
262    /// Getter for the x86_64 CPU feature `sse4_1`.
263    pub fn sse4_1(&self) -> bool {
264        self.sse4_1
265    }
266    /// Getter for the x86_64 CPU feature `sse4_2`.
267    pub fn sse4_2(&self) -> bool {
268        self.sse4_2
269    }
270    /// Getter for the x86_64 CPU feature `aes`.
271    pub fn aes(&self) -> bool {
272        self.aes
273    }
274    /// Getter for the x86_64 CPU feature `avx1_0`.
275    pub fn avx1_0(&self) -> bool {
276        self.avx1_0
277    }
278    /// Getter for the x86_64 CPU feature `avx2_0`.
279    pub fn avx2_0(&self) -> bool {
280        self.avx2_0
281    }
282    /// Getter for the x86_64 CPU feature `avx512f`.
283    pub fn avx512f(&self) -> bool {
284        self.avx512f
285    }
286    /// Getter for the x86_64 CPU feature `avx512cd`.
287    pub fn avx512cd(&self) -> bool {
288        self.avx512cd
289    }
290    /// Getter for the x86_64 CPU feature `avx512dq`.
291    pub fn avx512dq(&self) -> bool {
292        self.avx512dq
293    }
294    /// Getter for the x86_64 CPU feature `avx512bw`.
295    pub fn avx512bw(&self) -> bool {
296        self.avx512bw
297    }
298    /// Getter for the x86_64 CPU feature `avx512vl`.
299    pub fn avx512vl(&self) -> bool {
300        self.avx512vl
301    }
302    /// Getter for the x86_64 CPU feature `avx512ifma`.
303    pub fn avx512ifma(&self) -> bool {
304        self.avx512ifma
305    }
306    /// Getter for the x86_64 CPU feature `avx512vbmi`.
307    pub fn avx512vbmi(&self) -> bool {
308        self.avx512vbmi
309    }
310}
311