// Copyright (c) 2025 shibedrill // SPDX-License-Identifier: MIT #![allow(dead_code)] use lazy_static::lazy_static; use raw_cpuid::CpuId; use raw_cpuid::CpuIdReaderNative; use crate::arch::x86_64::amd_virt::amd_v_supported; use crate::arch::x86_64::intel_virt::intel_vt_supported; lazy_static! { pub static ref CPUID: CpuId = CpuId::new(); } #[derive(Debug)] pub enum VirtualizationProvider { AmdV, IntelVTx, None, } #[derive(PartialEq, Eq)] #[allow(clippy::upper_case_acronyms)] pub enum ProcessorVendor { AMD, Intel, Via, Transmeta, Cyrix, Centaur, Nexgen, UMC, SiS, NSC, Rise, Vortex, AO486, Zaoxin, Hygon, Elbrus, QEMU, KVM, VMware, VirtualBox, Xen, HyperV, Parallels, QNX, } impl TryFrom<&str> for ProcessorVendor { type Error = (); fn try_from(from: &str) -> Result { match from { "AuthenticAMD" | "AMDisbetter!" => Ok(Self::AMD), // "GenuineIotel" is a legit string found in some mildly defective Intel CPUs "GenuineIntel" | "GenuineIotel" => Ok(Self::Intel), "VIA VIA VIA " => Ok(Self::Via), "GenuineTMx86" | "TransmetaCPU" => Ok(Self::Transmeta), "CyrixInstead" => Ok(Self::Cyrix), "CentaurHauls" => Ok(Self::Centaur), "NexGenDriven" => Ok(Self::Nexgen), "UMC UMC UMC " => Ok(Self::UMC), "SiS SiS SiS " => Ok(Self::SiS), "Geode by NSC" => Ok(Self::NSC), "RiseRiseRise" => Ok(Self::Rise), "Vortex86 SoC" => Ok(Self::Vortex), "MiSTer AO486" | "GenuineAO486" => Ok(Self::AO486), " Shanghai " => Ok(Self::Zaoxin), "HygonGenuine" => Ok(Self::Hygon), "E2K MACHINE " => Ok(Self::Elbrus), "TCGTCGTCGTCG" => Ok(Self::QEMU), " KVMKVMKVM " => Ok(Self::KVM), "VMwareVMware" => Ok(Self::VMware), "VBoxVBoxVBox" => Ok(Self::VirtualBox), "XenVMMXenVMM" => Ok(Self::Xen), "Microsoft Hv" => Ok(Self::HyperV), // " lrpepyh vr " is a legit string found in some implementations of the // Parallels hypervisor due to an endianness mismatch " prl hyperv " | " lrpepyh vr " => Ok(Self::Parallels), " QNXQVMBSQG " => Ok(Self::QNX), _ => Err(()), } } } impl ProcessorVendor { pub fn is_hypervisor(&self) -> bool { matches!( self, Self::QEMU | Self::KVM | Self::VMware | Self::VirtualBox | Self::HyperV | Self::Parallels | Self::QNX ) } pub fn try_get_current() -> Result { if let Some(brand_string) = CPUID.get_vendor_info() { Self::try_from(brand_string.as_str()) } else { Err(()) } } } pub fn virt_supported() -> VirtualizationProvider { match ProcessorVendor::try_get_current() { Err(_) => VirtualizationProvider::None, Ok(ProcessorVendor::Intel) => { if intel_vt_supported() { VirtualizationProvider::IntelVTx } else { VirtualizationProvider::None } } Ok(ProcessorVendor::AMD) => { if amd_v_supported() { VirtualizationProvider::AmdV } else { VirtualizationProvider::None } } _ => VirtualizationProvider::None, } }