diff --git a/src/frame.rs b/src/frame.rs index 34350a7..be7568a 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -1,37 +1,28 @@ +use core::marker::PhantomData; + use axaddrspace::HostPhysAddr; use axerrno::{ax_err_type, AxResult}; -use memory_addr::{PhysAddr, VirtAddr}; -pub(crate) use memory_addr::PAGE_SIZE_4K as PAGE_SIZE; +use axvcpu::AxVCpuHal; -/// Low-level resource interfaces that must be implemented by the crate user. -#[crate_interface::def_interface] -pub trait PhysFrameIf { - /// Request to allocate a 4K-sized physical frame. - fn alloc_frame() -> Option; - /// Request to free a allocated physical frame. - fn dealloc_frame(paddr: PhysAddr); - /// Returns a virtual address that maps to the given physical address. - /// - /// Used to access the physical memory directly in PhysFrame implementation through `as_mut_ptr()`. - fn phys_to_virt(paddr: PhysAddr) -> VirtAddr; -} +pub(crate) use memory_addr::PAGE_SIZE_4K as PAGE_SIZE; /// A 4K-sized contiguous physical memory page, it will deallocate the page /// automatically on drop. #[derive(Debug)] -pub struct PhysFrame { +pub struct PhysFrame { start_paddr: Option, + _marker: PhantomData, } -impl PhysFrame { +impl PhysFrame { pub fn alloc() -> AxResult { - let start_paddr = crate_interface::call_interface!(PhysFrameIf::alloc_frame) + let start_paddr = H::alloc_frame() .ok_or_else(|| ax_err_type!(NoMemory, "allocate physical frame failed"))?; assert_ne!(start_paddr.as_usize(), 0); - debug!("[AxVM] allocated PhysFrame({:#x})", start_paddr); Ok(Self { start_paddr: Some(start_paddr), + _marker: PhantomData, }) } @@ -42,7 +33,10 @@ impl PhysFrame { } pub const unsafe fn uninit() -> Self { - Self { start_paddr: None } + Self { + start_paddr: None, + _marker: PhantomData, + } } pub fn start_paddr(&self) -> HostPhysAddr { @@ -50,7 +44,7 @@ impl PhysFrame { } pub fn as_mut_ptr(&self) -> *mut u8 { - crate_interface::call_interface!(PhysFrameIf::phys_to_virt(self.start_paddr())).as_mut_ptr() + H::phys_to_virt(self.start_paddr()).as_mut_ptr() } pub fn fill(&mut self, byte: u8) { @@ -58,10 +52,10 @@ impl PhysFrame { } } -impl Drop for PhysFrame { +impl Drop for PhysFrame { fn drop(&mut self) { if let Some(start_paddr) = self.start_paddr { - crate_interface::call_interface!(PhysFrameIf::dealloc_frame(start_paddr)); + H::dealloc_frame(start_paddr); debug!("[AxVM] deallocated PhysFrame({:#x})", start_paddr); } } diff --git a/src/lib.rs b/src/lib.rs index 69d7233..d92d0b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,5 @@ cfg_if::cfg_if! { } pub use ept::GuestPageWalkInfo; -pub use frame::PhysFrameIf; pub use regs::GeneralRegisters; pub use vender::has_hardware_support; diff --git a/src/vmx/percpu.rs b/src/vmx/percpu.rs index 7250150..a052d18 100644 --- a/src/vmx/percpu.rs +++ b/src/vmx/percpu.rs @@ -2,7 +2,7 @@ use x86::bits64::vmx; use x86_64::registers::control::{Cr0, Cr4, Cr4Flags}; use axerrno::{ax_err, ax_err_type, AxResult}; -use axvcpu::AxArchPerCpu; +use axvcpu::{AxArchPerCpu, AxVCpuHal}; use memory_addr::PAGE_SIZE_4K as PAGE_SIZE; use crate::msr::Msr; @@ -14,7 +14,7 @@ use crate::vmx::structs::{FeatureControl, FeatureControlFlags, VmxBasic, VmxRegi /// This structure holds the state information specific to a CPU core /// when operating in VMX mode, including the VMCS revision identifier and /// the VMX region. -pub struct VmxPerCpuState { +pub struct VmxPerCpuState { /// The VMCS (Virtual Machine Control Structure) revision identifier. /// /// This identifier is used to ensure compatibility between the software @@ -25,10 +25,10 @@ pub struct VmxPerCpuState { /// /// This region typically contains the VMCS and other state information /// required for managing virtual machines on this particular CPU. - vmx_region: VmxRegion, + vmx_region: VmxRegion, } -impl AxArchPerCpu for VmxPerCpuState { +impl AxArchPerCpu for VmxPerCpuState { fn new(_cpu_id: usize) -> AxResult { Ok(Self { vmcs_revision_id: 0, diff --git a/src/vmx/structs.rs b/src/vmx/structs.rs index 442a4fd..daecdc5 100644 --- a/src/vmx/structs.rs +++ b/src/vmx/structs.rs @@ -1,20 +1,22 @@ use bit_field::BitField; use bitflags::bitflags; +use memory_addr::PAGE_SIZE_4K as PAGE_SIZE; + use axaddrspace::HostPhysAddr; use axerrno::AxResult; -use memory_addr::PAGE_SIZE_4K as PAGE_SIZE; +use axvcpu::AxVCpuHal; use crate::frame::PhysFrame; use crate::msr::{Msr, MsrReadWrite}; /// VMCS/VMXON region in 4K size. (SDM Vol. 3C, Section 24.2) #[derive(Debug)] -pub struct VmxRegion { - frame: PhysFrame, +pub struct VmxRegion { + frame: PhysFrame, } -impl VmxRegion { +impl VmxRegion { pub const unsafe fn uninit() -> Self { Self { frame: PhysFrame::uninit(), @@ -41,12 +43,12 @@ impl VmxRegion { // I/O bitmap A contains one bit for each I/O port in the range 0000H through 7FFFH; // I/O bitmap B contains bits for ports in the range 8000H through FFFFH. #[derive(Debug)] -pub struct IOBitmap { - io_bitmap_a_frame: PhysFrame, - io_bitmap_b_frame: PhysFrame, +pub struct IOBitmap { + io_bitmap_a_frame: PhysFrame, + io_bitmap_b_frame: PhysFrame, } -impl IOBitmap { +impl IOBitmap { pub fn passthrough_all() -> AxResult { Ok(Self { io_bitmap_a_frame: PhysFrame::alloc_zero()?, @@ -101,11 +103,11 @@ impl IOBitmap { } #[derive(Debug)] -pub struct MsrBitmap { - frame: PhysFrame, +pub struct MsrBitmap { + frame: PhysFrame, } -impl MsrBitmap { +impl MsrBitmap { pub fn passthrough_all() -> AxResult { Ok(Self { frame: PhysFrame::alloc_zero()?, diff --git a/src/vmx/vcpu.rs b/src/vmx/vcpu.rs index ff58c60..e772cbf 100644 --- a/src/vmx/vcpu.rs +++ b/src/vmx/vcpu.rs @@ -11,7 +11,7 @@ use x86_64::registers::control::{Cr0, Cr0Flags, Cr3, Cr4, Cr4Flags, EferFlags}; use axaddrspace::{GuestPhysAddr, GuestVirtAddr, HostPhysAddr, NestedPageFaultInfo}; use axerrno::{ax_err, ax_err_type, AxResult}; -use axvcpu::{AccessWidth, AxArchVCpu, AxVCpuExitReason}; +use axvcpu::{AccessWidth, AxArchVCpu, AxVCpuExitReason, AxVCpuHal}; use super::as_axerr; use super::definitions::VmxExitReason; @@ -65,15 +65,15 @@ const CR0_PE: usize = 1 << 0; /// A virtual CPU within a guest. #[repr(C)] -pub struct VmxVcpu { +pub struct VmxVcpu { // DO NOT modify `guest_regs` and `host_stack_top` and their order unless you do know what you are doing! // DO NOT add anything before or between them unless you do know what you are doing! guest_regs: GeneralRegisters, host_stack_top: u64, launched: bool, - vmcs: VmxRegion, - io_bitmap: IOBitmap, - msr_bitmap: MsrBitmap, + vmcs: VmxRegion, + io_bitmap: IOBitmap, + msr_bitmap: MsrBitmap, pending_events: VecDeque<(u8, Option)>, xstate: XState, entry: Option, @@ -81,7 +81,7 @@ pub struct VmxVcpu { // is_host: bool, temporary removed because we don't care about type 1.5 now } -impl VmxVcpu { +impl VmxVcpu { /// Create a new [`VmxVcpu`]. pub fn new() -> AxResult { let vmcs_revision_id = super::read_vmcs_revision_id(); @@ -352,7 +352,7 @@ impl VmxVcpu { } // Implementation of private methods -impl VmxVcpu { +impl VmxVcpu { #[allow(dead_code)] fn setup_io_bitmap(&mut self) -> AxResult { // By default, I/O bitmap is set as `intercept_all`. @@ -657,7 +657,7 @@ impl VmxVcpu { // Implementaton for type1.5 hypervisor // #[cfg(feature = "type1_5")] -impl VmxVcpu { +impl VmxVcpu { fn set_cr(&mut self, cr_idx: usize, val: u64) { (|| -> AxResult { // debug!("set guest CR{} to val {:#x}", cr_idx, val); @@ -731,7 +731,7 @@ macro_rules! vmx_entry_with { } } -impl VmxVcpu { +impl VmxVcpu { #[naked] /// Enter guest with vmlaunch. /// @@ -1018,7 +1018,7 @@ impl VmxVcpu { } } -impl Drop for VmxVcpu { +impl Drop for VmxVcpu { fn drop(&mut self) { unsafe { vmx::vmclear(self.vmcs.phys_addr().as_usize() as u64).unwrap() }; info!("[HV] dropped VmxVcpu(vmcs: {:#x})", self.vmcs.phys_addr()); @@ -1041,7 +1041,7 @@ fn get_tr_base(tr: SegmentSelector, gdt: &DescriptorTablePointer) -> u64 { } } -impl Debug for VmxVcpu { +impl Debug for VmxVcpu { fn fmt(&self, f: &mut Formatter) -> Result { (|| -> AxResult { Ok(f.debug_struct("VmxVcpu") @@ -1062,7 +1062,7 @@ impl Debug for VmxVcpu { } } -impl AxArchVCpu for VmxVcpu { +impl AxArchVCpu for VmxVcpu { type CreateConfig = (); type SetupConfig = ();