vmm/arch/x86_64/
cpu_model.rs

1// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::arch::x86_64::__cpuid as host_cpuid;
5use std::cmp::{Eq, PartialEq};
6
7/// Structure representing x86_64 CPU model.
8#[derive(Debug, Eq, PartialEq)]
9pub struct CpuModel {
10    /// Extended family.
11    pub extended_family: u8,
12    /// Extended model.
13    pub extended_model: u8,
14    /// Family.
15    pub family: u8,
16    /// Model.
17    pub model: u8,
18    /// Stepping.
19    pub stepping: u8,
20}
21
22/// Family / Model / Stepping for Intel Skylake
23pub const SKYLAKE_FMS: CpuModel = CpuModel {
24    extended_family: 0x0,
25    extended_model: 0x5,
26    family: 0x6,
27    model: 0x5,
28    stepping: 0x4,
29};
30
31/// Family / Model / Stepping for Intel Cascade Lake
32pub const CASCADE_LAKE_FMS: CpuModel = CpuModel {
33    extended_family: 0x0,
34    extended_model: 0x5,
35    family: 0x6,
36    model: 0x5,
37    stepping: 0x7,
38};
39
40/// Family / Model / Stepping for Intel Ice Lake
41pub const ICE_LAKE_FMS: CpuModel = CpuModel {
42    extended_family: 0x0,
43    extended_model: 0x6,
44    family: 0x6,
45    model: 0xa,
46    stepping: 0x6,
47};
48
49/// Family / Model / Stepping for AMD Milan
50pub const MILAN_FMS: CpuModel = CpuModel {
51    extended_family: 0xa,
52    extended_model: 0x0,
53    family: 0xf,
54    model: 0x1,
55    stepping: 0x1,
56};
57
58impl CpuModel {
59    /// Get CPU model from current machine.
60    pub fn get_cpu_model() -> Self {
61        // SAFETY: This operation is safe as long as the processor implements this CPUID function.
62        // 0x1 is the defined code for getting the processor version information.
63        let eax = unsafe { host_cpuid(0x1) }.eax;
64        CpuModel::from(&eax)
65    }
66}
67
68impl From<&u32> for CpuModel {
69    fn from(eax: &u32) -> Self {
70        CpuModel {
71            extended_family: ((eax >> 20) & 0xff) as u8,
72            extended_model: ((eax >> 16) & 0xf) as u8,
73            family: ((eax >> 8) & 0xf) as u8,
74            model: ((eax >> 4) & 0xf) as u8,
75            stepping: (eax & 0xf) as u8,
76        }
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn cpu_model_from() {
86        let skylake_eax = 0x00050654;
87        assert_eq!(CpuModel::from(&skylake_eax), SKYLAKE_FMS);
88
89        let cascade_lake_eax = 0x00050657;
90        assert_eq!(CpuModel::from(&cascade_lake_eax), CASCADE_LAKE_FMS);
91
92        let ice_lake_eax = 0x000606a6;
93        assert_eq!(CpuModel::from(&ice_lake_eax), ICE_LAKE_FMS);
94
95        let milan_eax = 0x00a00f11;
96        assert_eq!(CpuModel::from(&milan_eax), MILAN_FMS);
97    }
98}