Compare commits
10 Commits
v0.0.3
...
0bfb86a2b4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bfb86a2b4 | ||
|
|
baeed3320f | ||
|
|
525b6cbf0d | ||
|
|
33c511dcb0 | ||
|
|
53a31749b4 | ||
|
|
a355e91c6e | ||
|
|
294e4f719d | ||
|
|
1606184551 | ||
|
|
a0188056f0 | ||
|
|
db650f470f |
@@ -1,9 +1,16 @@
|
||||
#!/bin/sh -ex
|
||||
#!/bin/bash -ex
|
||||
|
||||
EFI_BINARY="$1"
|
||||
|
||||
cd ../nel_os_kernel
|
||||
cargo build --release -q
|
||||
if [[ "$EFI_BINARY" == "target/x86_64-unknown-uefi/release/"* ]]; then
|
||||
cargo build --release -q
|
||||
elif [[ "$EFI_BINARY" == "target/x86_64-unknown-uefi/debug/"* ]]; then
|
||||
cargo build -q
|
||||
else
|
||||
echo "Error: EFI binary path must contain either '/target/x86_64-unknown-uefi/release/' or '/target/x86_64-unknown-uefi/debug/'"
|
||||
exit 1
|
||||
fi
|
||||
cd ../nel_os_bootloader
|
||||
|
||||
dd if=/dev/zero of=fat.img bs=1k count=32768
|
||||
|
||||
@@ -60,9 +60,7 @@ pub fn unsubscribe(callback: SubscriberCallback) -> Result<(), &'static str> {
|
||||
pub fn dispatch_to_subscribers(context: &InterruptContext) {
|
||||
let subscribers = SUBSCRIBERS.lock();
|
||||
|
||||
for subscriber in subscribers.iter() {
|
||||
if let Some(subscriber) = subscriber {
|
||||
(subscriber.callback)(subscriber.context, context);
|
||||
}
|
||||
for subscriber in subscribers.iter().flatten() {
|
||||
(subscriber.callback)(subscriber.context, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#[macro_export]
|
||||
macro_rules! info {
|
||||
($($arg:tt)*) => ($crate::print!("[{:>12.5} I] {}\n", crate::time::get_ticks() as f64 / 1000., format_args!($($arg)*)));
|
||||
($($arg:tt)*) => ($crate::print!("[{:>12.5} I] {}\n", $crate::time::get_ticks() as f64 / 1000., format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! error {
|
||||
($($arg:tt)*) => ($crate::print!("[{:>12.5} E] {}\n", crate::time::get_ticks() as f64 / 1000., format_args!($($arg)*)));
|
||||
($($arg:tt)*) => ($crate::print!("[{:>12.5} E] {}\n", $crate::time::get_ticks() as f64 / 1000., format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! warn {
|
||||
($($arg:tt)*) => ($crate::print!("[{:>12.5} W] {}\n", crate::time::get_ticks() as f64 / 1000., format_args!($($arg)*)));
|
||||
($($arg:tt)*) => ($crate::print!("[{:>12.5} W] {}\n", $crate::time::get_ticks() as f64 / 1000., format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ use crate::{
|
||||
constant::{KERNEL_STACK_SIZE, PKG_VERSION},
|
||||
graphics::{FrameBuffer, FRAME_BUFFER},
|
||||
interrupt::apic,
|
||||
memory::{allocator, memory::BitmapMemoryTable, paging},
|
||||
memory::{allocator, bitmap::BitmapMemoryTable, paging},
|
||||
};
|
||||
|
||||
pub static BZIMAGE_ADDR: Once<u64> = Once::new();
|
||||
@@ -104,7 +104,7 @@ pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) {
|
||||
max_range = max_range.max(range.end);
|
||||
}
|
||||
info!("Usable memory: {}MiB", count / 1024 / 1024);
|
||||
memory::memory::MAX_MEMORY.call_once(|| max_range as usize * 2);
|
||||
memory::bitmap::MAX_MEMORY.call_once(|| max_range as usize * 2);
|
||||
|
||||
let mut bitmap_table = BitmapMemoryTable::init(&boot_info.usable_memory);
|
||||
info!(
|
||||
@@ -133,7 +133,7 @@ pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) {
|
||||
|
||||
if boot_info.frame_buffer.is_some() {
|
||||
let frame_buffer =
|
||||
FrameBuffer::from_raw_buffer(&boot_info.frame_buffer.as_ref().unwrap(), (64, 64, 64));
|
||||
FrameBuffer::from_raw_buffer(boot_info.frame_buffer.as_ref().unwrap(), (64, 64, 64));
|
||||
frame_buffer.clear();
|
||||
|
||||
FRAME_BUFFER.lock().replace(frame_buffer);
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
pub mod allocator;
|
||||
pub mod memory;
|
||||
pub mod bitmap;
|
||||
pub mod paging;
|
||||
|
||||
@@ -47,6 +47,27 @@ pub fn _print(args: ::core::fmt::Arguments) {
|
||||
});
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn write_byte(byte: u8) {
|
||||
use x86_64::instructions::interrupts;
|
||||
|
||||
interrupts::without_interrupts(|| {
|
||||
SERIAL1.lock().send(byte);
|
||||
});
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn write_bytes(bytes: &[u8]) {
|
||||
use x86_64::instructions::interrupts;
|
||||
|
||||
interrupts::without_interrupts(|| {
|
||||
let mut serial = SERIAL1.lock();
|
||||
for &b in bytes {
|
||||
serial.send(b);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => {
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
pub mod vcpu;
|
||||
pub mod vmcb;
|
||||
|
||||
@@ -3,18 +3,32 @@ use x86_64::structures::paging::{FrameAllocator, Size4KiB};
|
||||
|
||||
use crate::{
|
||||
error, info,
|
||||
vmm::{x86_64::common, VCpu},
|
||||
vmm::{
|
||||
x86_64::{amd::vmcb::Vmcb, common},
|
||||
VCpu,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct AMDVCpu;
|
||||
pub struct AMDVCpu {
|
||||
vmcb: Vmcb,
|
||||
}
|
||||
|
||||
impl AMDVCpu {
|
||||
pub fn setup(&mut self) -> Result<(), &'static str> {
|
||||
info!("Setting up AMD VCPU");
|
||||
|
||||
let raw_vmcb = self.vmcb.get_raw_vmcb();
|
||||
raw_vmcb.set_intercept_hlt(true);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl VCpu for AMDVCpu {
|
||||
fn run(
|
||||
&mut self,
|
||||
_frame_allocator: &mut dyn FrameAllocator<Size4KiB>,
|
||||
) -> Result<(), &'static str> {
|
||||
info!("VCpu on AMD");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -39,7 +53,7 @@ impl VCpu for AMDVCpu {
|
||||
unimplemented!("AMDVCpu::get_guest_memory_size is not implemented yet")
|
||||
}
|
||||
|
||||
fn new(_frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str>
|
||||
fn new(frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
@@ -47,7 +61,9 @@ impl VCpu for AMDVCpu {
|
||||
efer |= 1 << 12;
|
||||
common::write_msr(0xc000_0080, efer);
|
||||
|
||||
Ok(AMDVCpu)
|
||||
Ok(AMDVCpu {
|
||||
vmcb: Vmcb::new(frame_allocator)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn is_supported() -> bool
|
||||
|
||||
170
nel_os_kernel/src/vmm/x86_64/amd/vmcb.rs
Normal file
170
nel_os_kernel/src/vmm/x86_64/amd/vmcb.rs
Normal file
@@ -0,0 +1,170 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use modular_bitfield::{bitfield, prelude::*};
|
||||
use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB};
|
||||
|
||||
pub struct Vmcb {
|
||||
pub frame: PhysFrame,
|
||||
}
|
||||
|
||||
impl Vmcb {
|
||||
pub fn new(frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str> {
|
||||
let frame = frame_allocator
|
||||
.allocate_frame()
|
||||
.ok_or("Failed to allocate VMCB frame")?;
|
||||
Ok(Vmcb { frame })
|
||||
}
|
||||
|
||||
pub fn get_raw_vmcb(&self) -> &mut RawVmcb {
|
||||
let ptr = self.frame.start_address().as_u64() as *mut RawVmcb;
|
||||
unsafe { &mut *ptr }
|
||||
}
|
||||
}
|
||||
|
||||
#[bitfield]
|
||||
pub struct RawVmcb {
|
||||
// 000h
|
||||
pub intercept_cr_read: B16,
|
||||
pub intercept_cr_write: B16,
|
||||
// 004h
|
||||
pub intercept_dr_read: B16,
|
||||
pub intercept_dr_write: B16,
|
||||
// 008h
|
||||
pub intercept_exceptions: B32,
|
||||
// 00Ch
|
||||
pub intercept_intr: bool,
|
||||
pub intercept_nmi: bool,
|
||||
pub intercept_smi: bool,
|
||||
pub intercept_init: bool,
|
||||
pub intercept_vintr: bool,
|
||||
pub intercept_cr0_write_ts_or_mp: bool,
|
||||
pub intercept_read_idtr: bool,
|
||||
pub intercept_read_gdtr: bool,
|
||||
pub intercept_read_ldtr: bool,
|
||||
pub intercept_read_tr: bool,
|
||||
pub intercept_write_idtr: bool,
|
||||
pub intercept_write_gdtr: bool,
|
||||
pub intercept_write_ldtr: bool,
|
||||
pub intercept_write_tr: bool,
|
||||
pub intercept_rdtsc: bool,
|
||||
pub intercept_rdpmc: bool,
|
||||
pub intercept_pushf: bool,
|
||||
pub intercept_popf: bool,
|
||||
pub intercept_cpuid: bool,
|
||||
pub intercept_rsm: bool,
|
||||
pub intercept_iret: bool,
|
||||
pub intercept_int_n: bool,
|
||||
pub intercept_invd: bool,
|
||||
pub intercept_pause: bool,
|
||||
pub intercept_hlt: bool,
|
||||
pub intercept_invlpg: bool,
|
||||
pub intercept_invlpga: bool,
|
||||
pub intercept_ioio_prot: bool,
|
||||
pub intercept_msr_prot: bool,
|
||||
pub intercept_task_switch: bool,
|
||||
pub intercept_ferr_freeze: bool,
|
||||
pub intercept_shutdown: bool,
|
||||
// 010h
|
||||
pub intercept_vmrun: bool,
|
||||
pub intercept_vmcall: bool,
|
||||
pub intercept_vmload: bool,
|
||||
pub intercept_vmsave: bool,
|
||||
pub intercept_stgi: bool,
|
||||
pub intercept_clgi: bool,
|
||||
pub intercept_skinit: bool,
|
||||
pub intercept_rdtscp: bool,
|
||||
pub intercept_icebp: bool,
|
||||
pub intercept_wbinvd_and_wbnoinvd: bool,
|
||||
pub intercept_monitor_and_monitorx: bool,
|
||||
pub intercept_mwait_and_mwaitx_unconditionally: bool,
|
||||
pub intercept_mwait_and_mwaitx: bool,
|
||||
pub intercept_xsetbv: bool,
|
||||
pub intercept_rdpru: bool,
|
||||
pub intercept_write_efer_after_guest_inst_finish: bool,
|
||||
pub intercept_write_cr0_after_guest_inst_finish: B16,
|
||||
// 014h
|
||||
pub intercept_all_invlpgb: bool,
|
||||
pub intercept_illegally_specified_invlpgb: bool,
|
||||
pub intercept_invpcid: bool,
|
||||
pub intercept_mcommit: bool,
|
||||
pub intercept_tlbsync: bool,
|
||||
pub intercept_bus_lock: bool,
|
||||
pub intercept_idle_hlt: bool,
|
||||
_reserved1: B25,
|
||||
// 018h-03Bh
|
||||
_reserved2: B128,
|
||||
_reserved3: B128,
|
||||
_reserved4: B32,
|
||||
// 03Ch
|
||||
pub pause_filter_threshold: B16,
|
||||
// 03Eh
|
||||
pub pause_filter_count: B16,
|
||||
// 040h
|
||||
pub iopm_base_physical_address: B64,
|
||||
// 048h
|
||||
pub msrpm_base_physical_address: B64,
|
||||
// 050h
|
||||
pub tsc_offset: B64,
|
||||
// 058h
|
||||
pub guest_asid: B32,
|
||||
pub tlb_control: TlbControl,
|
||||
pub allow_larger_rap: bool,
|
||||
pub clear_rap_on_vmrun: bool,
|
||||
_reserved5: B22,
|
||||
// 060h
|
||||
pub v_tpr: B8,
|
||||
pub v_irq: bool,
|
||||
pub vgif: bool,
|
||||
pub v_nmi: bool,
|
||||
pub v_nmi_mask: bool,
|
||||
_reserved6: B3,
|
||||
pub v_intr_prio: B4,
|
||||
pub v_ign_tpr: bool,
|
||||
_reserved7: B3,
|
||||
pub v_intr_masking: bool,
|
||||
pub amd_virtual_gif: bool,
|
||||
pub v_nmi_enable: bool,
|
||||
_reserved8: B3,
|
||||
pub x2avic_enable: bool,
|
||||
pub avic_enable: bool,
|
||||
pub v_intr_vector: B8,
|
||||
_reserved9: B24,
|
||||
// 068h
|
||||
pub interrupt_shadow: bool,
|
||||
pub guest_interrupt_mask: bool,
|
||||
_reserved10: B62,
|
||||
// 070h
|
||||
pub exit_code: B64,
|
||||
// 078h
|
||||
pub exit_info1: B64,
|
||||
// 080h
|
||||
pub exit_info2: B64,
|
||||
// 088h
|
||||
pub exit_int_info: B64,
|
||||
// 090h
|
||||
pub np_enable: bool,
|
||||
pub enable_sev: bool,
|
||||
pub enable_encrypted_state: bool,
|
||||
pub guest_mode_execution_trap: bool,
|
||||
pub sss_check_enable: bool,
|
||||
pub virtual_transparent_encryption: bool,
|
||||
pub enable_read_only_guest_page_table: bool,
|
||||
pub enable_invlpgb_and_tlbsync: bool,
|
||||
_reserved11: B56,
|
||||
// 098h
|
||||
_reserved12: B12,
|
||||
pub avic_apic_bar: B52,
|
||||
}
|
||||
|
||||
#[derive(Specifier, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum TlbControl {
|
||||
DoNothing = 0,
|
||||
FlushAll = 1,
|
||||
_RESERVED1 = 2,
|
||||
FlushGuest = 3,
|
||||
_RESERVED2 = 4,
|
||||
FlushHost = 5,
|
||||
_RESERVED3 = 6,
|
||||
FlushGuestNonGlobal = 7,
|
||||
}
|
||||
@@ -46,7 +46,7 @@ pub fn load_kernel(vcpu: &mut dyn VCpu) -> Result<(), &'static str> {
|
||||
256
|
||||
};
|
||||
|
||||
let cmdline_start = LAYOUT_CMDLINE as u64;
|
||||
let cmdline_start = LAYOUT_CMDLINE;
|
||||
let cmdline_end = cmdline_start + cmdline_max_size as u64;
|
||||
vcpu.write_memory_ranged(cmdline_start, cmdline_end, 0)?;
|
||||
let cmdline_val = "console=ttyS0 earlyprintk=serial nokaslr";
|
||||
@@ -128,11 +128,17 @@ pub struct BootParams {
|
||||
pub _unimplemented: [u8; 0x330],
|
||||
}
|
||||
|
||||
impl Default for BootParams {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl BootParams {
|
||||
pub const E820MAX: usize = 128;
|
||||
|
||||
pub fn new() -> Self {
|
||||
let params = Self {
|
||||
Self {
|
||||
_screen_info: [0; 0x40],
|
||||
_apm_bios_info: [0; 0x14],
|
||||
_pad2: [0; 4],
|
||||
@@ -162,9 +168,7 @@ impl BootParams {
|
||||
type_: E820Type::Ram as u32,
|
||||
}; Self::E820MAX],
|
||||
_unimplemented: [0; 0x330],
|
||||
};
|
||||
|
||||
params
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, &'static str> {
|
||||
|
||||
@@ -44,20 +44,20 @@ pub fn check_vmcs_control_fields() -> Result<(), &'static str> {
|
||||
fn is_valid_ept_ptr(ept_ptr: u64) -> Result<(), &'static str> {
|
||||
let memory_type = ept_ptr & 0b111;
|
||||
if memory_type != 0 && memory_type != 6 {
|
||||
return Err("VMCS EPT pointer memory type is not valid (must be 0 or 6)");
|
||||
return Err("VMCS Ept pointer memory type is not valid (must be 0 or 6)");
|
||||
}
|
||||
|
||||
let walk_length = (ept_ptr >> 3) & 0b111;
|
||||
if walk_length != 3 {
|
||||
return Err("VMCS EPT pointer walk length is not valid (must be 3)");
|
||||
return Err("VMCS Ept pointer walk length is not valid (must be 3)");
|
||||
}
|
||||
|
||||
if ept_ptr & 0xf00 != 0 {
|
||||
return Err("VMCS EPT pointer reserved bits are not zero");
|
||||
return Err("VMCS Ept pointer reserved bits are not zero");
|
||||
}
|
||||
|
||||
if !is_valid_phys_addr(ept_ptr) {
|
||||
return Err("VMCS EPT pointer is not a valid physical address");
|
||||
return Err("VMCS Ept pointer is not a valid physical address");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -72,12 +72,12 @@ fn check_ept() -> Result<(), &'static str> {
|
||||
} else {
|
||||
if secondary_exec_ctrl.unrestricted_guest() {
|
||||
return Err(
|
||||
"VMCS Secondary processor-based execution controls field: EPT is not set while unrestricted guest is set",
|
||||
"VMCS Secondary processor-based execution controls field: Ept is not set while unrestricted guest is set",
|
||||
);
|
||||
}
|
||||
if secondary_exec_ctrl.mode_based_control_ept() {
|
||||
return Err(
|
||||
"VMCS Secondary processor-based execution controls field: EPT is not set while mode-based control for EPT is set",
|
||||
"VMCS Secondary processor-based execution controls field: Ept is not set while mode-based control for Ept is set",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -107,15 +107,13 @@ fn check_interrupt() -> Result<(), &'static str> {
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
} else {
|
||||
if secondary_exec_ctrl.virtualize_x2apic_mode()
|
||||
|| secondary_exec_ctrl.apic_register_virtualization()
|
||||
|| secondary_exec_ctrl.virtual_interrupt_delivery()
|
||||
{
|
||||
return Err(
|
||||
"VMCS Primary processor-based execution controls field: Use TPR shadow is not set while virtualize x2APIC mode, APIC register virtualization, or virtual interrupt delivery is set",
|
||||
);
|
||||
}
|
||||
} else if secondary_exec_ctrl.virtualize_x2apic_mode()
|
||||
|| secondary_exec_ctrl.apic_register_virtualization()
|
||||
|| secondary_exec_ctrl.virtual_interrupt_delivery()
|
||||
{
|
||||
return Err(
|
||||
"VMCS Primary processor-based execution controls field: Use TPR shadow is not set while virtualize x2APIC mode, APIC register virtualization, or virtual interrupt delivery is set",
|
||||
);
|
||||
}
|
||||
|
||||
// TODO
|
||||
@@ -130,7 +128,7 @@ fn check_ept_violation_exception_info() -> Result<(), &'static str> {
|
||||
let exception_info = vmread(vmcs::control::VIRT_EXCEPTION_INFO_ADDR_FULL)?;
|
||||
|
||||
if is_valid_page_aligned_phys_addr(exception_info) {
|
||||
return Err("VMCS EPT violation exception info address is not a valid page-aligned physical address");
|
||||
return Err("VMCS Ept violation exception info address is not a valid page-aligned physical address");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -258,6 +258,7 @@ pub struct ExtFeatureEbx0 {
|
||||
pub avx512vl: bool,
|
||||
}
|
||||
|
||||
#[allow(clippy::enum_clike_unportable_variant)]
|
||||
pub enum VmxLeaf {
|
||||
MAXIMUM_INPUT = 0x0,
|
||||
VERSION_AND_FEATURE_INFO = 0x1,
|
||||
@@ -268,7 +269,7 @@ pub enum VmxLeaf {
|
||||
EXTENDED_FEATURE_2 = 0x80000002,
|
||||
EXTENDED_FEATURE_3 = 0x80000003,
|
||||
EXTENDED_FEATURE_4 = 0x80000004,
|
||||
UNKNOWN = 0xFFFFFFFF,
|
||||
Unknown = 0xFFFFFFFF,
|
||||
}
|
||||
|
||||
impl VmxLeaf {
|
||||
@@ -283,7 +284,7 @@ impl VmxLeaf {
|
||||
0x80000002 => VmxLeaf::EXTENDED_FEATURE_2,
|
||||
0x80000003 => VmxLeaf::EXTENDED_FEATURE_3,
|
||||
0x80000004 => VmxLeaf::EXTENDED_FEATURE_4,
|
||||
_ => VmxLeaf::UNKNOWN,
|
||||
_ => VmxLeaf::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,15 +9,15 @@ use x86_64::{
|
||||
PhysAddr,
|
||||
};
|
||||
|
||||
pub struct EPT {
|
||||
pub struct Ept {
|
||||
pub root_table: PhysFrame,
|
||||
}
|
||||
|
||||
impl EPT {
|
||||
impl Ept {
|
||||
pub fn new(allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str> {
|
||||
let root_table_frame = allocator
|
||||
.allocate_frame()
|
||||
.ok_or("Failed to allocate EPT root table frame")?;
|
||||
.ok_or("Failed to allocate Ept root table frame")?;
|
||||
|
||||
Self::init_table(&root_table_frame);
|
||||
|
||||
@@ -289,7 +289,7 @@ impl EPT {
|
||||
#[bitfield]
|
||||
#[repr(u64)]
|
||||
#[derive(Debug)]
|
||||
pub struct EPTP {
|
||||
pub struct Eptp {
|
||||
pub typ: B3,
|
||||
pub level: B3,
|
||||
pub dirty_accessed: bool,
|
||||
@@ -298,9 +298,9 @@ pub struct EPTP {
|
||||
pub phys: B52,
|
||||
}
|
||||
|
||||
impl EPTP {
|
||||
impl Eptp {
|
||||
pub fn init(lv4_table: &PhysFrame) -> Self {
|
||||
EPTP::new()
|
||||
Eptp::new()
|
||||
.with_typ(6)
|
||||
.with_level(3)
|
||||
.with_dirty_accessed(true)
|
||||
@@ -308,7 +308,7 @@ impl EPTP {
|
||||
.with_phys(lv4_table.start_address().as_u64() >> 12)
|
||||
}
|
||||
|
||||
pub fn get_lv4_table(&self) -> &mut [EntryBase; 512] {
|
||||
pub fn get_lv4_table(&mut self) -> &mut [EntryBase; 512] {
|
||||
let table_ptr = self.phys() << 12;
|
||||
|
||||
unsafe { &mut *(table_ptr as *mut [EntryBase; 512]) }
|
||||
|
||||
@@ -36,11 +36,11 @@ pub fn set_xcr(vcpu: &mut IntelVCpu, index: u32, xcr: u64) -> Result<(), &'stati
|
||||
return Err("Invalid XCR index");
|
||||
}
|
||||
|
||||
if !(xcr & 0b1 != 0) {
|
||||
if xcr & 0b1 == 0 {
|
||||
return Err("X87 is not enabled");
|
||||
}
|
||||
|
||||
if (xcr & 0b100 != 0) && !(xcr & 0b10 != 0) {
|
||||
if (xcr & 0b100 != 0) && (xcr & 0b10 == 0) {
|
||||
return Err("SSE is not enabled");
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ pub fn set_xcr(vcpu: &mut IntelVCpu, index: u32, xcr: u64) -> Result<(), &'stati
|
||||
}
|
||||
|
||||
if xcr & 0b11100000 != 0 {
|
||||
if !(xcr & 0b100 != 0) {
|
||||
if xcr & 0b100 == 0 {
|
||||
return Err("YMM bits are not enabled");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
use x86::vmx::{self, vmcs};
|
||||
use x86::{
|
||||
io::inb,
|
||||
vmx::{self, vmcs},
|
||||
};
|
||||
use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB};
|
||||
|
||||
use super::qual::QualIo;
|
||||
use crate::{
|
||||
info,
|
||||
interrupt::subscriber::InterruptContext,
|
||||
serial,
|
||||
vmm::x86_64::intel::{
|
||||
register::GuestRegisters, vmcs::controls::EntryIntrInfo, vmread, vmwrite,
|
||||
},
|
||||
@@ -19,7 +23,7 @@ pub fn vmm_interrupt_subscriber(vcpu_ptr: *mut core::ffi::c_void, context: &Inte
|
||||
|
||||
if 0x20 <= context.vector && context.vector <= 0x20 + 16 {
|
||||
let irq = context.vector - 0x20;
|
||||
vcpu.pending_irq |= 1 << irq;
|
||||
vcpu.pic.pending_irq |= 1 << irq;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,11 +37,17 @@ pub enum InitPhase {
|
||||
}
|
||||
|
||||
pub enum ReadSel {
|
||||
IRR,
|
||||
ISR,
|
||||
Irr,
|
||||
Isr,
|
||||
}
|
||||
|
||||
pub struct PIC {
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct Serial {
|
||||
pub ier: u8,
|
||||
pub mcr: u8,
|
||||
}
|
||||
|
||||
pub struct Pic {
|
||||
pub primary_mask: u8,
|
||||
pub secondary_mask: u8,
|
||||
pub primary_phase: InitPhase,
|
||||
@@ -50,9 +60,11 @@ pub struct PIC {
|
||||
pub secondary_isr: u8,
|
||||
pub primary_read_sel: ReadSel,
|
||||
pub secondary_read_sel: ReadSel,
|
||||
pub serial: Serial,
|
||||
pub pending_irq: u16,
|
||||
}
|
||||
|
||||
impl PIC {
|
||||
impl Pic {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
primary_mask: 0xFF,
|
||||
@@ -65,8 +77,10 @@ impl PIC {
|
||||
primary_isr: 0,
|
||||
secondary_irr: 0,
|
||||
secondary_isr: 0,
|
||||
primary_read_sel: ReadSel::IRR,
|
||||
secondary_read_sel: ReadSel::IRR,
|
||||
primary_read_sel: ReadSel::Irr,
|
||||
secondary_read_sel: ReadSel::Irr,
|
||||
serial: Serial::default(),
|
||||
pending_irq: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,11 +96,8 @@ impl PIC {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inject_external_interrupt(
|
||||
&mut self,
|
||||
pending_irq: &mut u16,
|
||||
) -> Result<bool, &'static str> {
|
||||
let pending = *pending_irq;
|
||||
pub fn inject_external_interrupt(&mut self) -> Result<bool, &'static str> {
|
||||
let pending = self.pending_irq;
|
||||
|
||||
if pending == 0 {
|
||||
return Ok(false);
|
||||
@@ -148,7 +159,7 @@ impl PIC {
|
||||
u32::from(interrupt_info) as u64,
|
||||
)?;
|
||||
|
||||
*pending_irq &= !irq_bit;
|
||||
self.pending_irq &= !irq_bit;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
@@ -160,10 +171,7 @@ impl PIC {
|
||||
vector: u32,
|
||||
error_code: Option<u32>,
|
||||
) -> Result<(), &'static str> {
|
||||
let has_error_code = match vector {
|
||||
8 | 10..=14 | 17 | 21 => true,
|
||||
_ => false,
|
||||
};
|
||||
let has_error_code = matches!(vector, 8 | 10..=14 | 17 | 21);
|
||||
|
||||
let interrupt_info = EntryIntrInfo::new()
|
||||
.with_vector(vector as u8)
|
||||
@@ -191,6 +199,7 @@ impl PIC {
|
||||
0x20..=0x21 => self.handle_pic_in(regs, qual),
|
||||
0xA0..=0xA1 => self.handle_pic_in(regs, qual),
|
||||
0x0070..=0x0071 => regs.rax = 0,
|
||||
0x03F8..=0x03FF => self.handle_serial_in(regs, qual),
|
||||
_ => regs.rax = 0,
|
||||
}
|
||||
}
|
||||
@@ -201,24 +210,69 @@ impl PIC {
|
||||
0xC000..=0xCFFF => {} //ignore
|
||||
0x20..=0x21 => self.handle_pic_out(regs, qual),
|
||||
0xA0..=0xA1 => self.handle_pic_out(regs, qual),
|
||||
0x03F8..=0x03FF => self.handle_serial_out(regs, qual),
|
||||
0x0070..=0x0071 => {} //ignore
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_serial_in(&self, regs: &mut GuestRegisters, qual: QualIo) {
|
||||
match qual.port() {
|
||||
0x3F8 => regs.rax = unsafe { inb(qual.port()).into() },
|
||||
0x3F9 => regs.rax = self.serial.ier as u64,
|
||||
0x3FA => {} //regs.rax = 0, // unsafe { inb(qual.port()).into() },
|
||||
0x3FB => {} //regs.rax = 0,
|
||||
0x3FC => {} //regs.rax = 0, //self.serial.mcr as u64,
|
||||
0x3FD => {
|
||||
if qual.size() == 1 {
|
||||
regs.rax = 0x60
|
||||
}
|
||||
}
|
||||
0x3FE => {
|
||||
if qual.size() == 1 {
|
||||
regs.rax = 0xb0
|
||||
}
|
||||
}
|
||||
0x3FF => {} //regs.rax = 0,
|
||||
_ => {
|
||||
panic!("Serial in: invalid port: {:#x}", qual.port());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_serial_out(&mut self, regs: &mut GuestRegisters, qual: QualIo) {
|
||||
match qual.port() {
|
||||
0x3F8 => serial::write_byte(regs.rax as u8),
|
||||
0x3F9 => {
|
||||
self.serial.ier = regs.rax as u8;
|
||||
if regs.rax & 0b10 != 0 {
|
||||
self.pending_irq |= 1 << 4;
|
||||
}
|
||||
}
|
||||
0x3FA => {}
|
||||
0x3FB => {}
|
||||
0x3FC => self.serial.mcr = regs.rax as u8,
|
||||
0x3FD => {}
|
||||
0x3FF => {}
|
||||
_ => {
|
||||
panic!("Serial out: invalid port: {:#x}", qual.port());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_pic_in(&self, regs: &mut GuestRegisters, qual: QualIo) {
|
||||
match qual.port() {
|
||||
0x20 => {
|
||||
let v = match self.primary_read_sel {
|
||||
ReadSel::IRR => self.primary_irr,
|
||||
ReadSel::ISR => self.primary_isr,
|
||||
ReadSel::Irr => self.primary_irr,
|
||||
ReadSel::Isr => self.primary_isr,
|
||||
};
|
||||
regs.rax = v as u64;
|
||||
}
|
||||
0xA0 => {
|
||||
let v = match self.secondary_read_sel {
|
||||
ReadSel::IRR => self.secondary_irr,
|
||||
ReadSel::ISR => self.secondary_isr,
|
||||
ReadSel::Irr => self.secondary_irr,
|
||||
ReadSel::Isr => self.secondary_isr,
|
||||
};
|
||||
regs.rax = v as u64;
|
||||
}
|
||||
@@ -244,8 +298,8 @@ impl PIC {
|
||||
match qual.port() {
|
||||
0x20 => match dx {
|
||||
0x11 => pic.primary_phase = InitPhase::Phase1,
|
||||
0x0A => pic.primary_read_sel = ReadSel::ISR,
|
||||
0x0B => pic.primary_read_sel = ReadSel::IRR,
|
||||
0x0A => pic.primary_read_sel = ReadSel::Isr,
|
||||
0x0B => pic.primary_read_sel = ReadSel::Irr,
|
||||
0x20 => {
|
||||
pic.primary_isr = 0;
|
||||
}
|
||||
@@ -253,7 +307,7 @@ impl PIC {
|
||||
let irq = dx & 0x7;
|
||||
pic.primary_isr &= !(1 << irq);
|
||||
}
|
||||
_ => panic!("Primary PIC command: {:#x}", dx),
|
||||
_ => panic!("Primary Pic command: {:#x}", dx),
|
||||
},
|
||||
0x21 => match pic.primary_phase {
|
||||
InitPhase::Uninitialized | InitPhase::Initialized => pic.primary_mask = dx,
|
||||
@@ -265,14 +319,14 @@ impl PIC {
|
||||
pic.primary_phase = InitPhase::Phase3;
|
||||
}
|
||||
InitPhase::Phase3 => {
|
||||
info!("Primary PIC Initialized");
|
||||
info!("Primary Pic Initialized");
|
||||
pic.primary_phase = InitPhase::Initialized
|
||||
}
|
||||
},
|
||||
0xA0 => match dx {
|
||||
0x11 => pic.secondary_phase = InitPhase::Phase1,
|
||||
0x0A => pic.secondary_read_sel = ReadSel::ISR,
|
||||
0x0B => pic.secondary_read_sel = ReadSel::IRR,
|
||||
0x0A => pic.secondary_read_sel = ReadSel::Isr,
|
||||
0x0B => pic.secondary_read_sel = ReadSel::Irr,
|
||||
0x20 => {
|
||||
pic.secondary_isr = 0;
|
||||
}
|
||||
@@ -280,7 +334,7 @@ impl PIC {
|
||||
let irq = dx & 0x7;
|
||||
pic.secondary_isr &= !(1 << irq);
|
||||
}
|
||||
_ => panic!("Secondary PIC command: {:#x}", dx),
|
||||
_ => panic!("Secondary Pic command: {:#x}", dx),
|
||||
},
|
||||
0xA1 => match pic.secondary_phase {
|
||||
InitPhase::Uninitialized | InitPhase::Initialized => pic.secondary_mask = dx,
|
||||
@@ -292,7 +346,7 @@ impl PIC {
|
||||
pic.secondary_phase = InitPhase::Phase3;
|
||||
}
|
||||
InitPhase::Phase3 => {
|
||||
info!("Secondary PIC Initialized");
|
||||
info!("Secondary Pic Initialized");
|
||||
pic.secondary_phase = InitPhase::Initialized
|
||||
}
|
||||
},
|
||||
@@ -327,8 +381,8 @@ impl IOBitmap {
|
||||
core::ptr::write_bytes(bitmap_b_addr as *mut u8, u8::MAX, 4096);
|
||||
}
|
||||
|
||||
self.set_io_ports(0x02F8..=0x03FF);
|
||||
self.set_io_ports(0x0040..=0x0047);
|
||||
//self.set_io_ports(0x02F8..=0x03EF);
|
||||
|
||||
vmwrite(vmcs::control::IO_BITMAP_A_ADDR_FULL, bitmap_a_addr as u64)?;
|
||||
vmwrite(vmcs::control::IO_BITMAP_B_ADDR_FULL, bitmap_b_addr as u64)?;
|
||||
@@ -353,13 +407,13 @@ impl IOBitmap {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_bitmap_a(&self) -> &mut [u8] {
|
||||
fn get_bitmap_a(&mut self) -> &mut [u8] {
|
||||
unsafe {
|
||||
core::slice::from_raw_parts_mut(self.bitmap_a.start_address().as_u64() as *mut u8, 4096)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_bitmap_b(&self) -> &mut [u8] {
|
||||
fn get_bitmap_b(&mut self) -> &mut [u8] {
|
||||
unsafe {
|
||||
core::slice::from_raw_parts_mut(self.bitmap_b.start_address().as_u64() as *mut u8, 4096)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ type MsrIndex = u32;
|
||||
|
||||
const MAX_NUM_ENTS: usize = 512;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
#[repr(C, packed)]
|
||||
pub struct SavedMsr {
|
||||
pub index: MsrIndex,
|
||||
@@ -20,16 +20,6 @@ pub struct SavedMsr {
|
||||
pub data: u64,
|
||||
}
|
||||
|
||||
impl Default for SavedMsr {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
index: 0,
|
||||
reserved: 0,
|
||||
data: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShadowMsr {
|
||||
ents: Vec<SavedMsr>,
|
||||
@@ -126,6 +116,12 @@ pub fn _update_msrs(vcpu: &mut IntelVCpu) -> Result<(), MsrError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Default for ShadowMsr {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ShadowMsr {
|
||||
pub fn new() -> Self {
|
||||
let ents = vec![];
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt::Debug;
|
||||
|
||||
use modular_bitfield::prelude::{B1, B16, B32, B4, B8};
|
||||
use modular_bitfield::prelude::{B1, B16, B3, B32, B4, B9};
|
||||
use modular_bitfield::{bitfield, Specifier};
|
||||
|
||||
#[repr(u8)]
|
||||
@@ -113,12 +113,12 @@ pub struct QualCr {
|
||||
#[repr(u64)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct QualIo {
|
||||
pub size: B4,
|
||||
pub size: B3,
|
||||
pub direction: B1,
|
||||
pub string: B1,
|
||||
pub rep: B1,
|
||||
pub operand_encoding: B1,
|
||||
_reserved1: B8,
|
||||
_reserved1: B9,
|
||||
pub port: B16,
|
||||
_reserved2: B32,
|
||||
}
|
||||
|
||||
@@ -46,15 +46,14 @@ pub struct IntelVCpu {
|
||||
activated: bool,
|
||||
vmxon: vmxon::Vmxon,
|
||||
vmcs: vmcs::Vmcs,
|
||||
ept: ept::EPT,
|
||||
eptp: ept::EPTP,
|
||||
ept: ept::Ept,
|
||||
eptp: ept::Eptp,
|
||||
guest_memory_size: u64,
|
||||
pub host_msr: ShadowMsr,
|
||||
pub guest_msr: ShadowMsr,
|
||||
pub ia32e_enabled: bool,
|
||||
pic: super::io::PIC,
|
||||
pub pic: super::io::Pic,
|
||||
io_bitmap: IOBitmap,
|
||||
pub pending_irq: u16,
|
||||
pub host_xcr0: u64,
|
||||
pub guest_xcr0: XCR0,
|
||||
}
|
||||
@@ -87,10 +86,7 @@ impl IntelVCpu {
|
||||
|
||||
match exit_reason {
|
||||
VmxExitReason::HLT => {
|
||||
let injected = self
|
||||
.pic
|
||||
.inject_external_interrupt(&mut self.pending_irq)
|
||||
.unwrap_or(false);
|
||||
let injected = self.pic.inject_external_interrupt().unwrap_or(false);
|
||||
|
||||
if !injected {
|
||||
unsafe {
|
||||
@@ -151,12 +147,12 @@ impl IntelVCpu {
|
||||
asm!("cli");
|
||||
}
|
||||
|
||||
self.pic.inject_external_interrupt(&mut self.pending_irq)?;
|
||||
self.pic.inject_external_interrupt()?;
|
||||
}
|
||||
VmxExitReason::EPT_VIOLATION => {
|
||||
let guest_address = vmread(vmcs::ro::GUEST_PHYSICAL_ADDR_FULL)?;
|
||||
info!("EPT Violation at guest address: {:#x}", guest_address);
|
||||
return Err("EPT Violation");
|
||||
info!("Ept Violation at guest address: {:#x}", guest_address);
|
||||
return Err("Ept Violation");
|
||||
}
|
||||
VmxExitReason::TRIPLE_FAULT => {
|
||||
info!("Triple fault detected");
|
||||
@@ -378,7 +374,7 @@ impl IntelVCpu {
|
||||
pages -= 1;
|
||||
}
|
||||
|
||||
let eptp = ept::EPTP::init(&self.ept.root_table);
|
||||
let eptp = ept::Eptp::init(&self.ept.root_table);
|
||||
vmwrite(x86::vmx::vmcs::control::EPTP_FULL, u64::from(eptp))?;
|
||||
|
||||
Ok(())
|
||||
@@ -397,7 +393,7 @@ impl IntelVCpu {
|
||||
|
||||
vmwrite(
|
||||
vmcs::host::RIP,
|
||||
crate::vmm::x86_64::intel::asm::asm_vmexit_handler as u64,
|
||||
crate::vmm::x86_64::intel::asm::asm_vmexit_handler as usize as u64,
|
||||
)?;
|
||||
vmwrite(
|
||||
vmcs::host::RSP,
|
||||
@@ -556,11 +552,11 @@ impl IntelVCpu {
|
||||
return Ok(vaddr & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
let pml4_idx = ((vaddr >> 39) & 0x1FF) as u64;
|
||||
let pdpt_idx = ((vaddr >> 30) & 0x1FF) as u64;
|
||||
let pd_idx = ((vaddr >> 21) & 0x1FF) as u64;
|
||||
let pt_idx = ((vaddr >> 12) & 0x1FF) as u64;
|
||||
let page_offset = (vaddr & 0xFFF) as u64;
|
||||
let pml4_idx = (vaddr >> 39) & 0x1FF;
|
||||
let pdpt_idx = (vaddr >> 30) & 0x1FF;
|
||||
let pd_idx = (vaddr >> 21) & 0x1FF;
|
||||
let pt_idx = (vaddr >> 12) & 0x1FF;
|
||||
let page_offset = vaddr & 0xFFF;
|
||||
|
||||
let pml4_entry_addr = pml4_base + (pml4_idx * 8);
|
||||
let pml4_entry = self.read_guest_phys_u64(pml4_entry_addr)?;
|
||||
@@ -609,7 +605,7 @@ impl IntelVCpu {
|
||||
for i in 0..8 {
|
||||
match self.ept.get(gpa + i) {
|
||||
Ok(byte) => result_bytes[i as usize] = byte,
|
||||
Err(_) => return Err("Failed to read from EPT"),
|
||||
Err(_) => return Err("Failed to read from Ept"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -645,9 +641,9 @@ impl IntelVCpu {
|
||||
let exit_ctrl = vmread(x86::vmx::vmcs::control::VMEXIT_CONTROLS)?;
|
||||
info!("VM-exit controls: {:#x}", exit_ctrl);
|
||||
|
||||
// EPT pointer
|
||||
// Ept pointer
|
||||
let eptp = vmread(x86::vmx::vmcs::control::EPTP_FULL)?;
|
||||
info!("EPT pointer: {:#x}", eptp);
|
||||
info!("Ept pointer: {:#x}", eptp);
|
||||
|
||||
info!("=== Guest State ===");
|
||||
|
||||
@@ -899,8 +895,8 @@ impl VCpu for IntelVCpu {
|
||||
|
||||
let vmcs = vmcs::Vmcs::new(frame_allocator)?;
|
||||
|
||||
let ept = ept::EPT::new(frame_allocator)?;
|
||||
let eptp = ept::EPTP::init(&ept.root_table);
|
||||
let ept = ept::Ept::new(frame_allocator)?;
|
||||
let eptp = ept::Eptp::init(&ept.root_table);
|
||||
|
||||
Ok(IntelVCpu {
|
||||
launch_done: false,
|
||||
@@ -914,9 +910,8 @@ impl VCpu for IntelVCpu {
|
||||
host_msr: ShadowMsr::new(),
|
||||
guest_msr: ShadowMsr::new(),
|
||||
ia32e_enabled: false,
|
||||
pic: super::io::PIC::new(),
|
||||
pic: super::io::Pic::new(),
|
||||
io_bitmap: IOBitmap::new(frame_allocator),
|
||||
pending_irq: 0,
|
||||
host_xcr0: 0,
|
||||
guest_xcr0: XCR0::new(),
|
||||
})
|
||||
|
||||
@@ -23,7 +23,7 @@ impl PinBasedVmExecutionControls {
|
||||
pub fn read() -> Result<Self, &'static str> {
|
||||
vmcs::VmcsControl32::PIN_BASED_VM_EXECUTION_CONTROLS
|
||||
.read()
|
||||
.map(|value| PinBasedVmExecutionControls::from(value))
|
||||
.map(PinBasedVmExecutionControls::from)
|
||||
.map_err(|_| "Failed to read Pin-Based VM Execution Controls")
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ impl PrimaryProcessorBasedVmExecutionControls {
|
||||
pub fn read() -> Result<Self, &'static str> {
|
||||
vmcs::VmcsControl32::PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS
|
||||
.read()
|
||||
.map(|value| PrimaryProcessorBasedVmExecutionControls::from(value))
|
||||
.map(PrimaryProcessorBasedVmExecutionControls::from)
|
||||
.map_err(|_| "Failed to read Primary Processor-Based VM Execution Controls")
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ impl SecondaryProcessorBasedVmExecutionControls {
|
||||
pub fn read() -> Result<Self, &'static str> {
|
||||
vmcs::VmcsControl32::SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS
|
||||
.read()
|
||||
.map(|value| SecondaryProcessorBasedVmExecutionControls::from(value))
|
||||
.map(SecondaryProcessorBasedVmExecutionControls::from)
|
||||
.map_err(|_| "Failed to read Secondary Processor-Based VM Execution Controls")
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ impl EntryControls {
|
||||
pub fn read() -> Result<Self, &'static str> {
|
||||
vmcs::VmcsControl32::VM_ENTRY_CONTROLS
|
||||
.read()
|
||||
.map(|value| EntryControls::from(value))
|
||||
.map(EntryControls::from)
|
||||
.map_err(|_| "Failed to read VM Entry Controls")
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ impl PrimaryExitControls {
|
||||
pub fn read() -> Result<Self, &'static str> {
|
||||
vmcs::VmcsControl32::PRIMARY_VM_EXIT_CONTROLS
|
||||
.read()
|
||||
.map(|value| PrimaryExitControls::from(value))
|
||||
.map(PrimaryExitControls::from)
|
||||
.map_err(|_| "Failed to read Primary VM Exit Controls")
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ impl InstructionError {
|
||||
InstructionError::try_from(err).map_err(|_| "Unknown instruction error")
|
||||
}
|
||||
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
pub fn to_str(self) -> &'static str {
|
||||
match self {
|
||||
InstructionError::NOT_AVAILABLE => "Instruction not available",
|
||||
InstructionError::VMCALL_IN_VMXROOT => "VMCALL in VMX root operation",
|
||||
|
||||
@@ -139,8 +139,8 @@ impl VmxExitReason {
|
||||
VIRTUALIZED_EOI => "Virtualized EOI",
|
||||
ACCESS_TO_GDTR_OR_IDTR => "Access to GDTR or IDTR",
|
||||
ACCESS_TO_LDTR_OR_TR => "Access to LDTR or TR",
|
||||
EPT_VIOLATION => "EPT violation",
|
||||
EPT_MISCONFIGURATION => "EPT misconfiguration",
|
||||
EPT_VIOLATION => "Ept violation",
|
||||
EPT_MISCONFIGURATION => "Ept misconfiguration",
|
||||
INVEPT => "INVEPT instruction execution",
|
||||
RDTSCP => "RDTSCP instruction execution",
|
||||
VMX_PREEMPTION_TIMER_EXPIRED => "VMX-preemption timer expired",
|
||||
|
||||
Reference in New Issue
Block a user