mirror of
https://github.com/mii443/nel_os.git
synced 2025-12-10 06:38:23 +00:00
add VMCS read write
This commit is contained in:
136
src/vmm/vmcs.rs
136
src/vmm/vmcs.rs
@@ -1,8 +1,45 @@
|
|||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use bitfield::BitMut;
|
||||||
use x86::{bits64::vmx, vmx::VmFail};
|
use x86::{bits64::vmx, vmx::VmFail};
|
||||||
use x86_64::structures::paging::{FrameAllocator, PhysFrame};
|
use x86_64::structures::paging::{FrameAllocator, PhysFrame};
|
||||||
|
|
||||||
use crate::memory::BootInfoFrameAllocator;
|
use crate::memory::BootInfoFrameAllocator;
|
||||||
|
|
||||||
|
macro_rules! vmcs_read {
|
||||||
|
($field_enum: ident, u64) => {
|
||||||
|
impl $field_enum {
|
||||||
|
pub fn read(self) -> x86::vmx::Result<u64> {
|
||||||
|
unsafe { vmx::vmread(self as u32) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($field_enum: ident, $ux: ty) => {
|
||||||
|
impl $field_enum {
|
||||||
|
pub fn read(self) -> x86::vmx::Result<$ux> {
|
||||||
|
unsafe { vmx::vmread(self as u32).map(|v| v as $ux) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! vmcs_write {
|
||||||
|
($field_enum: ident, u64) => {
|
||||||
|
impl $field_enum {
|
||||||
|
pub fn write(self, value: u64) -> x86::vmx::Result<()> {
|
||||||
|
unsafe { vmx::vmwrite(self as u32, value) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($field_enum: ident, $ux: ty) => {
|
||||||
|
impl $field_enum {
|
||||||
|
pub fn write(self, value: $ux) -> x86::vmx::Result<()> {
|
||||||
|
unsafe { vmx::vmwrite(self as u32, value as u64) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Vmcs {
|
pub struct Vmcs {
|
||||||
pub frame: PhysFrame,
|
pub frame: PhysFrame,
|
||||||
}
|
}
|
||||||
@@ -66,11 +103,106 @@ impl InstructionError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read() -> Self {
|
pub fn read() -> Self {
|
||||||
let err = unsafe { vmx::vmread(0x4400) };
|
let err = VmcsReadOnlyData32::VM_INSTRUCTION_ERROR.read();
|
||||||
if err.is_err() {
|
if err.is_err() {
|
||||||
panic!("Failed to read VM instruction error");
|
panic!("Failed to read VM instruction error");
|
||||||
}
|
}
|
||||||
let err = err.unwrap();
|
let err = err.unwrap();
|
||||||
InstructionError(err as u32)
|
InstructionError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PinBasedVmExecutionControls(pub u32);
|
||||||
|
|
||||||
|
impl PinBasedVmExecutionControls {
|
||||||
|
pub fn set_external_interrupt_exiting(&mut self, value: bool) {
|
||||||
|
self.0.set_bit(0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_nmi_exiting(&mut self, value: bool) {
|
||||||
|
self.0.set_bit(3, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_virtual_nmi(&mut self, value: bool) {
|
||||||
|
self.0.set_bit(5, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_activate_vmx_preemption_timer(&mut self, value: bool) {
|
||||||
|
self.0.set_bit(6, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_process_posted_interrupts(&mut self, value: bool) {
|
||||||
|
self.0.set_bit(7, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_external_interrupt_exiting(&self) -> bool {
|
||||||
|
self.0 & (1 << 0) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_nmi_exiting(&self) -> bool {
|
||||||
|
self.0 & (1 << 3) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_virtual_nmi(&self) -> bool {
|
||||||
|
self.0 & (1 << 5) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_activate_vmx_preemption_timer(&self) -> bool {
|
||||||
|
self.0 & (1 << 6) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_process_posted_interrupts(&self) -> bool {
|
||||||
|
self.0 & (1 << 7) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read() -> Self {
|
||||||
|
let err = VmcsControl32::PIN_BASED_VM_EXECUTION_CONTROLS.read();
|
||||||
|
if err.is_err() {
|
||||||
|
panic!("Failed to read Pin Based VM Execution Controls");
|
||||||
|
}
|
||||||
|
let err = err.unwrap();
|
||||||
|
PinBasedVmExecutionControls(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self) {
|
||||||
|
VmcsControl32::PIN_BASED_VM_EXECUTION_CONTROLS
|
||||||
|
.write(self.0)
|
||||||
|
.expect("Failed to write Pin Based VM Execution Controls");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum VmcsControl32 {
|
||||||
|
PIN_BASED_VM_EXECUTION_CONTROLS = 0x00004000,
|
||||||
|
PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS = 0x00004002,
|
||||||
|
EXCEPTION_BITMAP = 0x00004004,
|
||||||
|
PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
|
||||||
|
PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
|
||||||
|
CR3_TARGET_COUNT = 0x0000400A,
|
||||||
|
PRIMARY_VM_EXIT_CONTROLS = 0x0000400C,
|
||||||
|
VM_EXIT_MSR_STORE_COUNT = 0x0000400E,
|
||||||
|
VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
|
||||||
|
VM_ENTRY_CONTROLS = 0x00004012,
|
||||||
|
VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
|
||||||
|
VM_ENTRY_INTERRUPTION_INFORMATION_FIELD = 0x00004016,
|
||||||
|
VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
|
||||||
|
VM_ENTRY_INSTRUCTION_LENGTH = 0x0000401A,
|
||||||
|
TPR_THRESHOLD = 0x0000401C,
|
||||||
|
SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS = 0x0000401E,
|
||||||
|
PLE_GAP = 0x00004020,
|
||||||
|
PLE_WINDOW = 0x00004022,
|
||||||
|
INSTRUCTION_TIMEOUT_CONTROL = 0x00004024,
|
||||||
|
}
|
||||||
|
vmcs_read!(VmcsControl32, u32);
|
||||||
|
vmcs_write!(VmcsControl32, u32);
|
||||||
|
|
||||||
|
pub enum VmcsReadOnlyData32 {
|
||||||
|
VM_INSTRUCTION_ERROR = 0x00004400,
|
||||||
|
VM_EXIT_REASON = 0x00004402,
|
||||||
|
VM_EXIT_INTERRUPTION_INFORMATION_FIELD = 0x00004404,
|
||||||
|
VM_EXIT_INTERRUPTION_ERROR_CODE = 0x00004406,
|
||||||
|
IDT_VECTORING_INFORMATION_FIELD = 0x00004408,
|
||||||
|
IDT_VECTORING_ERROR_CODE = 0x0000440A,
|
||||||
|
VM_EXIT_INSTRUCTION_LENGTH = 0x0000440C,
|
||||||
|
VM_EXIT_INSTRUCTION_INFO = 0x0000440E,
|
||||||
|
}
|
||||||
|
vmcs_read!(VmcsReadOnlyData32, u32);
|
||||||
|
|||||||
Reference in New Issue
Block a user