Skip to content

Commit 5f6eaf4

Browse files
authored
Migrate to Rust Edition 2024 (#12)
* Migrate to Rust Edition 2024 * [fix] update url
1 parent dc08868 commit 5f6eaf4

File tree

11 files changed

+93
-78
lines changed

11 files changed

+93
-78
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
strategy:
99
fail-fast: false
1010
matrix:
11-
rust-toolchain: [nightly-2024-05-02, nightly-2024-08-24]
11+
rust-toolchain: [nightly-2024-12-25, nightly]
1212
targets: [x86_64-unknown-none]
1313
steps:
1414
- uses: actions/checkout@v4

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
[package]
22
name = "x86_vcpu"
33
version = "0.1.0"
4-
edition = "2021"
4+
edition = "2024"
55

66
[dependencies]
77
log = "0.4.19"
88
cfg-if = "1.0"
99
bitflags = "2.2"
1010
bit_field = "0.10"
1111
x86 = "0.52"
12-
x86_64 = "0.14"
12+
x86_64 = "0.15"
1313
raw-cpuid = "11.0"
1414
numeric-enum-macro = "0.2"
1515

1616
axerrno = "0.1.0"
17-
page_table_entry = "0.4.1"
17+
page_table_entry = "0.5"
1818
memory_addr = "0.3.1"
1919
crate_interface = "0.1"
2020

src/frame.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::marker::PhantomData;
22

33
use axaddrspace::HostPhysAddr;
4-
use axerrno::{ax_err_type, AxResult};
4+
use axerrno::{AxResult, ax_err_type};
55

66
use axvcpu::AxVCpuHal;
77

src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#![no_std]
22
#![feature(doc_cfg)]
33
#![feature(concat_idents)]
4-
#![feature(asm_const)]
54
#![feature(naked_functions)]
65
#![doc = include_str!("../README.md")]
76

src/msr.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl Msr {
5454
/// effects.
5555
#[inline(always)]
5656
pub unsafe fn write(self, value: u64) {
57-
wrmsr(self as _, value)
57+
unsafe { wrmsr(self as _, value) }
5858
}
5959
}
6060

@@ -66,6 +66,8 @@ pub(super) trait MsrReadWrite {
6666
}
6767

6868
unsafe fn write_raw(flags: u64) {
69-
Self::MSR.write(flags);
69+
unsafe {
70+
Self::MSR.write(flags);
71+
}
7072
}
7173
}

src/vmx/definitions.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,23 @@ impl VmxInstructionError {
2323
15 => "VMXON executed in VMX root operation",
2424
16 => "VM entry with invalid executive-VMCS pointer",
2525
17 => "VM entry with non-launched executive VMCS",
26-
18 => "VM entry with executive-VMCS pointer not VMXON pointer (when attempting to deactivate the dual-monitor treatment of SMIs and SMM)",
27-
19 => "VMCALL with non-clear VMCS (when attempting to activate the dual-monitor treatment of SMIs and SMM)",
26+
18 => {
27+
"VM entry with executive-VMCS pointer not VMXON pointer (when attempting to deactivate the dual-monitor treatment of SMIs and SMM)"
28+
}
29+
19 => {
30+
"VMCALL with non-clear VMCS (when attempting to activate the dual-monitor treatment of SMIs and SMM)"
31+
}
2832
20 => "VMCALL with invalid VM-exit control fields",
29-
22 => "VMCALL with incorrect MSEG revision identifier (when attempting to activate the dual-monitor treatment of SMIs and SMM)",
33+
22 => {
34+
"VMCALL with incorrect MSEG revision identifier (when attempting to activate the dual-monitor treatment of SMIs and SMM)"
35+
}
3036
23 => "VMXOFF under dual-monitor treatment of SMIs and SMM",
31-
24 => "VMCALL with invalid SMM-monitor features (when attempting to activate the dual-monitor treatment of SMIs and SMM)",
32-
25 => "VM entry with invalid VM-execution control fields in executive VMCS (when attempting to return from SMM)",
37+
24 => {
38+
"VMCALL with invalid SMM-monitor features (when attempting to activate the dual-monitor treatment of SMIs and SMM)"
39+
}
40+
25 => {
41+
"VM entry with invalid VM-execution control fields in executive VMCS (when attempting to return from SMM)"
42+
}
3343
26 => "VM entry with events blocked by MOV SS",
3444
28 => "Invalid operand to INVEPT/INVVPID",
3545
_ => "[INVALID]",

src/vmx/instructions.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ pub enum InvEptType {
4343
/// descriptor specified in the memory operand.
4444
pub unsafe fn invept(inv_type: InvEptType, eptp: u64) -> Result<()> {
4545
let invept_desc = [eptp, 0];
46-
asm!("invept {0}, [{1}]", in(reg) inv_type as u64, in(reg) &invept_desc);
46+
unsafe {
47+
asm!("invept {0}, [{1}]", in(reg) inv_type as u64, in(reg) &invept_desc);
48+
}
4749
vmx_capture_status()
4850
}

src/vmx/percpu.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use x86::bits64::vmx;
22
use x86_64::registers::control::{Cr0, Cr4, Cr4Flags};
33

4-
use axerrno::{ax_err, ax_err_type, AxResult};
4+
use axerrno::{AxResult, ax_err, ax_err_type};
55
use axvcpu::{AxArchPerCpu, AxVCpuHal};
66
use memory_addr::PAGE_SIZE_4K as PAGE_SIZE;
77

src/vmx/structs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct VmxRegion<H: AxVCpuHal> {
1919
impl<H: AxVCpuHal> VmxRegion<H> {
2020
pub const unsafe fn uninit() -> Self {
2121
Self {
22-
frame: PhysFrame::uninit(),
22+
frame: unsafe { PhysFrame::uninit() },
2323
}
2424
}
2525

src/vmx/vcpu.rs

+60-58
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
use alloc::collections::VecDeque;
22
use bit_field::BitField;
33
use core::fmt::{Debug, Formatter, Result};
4-
use core::{arch::asm, mem::size_of};
4+
use core::{arch::naked_asm, mem::size_of};
55
use raw_cpuid::CpuId;
66
use x86::bits64::vmx;
7-
use x86::controlregs::{xcr0 as xcr0_read, xcr0_write, Xcr0};
7+
use x86::controlregs::{Xcr0, xcr0 as xcr0_read, xcr0_write};
88
use x86::dtables::{self, DescriptorTablePointer};
99
use x86::segmentation::SegmentSelector;
1010
use x86_64::registers::control::{Cr0, Cr0Flags, Cr3, Cr4, Cr4Flags, EferFlags};
1111

1212
use axaddrspace::{GuestPhysAddr, GuestVirtAddr, HostPhysAddr, NestedPageFaultInfo};
13-
use axerrno::{ax_err, ax_err_type, AxResult};
13+
use axerrno::{AxResult, ax_err, ax_err_type};
1414
use axvcpu::{AccessWidth, AxArchVCpu, AxVCpuExitReason, AxVCpuHal};
1515

16+
use super::VmxExitInfo;
1617
use super::as_axerr;
1718
use super::definitions::VmxExitReason;
1819
use super::structs::{IOBitmap, MsrBitmap, VmxRegion};
1920
use super::vmcs::{
2021
self, VmcsControl32, VmcsControl64, VmcsControlNW, VmcsGuest16, VmcsGuest32, VmcsGuest64,
2122
VmcsGuestNW, VmcsHost16, VmcsHost32, VmcsHost64, VmcsHostNW,
2223
};
23-
use super::VmxExitInfo;
2424
use crate::{ept::GuestPageWalkInfo, msr::Msr, regs::GeneralRegisters};
2525

26-
const VMX_PREEMPTION_TIMER_SET_VALUE: u32 = 1000_000;
26+
const VMX_PREEMPTION_TIMER_SET_VALUE: u32 = 1_000_000;
2727

2828
pub struct XState {
2929
host_xcr0: u64,
@@ -147,14 +147,14 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
147147
if (ia32_efer & MSR_IA32_EFER_LMA_BIT) != 0 {
148148
if (cs_access_right & 0x2000) != 0 {
149149
// CS.L = 1
150-
return VmCpuMode::Mode64;
150+
VmCpuMode::Mode64
151151
} else {
152-
return VmCpuMode::Compatibility;
152+
VmCpuMode::Compatibility
153153
}
154154
} else if (cr0 & CR0_PE) != 0 {
155-
return VmCpuMode::Protected;
155+
VmCpuMode::Protected
156156
} else {
157-
return VmCpuMode::Real;
157+
VmCpuMode::Real
158158
}
159159
}
160160

@@ -188,7 +188,12 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
188188
match self.builtin_vmexit_handler(&exit_info) {
189189
Some(result) => {
190190
if result.is_err() {
191-
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);
191+
panic!(
192+
"VmxVcpu failed to handle a VM-exit that should be handled by itself: {:?}, error {:?}, vcpu: {:#x?}",
193+
exit_info.exit_reason,
194+
result.unwrap_err(),
195+
self
196+
);
192197
}
193198

194199
None
@@ -245,12 +250,11 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
245250
/// Translate guest virtual addr to linear addr
246251
pub fn gla2gva(&self, guest_rip: GuestVirtAddr) -> GuestVirtAddr {
247252
let cpu_mode = self.get_cpu_mode();
248-
let seg_base;
249-
if cpu_mode == VmCpuMode::Mode64 {
250-
seg_base = 0;
253+
let seg_base = if cpu_mode == VmCpuMode::Mode64 {
254+
0
251255
} else {
252-
seg_base = VmcsGuestNW::CS_BASE.read().unwrap();
253-
}
256+
VmcsGuestNW::CS_BASE.read().unwrap()
257+
};
254258
// debug!(
255259
// "seg_base: {:#x}, guest_rip: {:#x} cpu mode:{:?}",
256260
// seg_base, guest_rip, cpu_mode
@@ -313,7 +317,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
313317

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

319323
/// Add a virtual interrupt or exception to the pending events list,
@@ -717,17 +721,19 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
717721
/// Get ready then vmlaunch or vmresume.
718722
macro_rules! vmx_entry_with {
719723
($instr:literal) => {
720-
asm!(
721-
save_regs_to_stack!(), // save host status
722-
"mov [rdi + {host_stack_size}], rsp", // save current RSP to Vcpu::host_stack_top
723-
"mov rsp, rdi", // set RSP to guest regs area
724-
restore_regs_from_stack!(), // restore guest status
725-
$instr, // let's go!
726-
"jmp {failed}",
727-
host_stack_size = const size_of::<GeneralRegisters>(),
728-
failed = sym Self::vmx_entry_failed,
729-
options(noreturn),
730-
)
724+
unsafe {
725+
naked_asm!(
726+
save_regs_to_stack!(), // save host status
727+
"mov [rdi + {host_stack_size}], rsp", // save current RSP to Vcpu::host_stack_top
728+
"mov rsp, rdi", // set RSP to guest regs area
729+
restore_regs_from_stack!(), // restore guest status
730+
$instr, // let's go!
731+
"jmp {failed}",
732+
host_stack_size = const size_of::<GeneralRegisters>(),
733+
failed = sym Self::vmx_entry_failed,
734+
// options(noreturn),
735+
)
736+
}
731737
}
732738
}
733739

@@ -757,14 +763,15 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
757763
///
758764
/// The return value is a dummy value.
759765
unsafe extern "C" fn vmx_exit(&mut self) -> usize {
760-
asm!(
761-
save_regs_to_stack!(), // save guest status
762-
"mov rsp, [rsp + {host_stack_top}]", // set RSP to Vcpu::host_stack_top
763-
restore_regs_from_stack!(), // restore host status
764-
"ret",
765-
host_stack_top = const size_of::<GeneralRegisters>(),
766-
options(noreturn),
767-
);
766+
unsafe {
767+
naked_asm!(
768+
save_regs_to_stack!(), // save guest status
769+
"mov rsp, [rsp + {host_stack_top}]", // set RSP to Vcpu::host_stack_top
770+
restore_regs_from_stack!(), // restore host status
771+
"ret",
772+
host_stack_top = const size_of::<GeneralRegisters>(),
773+
);
774+
}
768775
}
769776

770777
fn vmx_entry_failed() -> ! {
@@ -827,6 +834,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
827834
Ok(())
828835
}
829836

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

@@ -864,7 +872,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
864872
}
865873

866874
fn handle_cpuid(&mut self) -> AxResult {
867-
use raw_cpuid::{cpuid, CpuIdResult};
875+
use raw_cpuid::{CpuIdResult, cpuid};
868876

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

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

940948
trace!(
941949
"VM exit: CPUID({:#x}, {:#x}): {:?}",
942-
regs_clone.rax,
943-
regs_clone.rcx,
944-
res
950+
regs_clone.rax, regs_clone.rcx, res
945951
);
946952

947953
let regs = self.regs_mut();
@@ -980,14 +986,12 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
980986
if x.contains(Xcr0::XCR0_OPMASK_STATE)
981987
|| x.contains(Xcr0::XCR0_ZMM_HI256_STATE)
982988
|| x.contains(Xcr0::XCR0_HI16_ZMM_STATE)
989+
|| !x.contains(Xcr0::XCR0_AVX_STATE)
990+
|| !x.contains(Xcr0::XCR0_OPMASK_STATE)
991+
|| !x.contains(Xcr0::XCR0_ZMM_HI256_STATE)
992+
|| !x.contains(Xcr0::XCR0_HI16_ZMM_STATE)
983993
{
984-
if !x.contains(Xcr0::XCR0_AVX_STATE)
985-
|| !x.contains(Xcr0::XCR0_OPMASK_STATE)
986-
|| !x.contains(Xcr0::XCR0_ZMM_HI256_STATE)
987-
|| !x.contains(Xcr0::XCR0_HI16_ZMM_STATE)
988-
{
989-
return None;
990-
}
994+
return None;
991995
}
992996

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

11401144
if io_info.is_in {
11411145
AxVCpuExitReason::IoRead { port, width }
1146+
} else if port == QEMU_EXIT_PORT
1147+
&& width == AccessWidth::Word
1148+
&& self.regs().rax == QEMU_EXIT_MAGIC
1149+
{
1150+
AxVCpuExitReason::SystemDown
11421151
} else {
1143-
if port == QEMU_EXIT_PORT
1144-
&& width == AccessWidth::Word
1145-
&& self.regs().rax == QEMU_EXIT_MAGIC
1146-
{
1147-
AxVCpuExitReason::SystemDown
1148-
} else {
1149-
AxVCpuExitReason::IoWrite {
1150-
port,
1151-
width,
1152-
data: self.regs().rax.get_bits(width.bits_range()),
1153-
}
1152+
AxVCpuExitReason::IoWrite {
1153+
port,
1154+
width,
1155+
data: self.regs().rax.get_bits(width.bits_range()),
11541156
}
11551157
}
11561158
}

src/vmx/vmcs.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use bit_field::BitField;
77
use x86::bits64::vmx;
88

99
use axaddrspace::{GuestPhysAddr, HostPhysAddr, NestedPageFaultInfo};
10-
use axerrno::{ax_err, AxResult};
10+
use axerrno::{AxResult, ax_err};
1111
use page_table_entry::MappingFlags;
1212

1313
use super::as_axerr;
@@ -631,7 +631,7 @@ pub fn set_control(
631631
}
632632

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

658658
pub fn raw_interrupt_exit_info() -> AxResult<u32> {
659-
Ok(VmcsReadOnly32::VMEXIT_INTERRUPTION_INFO.read()?)
659+
VmcsReadOnly32::VMEXIT_INTERRUPTION_INFO.read()
660660
}
661661

662662
pub fn interrupt_exit_info() -> AxResult<VmxInterruptInfo> {
@@ -752,7 +752,7 @@ pub fn update_efer() -> AxResult {
752752
set_control(
753753
VmcsControl32::VMENTRY_CONTROLS,
754754
Msr::IA32_VMX_TRUE_ENTRY_CTLS,
755-
VmcsControl32::VMENTRY_CONTROLS.read()? as u32,
755+
VmcsControl32::VMENTRY_CONTROLS.read()?,
756756
(EntryCtrl::IA32E_MODE_GUEST).bits(),
757757
0,
758758
)?;

0 commit comments

Comments
 (0)