Initial work for hardware virtualization
This commit is contained in:
parent
4486507316
commit
a4ad6da4f7
30
src/kernel/arch/x86_64/amd_virt.rs
Normal file
30
src/kernel/arch/x86_64/amd_virt.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (c) 2025 shibedrill
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
use intbits::Bits;
|
||||||
|
use x86_64::registers::control::EferFlags;
|
||||||
|
|
||||||
|
use crate::arch::x86_64::cpuid::*;
|
||||||
|
|
||||||
|
pub fn amd_v_supported() -> bool {
|
||||||
|
match ProcessorVendor::try_get_current() {
|
||||||
|
Ok(vendor) => {
|
||||||
|
if vendor == ProcessorVendor::AMD {
|
||||||
|
match CPUID.get_extended_processor_and_feature_identifiers() {
|
||||||
|
Some(features) => features.has_svm(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_svm() {
|
||||||
|
let mut efer = x86_64::registers::model_specific::Efer::read().bits();
|
||||||
|
efer.set_bit(12, true);
|
||||||
|
assert!(efer.bit(12));
|
||||||
|
unsafe { x86_64::registers::model_specific::Efer::write(EferFlags::from_bits_retain(efer)) };
|
||||||
|
}
|
||||||
121
src/kernel/arch/x86_64/cpuid.rs
Normal file
121
src/kernel/arch/x86_64/cpuid.rs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
// Copyright (c) 2025 shibedrill
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
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<CpuIdReaderNative> = CpuId::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum VirtualizationProvider {
|
||||||
|
AmdV,
|
||||||
|
IntelVTx,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
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<Self, Self::Error> {
|
||||||
|
match from {
|
||||||
|
"AuthenticAMD" | "AMDisbetter!" => Ok(Self::AMD),
|
||||||
|
"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),
|
||||||
|
" 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<Self, ()> {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/kernel/arch/x86_64/intel_virt.rs
Normal file
17
src/kernel/arch/x86_64/intel_virt.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) 2025 shibedrill
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
use crate::arch::x86_64::cpuid::*;
|
||||||
|
|
||||||
|
pub fn intel_vt_supported() -> bool {
|
||||||
|
match ProcessorVendor::try_get_current() {
|
||||||
|
Ok(vendor) => match vendor == ProcessorVendor::Intel {
|
||||||
|
true => match CPUID.get_feature_info() {
|
||||||
|
Some(features) => features.has_vmx(),
|
||||||
|
None => false,
|
||||||
|
},
|
||||||
|
false => false,
|
||||||
|
},
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,11 @@
|
|||||||
// Copyright (c) 2025 shibedrill
|
// Copyright (c) 2025 shibedrill
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pub mod amd_virt;
|
||||||
pub mod asm;
|
pub mod asm;
|
||||||
|
pub mod cpuid;
|
||||||
pub mod gdt;
|
pub mod gdt;
|
||||||
|
pub mod intel_virt;
|
||||||
pub mod interrupts;
|
pub mod interrupts;
|
||||||
pub mod paging;
|
pub mod paging;
|
||||||
pub mod serial;
|
pub mod serial;
|
||||||
|
|||||||
@ -34,6 +34,8 @@ use lazy_static::lazy_static;
|
|||||||
use limine::firmware_type::FirmwareType;
|
use limine::firmware_type::FirmwareType;
|
||||||
use spin::mutex::Mutex;
|
use spin::mutex::Mutex;
|
||||||
|
|
||||||
|
use crate::arch::x86_64::{amd_virt, cpuid::{virt_supported, CPUID}};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref SERIAL_3F8: Mutex<SerialPort> =
|
pub static ref SERIAL_3F8: Mutex<SerialPort> =
|
||||||
Mutex::new(arch::x86_64::serial::SerialPort::new(0x3f8));
|
Mutex::new(arch::x86_64::serial::SerialPort::new(0x3f8));
|
||||||
@ -137,16 +139,19 @@ unsafe extern "C" fn main() -> ! {
|
|||||||
|
|
||||||
arch::x86_64::paging::get_mappings();
|
arch::x86_64::paging::get_mappings();
|
||||||
|
|
||||||
let cpuid = raw_cpuid::CpuId::new();
|
if let Some(string) = CPUID.get_processor_brand_string() {
|
||||||
if let Some(string) = cpuid.get_processor_brand_string() {
|
|
||||||
log_info!("CPU brand string: {}", string.as_str());
|
log_info!("CPU brand string: {}", string.as_str());
|
||||||
}
|
}
|
||||||
if let Some(string) = cpuid.get_vendor_info() {
|
if let Some(string) = CPUID.get_vendor_info() {
|
||||||
log_info!("CPU vendor: {}", string.as_str());
|
log_info!("CPU vendor: {}", string.as_str());
|
||||||
}
|
}
|
||||||
if let Some(string) = cpuid.get_hypervisor_info() {
|
if let Some(string) = CPUID.get_hypervisor_info() {
|
||||||
log_info!("Hypervisor: {:?}", string.identify());
|
log_info!("Hypervisor: {:?}", string.identify());
|
||||||
}
|
}
|
||||||
|
log_info!("Virtualization provider: {:?}", virt_supported());
|
||||||
|
log_info!("AMD-V info: {}", CPUID.get_svm_info().unwrap().revision());
|
||||||
|
amd_virt::enable_svm();
|
||||||
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
arch::asm::nop();
|
arch::asm::nop();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user