Skip to content
This repository was archived by the owner on Sep 1, 2024. It is now read-only.

Commit 2665672

Browse files
committed
Hypervisor works without any crashes. CPUID vmexits mostly.
1 parent 4b49a68 commit 2665672

File tree

3 files changed

+62
-12
lines changed

3 files changed

+62
-12
lines changed

driver/src/main.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
extern crate alloc;
66

7+
use crate::processor::MpManager;
78
use {
89
crate::virtualize::virtualize_system,
910
alloc::boxed::Box,
@@ -14,12 +15,12 @@ use {
1415
ept::paging::{AccessType, Ept},
1516
shared_data::SharedData,
1617
},
17-
vmm::is_hypervisor_present,
1818
},
1919
log::*,
2020
uefi::prelude::*,
2121
};
2222

23+
pub mod processor;
2324
pub mod virtualize;
2425

2526
#[entry]
@@ -34,6 +35,17 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
3435

3536
info!("The Matrix is an illusion");
3637

38+
let mp_manager =
39+
MpManager::new(system_table.boot_services()).expect("Failed to create MpManager");
40+
41+
// Get the processor count
42+
if let Ok(processor_count) = mp_manager.processor_count() {
43+
let total = processor_count.total;
44+
let enabled = processor_count.enabled;
45+
info!("Total processors: {}", total);
46+
info!("Enabled processors: {}", enabled);
47+
}
48+
3749
let mut shared_data = match setup_ept() {
3850
Ok(shared_data) => shared_data,
3951
Err(e) => panic!("Failed to setup EPT: {:?}", e),
@@ -46,8 +58,9 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
4658
// Since we captured RIP just above, the VM will start running from here.
4759
// Check if our hypervisor is already loaded. If so, done, otherwise, continue
4860
// installing the hypervisor.
49-
if !is_hypervisor_present() {
61+
if !mp_manager.is_virtualized() {
5062
debug!("Virtualizing the system");
63+
mp_manager.set_virtualized();
5164
virtualize_system(&regs, &mut shared_data, &system_table);
5265
}
5366

driver/src/processor.rs

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//! This module provides utility functions for processor-related operations in UEFI.
2+
3+
use core::sync::atomic::{AtomicU64, Ordering};
4+
use uefi::prelude::*;
5+
use uefi::proto::pi::mp::{MpServices, ProcessorCount};
6+
use uefi::table::boot::ScopedProtocol;
7+
8+
/// Atomic bitset used to track which processors have been virtualized.
9+
static VIRTUALIZED_BITSET: AtomicU64 = AtomicU64::new(0);
10+
11+
pub struct MpManager<'a> {
12+
mp_services: ScopedProtocol<'a, MpServices>,
13+
}
14+
15+
impl<'a> MpManager<'a> {
16+
/// Creates a new instance of MpManager, acquiring the MP Services Protocol.
17+
pub fn new(bt: &'a BootServices) -> uefi::Result<Self> {
18+
let handle = bt.get_handle_for_protocol::<MpServices>()?;
19+
let mp_services = bt.open_protocol_exclusive::<MpServices>(handle)?;
20+
Ok(Self { mp_services })
21+
}
22+
23+
/// Determines if the current processor is already virtualized.
24+
pub fn is_virtualized(&self) -> bool {
25+
let current_processor_index = self.current_processor_index().unwrap_or(0);
26+
let bit = 1 << current_processor_index;
27+
VIRTUALIZED_BITSET.load(Ordering::Relaxed) & bit != 0
28+
}
29+
30+
/// Marks the current processor as virtualized.
31+
pub fn set_virtualized(&self) {
32+
let current_processor_index = self.current_processor_index().unwrap_or(0);
33+
let bit = 1 << current_processor_index;
34+
VIRTUALIZED_BITSET.fetch_or(bit, Ordering::Relaxed);
35+
}
36+
37+
/// Returns the number of active logical processors.
38+
pub fn processor_count(&self) -> uefi::Result<ProcessorCount> {
39+
self.mp_services.get_number_of_processors()
40+
}
41+
42+
/// Gets the processor number of the logical processor that the caller is running on.
43+
pub fn current_processor_index(&self) -> uefi::Result<usize> {
44+
self.mp_services.who_am_i()
45+
}
46+
}

hypervisor/src/vmm.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,6 @@ use {
2626
},
2727
};
2828

29-
pub const CPUID_VENDOR_AND_MAX_FUNCTIONS: u32 = 0x4000_0000;
30-
pub const VENDOR_NAME: u32 = 0x5441_4c48; // "HLAT"
31-
32-
/// Checks if this hypervisor is already installed.
33-
pub fn is_hypervisor_present() -> bool {
34-
let regs = cpuid!(CPUID_VENDOR_AND_MAX_FUNCTIONS);
35-
(regs.ebx == regs.ecx) && (regs.ecx == regs.edx) && (regs.edx == VENDOR_NAME)
36-
}
37-
3829
// pass shared data to the hypervisor soon too
3930
pub fn start_hypervisor(guest_registers: &GuestRegisters, shared_data: &mut SharedData) -> ! {
4031
debug!("Starting hypervisor");
@@ -57,7 +48,7 @@ pub fn start_hypervisor(guest_registers: &GuestRegisters, shared_data: &mut Shar
5748
loop {
5849
if let Ok(basic_exit_reason) = vm.run() {
5950
let exit_type = match basic_exit_reason {
60-
//VmxBasicExitReason::ExceptionOrNmi => handle_exception(guest_registers, vmx),
51+
//VmxBasicExitReason::ExceptionOrNmi => handle_exception(vmx),
6152
VmxBasicExitReason::Cpuid => handle_cpuid(&mut vm.guest_registers),
6253

6354
// Grouping multiple exit reasons that are handled by the same function

0 commit comments

Comments
 (0)