Coverage Report

Created: 2026-04-01 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/x86-0.47.0/src/bits64/vmx.rs
Line
Count
Source
1
//! Virtualize processor hardware for multiple software environments using Virtual Machine Extensions.
2
3
use crate::bits64::rflags::{self, RFlags};
4
use crate::vmx::{Result, VmFail};
5
use core::arch::asm;
6
7
/// Helper used to extract VMX-specific Result in accordance with
8
/// conventions described in Intel SDM, Volume 3C, Section 30.2.
9
// We inline this to provide an obstruction-free path from this function's
10
// call site to the moment where `rflags::read()` reads RFLAGS. Otherwise it's
11
// possible for RFLAGS register to be clobbered by a function prologue,
12
// see https://github.com/gz/rust-x86/pull/50.
13
#[inline(always)]
14
0
fn vmx_capture_status() -> Result<()> {
15
0
    let flags = rflags::read();
16
17
0
    if flags.contains(RFlags::FLAGS_ZF) {
18
0
        Err(VmFail::VmFailValid)
19
0
    } else if flags.contains(RFlags::FLAGS_CF) {
20
0
        Err(VmFail::VmFailInvalid)
21
    } else {
22
0
        Ok(())
23
    }
24
0
}
25
26
/// Enable VMX operation.
27
///
28
/// `addr` specifies a 4KB-aligned physical address of VMXON region initialized
29
/// in accordance with Intel SDM, Volume 3C, Section 24.11.5.
30
///
31
/// # Safety
32
/// Needs CPL 0.
33
0
pub unsafe fn vmxon(addr: u64) -> Result<()> {
34
0
    asm!("vmxon ({0})", in(reg) &addr, options(att_syntax));
35
0
    vmx_capture_status()
36
0
}
37
38
/// Disable VMX operation.
39
///
40
/// # Safety
41
/// Needs CPL 0.
42
0
pub unsafe fn vmxoff() -> Result<()> {
43
0
    asm!("vmxoff");
44
0
    vmx_capture_status()
45
0
}
46
47
/// Clear VMCS.
48
///
49
/// Ensures that VMCS data maintained on the processor is copied to the VMCS region
50
/// located at 4KB-aligned physical address `addr` and initializes some parts of it.
51
///
52
/// # Safety
53
/// Needs CPL 0.
54
0
pub unsafe fn vmclear(addr: u64) -> Result<()> {
55
0
    asm!("vmclear ({0})", in(reg) &addr, options(att_syntax));
56
0
    vmx_capture_status()
57
0
}
58
59
/// Load current VMCS pointer.
60
///
61
/// Marks the current-VMCS pointer valid and loads it with the physical address `addr`.
62
///
63
/// # Safety
64
/// Needs CPL 0.
65
0
pub unsafe fn vmptrld(addr: u64) -> Result<()> {
66
0
    asm!("vmptrld ({0})", in(reg) &addr, options(att_syntax));
67
0
    vmx_capture_status()
68
0
}
69
70
/// Return current VMCS pointer.
71
///
72
/// # Safety
73
/// Needs CPL 0.
74
0
pub unsafe fn vmptrst() -> Result<u64> {
75
0
    let value: u64 = 0;
76
0
    asm!("vmptrst ({0})", in(reg) &value, options(att_syntax));
77
0
    vmx_capture_status().and(Ok(value))
78
0
}
79
80
/// Read a specified field from a VMCS.
81
///
82
/// # Safety
83
/// Needs CPL 0.
84
0
pub unsafe fn vmread(field: u32) -> Result<u64> {
85
0
    let field: u64 = field.into();
86
    let value: u64;
87
0
    asm!("vmread {0}, {1}", in(reg) field, out(reg) value, options(att_syntax));
88
0
    vmx_capture_status().and(Ok(value))
89
0
}
90
91
/// Write to a specified field in a VMCS.
92
///
93
/// # Safety
94
/// Needs CPL 0.
95
0
pub unsafe fn vmwrite(field: u32, value: u64) -> Result<()> {
96
0
    let field: u64 = field.into();
97
0
    asm!("vmwrite {1}, {0}", in(reg) field, in(reg) value, options(att_syntax));
98
0
    vmx_capture_status()
99
0
}
100
101
/// Launch virtual machine.
102
///
103
/// # Safety
104
/// Needs CPL 0.
105
#[inline(always)]
106
0
pub unsafe fn vmlaunch() -> Result<()> {
107
0
    asm!("vmlaunch");
108
0
    vmx_capture_status()
109
0
}
110
111
/// Resume virtual machine.
112
///
113
/// # Safety
114
/// Needs CPL 0.
115
#[inline(always)]
116
0
pub unsafe fn vmresume() -> Result<()> {
117
0
    asm!("vmresume");
118
0
    vmx_capture_status()
119
0
}