1
- use crate :: intel:: vmerror:: VmxBasicExitReason ;
2
- use x86:: vmx:: vmcs:: ro;
3
1
use {
4
2
crate :: {
5
3
error:: HypervisorError ,
11
9
shared_data:: SharedData ,
12
10
support:: { vmclear, vmptrld, vmread} ,
13
11
vmcs:: Vmcs ,
12
+ vmerror:: { VmInstructionError , VmxBasicExitReason } ,
14
13
vmlaunch:: launch_vm,
15
14
} ,
16
15
} ,
17
- alloc:: {
18
- boxed:: Box ,
19
- format,
20
- string:: { String , ToString } ,
21
- } ,
16
+ alloc:: boxed:: Box ,
22
17
bit_field:: BitField ,
23
18
core:: ptr:: NonNull ,
24
19
x86:: { bits64:: rflags:: RFlags , vmx:: vmcs} ,
@@ -113,7 +108,7 @@ impl Vm {
113
108
pub fn run ( & mut self ) -> Result < VmxBasicExitReason , HypervisorError > {
114
109
// Run the VM until the VM-exit occurs.
115
110
let flags = unsafe { launch_vm ( & mut self . guest_registers , u64:: from ( self . has_launched ) ) } ;
116
- Self :: vm_succeed ( RFlags :: from_raw ( flags) ) . unwrap ( ) ;
111
+ Self :: vm_succeed ( RFlags :: from_raw ( flags) ) ? ;
117
112
self . has_launched = true ;
118
113
119
114
// VM-exit occurred. Copy the guest register values from VMCS so that
@@ -122,7 +117,7 @@ impl Vm {
122
117
self . guest_registers . rsp = vmread ( vmcs:: guest:: RSP ) ;
123
118
self . guest_registers . rflags = vmread ( vmcs:: guest:: RFLAGS ) ;
124
119
125
- let exit_reason = vmread ( ro:: EXIT_REASON ) as u32 ;
120
+ let exit_reason = vmread ( vmcs :: ro:: EXIT_REASON ) as u32 ;
126
121
127
122
let Some ( basic_exit_reason) = VmxBasicExitReason :: from_u32 ( exit_reason) else {
128
123
log:: error!( "Unknown exit reason: {:#x}" , exit_reason) ;
@@ -132,20 +127,36 @@ impl Vm {
132
127
return Ok ( basic_exit_reason) ;
133
128
}
134
129
135
- /// Checks that the latest VMX instruction succeeded.
130
+ /// Verifies that the `launch_vm` function executed successfully.
131
+ ///
132
+ /// This method checks the RFlags for indications of failure from the `launch_vm` function.
133
+ /// If a failure is detected, it will panic with a detailed error message.
134
+ ///
135
+ /// # Arguments
136
136
///
137
- /// See: 31.2 CONVENTIONS
138
- fn vm_succeed ( flags : RFlags ) -> Result < ( ) , String > {
137
+ /// * `flags`: The RFlags value post-execution of the `launch_vm` function.
138
+ ///
139
+ /// Reference: Intel® 64 and IA-32 Architectures Software Developer's Manual:
140
+ /// - 31.2 CONVENTIONS
141
+ /// - 31.4 VM INSTRUCTION ERROR NUMBERS
142
+ fn vm_succeed ( flags : RFlags ) -> Result < ( ) , HypervisorError > {
139
143
if flags. contains ( RFlags :: FLAGS_ZF ) {
140
- // See: 31.4 VM INSTRUCTION ERROR NUMBERS
141
- Err ( format ! (
142
- "VmFailValid with {}" ,
143
- vmread( vmcs:: ro:: VM_INSTRUCTION_ERROR )
144
- ) )
144
+ let instruction_error = vmread ( vmcs:: ro:: VM_INSTRUCTION_ERROR ) as u32 ;
145
+ return match VmInstructionError :: from_u32 ( instruction_error) {
146
+ Some ( error) => {
147
+ log:: error!( "VM instruction error: {:?}" , error) ;
148
+ Err ( HypervisorError :: VmInstructionError )
149
+ }
150
+ None => {
151
+ log:: error!( "Unknown VM instruction error: {:#x}" , instruction_error) ;
152
+ Err ( HypervisorError :: UnknownVMInstructionError )
153
+ }
154
+ } ;
145
155
} else if flags. contains ( RFlags :: FLAGS_CF ) {
146
- Err ( "VmFailInvalid" . to_string ( ) )
147
- } else {
148
- Ok ( ( ) )
156
+ log:: error!( "VM instruction failed due to carry flag being set" ) ;
157
+ return Err ( HypervisorError :: VMFailToLaunch ) ;
149
158
}
159
+
160
+ Ok ( ( ) )
150
161
}
151
162
}
0 commit comments