Skip to content

Commit

Permalink
Migrate to Rust Edition 2024 (#12)
Browse files Browse the repository at this point in the history
* Migrate to Rust Edition 2024

* [fix] update url
  • Loading branch information
hky1999 authored Jan 2, 2025
1 parent dc08868 commit 5f6eaf4
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 78 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
rust-toolchain: [nightly-2024-05-02, nightly-2024-08-24]
rust-toolchain: [nightly-2024-12-25, nightly]
targets: [x86_64-unknown-none]
steps:
- uses: actions/checkout@v4
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
[package]
name = "x86_vcpu"
version = "0.1.0"
edition = "2021"
edition = "2024"

[dependencies]
log = "0.4.19"
cfg-if = "1.0"
bitflags = "2.2"
bit_field = "0.10"
x86 = "0.52"
x86_64 = "0.14"
x86_64 = "0.15"
raw-cpuid = "11.0"
numeric-enum-macro = "0.2"

axerrno = "0.1.0"
page_table_entry = "0.4.1"
page_table_entry = "0.5"
memory_addr = "0.3.1"
crate_interface = "0.1"

Expand Down
2 changes: 1 addition & 1 deletion src/frame.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use core::marker::PhantomData;

use axaddrspace::HostPhysAddr;
use axerrno::{ax_err_type, AxResult};
use axerrno::{AxResult, ax_err_type};

use axvcpu::AxVCpuHal;

Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![no_std]
#![feature(doc_cfg)]
#![feature(concat_idents)]
#![feature(asm_const)]
#![feature(naked_functions)]
#![doc = include_str!("../README.md")]

Expand Down
6 changes: 4 additions & 2 deletions src/msr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl Msr {
/// effects.
#[inline(always)]
pub unsafe fn write(self, value: u64) {
wrmsr(self as _, value)
unsafe { wrmsr(self as _, value) }
}
}

Expand All @@ -66,6 +66,8 @@ pub(super) trait MsrReadWrite {
}

unsafe fn write_raw(flags: u64) {
Self::MSR.write(flags);
unsafe {
Self::MSR.write(flags);
}
}
}
20 changes: 15 additions & 5 deletions src/vmx/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,23 @@ impl VmxInstructionError {
15 => "VMXON executed in VMX root operation",
16 => "VM entry with invalid executive-VMCS pointer",
17 => "VM entry with non-launched executive VMCS",
18 => "VM entry with executive-VMCS pointer not VMXON pointer (when attempting to deactivate the dual-monitor treatment of SMIs and SMM)",
19 => "VMCALL with non-clear VMCS (when attempting to activate the dual-monitor treatment of SMIs and SMM)",
18 => {
"VM entry with executive-VMCS pointer not VMXON pointer (when attempting to deactivate the dual-monitor treatment of SMIs and SMM)"
}
19 => {
"VMCALL with non-clear VMCS (when attempting to activate the dual-monitor treatment of SMIs and SMM)"
}
20 => "VMCALL with invalid VM-exit control fields",
22 => "VMCALL with incorrect MSEG revision identifier (when attempting to activate the dual-monitor treatment of SMIs and SMM)",
22 => {
"VMCALL with incorrect MSEG revision identifier (when attempting to activate the dual-monitor treatment of SMIs and SMM)"
}
23 => "VMXOFF under dual-monitor treatment of SMIs and SMM",
24 => "VMCALL with invalid SMM-monitor features (when attempting to activate the dual-monitor treatment of SMIs and SMM)",
25 => "VM entry with invalid VM-execution control fields in executive VMCS (when attempting to return from SMM)",
24 => {
"VMCALL with invalid SMM-monitor features (when attempting to activate the dual-monitor treatment of SMIs and SMM)"
}
25 => {
"VM entry with invalid VM-execution control fields in executive VMCS (when attempting to return from SMM)"
}
26 => "VM entry with events blocked by MOV SS",
28 => "Invalid operand to INVEPT/INVVPID",
_ => "[INVALID]",
Expand Down
4 changes: 3 additions & 1 deletion src/vmx/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ pub enum InvEptType {
/// descriptor specified in the memory operand.
pub unsafe fn invept(inv_type: InvEptType, eptp: u64) -> Result<()> {
let invept_desc = [eptp, 0];
asm!("invept {0}, [{1}]", in(reg) inv_type as u64, in(reg) &invept_desc);
unsafe {
asm!("invept {0}, [{1}]", in(reg) inv_type as u64, in(reg) &invept_desc);
}
vmx_capture_status()
}
2 changes: 1 addition & 1 deletion src/vmx/percpu.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use x86::bits64::vmx;
use x86_64::registers::control::{Cr0, Cr4, Cr4Flags};

use axerrno::{ax_err, ax_err_type, AxResult};
use axerrno::{AxResult, ax_err, ax_err_type};
use axvcpu::{AxArchPerCpu, AxVCpuHal};
use memory_addr::PAGE_SIZE_4K as PAGE_SIZE;

Expand Down
2 changes: 1 addition & 1 deletion src/vmx/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct VmxRegion<H: AxVCpuHal> {
impl<H: AxVCpuHal> VmxRegion<H> {
pub const unsafe fn uninit() -> Self {
Self {
frame: PhysFrame::uninit(),
frame: unsafe { PhysFrame::uninit() },
}
}

Expand Down
118 changes: 60 additions & 58 deletions src/vmx/vcpu.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
use alloc::collections::VecDeque;
use bit_field::BitField;
use core::fmt::{Debug, Formatter, Result};
use core::{arch::asm, mem::size_of};
use core::{arch::naked_asm, mem::size_of};
use raw_cpuid::CpuId;
use x86::bits64::vmx;
use x86::controlregs::{xcr0 as xcr0_read, xcr0_write, Xcr0};
use x86::controlregs::{Xcr0, xcr0 as xcr0_read, xcr0_write};
use x86::dtables::{self, DescriptorTablePointer};
use x86::segmentation::SegmentSelector;
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 axerrno::{AxResult, ax_err, ax_err_type};
use axvcpu::{AccessWidth, AxArchVCpu, AxVCpuExitReason, AxVCpuHal};

use super::VmxExitInfo;
use super::as_axerr;
use super::definitions::VmxExitReason;
use super::structs::{IOBitmap, MsrBitmap, VmxRegion};
use super::vmcs::{
self, VmcsControl32, VmcsControl64, VmcsControlNW, VmcsGuest16, VmcsGuest32, VmcsGuest64,
VmcsGuestNW, VmcsHost16, VmcsHost32, VmcsHost64, VmcsHostNW,
};
use super::VmxExitInfo;
use crate::{ept::GuestPageWalkInfo, msr::Msr, regs::GeneralRegisters};

const VMX_PREEMPTION_TIMER_SET_VALUE: u32 = 1000_000;
const VMX_PREEMPTION_TIMER_SET_VALUE: u32 = 1_000_000;

pub struct XState {
host_xcr0: u64,
Expand Down Expand Up @@ -147,14 +147,14 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
if (ia32_efer & MSR_IA32_EFER_LMA_BIT) != 0 {
if (cs_access_right & 0x2000) != 0 {
// CS.L = 1
return VmCpuMode::Mode64;
VmCpuMode::Mode64
} else {
return VmCpuMode::Compatibility;
VmCpuMode::Compatibility
}
} else if (cr0 & CR0_PE) != 0 {
return VmCpuMode::Protected;
VmCpuMode::Protected
} else {
return VmCpuMode::Real;
VmCpuMode::Real
}
}

Expand Down Expand Up @@ -188,7 +188,12 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
match self.builtin_vmexit_handler(&exit_info) {
Some(result) => {
if result.is_err() {
panic!("VmxVcpu failed to handle a VM-exit that should be handled by itself: {:?}, error {:?}, vcpu: {:#x?}", exit_info.exit_reason, result.unwrap_err(), self);
panic!(
"VmxVcpu failed to handle a VM-exit that should be handled by itself: {:?}, error {:?}, vcpu: {:#x?}",
exit_info.exit_reason,
result.unwrap_err(),
self
);
}

None
Expand Down Expand Up @@ -245,12 +250,11 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
/// Translate guest virtual addr to linear addr
pub fn gla2gva(&self, guest_rip: GuestVirtAddr) -> GuestVirtAddr {
let cpu_mode = self.get_cpu_mode();
let seg_base;
if cpu_mode == VmCpuMode::Mode64 {
seg_base = 0;
let seg_base = if cpu_mode == VmCpuMode::Mode64 {
0
} else {
seg_base = VmcsGuestNW::CS_BASE.read().unwrap();
}
VmcsGuestNW::CS_BASE.read().unwrap()
};
// debug!(
// "seg_base: {:#x}, guest_rip: {:#x} cpu mode:{:?}",
// seg_base, guest_rip, cpu_mode
Expand Down Expand Up @@ -313,7 +317,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {

/// Advance guest `RIP` by `instr_len` bytes.
pub fn advance_rip(&mut self, instr_len: u8) -> AxResult {
Ok(VmcsGuestNW::RIP.write(VmcsGuestNW::RIP.read()? + instr_len as usize)?)
VmcsGuestNW::RIP.write(VmcsGuestNW::RIP.read()? + instr_len as usize)
}

/// Add a virtual interrupt or exception to the pending events list,
Expand Down Expand Up @@ -717,17 +721,19 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
/// Get ready then vmlaunch or vmresume.
macro_rules! vmx_entry_with {
($instr:literal) => {
asm!(
save_regs_to_stack!(), // save host status
"mov [rdi + {host_stack_size}], rsp", // save current RSP to Vcpu::host_stack_top
"mov rsp, rdi", // set RSP to guest regs area
restore_regs_from_stack!(), // restore guest status
$instr, // let's go!
"jmp {failed}",
host_stack_size = const size_of::<GeneralRegisters>(),
failed = sym Self::vmx_entry_failed,
options(noreturn),
)
unsafe {
naked_asm!(
save_regs_to_stack!(), // save host status
"mov [rdi + {host_stack_size}], rsp", // save current RSP to Vcpu::host_stack_top
"mov rsp, rdi", // set RSP to guest regs area
restore_regs_from_stack!(), // restore guest status
$instr, // let's go!
"jmp {failed}",
host_stack_size = const size_of::<GeneralRegisters>(),
failed = sym Self::vmx_entry_failed,
// options(noreturn),
)
}
}
}

Expand Down Expand Up @@ -757,14 +763,15 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
///
/// The return value is a dummy value.
unsafe extern "C" fn vmx_exit(&mut self) -> usize {
asm!(
save_regs_to_stack!(), // save guest status
"mov rsp, [rsp + {host_stack_top}]", // set RSP to Vcpu::host_stack_top
restore_regs_from_stack!(), // restore host status
"ret",
host_stack_top = const size_of::<GeneralRegisters>(),
options(noreturn),
);
unsafe {
naked_asm!(
save_regs_to_stack!(), // save guest status
"mov rsp, [rsp + {host_stack_top}]", // set RSP to Vcpu::host_stack_top
restore_regs_from_stack!(), // restore host status
"ret",
host_stack_top = const size_of::<GeneralRegisters>(),
);
}
}

fn vmx_entry_failed() -> ! {
Expand Down Expand Up @@ -827,6 +834,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
Ok(())
}

#[allow(clippy::single_match)]
fn handle_cr(&mut self) -> AxResult {
const VM_EXIT_INSTR_LEN_MV_TO_CR: u8 = 3;

Expand Down Expand Up @@ -864,7 +872,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
}

fn handle_cpuid(&mut self) -> AxResult {
use raw_cpuid::{cpuid, CpuIdResult};
use raw_cpuid::{CpuIdResult, cpuid};

const VM_EXIT_INSTR_LEN_CPUID: u8 = 2;
const LEAF_FEATURE_INFO: u32 = 0x1;
Expand Down Expand Up @@ -895,7 +903,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
if regs_clone.rcx == 0 {
// Bit 05: WAITPKG.
res.ecx.set_bit(5, false); // clear waitpkg
// Bit 16: LA57. Supports 57-bit linear addresses and five-level paging if 1.
// Bit 16: LA57. Supports 57-bit linear addresses and five-level paging if 1.
res.ecx.set_bit(16, false); // clear LA57
}

Expand Down Expand Up @@ -939,9 +947,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {

trace!(
"VM exit: CPUID({:#x}, {:#x}): {:?}",
regs_clone.rax,
regs_clone.rcx,
res
regs_clone.rax, regs_clone.rcx, res
);

let regs = self.regs_mut();
Expand Down Expand Up @@ -980,14 +986,12 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
if x.contains(Xcr0::XCR0_OPMASK_STATE)
|| x.contains(Xcr0::XCR0_ZMM_HI256_STATE)
|| x.contains(Xcr0::XCR0_HI16_ZMM_STATE)
|| !x.contains(Xcr0::XCR0_AVX_STATE)
|| !x.contains(Xcr0::XCR0_OPMASK_STATE)
|| !x.contains(Xcr0::XCR0_ZMM_HI256_STATE)
|| !x.contains(Xcr0::XCR0_HI16_ZMM_STATE)
{
if !x.contains(Xcr0::XCR0_AVX_STATE)
|| !x.contains(Xcr0::XCR0_OPMASK_STATE)
|| !x.contains(Xcr0::XCR0_ZMM_HI256_STATE)
|| !x.contains(Xcr0::XCR0_HI16_ZMM_STATE)
{
return None;
}
return None;
}

Some(x)
Expand Down Expand Up @@ -1139,18 +1143,16 @@ impl<H: AxVCpuHal> AxArchVCpu for VmxVcpu<H> {

if io_info.is_in {
AxVCpuExitReason::IoRead { port, width }
} else if port == QEMU_EXIT_PORT
&& width == AccessWidth::Word
&& self.regs().rax == QEMU_EXIT_MAGIC
{
AxVCpuExitReason::SystemDown
} else {
if port == QEMU_EXIT_PORT
&& width == AccessWidth::Word
&& self.regs().rax == QEMU_EXIT_MAGIC
{
AxVCpuExitReason::SystemDown
} else {
AxVCpuExitReason::IoWrite {
port,
width,
data: self.regs().rax.get_bits(width.bits_range()),
}
AxVCpuExitReason::IoWrite {
port,
width,
data: self.regs().rax.get_bits(width.bits_range()),
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/vmx/vmcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bit_field::BitField;
use x86::bits64::vmx;

use axaddrspace::{GuestPhysAddr, HostPhysAddr, NestedPageFaultInfo};
use axerrno::{ax_err, AxResult};
use axerrno::{AxResult, ax_err};
use page_table_entry::MappingFlags;

use super::as_axerr;
Expand Down Expand Up @@ -631,7 +631,7 @@ pub fn set_control(
}

pub fn set_ept_pointer(pml4_paddr: HostPhysAddr) -> AxResult {
use super::instructions::{invept, InvEptType};
use super::instructions::{InvEptType, invept};
let eptp = super::structs::EPTPointer::from_table_phys(pml4_paddr).bits();
VmcsControl64::EPTP.write(eptp)?;
unsafe { invept(InvEptType::SingleContext, eptp).map_err(as_axerr)? };
Expand All @@ -656,7 +656,7 @@ pub fn exit_info() -> AxResult<VmxExitInfo> {
}

pub fn raw_interrupt_exit_info() -> AxResult<u32> {
Ok(VmcsReadOnly32::VMEXIT_INTERRUPTION_INFO.read()?)
VmcsReadOnly32::VMEXIT_INTERRUPTION_INFO.read()
}

pub fn interrupt_exit_info() -> AxResult<VmxInterruptInfo> {
Expand Down Expand Up @@ -752,7 +752,7 @@ pub fn update_efer() -> AxResult {
set_control(
VmcsControl32::VMENTRY_CONTROLS,
Msr::IA32_VMX_TRUE_ENTRY_CTLS,
VmcsControl32::VMENTRY_CONTROLS.read()? as u32,
VmcsControl32::VMENTRY_CONTROLS.read()?,
(EntryCtrl::IA32E_MODE_GUEST).bits(),
0,
)?;
Expand Down

0 comments on commit 5f6eaf4

Please sign in to comment.