mirror of
https://github.com/mii443/nel_os.git
synced 2025-08-22 16:15:38 +00:00
wip
This commit is contained in:
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -107,6 +107,7 @@ dependencies = [
|
||||
"pc-keyboard",
|
||||
"pic8259",
|
||||
"rand",
|
||||
"raw-cpuid 11.5.0",
|
||||
"spin 0.5.2",
|
||||
"uart_16550",
|
||||
"volatile 0.2.7",
|
||||
@ -253,6 +254,15 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-cpuid"
|
||||
version = "11.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.20"
|
||||
@ -356,7 +366,7 @@ checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags 1.3.2",
|
||||
"raw-cpuid",
|
||||
"raw-cpuid 10.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -16,6 +16,7 @@ x86 = "0.52.0"
|
||||
bitfield = "0.19.0"
|
||||
numeric-enum-macro = "0.2.0"
|
||||
rand = { version = "0.6.5", default-features = false }
|
||||
raw-cpuid = "11.5.0"
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.0"
|
||||
|
257
src/vmm/cpuid.rs
Normal file
257
src/vmm/cpuid.rs
Normal file
@ -0,0 +1,257 @@
|
||||
use raw_cpuid::cpuid;
|
||||
|
||||
use crate::info;
|
||||
|
||||
use super::{vcpu::VCpu, vmcs::VmxLeaf};
|
||||
|
||||
pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
|
||||
let regs = &mut vcpu.guest_registers;
|
||||
let vendor: &[u8; 12] = b"NelogikaNelo";
|
||||
let vendor = unsafe { core::mem::transmute::<&[u8; 12], &[u32; 3]>(vendor) };
|
||||
match VmxLeaf::from(regs.rax) {
|
||||
VmxLeaf::MAXIMUM_INPUT => {
|
||||
info!("CPUID max input");
|
||||
regs.rax = 0x20;
|
||||
regs.rbx = vendor[0] as u64;
|
||||
regs.rcx = vendor[1] as u64;
|
||||
regs.rdx = vendor[2] as u64;
|
||||
}
|
||||
VmxLeaf::VERSION_AND_FEATURE_INFO => {
|
||||
info!("CPUID version and feature info");
|
||||
let ecx = FeatureInfoEcx {
|
||||
sse3: false,
|
||||
pclmulqdq: false,
|
||||
dtes64: false,
|
||||
monitor: false,
|
||||
ds_cpl: false,
|
||||
vmx: false,
|
||||
smx: false,
|
||||
eist: false,
|
||||
tm2: false,
|
||||
ssse3: false,
|
||||
cnxt_id: false,
|
||||
sdbg: false,
|
||||
fma: false,
|
||||
cmpxchg16b: false,
|
||||
xtpr: false,
|
||||
pdcm: false,
|
||||
_reserved_0: false,
|
||||
pcid: true,
|
||||
dca: false,
|
||||
sse4_1: false,
|
||||
sse4_2: false,
|
||||
x2apic: false,
|
||||
movbe: false,
|
||||
popcnt: false,
|
||||
tsc_deadline: false,
|
||||
aesni: false,
|
||||
xsave: false,
|
||||
osxsave: false,
|
||||
avx: false,
|
||||
f16c: false,
|
||||
rdrand: false,
|
||||
hypervisor: false,
|
||||
};
|
||||
let edx = FeatureInfoEdx {
|
||||
fpu: true,
|
||||
vme: true,
|
||||
de: true,
|
||||
pse: true,
|
||||
tsc: false,
|
||||
msr: true,
|
||||
pae: true,
|
||||
mce: false,
|
||||
cx8: true,
|
||||
apic: false,
|
||||
_reserved_0: false,
|
||||
sep: true,
|
||||
mtrr: false,
|
||||
pge: true,
|
||||
mca: false,
|
||||
cmov: true,
|
||||
pat: false,
|
||||
pse36: true,
|
||||
psn: false,
|
||||
clfsh: false,
|
||||
_reserved_1: false,
|
||||
ds: false,
|
||||
acpi: true,
|
||||
mmx: false,
|
||||
fxsr: true,
|
||||
sse: false,
|
||||
sse2: false,
|
||||
ss: false,
|
||||
htt: false,
|
||||
tm: false,
|
||||
_reserved_2: false,
|
||||
pbe: false,
|
||||
};
|
||||
let cpuid = cpuid!(0x1, 0);
|
||||
regs.rax = cpuid.eax as u64;
|
||||
regs.rbx = cpuid.ebx as u64;
|
||||
regs.rcx = ecx.to_u32() as u64;
|
||||
regs.rdx = edx.to_u32() as u64;
|
||||
}
|
||||
_ => {
|
||||
info!("Unhandled CPUID leaf: {:#x}", regs.rax);
|
||||
invalid(vcpu);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn invalid(vcpu: &mut VCpu) {
|
||||
let regs = &mut vcpu.guest_registers;
|
||||
|
||||
regs.rax = 0;
|
||||
regs.rbx = 0;
|
||||
regs.rcx = 0;
|
||||
regs.rdx = 0;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[repr(C, packed)]
|
||||
pub struct FeatureInfoEcx {
|
||||
pub sse3: bool,
|
||||
pub pclmulqdq: bool,
|
||||
pub dtes64: bool,
|
||||
pub monitor: bool,
|
||||
pub ds_cpl: bool,
|
||||
pub vmx: bool,
|
||||
pub smx: bool,
|
||||
pub eist: bool,
|
||||
pub tm2: bool,
|
||||
pub ssse3: bool,
|
||||
pub cnxt_id: bool,
|
||||
pub sdbg: bool,
|
||||
pub fma: bool,
|
||||
pub cmpxchg16b: bool,
|
||||
pub xtpr: bool,
|
||||
pub pdcm: bool,
|
||||
pub _reserved_0: bool,
|
||||
pub pcid: bool,
|
||||
pub dca: bool,
|
||||
pub sse4_1: bool,
|
||||
pub sse4_2: bool,
|
||||
pub x2apic: bool,
|
||||
pub movbe: bool,
|
||||
pub popcnt: bool,
|
||||
pub tsc_deadline: bool,
|
||||
pub aesni: bool,
|
||||
pub xsave: bool,
|
||||
pub osxsave: bool,
|
||||
pub avx: bool,
|
||||
pub f16c: bool,
|
||||
pub rdrand: bool,
|
||||
pub hypervisor: bool,
|
||||
}
|
||||
|
||||
impl FeatureInfoEcx {
|
||||
pub fn to_u32(&self) -> u32 {
|
||||
(self.sse3 as u32) << 0
|
||||
| (self.pclmulqdq as u32) << 1
|
||||
| (self.dtes64 as u32) << 2
|
||||
| (self.monitor as u32) << 3
|
||||
| (self.ds_cpl as u32) << 4
|
||||
| (self.vmx as u32) << 5
|
||||
| (self.smx as u32) << 6
|
||||
| (self.eist as u32) << 7
|
||||
| (self.tm2 as u32) << 8
|
||||
| (self.ssse3 as u32) << 9
|
||||
| (self.cnxt_id as u32) << 10
|
||||
| (self.sdbg as u32) << 11
|
||||
| (self.fma as u32) << 12
|
||||
| (self.cmpxchg16b as u32) << 13
|
||||
| (self.xtpr as u32) << 14
|
||||
| (self.pdcm as u32) << 15
|
||||
| (self._reserved_0 as u32) << 16
|
||||
| (self.pcid as u32) << 17
|
||||
| (self.dca as u32) << 18
|
||||
| (self.sse4_1 as u32) << 19
|
||||
| (self.sse4_2 as u32) << 20
|
||||
| (self.x2apic as u32) << 21
|
||||
| (self.movbe as u32) << 22
|
||||
| (self.popcnt as u32) << 23
|
||||
| (self.tsc_deadline as u32) << 24
|
||||
| (self.aesni as u32) << 25
|
||||
| (self.xsave as u32) << 26
|
||||
| (self.osxsave as u32) << 27
|
||||
| (self.avx as u32) << 28
|
||||
| (self.f16c as u32) << 29
|
||||
| (self.rdrand as u32) << 30
|
||||
| (self.hypervisor as u32) << 31
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[repr(C, packed)]
|
||||
pub struct FeatureInfoEdx {
|
||||
pub fpu: bool,
|
||||
pub vme: bool,
|
||||
pub de: bool,
|
||||
pub pse: bool,
|
||||
pub tsc: bool,
|
||||
pub msr: bool,
|
||||
pub pae: bool,
|
||||
pub mce: bool,
|
||||
pub cx8: bool,
|
||||
pub apic: bool,
|
||||
pub _reserved_0: bool,
|
||||
pub sep: bool,
|
||||
pub mtrr: bool,
|
||||
pub pge: bool,
|
||||
pub mca: bool,
|
||||
pub cmov: bool,
|
||||
pub pat: bool,
|
||||
pub pse36: bool,
|
||||
pub psn: bool,
|
||||
pub clfsh: bool,
|
||||
pub _reserved_1: bool,
|
||||
pub ds: bool,
|
||||
pub acpi: bool,
|
||||
pub mmx: bool,
|
||||
pub fxsr: bool,
|
||||
pub sse: bool,
|
||||
pub sse2: bool,
|
||||
pub ss: bool,
|
||||
pub htt: bool,
|
||||
pub tm: bool,
|
||||
pub _reserved_2: bool,
|
||||
pub pbe: bool,
|
||||
}
|
||||
|
||||
impl FeatureInfoEdx {
|
||||
pub fn to_u32(&self) -> u32 {
|
||||
(self.fpu as u32) << 0
|
||||
| (self.vme as u32) << 1
|
||||
| (self.de as u32) << 2
|
||||
| (self.pse as u32) << 3
|
||||
| (self.tsc as u32) << 4
|
||||
| (self.msr as u32) << 5
|
||||
| (self.pae as u32) << 6
|
||||
| (self.mce as u32) << 7
|
||||
| (self.cx8 as u32) << 8
|
||||
| (self.apic as u32) << 9
|
||||
| (self._reserved_0 as u32) << 10
|
||||
| (self.sep as u32) << 11
|
||||
| (self.mtrr as u32) << 12
|
||||
| (self.pge as u32) << 13
|
||||
| (self.mca as u32) << 14
|
||||
| (self.cmov as u32) << 15
|
||||
| (self.pat as u32) << 16
|
||||
| (self.pse36 as u32) << 17
|
||||
| (self.psn as u32) << 18
|
||||
| (self.clfsh as u32) << 19
|
||||
| (self._reserved_1 as u32) << 20
|
||||
| (self.ds as u32) << 21
|
||||
| (self.acpi as u32) << 22
|
||||
| (self.mmx as u32) << 23
|
||||
| (self.fxsr as u32) << 24
|
||||
| (self.sse as u32) << 25
|
||||
| (self.sse2 as u32) << 26
|
||||
| (self.ss as u32) << 27
|
||||
| (self.htt as u32) << 28
|
||||
| (self.tm as u32) << 29
|
||||
| (self._reserved_2 as u32) << 30
|
||||
| (self.pbe as u32) << 31
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
pub mod asm;
|
||||
pub mod cpuid;
|
||||
pub mod ept;
|
||||
pub mod error;
|
||||
pub mod linux;
|
||||
|
@ -11,10 +11,13 @@ use x86_64::VirtAddr;
|
||||
use crate::{
|
||||
info,
|
||||
memory::BootInfoFrameAllocator,
|
||||
vmm::vmcs::{
|
||||
DescriptorType, EntryControls, Granularity, PrimaryExitControls,
|
||||
PrimaryProcessorBasedVmExecutionControls, SecondaryProcessorBasedVmExecutionControls,
|
||||
SegmentRights, VmxExitInfo, VmxExitReason,
|
||||
vmm::{
|
||||
cpuid,
|
||||
vmcs::{
|
||||
DescriptorType, EntryControls, Granularity, PrimaryExitControls,
|
||||
PrimaryProcessorBasedVmExecutionControls, SecondaryProcessorBasedVmExecutionControls,
|
||||
SegmentRights, VmxExitInfo, VmxExitReason,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -215,7 +218,7 @@ impl VCpu {
|
||||
|
||||
primary_exec_ctrl.0 |= (reserved_bits & 0xFFFFFFFF) as u32;
|
||||
primary_exec_ctrl.0 &= (reserved_bits >> 32) as u32;
|
||||
primary_exec_ctrl.set_hlt(true);
|
||||
primary_exec_ctrl.set_hlt(false);
|
||||
primary_exec_ctrl.set_activate_secondary_controls(true);
|
||||
|
||||
primary_exec_ctrl.write();
|
||||
@ -256,6 +259,8 @@ impl VCpu {
|
||||
entry_ctrl.0 |= (reserved_bits & 0xFFFFFFFF) as u32;
|
||||
entry_ctrl.0 &= (reserved_bits >> 32) as u32;
|
||||
entry_ctrl.set_ia32e_mode_guest(false);
|
||||
entry_ctrl.set_load_ia32_efer(true);
|
||||
entry_ctrl.set_load_ia32_pat(true);
|
||||
|
||||
entry_ctrl.write();
|
||||
|
||||
@ -279,6 +284,9 @@ impl VCpu {
|
||||
exit_ctrl.0 &= (reserved_bits >> 32) as u32;
|
||||
exit_ctrl.set_host_addr_space_size(true);
|
||||
exit_ctrl.set_load_ia32_efer(true);
|
||||
exit_ctrl.set_save_ia32_efer(true);
|
||||
exit_ctrl.set_load_ia32_pat(true);
|
||||
exit_ctrl.set_save_ia32_pat(true);
|
||||
|
||||
exit_ctrl.write();
|
||||
|
||||
@ -355,8 +363,6 @@ impl VCpu {
|
||||
vmwrite(vmcs::guest::SS_BASE, 0)?;
|
||||
vmwrite(vmcs::guest::DS_BASE, 0)?;
|
||||
vmwrite(vmcs::guest::ES_BASE, 0)?;
|
||||
vmwrite(vmcs::guest::FS_BASE, 0)?;
|
||||
vmwrite(vmcs::guest::GS_BASE, 0)?;
|
||||
vmwrite(vmcs::guest::TR_BASE, 0)?;
|
||||
vmwrite(vmcs::guest::GDTR_BASE, 0)?;
|
||||
vmwrite(vmcs::guest::IDTR_BASE, 0)?;
|
||||
@ -373,15 +379,6 @@ impl VCpu {
|
||||
vmwrite(vmcs::guest::IDTR_LIMIT, 0)?;
|
||||
vmwrite(vmcs::guest::LDTR_LIMIT, 0)?;
|
||||
|
||||
vmwrite(vmcs::guest::CS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::SS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::DS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::ES_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::FS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::GS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::TR_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::LDTR_SELECTOR, 0)?;
|
||||
|
||||
let cs_right = {
|
||||
let mut rights = SegmentRights::default();
|
||||
rights.set_rw(true);
|
||||
@ -448,7 +445,19 @@ impl VCpu {
|
||||
vmwrite(vmcs::guest::TR_ACCESS_RIGHTS, tr_right.0 as u64)?;
|
||||
vmwrite(vmcs::guest::LDTR_ACCESS_RIGHTS, ldtr_right.0 as u64)?;
|
||||
|
||||
vmwrite(vmcs::guest::CS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::SS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::DS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::ES_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::FS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::GS_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::TR_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::LDTR_SELECTOR, 0)?;
|
||||
vmwrite(vmcs::guest::FS_BASE, 0)?;
|
||||
vmwrite(vmcs::guest::GS_BASE, 0)?;
|
||||
|
||||
vmwrite(vmcs::guest::IA32_EFER_FULL, 0)?;
|
||||
vmwrite(vmcs::guest::IA32_EFER_HIGH, 0)?;
|
||||
vmwrite(vmcs::guest::RFLAGS, 0x2)?;
|
||||
vmwrite(vmcs::guest::LINK_PTR_FULL, u64::MAX)?;
|
||||
|
||||
@ -477,9 +486,29 @@ impl VCpu {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_guest_regs(&self) {
|
||||
info!("Guest Registers:");
|
||||
info!("RAX: {:#x}", self.guest_registers.rax);
|
||||
info!("RBX: {:#x}", self.guest_registers.rbx);
|
||||
info!("RCX: {:#x}", self.guest_registers.rcx);
|
||||
info!("RDX: {:#x}", self.guest_registers.rdx);
|
||||
info!("RSI: {:#x}", self.guest_registers.rsi);
|
||||
info!("RDI: {:#x}", self.guest_registers.rdi);
|
||||
info!("RBP: {:#x}", self.guest_registers.rbp);
|
||||
info!("R8: {:#x}", self.guest_registers.r8);
|
||||
info!("R9: {:#x}", self.guest_registers.r9);
|
||||
info!("R10: {:#x}", self.guest_registers.r10);
|
||||
info!("R11: {:#x}", self.guest_registers.r11);
|
||||
info!("R12: {:#x}", self.guest_registers.r12);
|
||||
info!("R13: {:#x}", self.guest_registers.r13);
|
||||
info!("R14: {:#x}", self.guest_registers.r14);
|
||||
info!("R15: {:#x}", self.guest_registers.r15);
|
||||
}
|
||||
|
||||
fn vmentry(&mut self) -> Result<(), InstructionError> {
|
||||
let success = {
|
||||
let result: u16;
|
||||
self.print_guest_regs();
|
||||
if !self.launch_done {
|
||||
unsafe {
|
||||
result = crate::vmm::asm::asm_vm_entry(self as *mut _);
|
||||
@ -512,6 +541,16 @@ impl VCpu {
|
||||
vmwrite(vmcs::host::RSP, rsp).unwrap();
|
||||
}
|
||||
|
||||
fn step_next_inst(&mut self) -> Result<(), VmFail> {
|
||||
unsafe {
|
||||
let rip = vmread(vmcs::guest::RIP)?;
|
||||
vmwrite(
|
||||
vmcs::guest::RIP,
|
||||
rip + vmread(vmcs::ro::VMEXIT_INSTRUCTION_LEN)?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn vmexit_handler(&mut self) {
|
||||
let info = VmxExitInfo::read();
|
||||
|
||||
@ -530,14 +569,16 @@ impl VCpu {
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
info!(
|
||||
"vcpu RIP: {:#x}",
|
||||
unsafe { vmread(vmcs::guest::RIP) }.unwrap()
|
||||
);
|
||||
info!("RIP: {:#x}", unsafe { vmread(vmcs::guest::RIP) }.unwrap());
|
||||
match info.get_reason() {
|
||||
VmxExitReason::HLT => {
|
||||
info!("HLT instruction executed");
|
||||
}
|
||||
VmxExitReason::CPUID => {
|
||||
info!("CPUID instruction executed");
|
||||
cpuid::handle_cpuid_exit(self);
|
||||
self.step_next_inst().unwrap();
|
||||
}
|
||||
_ => {
|
||||
panic!("VMExit reason: {:?}", info.get_reason());
|
||||
}
|
||||
|
@ -629,3 +629,27 @@ impl VmxExitInfo {
|
||||
reason.try_into().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum VmxLeaf {
|
||||
MAXIMUM_INPUT = 0x0,
|
||||
VERSION_AND_FEATURE_INFO = 0x1,
|
||||
EXTENDED_FEATURE = 0x7,
|
||||
EXTENDED_ENUMERATION = 0xD,
|
||||
EXTENDED_FUNCTION = 0x80000000,
|
||||
EXTENDED_PROCESSOR_SIGNATURE = 0x80000001,
|
||||
UNKNOWN = 0xFFFFFFFF,
|
||||
}
|
||||
|
||||
impl VmxLeaf {
|
||||
pub fn from(rax: u64) -> VmxLeaf {
|
||||
match rax {
|
||||
0x0 => VmxLeaf::MAXIMUM_INPUT,
|
||||
0x1 => VmxLeaf::VERSION_AND_FEATURE_INFO,
|
||||
0x7 => VmxLeaf::EXTENDED_FEATURE,
|
||||
0xD => VmxLeaf::EXTENDED_ENUMERATION,
|
||||
0x80000000 => VmxLeaf::EXTENDED_FUNCTION,
|
||||
0x80000001 => VmxLeaf::EXTENDED_PROCESSOR_SIGNATURE,
|
||||
_ => VmxLeaf::UNKNOWN,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user