pub(crate) mod native_cpuid {
#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(C)]
pub struct CpuIdResult {
pub eax: u32,
pub ebx: u32,
pub ecx: u32,
pub edx: u32,
}
#[allow(unreachable_code)]
pub fn cpuid_count(a: u32, c: u32) -> CpuIdResult {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
#[cfg(all(target_arch = "x86", not(target_env = "sgx"), target_feature = "sse"))]
use core::arch::x86 as arch;
#[cfg(all(target_arch = "x86_64", not(target_env = "sgx")))]
use core::arch::x86_64 as arch;
let result = unsafe { arch::__cpuid_count(a, c) };
return CpuIdResult {
eax: result.eax,
ebx: result.ebx,
ecx: result.ecx,
edx: result.edx,
};
}
CpuIdResult {
eax: 22,
ebx: 1970169159,
ecx: 1818588270,
edx: 1231384169,
}
}
}
#[derive(PartialEq, Eq)]
#[repr(C)]
struct VendorInfo {
ebx: u32,
edx: u32,
ecx: u32,
}
impl VendorInfo {
fn as_str(&self) -> &str {
let brand_string_start = self as *const VendorInfo as *const u8;
let slice = unsafe {
core::slice::from_raw_parts(brand_string_start, core::mem::size_of::<VendorInfo>())
};
core::str::from_utf8(slice).unwrap_or("InvalidVendorString")
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Cpu {
AMD,
Intel,
Unknown,
}
#[allow(clippy::absurd_extreme_comparisons)]
pub fn get_cpu() -> Cpu {
const EAX_VENDOR_INFO: u32 = 0x0;
let vendor_leaf = native_cpuid::cpuid_count(EAX_VENDOR_INFO, 0);
let is_leaf_supported = EAX_VENDOR_INFO <= vendor_leaf.eax;
match is_leaf_supported {
true => {
let vendor = VendorInfo {
ebx: vendor_leaf.ebx,
ecx: vendor_leaf.ecx,
edx: vendor_leaf.edx,
};
match vendor.as_str() {
"AuthenticAMD" => Cpu::AMD,
"GenuineIntel" => Cpu::Intel,
_ => Cpu::Unknown,
}
}
false => Cpu::Unknown,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_cpu() {
println!("{:?}", get_cpu());
}
}