/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 | } |