xref: /aosp_15_r20/external/crosvm/hypervisor/src/whpx/vcpu.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use core::ffi::c_void;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::arch::x86_64::CpuidResult;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryInto;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of_val;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
12*bb4ee6a4SAndroid Build Coastguard Worker 
13*bb4ee6a4SAndroid Build Coastguard Worker use base::Error;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
15*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL;
16*bb4ee6a4SAndroid Build Coastguard Worker use libc::EIO;
17*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOENT;
18*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENXIO;
19*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
20*bb4ee6a4SAndroid Build Coastguard Worker use winapi::shared::winerror::E_UNEXPECTED;
21*bb4ee6a4SAndroid Build Coastguard Worker use windows::Win32::Foundation::WHV_E_INSUFFICIENT_BUFFER;
22*bb4ee6a4SAndroid Build Coastguard Worker 
23*bb4ee6a4SAndroid Build Coastguard Worker use super::types::*;
24*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
25*bb4ee6a4SAndroid Build Coastguard Worker use crate::CpuId;
26*bb4ee6a4SAndroid Build Coastguard Worker use crate::CpuIdEntry;
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::DebugRegs;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::Fpu;
29*bb4ee6a4SAndroid Build Coastguard Worker use crate::IoOperation;
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::IoParams;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::Regs;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::Sregs;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::Vcpu;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuExit;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuX86_64;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::Xsave;
37*bb4ee6a4SAndroid Build Coastguard Worker 
38*bb4ee6a4SAndroid Build Coastguard Worker const WHPX_EXIT_DIRECTION_MMIO_READ: u8 = 0;
39*bb4ee6a4SAndroid Build Coastguard Worker const WHPX_EXIT_DIRECTION_MMIO_WRITE: u8 = 1;
40*bb4ee6a4SAndroid Build Coastguard Worker const WHPX_EXIT_DIRECTION_PIO_IN: u8 = 0;
41*bb4ee6a4SAndroid Build Coastguard Worker const WHPX_EXIT_DIRECTION_PIO_OUT: u8 = 1;
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker /// This is the whpx instruction emulator, useful for deconstructing
44*bb4ee6a4SAndroid Build Coastguard Worker /// io & memory port instructions. Whpx does not do this automatically.
45*bb4ee6a4SAndroid Build Coastguard Worker struct SafeInstructionEmulator {
46*bb4ee6a4SAndroid Build Coastguard Worker     handle: WHV_EMULATOR_HANDLE,
47*bb4ee6a4SAndroid Build Coastguard Worker }
48*bb4ee6a4SAndroid Build Coastguard Worker 
49*bb4ee6a4SAndroid Build Coastguard Worker impl SafeInstructionEmulator {
new() -> Result<SafeInstructionEmulator>50*bb4ee6a4SAndroid Build Coastguard Worker     fn new() -> Result<SafeInstructionEmulator> {
51*bb4ee6a4SAndroid Build Coastguard Worker         const EMULATOR_CALLBACKS: WHV_EMULATOR_CALLBACKS = WHV_EMULATOR_CALLBACKS {
52*bb4ee6a4SAndroid Build Coastguard Worker             Size: size_of::<WHV_EMULATOR_CALLBACKS>() as u32,
53*bb4ee6a4SAndroid Build Coastguard Worker             Reserved: 0,
54*bb4ee6a4SAndroid Build Coastguard Worker             WHvEmulatorIoPortCallback: Some(SafeInstructionEmulator::io_port_cb),
55*bb4ee6a4SAndroid Build Coastguard Worker             WHvEmulatorMemoryCallback: Some(SafeInstructionEmulator::memory_cb),
56*bb4ee6a4SAndroid Build Coastguard Worker             WHvEmulatorGetVirtualProcessorRegisters: Some(
57*bb4ee6a4SAndroid Build Coastguard Worker                 SafeInstructionEmulator::get_virtual_processor_registers_cb,
58*bb4ee6a4SAndroid Build Coastguard Worker             ),
59*bb4ee6a4SAndroid Build Coastguard Worker             WHvEmulatorSetVirtualProcessorRegisters: Some(
60*bb4ee6a4SAndroid Build Coastguard Worker                 SafeInstructionEmulator::set_virtual_processor_registers_cb,
61*bb4ee6a4SAndroid Build Coastguard Worker             ),
62*bb4ee6a4SAndroid Build Coastguard Worker             WHvEmulatorTranslateGvaPage: Some(SafeInstructionEmulator::translate_gva_page_cb),
63*bb4ee6a4SAndroid Build Coastguard Worker         };
64*bb4ee6a4SAndroid Build Coastguard Worker         let mut handle: WHV_EMULATOR_HANDLE = std::ptr::null_mut();
65*bb4ee6a4SAndroid Build Coastguard Worker         // safe because pass in valid callbacks and a emulator handle for the kernel to place the
66*bb4ee6a4SAndroid Build Coastguard Worker         // allocated handle into.
67*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe { WHvEmulatorCreateEmulator(&EMULATOR_CALLBACKS, &mut handle) })?;
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker         Ok(SafeInstructionEmulator { handle })
70*bb4ee6a4SAndroid Build Coastguard Worker     }
71*bb4ee6a4SAndroid Build Coastguard Worker }
72*bb4ee6a4SAndroid Build Coastguard Worker 
73*bb4ee6a4SAndroid Build Coastguard Worker trait InstructionEmulatorCallbacks {
io_port_cb( context: *mut ::std::os::raw::c_void, io_access: *mut WHV_EMULATOR_IO_ACCESS_INFO, ) -> HRESULT74*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn io_port_cb(
75*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
76*bb4ee6a4SAndroid Build Coastguard Worker         io_access: *mut WHV_EMULATOR_IO_ACCESS_INFO,
77*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT;
memory_cb( context: *mut ::std::os::raw::c_void, memory_access: *mut WHV_EMULATOR_MEMORY_ACCESS_INFO, ) -> HRESULT78*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn memory_cb(
79*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
80*bb4ee6a4SAndroid Build Coastguard Worker         memory_access: *mut WHV_EMULATOR_MEMORY_ACCESS_INFO,
81*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT;
get_virtual_processor_registers_cb( context: *mut ::std::os::raw::c_void, register_names: *const WHV_REGISTER_NAME, register_count: UINT32, register_values: *mut WHV_REGISTER_VALUE, ) -> HRESULT82*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn get_virtual_processor_registers_cb(
83*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
84*bb4ee6a4SAndroid Build Coastguard Worker         register_names: *const WHV_REGISTER_NAME,
85*bb4ee6a4SAndroid Build Coastguard Worker         register_count: UINT32,
86*bb4ee6a4SAndroid Build Coastguard Worker         register_values: *mut WHV_REGISTER_VALUE,
87*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT;
set_virtual_processor_registers_cb( context: *mut ::std::os::raw::c_void, register_names: *const WHV_REGISTER_NAME, register_count: UINT32, register_values: *const WHV_REGISTER_VALUE, ) -> HRESULT88*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn set_virtual_processor_registers_cb(
89*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
90*bb4ee6a4SAndroid Build Coastguard Worker         register_names: *const WHV_REGISTER_NAME,
91*bb4ee6a4SAndroid Build Coastguard Worker         register_count: UINT32,
92*bb4ee6a4SAndroid Build Coastguard Worker         register_values: *const WHV_REGISTER_VALUE,
93*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT;
translate_gva_page_cb( context: *mut ::std::os::raw::c_void, gva: WHV_GUEST_VIRTUAL_ADDRESS, translate_flags: WHV_TRANSLATE_GVA_FLAGS, translation_result: *mut WHV_TRANSLATE_GVA_RESULT_CODE, gpa: *mut WHV_GUEST_PHYSICAL_ADDRESS, ) -> HRESULT94*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn translate_gva_page_cb(
95*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
96*bb4ee6a4SAndroid Build Coastguard Worker         gva: WHV_GUEST_VIRTUAL_ADDRESS,
97*bb4ee6a4SAndroid Build Coastguard Worker         translate_flags: WHV_TRANSLATE_GVA_FLAGS,
98*bb4ee6a4SAndroid Build Coastguard Worker         translation_result: *mut WHV_TRANSLATE_GVA_RESULT_CODE,
99*bb4ee6a4SAndroid Build Coastguard Worker         gpa: *mut WHV_GUEST_PHYSICAL_ADDRESS,
100*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT;
101*bb4ee6a4SAndroid Build Coastguard Worker }
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker /// Context passed into the instruction emulator when trying io or mmio emulation.
104*bb4ee6a4SAndroid Build Coastguard Worker /// Since we need this for set/get registers and memory translation,
105*bb4ee6a4SAndroid Build Coastguard Worker /// a single context is used that captures all necessary contextual information for the operation.
106*bb4ee6a4SAndroid Build Coastguard Worker struct InstructionEmulatorContext<'a> {
107*bb4ee6a4SAndroid Build Coastguard Worker     vm_partition: Arc<SafePartition>,
108*bb4ee6a4SAndroid Build Coastguard Worker     index: u32,
109*bb4ee6a4SAndroid Build Coastguard Worker     handle_mmio: Option<&'a mut dyn FnMut(IoParams) -> Result<()>>,
110*bb4ee6a4SAndroid Build Coastguard Worker     handle_io: Option<&'a mut dyn FnMut(IoParams)>,
111*bb4ee6a4SAndroid Build Coastguard Worker }
112*bb4ee6a4SAndroid Build Coastguard Worker 
113*bb4ee6a4SAndroid Build Coastguard Worker impl InstructionEmulatorCallbacks for SafeInstructionEmulator {
io_port_cb( context: *mut ::std::os::raw::c_void, io_access: *mut WHV_EMULATOR_IO_ACCESS_INFO, ) -> HRESULT114*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn io_port_cb(
115*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
116*bb4ee6a4SAndroid Build Coastguard Worker         io_access: *mut WHV_EMULATOR_IO_ACCESS_INFO,
117*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT {
118*bb4ee6a4SAndroid Build Coastguard Worker         // unsafe because windows could decide to call this at any time.
119*bb4ee6a4SAndroid Build Coastguard Worker         // However, we trust the kernel to call this while the vm/vcpu is valid.
120*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = unsafe { &mut *(context as *mut InstructionEmulatorContext) };
121*bb4ee6a4SAndroid Build Coastguard Worker         let Some(handle_io) = &mut ctx.handle_io else {
122*bb4ee6a4SAndroid Build Coastguard Worker             return E_UNEXPECTED;
123*bb4ee6a4SAndroid Build Coastguard Worker         };
124*bb4ee6a4SAndroid Build Coastguard Worker 
125*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we trust the kernel to fill in the io_access
126*bb4ee6a4SAndroid Build Coastguard Worker         let io_access_info = unsafe { &mut *io_access };
127*bb4ee6a4SAndroid Build Coastguard Worker         let address = io_access_info.Port.into();
128*bb4ee6a4SAndroid Build Coastguard Worker         let size = io_access_info.AccessSize as usize;
129*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: We trust the kernel to fill in the io_access
130*bb4ee6a4SAndroid Build Coastguard Worker         let data: &mut [u8] = unsafe {
131*bb4ee6a4SAndroid Build Coastguard Worker             assert!(size <= size_of_val(&io_access_info.Data));
132*bb4ee6a4SAndroid Build Coastguard Worker             std::slice::from_raw_parts_mut(&mut io_access_info.Data as *mut u32 as *mut u8, size)
133*bb4ee6a4SAndroid Build Coastguard Worker         };
134*bb4ee6a4SAndroid Build Coastguard Worker         match io_access_info.Direction {
135*bb4ee6a4SAndroid Build Coastguard Worker             WHPX_EXIT_DIRECTION_PIO_IN => {
136*bb4ee6a4SAndroid Build Coastguard Worker                 handle_io(IoParams {
137*bb4ee6a4SAndroid Build Coastguard Worker                     address,
138*bb4ee6a4SAndroid Build Coastguard Worker                     operation: IoOperation::Read(data),
139*bb4ee6a4SAndroid Build Coastguard Worker                 });
140*bb4ee6a4SAndroid Build Coastguard Worker                 S_OK
141*bb4ee6a4SAndroid Build Coastguard Worker             }
142*bb4ee6a4SAndroid Build Coastguard Worker             WHPX_EXIT_DIRECTION_PIO_OUT => {
143*bb4ee6a4SAndroid Build Coastguard Worker                 handle_io(IoParams {
144*bb4ee6a4SAndroid Build Coastguard Worker                     address,
145*bb4ee6a4SAndroid Build Coastguard Worker                     operation: IoOperation::Write(data),
146*bb4ee6a4SAndroid Build Coastguard Worker                 });
147*bb4ee6a4SAndroid Build Coastguard Worker                 S_OK
148*bb4ee6a4SAndroid Build Coastguard Worker             }
149*bb4ee6a4SAndroid Build Coastguard Worker             _ => E_UNEXPECTED,
150*bb4ee6a4SAndroid Build Coastguard Worker         }
151*bb4ee6a4SAndroid Build Coastguard Worker     }
memory_cb( context: *mut ::std::os::raw::c_void, memory_access: *mut WHV_EMULATOR_MEMORY_ACCESS_INFO, ) -> HRESULT152*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn memory_cb(
153*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
154*bb4ee6a4SAndroid Build Coastguard Worker         memory_access: *mut WHV_EMULATOR_MEMORY_ACCESS_INFO,
155*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT {
156*bb4ee6a4SAndroid Build Coastguard Worker         // unsafe because windows could decide to call this at any time.
157*bb4ee6a4SAndroid Build Coastguard Worker         // However, we trust the kernel to call this while the vm/vcpu is valid.
158*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = unsafe { &mut *(context as *mut InstructionEmulatorContext) };
159*bb4ee6a4SAndroid Build Coastguard Worker         let Some(handle_mmio) = &mut ctx.handle_mmio else {
160*bb4ee6a4SAndroid Build Coastguard Worker             return E_UNEXPECTED;
161*bb4ee6a4SAndroid Build Coastguard Worker         };
162*bb4ee6a4SAndroid Build Coastguard Worker 
163*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we trust the kernel to fill in the memory_access
164*bb4ee6a4SAndroid Build Coastguard Worker         let memory_access_info = unsafe { &mut *memory_access };
165*bb4ee6a4SAndroid Build Coastguard Worker         let address = memory_access_info.GpaAddress;
166*bb4ee6a4SAndroid Build Coastguard Worker         let size = memory_access_info.AccessSize as usize;
167*bb4ee6a4SAndroid Build Coastguard Worker         let data = &mut memory_access_info.Data[..size];
168*bb4ee6a4SAndroid Build Coastguard Worker 
169*bb4ee6a4SAndroid Build Coastguard Worker         match memory_access_info.Direction {
170*bb4ee6a4SAndroid Build Coastguard Worker             WHPX_EXIT_DIRECTION_MMIO_READ => {
171*bb4ee6a4SAndroid Build Coastguard Worker                 if let Err(e) = handle_mmio(IoParams {
172*bb4ee6a4SAndroid Build Coastguard Worker                     address,
173*bb4ee6a4SAndroid Build Coastguard Worker                     operation: IoOperation::Read(data),
174*bb4ee6a4SAndroid Build Coastguard Worker                 }) {
175*bb4ee6a4SAndroid Build Coastguard Worker                     error!("handle_mmio failed with {e}");
176*bb4ee6a4SAndroid Build Coastguard Worker                     E_UNEXPECTED
177*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
178*bb4ee6a4SAndroid Build Coastguard Worker                     S_OK
179*bb4ee6a4SAndroid Build Coastguard Worker                 }
180*bb4ee6a4SAndroid Build Coastguard Worker             }
181*bb4ee6a4SAndroid Build Coastguard Worker             WHPX_EXIT_DIRECTION_MMIO_WRITE => {
182*bb4ee6a4SAndroid Build Coastguard Worker                 if let Err(e) = handle_mmio(IoParams {
183*bb4ee6a4SAndroid Build Coastguard Worker                     address,
184*bb4ee6a4SAndroid Build Coastguard Worker                     operation: IoOperation::Write(data),
185*bb4ee6a4SAndroid Build Coastguard Worker                 }) {
186*bb4ee6a4SAndroid Build Coastguard Worker                     error!("handle_mmio write with {e}");
187*bb4ee6a4SAndroid Build Coastguard Worker                     E_UNEXPECTED
188*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
189*bb4ee6a4SAndroid Build Coastguard Worker                     S_OK
190*bb4ee6a4SAndroid Build Coastguard Worker                 }
191*bb4ee6a4SAndroid Build Coastguard Worker             }
192*bb4ee6a4SAndroid Build Coastguard Worker             _ => E_UNEXPECTED,
193*bb4ee6a4SAndroid Build Coastguard Worker         }
194*bb4ee6a4SAndroid Build Coastguard Worker     }
get_virtual_processor_registers_cb( context: *mut ::std::os::raw::c_void, register_names: *const WHV_REGISTER_NAME, register_count: UINT32, register_values: *mut WHV_REGISTER_VALUE, ) -> HRESULT195*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn get_virtual_processor_registers_cb(
196*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
197*bb4ee6a4SAndroid Build Coastguard Worker         register_names: *const WHV_REGISTER_NAME,
198*bb4ee6a4SAndroid Build Coastguard Worker         register_count: UINT32,
199*bb4ee6a4SAndroid Build Coastguard Worker         register_values: *mut WHV_REGISTER_VALUE,
200*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT {
201*bb4ee6a4SAndroid Build Coastguard Worker         // unsafe because windows could decide to call this at any time.
202*bb4ee6a4SAndroid Build Coastguard Worker         // However, we trust the kernel to call this while the vm/vcpu is valid.
203*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = unsafe { &*(context as *const InstructionEmulatorContext) };
204*bb4ee6a4SAndroid Build Coastguard Worker         // safe because the ctx has a weak reference to the vm partition, which should be
205*bb4ee6a4SAndroid Build Coastguard Worker         // alive longer than the ctx
206*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
207*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorRegisters(
208*bb4ee6a4SAndroid Build Coastguard Worker                 ctx.vm_partition.partition,
209*bb4ee6a4SAndroid Build Coastguard Worker                 ctx.index,
210*bb4ee6a4SAndroid Build Coastguard Worker                 register_names,
211*bb4ee6a4SAndroid Build Coastguard Worker                 register_count,
212*bb4ee6a4SAndroid Build Coastguard Worker                 register_values,
213*bb4ee6a4SAndroid Build Coastguard Worker             )
214*bb4ee6a4SAndroid Build Coastguard Worker         }
215*bb4ee6a4SAndroid Build Coastguard Worker     }
set_virtual_processor_registers_cb( context: *mut ::std::os::raw::c_void, register_names: *const WHV_REGISTER_NAME, register_count: UINT32, register_values: *const WHV_REGISTER_VALUE, ) -> HRESULT216*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn set_virtual_processor_registers_cb(
217*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
218*bb4ee6a4SAndroid Build Coastguard Worker         register_names: *const WHV_REGISTER_NAME,
219*bb4ee6a4SAndroid Build Coastguard Worker         register_count: UINT32,
220*bb4ee6a4SAndroid Build Coastguard Worker         register_values: *const WHV_REGISTER_VALUE,
221*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT {
222*bb4ee6a4SAndroid Build Coastguard Worker         // unsafe because windows could decide to call this at any time.
223*bb4ee6a4SAndroid Build Coastguard Worker         // However, we trust the kernel to call this while the vm/vcpu is valid.
224*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = unsafe { &*(context as *const InstructionEmulatorContext) };
225*bb4ee6a4SAndroid Build Coastguard Worker         // safe because the ctx has a weak reference to the vm partition, which should be
226*bb4ee6a4SAndroid Build Coastguard Worker         // alive longer than the ctx
227*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
228*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
229*bb4ee6a4SAndroid Build Coastguard Worker                 ctx.vm_partition.partition,
230*bb4ee6a4SAndroid Build Coastguard Worker                 ctx.index,
231*bb4ee6a4SAndroid Build Coastguard Worker                 register_names,
232*bb4ee6a4SAndroid Build Coastguard Worker                 register_count,
233*bb4ee6a4SAndroid Build Coastguard Worker                 register_values,
234*bb4ee6a4SAndroid Build Coastguard Worker             )
235*bb4ee6a4SAndroid Build Coastguard Worker         }
236*bb4ee6a4SAndroid Build Coastguard Worker     }
translate_gva_page_cb( context: *mut ::std::os::raw::c_void, gva: WHV_GUEST_VIRTUAL_ADDRESS, translate_flags: WHV_TRANSLATE_GVA_FLAGS, translation_result_code: *mut WHV_TRANSLATE_GVA_RESULT_CODE, gpa: *mut WHV_GUEST_PHYSICAL_ADDRESS, ) -> HRESULT237*bb4ee6a4SAndroid Build Coastguard Worker     extern "stdcall" fn translate_gva_page_cb(
238*bb4ee6a4SAndroid Build Coastguard Worker         context: *mut ::std::os::raw::c_void,
239*bb4ee6a4SAndroid Build Coastguard Worker         gva: WHV_GUEST_VIRTUAL_ADDRESS,
240*bb4ee6a4SAndroid Build Coastguard Worker         translate_flags: WHV_TRANSLATE_GVA_FLAGS,
241*bb4ee6a4SAndroid Build Coastguard Worker         translation_result_code: *mut WHV_TRANSLATE_GVA_RESULT_CODE,
242*bb4ee6a4SAndroid Build Coastguard Worker         gpa: *mut WHV_GUEST_PHYSICAL_ADDRESS,
243*bb4ee6a4SAndroid Build Coastguard Worker     ) -> HRESULT {
244*bb4ee6a4SAndroid Build Coastguard Worker         // unsafe because windows could decide to call this at any time.
245*bb4ee6a4SAndroid Build Coastguard Worker         // However, we trust the kernel to call this while the vm/vcpu is valid.
246*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = unsafe { &*(context as *const InstructionEmulatorContext) };
247*bb4ee6a4SAndroid Build Coastguard Worker         let mut translation_result: WHV_TRANSLATE_GVA_RESULT = Default::default();
248*bb4ee6a4SAndroid Build Coastguard Worker         // safe because the ctx has a weak reference to the vm partition, which should be
249*bb4ee6a4SAndroid Build Coastguard Worker         // alive longer than the ctx
250*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
251*bb4ee6a4SAndroid Build Coastguard Worker             WHvTranslateGva(
252*bb4ee6a4SAndroid Build Coastguard Worker                 ctx.vm_partition.partition,
253*bb4ee6a4SAndroid Build Coastguard Worker                 ctx.index,
254*bb4ee6a4SAndroid Build Coastguard Worker                 gva,
255*bb4ee6a4SAndroid Build Coastguard Worker                 translate_flags,
256*bb4ee6a4SAndroid Build Coastguard Worker                 &mut translation_result,
257*bb4ee6a4SAndroid Build Coastguard Worker                 gpa,
258*bb4ee6a4SAndroid Build Coastguard Worker             )
259*bb4ee6a4SAndroid Build Coastguard Worker         };
260*bb4ee6a4SAndroid Build Coastguard Worker         if ret == S_OK {
261*bb4ee6a4SAndroid Build Coastguard Worker             // safe assuming the kernel passed in a valid result_code ptr
262*bb4ee6a4SAndroid Build Coastguard Worker             unsafe {
263*bb4ee6a4SAndroid Build Coastguard Worker                 *translation_result_code = translation_result.ResultCode;
264*bb4ee6a4SAndroid Build Coastguard Worker             }
265*bb4ee6a4SAndroid Build Coastguard Worker         }
266*bb4ee6a4SAndroid Build Coastguard Worker         ret
267*bb4ee6a4SAndroid Build Coastguard Worker     }
268*bb4ee6a4SAndroid Build Coastguard Worker }
269*bb4ee6a4SAndroid Build Coastguard Worker 
270*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for SafeInstructionEmulator {
drop(&mut self)271*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
272*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we own the instruction emulator
273*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe { WHvEmulatorDestroyEmulator(self.handle) }).unwrap();
274*bb4ee6a4SAndroid Build Coastguard Worker     }
275*bb4ee6a4SAndroid Build Coastguard Worker }
276*bb4ee6a4SAndroid Build Coastguard Worker 
277*bb4ee6a4SAndroid Build Coastguard Worker // we can send and share the instruction emulator over threads safely even though it is void*.
278*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Send for SafeInstructionEmulator {}
279*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Sync for SafeInstructionEmulator {}
280*bb4ee6a4SAndroid Build Coastguard Worker 
281*bb4ee6a4SAndroid Build Coastguard Worker struct SafeVirtualProcessor {
282*bb4ee6a4SAndroid Build Coastguard Worker     vm_partition: Arc<SafePartition>,
283*bb4ee6a4SAndroid Build Coastguard Worker     index: u32,
284*bb4ee6a4SAndroid Build Coastguard Worker }
285*bb4ee6a4SAndroid Build Coastguard Worker 
286*bb4ee6a4SAndroid Build Coastguard Worker impl SafeVirtualProcessor {
new(vm_partition: Arc<SafePartition>, index: u32) -> Result<SafeVirtualProcessor>287*bb4ee6a4SAndroid Build Coastguard Worker     fn new(vm_partition: Arc<SafePartition>, index: u32) -> Result<SafeVirtualProcessor> {
288*bb4ee6a4SAndroid Build Coastguard Worker         // safe since the vm partition should be valid.
289*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe { WHvCreateVirtualProcessor(vm_partition.partition, index, 0) })?;
290*bb4ee6a4SAndroid Build Coastguard Worker         Ok(SafeVirtualProcessor {
291*bb4ee6a4SAndroid Build Coastguard Worker             vm_partition,
292*bb4ee6a4SAndroid Build Coastguard Worker             index,
293*bb4ee6a4SAndroid Build Coastguard Worker         })
294*bb4ee6a4SAndroid Build Coastguard Worker     }
295*bb4ee6a4SAndroid Build Coastguard Worker }
296*bb4ee6a4SAndroid Build Coastguard Worker 
297*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for SafeVirtualProcessor {
drop(&mut self)298*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
299*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we are the owner of this windows virtual processor.
300*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe { WHvDeleteVirtualProcessor(self.vm_partition.partition, self.index,) })
301*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
302*bb4ee6a4SAndroid Build Coastguard Worker     }
303*bb4ee6a4SAndroid Build Coastguard Worker }
304*bb4ee6a4SAndroid Build Coastguard Worker 
305*bb4ee6a4SAndroid Build Coastguard Worker pub struct WhpxVcpu {
306*bb4ee6a4SAndroid Build Coastguard Worker     index: u32,
307*bb4ee6a4SAndroid Build Coastguard Worker     safe_virtual_processor: Arc<SafeVirtualProcessor>,
308*bb4ee6a4SAndroid Build Coastguard Worker     vm_partition: Arc<SafePartition>,
309*bb4ee6a4SAndroid Build Coastguard Worker     last_exit_context: Arc<WHV_RUN_VP_EXIT_CONTEXT>,
310*bb4ee6a4SAndroid Build Coastguard Worker     // must be arc, since we cannot "dupe" an instruction emulator similar to a handle.
311*bb4ee6a4SAndroid Build Coastguard Worker     instruction_emulator: Arc<SafeInstructionEmulator>,
312*bb4ee6a4SAndroid Build Coastguard Worker     tsc_frequency: Option<u64>,
313*bb4ee6a4SAndroid Build Coastguard Worker     apic_frequency: Option<u32>,
314*bb4ee6a4SAndroid Build Coastguard Worker }
315*bb4ee6a4SAndroid Build Coastguard Worker 
316*bb4ee6a4SAndroid Build Coastguard Worker impl WhpxVcpu {
317*bb4ee6a4SAndroid Build Coastguard Worker     /// The SafePartition passed in is weak, so that there is no circular references.
318*bb4ee6a4SAndroid Build Coastguard Worker     /// However, the SafePartition should be valid as long as this VCPU is alive. The index
319*bb4ee6a4SAndroid Build Coastguard Worker     /// is the index for this vcpu.
new(vm_partition: Arc<SafePartition>, index: u32) -> Result<WhpxVcpu>320*bb4ee6a4SAndroid Build Coastguard Worker     pub(super) fn new(vm_partition: Arc<SafePartition>, index: u32) -> Result<WhpxVcpu> {
321*bb4ee6a4SAndroid Build Coastguard Worker         let safe_virtual_processor = SafeVirtualProcessor::new(vm_partition.clone(), index)?;
322*bb4ee6a4SAndroid Build Coastguard Worker         let instruction_emulator = SafeInstructionEmulator::new()?;
323*bb4ee6a4SAndroid Build Coastguard Worker         Ok(WhpxVcpu {
324*bb4ee6a4SAndroid Build Coastguard Worker             index,
325*bb4ee6a4SAndroid Build Coastguard Worker             safe_virtual_processor: Arc::new(safe_virtual_processor),
326*bb4ee6a4SAndroid Build Coastguard Worker             vm_partition,
327*bb4ee6a4SAndroid Build Coastguard Worker             last_exit_context: Arc::new(Default::default()),
328*bb4ee6a4SAndroid Build Coastguard Worker             instruction_emulator: Arc::new(instruction_emulator),
329*bb4ee6a4SAndroid Build Coastguard Worker             tsc_frequency: None,
330*bb4ee6a4SAndroid Build Coastguard Worker             apic_frequency: None,
331*bb4ee6a4SAndroid Build Coastguard Worker         })
332*bb4ee6a4SAndroid Build Coastguard Worker     }
333*bb4ee6a4SAndroid Build Coastguard Worker 
set_frequencies(&mut self, tsc_frequency: Option<u64>, lapic_frequency: u32)334*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_frequencies(&mut self, tsc_frequency: Option<u64>, lapic_frequency: u32) {
335*bb4ee6a4SAndroid Build Coastguard Worker         self.tsc_frequency = tsc_frequency;
336*bb4ee6a4SAndroid Build Coastguard Worker         self.apic_frequency = Some(lapic_frequency);
337*bb4ee6a4SAndroid Build Coastguard Worker     }
338*bb4ee6a4SAndroid Build Coastguard Worker 
339*bb4ee6a4SAndroid Build Coastguard Worker     /// Handle reading the MSR with id `id`. If MSR `id` is not supported, inject a GP fault.
handle_msr_read(&mut self, id: u32) -> Result<()>340*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_msr_read(&mut self, id: u32) -> Result<()> {
341*bb4ee6a4SAndroid Build Coastguard Worker         // Verify that we're only being called in a situation where the last exit reason was
342*bb4ee6a4SAndroid Build Coastguard Worker         // ExitReasonX64MsrAccess
343*bb4ee6a4SAndroid Build Coastguard Worker         if self.last_exit_context.ExitReason
344*bb4ee6a4SAndroid Build Coastguard Worker             != WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64MsrAccess
345*bb4ee6a4SAndroid Build Coastguard Worker         {
346*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(EINVAL));
347*bb4ee6a4SAndroid Build Coastguard Worker         }
348*bb4ee6a4SAndroid Build Coastguard Worker 
349*bb4ee6a4SAndroid Build Coastguard Worker         let value = match id {
350*bb4ee6a4SAndroid Build Coastguard Worker             HV_X64_MSR_TSC_FREQUENCY => Some(self.tsc_frequency.unwrap_or(0)),
351*bb4ee6a4SAndroid Build Coastguard Worker             HV_X64_MSR_APIC_FREQUENCY => Some(self.apic_frequency.unwrap_or(0) as u64),
352*bb4ee6a4SAndroid Build Coastguard Worker             _ => None,
353*bb4ee6a4SAndroid Build Coastguard Worker         };
354*bb4ee6a4SAndroid Build Coastguard Worker 
355*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(value) = value {
356*bb4ee6a4SAndroid Build Coastguard Worker             // Get the next rip from the exit context
357*bb4ee6a4SAndroid Build Coastguard Worker             let rip = self.last_exit_context.VpContext.Rip
358*bb4ee6a4SAndroid Build Coastguard Worker                 + self.last_exit_context.VpContext.InstructionLength() as u64;
359*bb4ee6a4SAndroid Build Coastguard Worker 
360*bb4ee6a4SAndroid Build Coastguard Worker             const REG_NAMES: [WHV_REGISTER_NAME; 3] = [
361*bb4ee6a4SAndroid Build Coastguard Worker                 WHV_REGISTER_NAME_WHvX64RegisterRip,
362*bb4ee6a4SAndroid Build Coastguard Worker                 WHV_REGISTER_NAME_WHvX64RegisterRax,
363*bb4ee6a4SAndroid Build Coastguard Worker                 WHV_REGISTER_NAME_WHvX64RegisterRdx,
364*bb4ee6a4SAndroid Build Coastguard Worker             ];
365*bb4ee6a4SAndroid Build Coastguard Worker 
366*bb4ee6a4SAndroid Build Coastguard Worker             let values = vec![
367*bb4ee6a4SAndroid Build Coastguard Worker                 WHV_REGISTER_VALUE { Reg64: rip },
368*bb4ee6a4SAndroid Build Coastguard Worker                 // RDMSR instruction puts lower 32 bits in EAX and upper 32 bits in EDX
369*bb4ee6a4SAndroid Build Coastguard Worker                 WHV_REGISTER_VALUE {
370*bb4ee6a4SAndroid Build Coastguard Worker                     Reg64: (value & 0xffffffff),
371*bb4ee6a4SAndroid Build Coastguard Worker                 },
372*bb4ee6a4SAndroid Build Coastguard Worker                 WHV_REGISTER_VALUE {
373*bb4ee6a4SAndroid Build Coastguard Worker                     Reg64: (value >> 32),
374*bb4ee6a4SAndroid Build Coastguard Worker                 },
375*bb4ee6a4SAndroid Build Coastguard Worker             ];
376*bb4ee6a4SAndroid Build Coastguard Worker 
377*bb4ee6a4SAndroid Build Coastguard Worker             // safe because we have enough space for all the registers
378*bb4ee6a4SAndroid Build Coastguard Worker             check_whpx!(unsafe {
379*bb4ee6a4SAndroid Build Coastguard Worker                 WHvSetVirtualProcessorRegisters(
380*bb4ee6a4SAndroid Build Coastguard Worker                     self.vm_partition.partition,
381*bb4ee6a4SAndroid Build Coastguard Worker                     self.index,
382*bb4ee6a4SAndroid Build Coastguard Worker                     &REG_NAMES as *const WHV_REGISTER_NAME,
383*bb4ee6a4SAndroid Build Coastguard Worker                     REG_NAMES.len() as u32,
384*bb4ee6a4SAndroid Build Coastguard Worker                     values.as_ptr() as *const WHV_REGISTER_VALUE,
385*bb4ee6a4SAndroid Build Coastguard Worker                 )
386*bb4ee6a4SAndroid Build Coastguard Worker             })
387*bb4ee6a4SAndroid Build Coastguard Worker         } else {
388*bb4ee6a4SAndroid Build Coastguard Worker             self.inject_gp_fault()
389*bb4ee6a4SAndroid Build Coastguard Worker         }
390*bb4ee6a4SAndroid Build Coastguard Worker     }
391*bb4ee6a4SAndroid Build Coastguard Worker 
392*bb4ee6a4SAndroid Build Coastguard Worker     /// Handle writing the MSR with id `id`. If MSR `id` is not supported, inject a GP fault.
handle_msr_write(&mut self, id: u32, _value: u64) -> Result<()>393*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_msr_write(&mut self, id: u32, _value: u64) -> Result<()> {
394*bb4ee6a4SAndroid Build Coastguard Worker         // Verify that we're only being called in a situation where the last exit reason was
395*bb4ee6a4SAndroid Build Coastguard Worker         // ExitReasonX64MsrAccess
396*bb4ee6a4SAndroid Build Coastguard Worker         if self.last_exit_context.ExitReason
397*bb4ee6a4SAndroid Build Coastguard Worker             != WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64MsrAccess
398*bb4ee6a4SAndroid Build Coastguard Worker         {
399*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(EINVAL));
400*bb4ee6a4SAndroid Build Coastguard Worker         }
401*bb4ee6a4SAndroid Build Coastguard Worker 
402*bb4ee6a4SAndroid Build Coastguard Worker         // Do nothing, we assume TSC is always invariant
403*bb4ee6a4SAndroid Build Coastguard Worker         let success = matches!(id, HV_X64_MSR_TSC_INVARIANT_CONTROL);
404*bb4ee6a4SAndroid Build Coastguard Worker 
405*bb4ee6a4SAndroid Build Coastguard Worker         if !success {
406*bb4ee6a4SAndroid Build Coastguard Worker             return self.inject_gp_fault();
407*bb4ee6a4SAndroid Build Coastguard Worker         }
408*bb4ee6a4SAndroid Build Coastguard Worker 
409*bb4ee6a4SAndroid Build Coastguard Worker         // Get the next rip from the exit context
410*bb4ee6a4SAndroid Build Coastguard Worker         let rip = self.last_exit_context.VpContext.Rip
411*bb4ee6a4SAndroid Build Coastguard Worker             + self.last_exit_context.VpContext.InstructionLength() as u64;
412*bb4ee6a4SAndroid Build Coastguard Worker 
413*bb4ee6a4SAndroid Build Coastguard Worker         const REG_NAMES: [WHV_REGISTER_NAME; 1] = [WHV_REGISTER_NAME_WHvX64RegisterRip];
414*bb4ee6a4SAndroid Build Coastguard Worker 
415*bb4ee6a4SAndroid Build Coastguard Worker         let values = vec![WHV_REGISTER_VALUE { Reg64: rip }];
416*bb4ee6a4SAndroid Build Coastguard Worker 
417*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
418*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
419*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
420*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
421*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
422*bb4ee6a4SAndroid Build Coastguard Worker                 &REG_NAMES as *const WHV_REGISTER_NAME,
423*bb4ee6a4SAndroid Build Coastguard Worker                 REG_NAMES.len() as u32,
424*bb4ee6a4SAndroid Build Coastguard Worker                 values.as_ptr() as *const WHV_REGISTER_VALUE,
425*bb4ee6a4SAndroid Build Coastguard Worker             )
426*bb4ee6a4SAndroid Build Coastguard Worker         })
427*bb4ee6a4SAndroid Build Coastguard Worker     }
428*bb4ee6a4SAndroid Build Coastguard Worker 
inject_gp_fault(&self) -> Result<()>429*bb4ee6a4SAndroid Build Coastguard Worker     fn inject_gp_fault(&self) -> Result<()> {
430*bb4ee6a4SAndroid Build Coastguard Worker         const REG_NAMES: [WHV_REGISTER_NAME; 1] = [WHV_REGISTER_NAME_WHvRegisterPendingEvent];
431*bb4ee6a4SAndroid Build Coastguard Worker 
432*bb4ee6a4SAndroid Build Coastguard Worker         let mut event = WHV_REGISTER_VALUE {
433*bb4ee6a4SAndroid Build Coastguard Worker             ExceptionEvent: WHV_X64_PENDING_EXCEPTION_EVENT {
434*bb4ee6a4SAndroid Build Coastguard Worker                 __bindgen_anon_1: Default::default(),
435*bb4ee6a4SAndroid Build Coastguard Worker             },
436*bb4ee6a4SAndroid Build Coastguard Worker         };
437*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
438*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
439*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorRegisters(
440*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
441*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
442*bb4ee6a4SAndroid Build Coastguard Worker                 &REG_NAMES as *const WHV_REGISTER_NAME,
443*bb4ee6a4SAndroid Build Coastguard Worker                 REG_NAMES.len() as u32,
444*bb4ee6a4SAndroid Build Coastguard Worker                 &mut event as *mut WHV_REGISTER_VALUE,
445*bb4ee6a4SAndroid Build Coastguard Worker             )
446*bb4ee6a4SAndroid Build Coastguard Worker         })?;
447*bb4ee6a4SAndroid Build Coastguard Worker 
448*bb4ee6a4SAndroid Build Coastguard Worker         if unsafe { event.ExceptionEvent.__bindgen_anon_1.EventPending() } != 0 {
449*bb4ee6a4SAndroid Build Coastguard Worker             error!("Unable to inject gp fault because pending exception exists");
450*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(EINVAL));
451*bb4ee6a4SAndroid Build Coastguard Worker         }
452*bb4ee6a4SAndroid Build Coastguard Worker 
453*bb4ee6a4SAndroid Build Coastguard Worker         let mut pending_exception = unsafe { event.ExceptionEvent.__bindgen_anon_1 };
454*bb4ee6a4SAndroid Build Coastguard Worker 
455*bb4ee6a4SAndroid Build Coastguard Worker         pending_exception.set_EventPending(1);
456*bb4ee6a4SAndroid Build Coastguard Worker         // GP faults set error code
457*bb4ee6a4SAndroid Build Coastguard Worker         pending_exception.set_DeliverErrorCode(1);
458*bb4ee6a4SAndroid Build Coastguard Worker         // GP fault error code is 0 unless the fault is segment related
459*bb4ee6a4SAndroid Build Coastguard Worker         pending_exception.ErrorCode = 0;
460*bb4ee6a4SAndroid Build Coastguard Worker         // This must be set to WHvX64PendingEventException
461*bb4ee6a4SAndroid Build Coastguard Worker         pending_exception
462*bb4ee6a4SAndroid Build Coastguard Worker             .set_EventType(WHV_X64_PENDING_EVENT_TYPE_WHvX64PendingEventException as u32);
463*bb4ee6a4SAndroid Build Coastguard Worker         // GP fault vector is 13
464*bb4ee6a4SAndroid Build Coastguard Worker         const GP_VECTOR: u32 = 13;
465*bb4ee6a4SAndroid Build Coastguard Worker         pending_exception.set_Vector(GP_VECTOR);
466*bb4ee6a4SAndroid Build Coastguard Worker 
467*bb4ee6a4SAndroid Build Coastguard Worker         let event = WHV_REGISTER_VALUE {
468*bb4ee6a4SAndroid Build Coastguard Worker             ExceptionEvent: WHV_X64_PENDING_EXCEPTION_EVENT {
469*bb4ee6a4SAndroid Build Coastguard Worker                 __bindgen_anon_1: pending_exception,
470*bb4ee6a4SAndroid Build Coastguard Worker             },
471*bb4ee6a4SAndroid Build Coastguard Worker         };
472*bb4ee6a4SAndroid Build Coastguard Worker 
473*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
474*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
475*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
476*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
477*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
478*bb4ee6a4SAndroid Build Coastguard Worker                 &REG_NAMES as *const WHV_REGISTER_NAME,
479*bb4ee6a4SAndroid Build Coastguard Worker                 REG_NAMES.len() as u32,
480*bb4ee6a4SAndroid Build Coastguard Worker                 &event as *const WHV_REGISTER_VALUE,
481*bb4ee6a4SAndroid Build Coastguard Worker             )
482*bb4ee6a4SAndroid Build Coastguard Worker         })
483*bb4ee6a4SAndroid Build Coastguard Worker     }
484*bb4ee6a4SAndroid Build Coastguard Worker }
485*bb4ee6a4SAndroid Build Coastguard Worker 
486*bb4ee6a4SAndroid Build Coastguard Worker impl Vcpu for WhpxVcpu {
487*bb4ee6a4SAndroid Build Coastguard Worker     /// Makes a shallow clone of this `Vcpu`.
try_clone(&self) -> Result<Self>488*bb4ee6a4SAndroid Build Coastguard Worker     fn try_clone(&self) -> Result<Self> {
489*bb4ee6a4SAndroid Build Coastguard Worker         Ok(WhpxVcpu {
490*bb4ee6a4SAndroid Build Coastguard Worker             index: self.index,
491*bb4ee6a4SAndroid Build Coastguard Worker             safe_virtual_processor: self.safe_virtual_processor.clone(),
492*bb4ee6a4SAndroid Build Coastguard Worker             vm_partition: self.vm_partition.clone(),
493*bb4ee6a4SAndroid Build Coastguard Worker             last_exit_context: self.last_exit_context.clone(),
494*bb4ee6a4SAndroid Build Coastguard Worker             instruction_emulator: self.instruction_emulator.clone(),
495*bb4ee6a4SAndroid Build Coastguard Worker             tsc_frequency: self.tsc_frequency,
496*bb4ee6a4SAndroid Build Coastguard Worker             apic_frequency: self.apic_frequency,
497*bb4ee6a4SAndroid Build Coastguard Worker         })
498*bb4ee6a4SAndroid Build Coastguard Worker     }
499*bb4ee6a4SAndroid Build Coastguard Worker 
as_vcpu(&self) -> &dyn Vcpu500*bb4ee6a4SAndroid Build Coastguard Worker     fn as_vcpu(&self) -> &dyn Vcpu {
501*bb4ee6a4SAndroid Build Coastguard Worker         self
502*bb4ee6a4SAndroid Build Coastguard Worker     }
503*bb4ee6a4SAndroid Build Coastguard Worker 
504*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the vcpu id.
id(&self) -> usize505*bb4ee6a4SAndroid Build Coastguard Worker     fn id(&self) -> usize {
506*bb4ee6a4SAndroid Build Coastguard Worker         self.index.try_into().unwrap()
507*bb4ee6a4SAndroid Build Coastguard Worker     }
508*bb4ee6a4SAndroid Build Coastguard Worker 
509*bb4ee6a4SAndroid Build Coastguard Worker     /// Exits the vcpu immediately if exit is true
set_immediate_exit(&self, exit: bool)510*bb4ee6a4SAndroid Build Coastguard Worker     fn set_immediate_exit(&self, exit: bool) {
511*bb4ee6a4SAndroid Build Coastguard Worker         if exit {
512*bb4ee6a4SAndroid Build Coastguard Worker             // safe because we own this whpx virtual processor index, and assume the vm partition is
513*bb4ee6a4SAndroid Build Coastguard Worker             // still valid
514*bb4ee6a4SAndroid Build Coastguard Worker             unsafe {
515*bb4ee6a4SAndroid Build Coastguard Worker                 WHvCancelRunVirtualProcessor(self.vm_partition.partition, self.index, 0);
516*bb4ee6a4SAndroid Build Coastguard Worker             }
517*bb4ee6a4SAndroid Build Coastguard Worker         }
518*bb4ee6a4SAndroid Build Coastguard Worker     }
519*bb4ee6a4SAndroid Build Coastguard Worker 
520*bb4ee6a4SAndroid Build Coastguard Worker     /// Signals to the hypervisor that this guest is being paused by userspace. On some hypervisors,
521*bb4ee6a4SAndroid Build Coastguard Worker     /// this is used to control the pvclock. On WHPX, we handle it separately with virtio-pvclock.
522*bb4ee6a4SAndroid Build Coastguard Worker     /// So the correct implementation here is to do nothing.
on_suspend(&self) -> Result<()>523*bb4ee6a4SAndroid Build Coastguard Worker     fn on_suspend(&self) -> Result<()> {
524*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
525*bb4ee6a4SAndroid Build Coastguard Worker     }
526*bb4ee6a4SAndroid Build Coastguard Worker 
527*bb4ee6a4SAndroid Build Coastguard Worker     /// Enables a hypervisor-specific extension on this Vcpu.  `cap` is a constant defined by the
528*bb4ee6a4SAndroid Build Coastguard Worker     /// hypervisor API (e.g., kvm.h).  `args` are the arguments for enabling the feature, if any.
enable_raw_capability(&self, _cap: u32, _args: &[u64; 4]) -> Result<()>529*bb4ee6a4SAndroid Build Coastguard Worker     unsafe fn enable_raw_capability(&self, _cap: u32, _args: &[u64; 4]) -> Result<()> {
530*bb4ee6a4SAndroid Build Coastguard Worker         // Whpx does not support raw capability on the vcpu.
531*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::new(ENXIO))
532*bb4ee6a4SAndroid Build Coastguard Worker     }
533*bb4ee6a4SAndroid Build Coastguard Worker 
534*bb4ee6a4SAndroid Build Coastguard Worker     /// This function should be called after `Vcpu::run` returns `VcpuExit::Mmio`.
535*bb4ee6a4SAndroid Build Coastguard Worker     ///
536*bb4ee6a4SAndroid Build Coastguard Worker     /// Once called, it will determine whether a mmio read or mmio write was the reason for the mmio
537*bb4ee6a4SAndroid Build Coastguard Worker     /// exit, call `handle_fn` with the respective IoOperation to perform the mmio read or
538*bb4ee6a4SAndroid Build Coastguard Worker     /// write, and set the return data in the vcpu so that the vcpu can resume running.
handle_mmio(&self, handle_fn: &mut dyn FnMut(IoParams) -> Result<()>) -> Result<()>539*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_mmio(&self, handle_fn: &mut dyn FnMut(IoParams) -> Result<()>) -> Result<()> {
540*bb4ee6a4SAndroid Build Coastguard Worker         let mut status: WHV_EMULATOR_STATUS = Default::default();
541*bb4ee6a4SAndroid Build Coastguard Worker         let mut ctx = InstructionEmulatorContext {
542*bb4ee6a4SAndroid Build Coastguard Worker             vm_partition: self.vm_partition.clone(),
543*bb4ee6a4SAndroid Build Coastguard Worker             index: self.index,
544*bb4ee6a4SAndroid Build Coastguard Worker             handle_mmio: Some(handle_fn),
545*bb4ee6a4SAndroid Build Coastguard Worker             handle_io: None,
546*bb4ee6a4SAndroid Build Coastguard Worker         };
547*bb4ee6a4SAndroid Build Coastguard Worker         // safe as long as all callbacks occur before this fn returns.
548*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
549*bb4ee6a4SAndroid Build Coastguard Worker             WHvEmulatorTryMmioEmulation(
550*bb4ee6a4SAndroid Build Coastguard Worker                 self.instruction_emulator.handle,
551*bb4ee6a4SAndroid Build Coastguard Worker                 &mut ctx as *mut _ as *mut c_void,
552*bb4ee6a4SAndroid Build Coastguard Worker                 &self.last_exit_context.VpContext,
553*bb4ee6a4SAndroid Build Coastguard Worker                 &self.last_exit_context.__bindgen_anon_1.MemoryAccess,
554*bb4ee6a4SAndroid Build Coastguard Worker                 &mut status,
555*bb4ee6a4SAndroid Build Coastguard Worker             )
556*bb4ee6a4SAndroid Build Coastguard Worker         })?;
557*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we trust the kernel to fill in the union field properly.
558*bb4ee6a4SAndroid Build Coastguard Worker         let success = unsafe { status.__bindgen_anon_1.EmulationSuccessful() > 0 };
559*bb4ee6a4SAndroid Build Coastguard Worker         if success {
560*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
561*bb4ee6a4SAndroid Build Coastguard Worker         } else {
562*bb4ee6a4SAndroid Build Coastguard Worker             self.inject_gp_fault()?;
563*bb4ee6a4SAndroid Build Coastguard Worker             // safe because we trust the kernel to fill in the union field properly.
564*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::new(unsafe { status.AsUINT32 }))
565*bb4ee6a4SAndroid Build Coastguard Worker         }
566*bb4ee6a4SAndroid Build Coastguard Worker     }
567*bb4ee6a4SAndroid Build Coastguard Worker 
568*bb4ee6a4SAndroid Build Coastguard Worker     /// This function should be called after `Vcpu::run` returns `VcpuExit::Io`.
569*bb4ee6a4SAndroid Build Coastguard Worker     ///
570*bb4ee6a4SAndroid Build Coastguard Worker     /// Once called, it will determine whether an io in or io out was the reason for the io exit,
571*bb4ee6a4SAndroid Build Coastguard Worker     /// call `handle_fn` with the respective IoOperation to perform the io in or io out,
572*bb4ee6a4SAndroid Build Coastguard Worker     /// and set the return data in the vcpu so that the vcpu can resume running.
handle_io(&self, handle_fn: &mut dyn FnMut(IoParams)) -> Result<()>573*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_io(&self, handle_fn: &mut dyn FnMut(IoParams)) -> Result<()> {
574*bb4ee6a4SAndroid Build Coastguard Worker         let mut status: WHV_EMULATOR_STATUS = Default::default();
575*bb4ee6a4SAndroid Build Coastguard Worker         let mut ctx = InstructionEmulatorContext {
576*bb4ee6a4SAndroid Build Coastguard Worker             vm_partition: self.vm_partition.clone(),
577*bb4ee6a4SAndroid Build Coastguard Worker             index: self.index,
578*bb4ee6a4SAndroid Build Coastguard Worker             handle_mmio: None,
579*bb4ee6a4SAndroid Build Coastguard Worker             handle_io: Some(handle_fn),
580*bb4ee6a4SAndroid Build Coastguard Worker         };
581*bb4ee6a4SAndroid Build Coastguard Worker         // safe as long as all callbacks occur before this fn returns.
582*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
583*bb4ee6a4SAndroid Build Coastguard Worker             WHvEmulatorTryIoEmulation(
584*bb4ee6a4SAndroid Build Coastguard Worker                 self.instruction_emulator.handle,
585*bb4ee6a4SAndroid Build Coastguard Worker                 &mut ctx as *mut _ as *mut c_void,
586*bb4ee6a4SAndroid Build Coastguard Worker                 &self.last_exit_context.VpContext,
587*bb4ee6a4SAndroid Build Coastguard Worker                 &self.last_exit_context.__bindgen_anon_1.IoPortAccess,
588*bb4ee6a4SAndroid Build Coastguard Worker                 &mut status,
589*bb4ee6a4SAndroid Build Coastguard Worker             )
590*bb4ee6a4SAndroid Build Coastguard Worker         })?; // safe because we trust the kernel to fill in the union field properly.
591*bb4ee6a4SAndroid Build Coastguard Worker         let success = unsafe { status.__bindgen_anon_1.EmulationSuccessful() > 0 };
592*bb4ee6a4SAndroid Build Coastguard Worker         if success {
593*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
594*bb4ee6a4SAndroid Build Coastguard Worker         } else {
595*bb4ee6a4SAndroid Build Coastguard Worker             // safe because we trust the kernel to fill in the union field properly.
596*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::new(unsafe { status.AsUINT32 }))
597*bb4ee6a4SAndroid Build Coastguard Worker         }
598*bb4ee6a4SAndroid Build Coastguard Worker     }
599*bb4ee6a4SAndroid Build Coastguard Worker 
600*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(non_upper_case_globals)]
run(&mut self) -> Result<VcpuExit>601*bb4ee6a4SAndroid Build Coastguard Worker     fn run(&mut self) -> Result<VcpuExit> {
602*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we own this whpx virtual processor index, and assume the vm partition is
603*bb4ee6a4SAndroid Build Coastguard Worker         // still valid
604*bb4ee6a4SAndroid Build Coastguard Worker         let exit_context_ptr = Arc::as_ptr(&self.last_exit_context);
605*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
606*bb4ee6a4SAndroid Build Coastguard Worker             WHvRunVirtualProcessor(
607*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
608*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
609*bb4ee6a4SAndroid Build Coastguard Worker                 exit_context_ptr as *mut WHV_RUN_VP_EXIT_CONTEXT as *mut c_void,
610*bb4ee6a4SAndroid Build Coastguard Worker                 size_of::<WHV_RUN_VP_EXIT_CONTEXT>() as u32,
611*bb4ee6a4SAndroid Build Coastguard Worker             )
612*bb4ee6a4SAndroid Build Coastguard Worker         })?;
613*bb4ee6a4SAndroid Build Coastguard Worker 
614*bb4ee6a4SAndroid Build Coastguard Worker         match self.last_exit_context.ExitReason {
615*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonMemoryAccess => Ok(VcpuExit::Mmio),
616*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64IoPortAccess => Ok(VcpuExit::Io),
617*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonUnrecoverableException => {
618*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(VcpuExit::UnrecoverableException)
619*bb4ee6a4SAndroid Build Coastguard Worker             }
620*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonInvalidVpRegisterValue => {
621*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(VcpuExit::InvalidVpRegister)
622*bb4ee6a4SAndroid Build Coastguard Worker             }
623*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonUnsupportedFeature => {
624*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(VcpuExit::UnsupportedFeature)
625*bb4ee6a4SAndroid Build Coastguard Worker             }
626*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64InterruptWindow => {
627*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(VcpuExit::IrqWindowOpen)
628*bb4ee6a4SAndroid Build Coastguard Worker             }
629*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64Halt => Ok(VcpuExit::Hlt),
630*bb4ee6a4SAndroid Build Coastguard Worker             // additional exits that are configurable
631*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64ApicEoi => {
632*bb4ee6a4SAndroid Build Coastguard Worker                 // safe because we trust the kernel to fill in the union field properly.
633*bb4ee6a4SAndroid Build Coastguard Worker                 let vector = unsafe {
634*bb4ee6a4SAndroid Build Coastguard Worker                     self.last_exit_context
635*bb4ee6a4SAndroid Build Coastguard Worker                         .__bindgen_anon_1
636*bb4ee6a4SAndroid Build Coastguard Worker                         .ApicEoi
637*bb4ee6a4SAndroid Build Coastguard Worker                         .InterruptVector as u8
638*bb4ee6a4SAndroid Build Coastguard Worker                 };
639*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(VcpuExit::IoapicEoi { vector })
640*bb4ee6a4SAndroid Build Coastguard Worker             }
641*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64MsrAccess => {
642*bb4ee6a4SAndroid Build Coastguard Worker                 // Safe because we know this was an MSR access exit.
643*bb4ee6a4SAndroid Build Coastguard Worker                 let id = unsafe { self.last_exit_context.__bindgen_anon_1.MsrAccess.MsrNumber };
644*bb4ee6a4SAndroid Build Coastguard Worker 
645*bb4ee6a4SAndroid Build Coastguard Worker                 // Safe because we know this was an MSR access exit
646*bb4ee6a4SAndroid Build Coastguard Worker                 let is_write = unsafe {
647*bb4ee6a4SAndroid Build Coastguard Worker                     self.last_exit_context
648*bb4ee6a4SAndroid Build Coastguard Worker                         .__bindgen_anon_1
649*bb4ee6a4SAndroid Build Coastguard Worker                         .MsrAccess
650*bb4ee6a4SAndroid Build Coastguard Worker                         .AccessInfo
651*bb4ee6a4SAndroid Build Coastguard Worker                         .__bindgen_anon_1
652*bb4ee6a4SAndroid Build Coastguard Worker                         .IsWrite()
653*bb4ee6a4SAndroid Build Coastguard Worker                         == 1
654*bb4ee6a4SAndroid Build Coastguard Worker                 };
655*bb4ee6a4SAndroid Build Coastguard Worker                 if is_write {
656*bb4ee6a4SAndroid Build Coastguard Worker                     // Safe because we know this was an MSR access exit
657*bb4ee6a4SAndroid Build Coastguard Worker                     let value = unsafe {
658*bb4ee6a4SAndroid Build Coastguard Worker                         // WRMSR writes the contents of registers EDX:EAX into the 64-bit model
659*bb4ee6a4SAndroid Build Coastguard Worker                         // specific register
660*bb4ee6a4SAndroid Build Coastguard Worker                         (self.last_exit_context.__bindgen_anon_1.MsrAccess.Rdx << 32)
661*bb4ee6a4SAndroid Build Coastguard Worker                             | (self.last_exit_context.__bindgen_anon_1.MsrAccess.Rax & 0xffffffff)
662*bb4ee6a4SAndroid Build Coastguard Worker                     };
663*bb4ee6a4SAndroid Build Coastguard Worker                     self.handle_msr_write(id, value)?;
664*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
665*bb4ee6a4SAndroid Build Coastguard Worker                     self.handle_msr_read(id)?;
666*bb4ee6a4SAndroid Build Coastguard Worker                 }
667*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(VcpuExit::MsrAccess)
668*bb4ee6a4SAndroid Build Coastguard Worker             }
669*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64Cpuid => {
670*bb4ee6a4SAndroid Build Coastguard Worker                 // Safe because we know this was a CPUID exit.
671*bb4ee6a4SAndroid Build Coastguard Worker                 let entry = unsafe {
672*bb4ee6a4SAndroid Build Coastguard Worker                     CpuIdEntry {
673*bb4ee6a4SAndroid Build Coastguard Worker                         function: self.last_exit_context.__bindgen_anon_1.CpuidAccess.Rax as u32,
674*bb4ee6a4SAndroid Build Coastguard Worker                         index: self.last_exit_context.__bindgen_anon_1.CpuidAccess.Rcx as u32,
675*bb4ee6a4SAndroid Build Coastguard Worker                         flags: 0,
676*bb4ee6a4SAndroid Build Coastguard Worker                         cpuid: CpuidResult {
677*bb4ee6a4SAndroid Build Coastguard Worker                             eax: self
678*bb4ee6a4SAndroid Build Coastguard Worker                                 .last_exit_context
679*bb4ee6a4SAndroid Build Coastguard Worker                                 .__bindgen_anon_1
680*bb4ee6a4SAndroid Build Coastguard Worker                                 .CpuidAccess
681*bb4ee6a4SAndroid Build Coastguard Worker                                 .DefaultResultRax as u32,
682*bb4ee6a4SAndroid Build Coastguard Worker                             ebx: self
683*bb4ee6a4SAndroid Build Coastguard Worker                                 .last_exit_context
684*bb4ee6a4SAndroid Build Coastguard Worker                                 .__bindgen_anon_1
685*bb4ee6a4SAndroid Build Coastguard Worker                                 .CpuidAccess
686*bb4ee6a4SAndroid Build Coastguard Worker                                 .DefaultResultRbx as u32,
687*bb4ee6a4SAndroid Build Coastguard Worker                             ecx: self
688*bb4ee6a4SAndroid Build Coastguard Worker                                 .last_exit_context
689*bb4ee6a4SAndroid Build Coastguard Worker                                 .__bindgen_anon_1
690*bb4ee6a4SAndroid Build Coastguard Worker                                 .CpuidAccess
691*bb4ee6a4SAndroid Build Coastguard Worker                                 .DefaultResultRcx as u32,
692*bb4ee6a4SAndroid Build Coastguard Worker                             edx: self
693*bb4ee6a4SAndroid Build Coastguard Worker                                 .last_exit_context
694*bb4ee6a4SAndroid Build Coastguard Worker                                 .__bindgen_anon_1
695*bb4ee6a4SAndroid Build Coastguard Worker                                 .CpuidAccess
696*bb4ee6a4SAndroid Build Coastguard Worker                                 .DefaultResultRdx as u32,
697*bb4ee6a4SAndroid Build Coastguard Worker                         },
698*bb4ee6a4SAndroid Build Coastguard Worker                     }
699*bb4ee6a4SAndroid Build Coastguard Worker                 };
700*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(VcpuExit::Cpuid { entry })
701*bb4ee6a4SAndroid Build Coastguard Worker             }
702*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonException => Ok(VcpuExit::Exception),
703*bb4ee6a4SAndroid Build Coastguard Worker             // undocumented exit calls from the header file, WinHvPlatformDefs.h.
704*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64Rdtsc => Ok(VcpuExit::RdTsc),
705*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64ApicSmiTrap => Ok(VcpuExit::ApicSmiTrap),
706*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonHypercall => Ok(VcpuExit::Hypercall),
707*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64ApicInitSipiTrap => {
708*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(VcpuExit::ApicInitSipiTrap)
709*bb4ee6a4SAndroid Build Coastguard Worker             }
710*bb4ee6a4SAndroid Build Coastguard Worker             // exit caused by host cancellation thorugh WHvCancelRunVirtualProcessor,
711*bb4ee6a4SAndroid Build Coastguard Worker             WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonCanceled => Ok(VcpuExit::Canceled),
712*bb4ee6a4SAndroid Build Coastguard Worker             r => panic!("unknown exit reason: {}", r),
713*bb4ee6a4SAndroid Build Coastguard Worker         }
714*bb4ee6a4SAndroid Build Coastguard Worker     }
715*bb4ee6a4SAndroid Build Coastguard Worker }
716*bb4ee6a4SAndroid Build Coastguard Worker 
717*bb4ee6a4SAndroid Build Coastguard Worker impl VcpuX86_64 for WhpxVcpu {
718*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets or clears the flag that requests the VCPU to exit when it becomes possible to inject
719*bb4ee6a4SAndroid Build Coastguard Worker     /// interrupts into the guest.
set_interrupt_window_requested(&self, requested: bool)720*bb4ee6a4SAndroid Build Coastguard Worker     fn set_interrupt_window_requested(&self, requested: bool) {
721*bb4ee6a4SAndroid Build Coastguard Worker         const REG_NAMES: [WHV_REGISTER_NAME; 1] =
722*bb4ee6a4SAndroid Build Coastguard Worker             [WHV_REGISTER_NAME_WHvX64RegisterDeliverabilityNotifications];
723*bb4ee6a4SAndroid Build Coastguard Worker         let mut notifications: WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER__bindgen_ty_1 =
724*bb4ee6a4SAndroid Build Coastguard Worker             Default::default();
725*bb4ee6a4SAndroid Build Coastguard Worker         notifications.set_InterruptNotification(if requested { 1 } else { 0 });
726*bb4ee6a4SAndroid Build Coastguard Worker         let notify_register = WHV_REGISTER_VALUE {
727*bb4ee6a4SAndroid Build Coastguard Worker             DeliverabilityNotifications: WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER {
728*bb4ee6a4SAndroid Build Coastguard Worker                 __bindgen_anon_1: notifications,
729*bb4ee6a4SAndroid Build Coastguard Worker             },
730*bb4ee6a4SAndroid Build Coastguard Worker         };
731*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
732*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
733*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
734*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
735*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
736*bb4ee6a4SAndroid Build Coastguard Worker                 &REG_NAMES as *const WHV_REGISTER_NAME,
737*bb4ee6a4SAndroid Build Coastguard Worker                 REG_NAMES.len() as u32,
738*bb4ee6a4SAndroid Build Coastguard Worker                 &notify_register as *const WHV_REGISTER_VALUE,
739*bb4ee6a4SAndroid Build Coastguard Worker             )
740*bb4ee6a4SAndroid Build Coastguard Worker         })
741*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
742*bb4ee6a4SAndroid Build Coastguard Worker     }
743*bb4ee6a4SAndroid Build Coastguard Worker 
744*bb4ee6a4SAndroid Build Coastguard Worker     /// Checks if we can inject an interrupt into the VCPU.
ready_for_interrupt(&self) -> bool745*bb4ee6a4SAndroid Build Coastguard Worker     fn ready_for_interrupt(&self) -> bool {
746*bb4ee6a4SAndroid Build Coastguard Worker         // safe because InterruptionPending bit is always valid in ExecutionState struct
747*bb4ee6a4SAndroid Build Coastguard Worker         let pending = unsafe {
748*bb4ee6a4SAndroid Build Coastguard Worker             self.last_exit_context
749*bb4ee6a4SAndroid Build Coastguard Worker                 .VpContext
750*bb4ee6a4SAndroid Build Coastguard Worker                 .ExecutionState
751*bb4ee6a4SAndroid Build Coastguard Worker                 .__bindgen_anon_1
752*bb4ee6a4SAndroid Build Coastguard Worker                 .InterruptionPending()
753*bb4ee6a4SAndroid Build Coastguard Worker         };
754*bb4ee6a4SAndroid Build Coastguard Worker         // safe because InterruptShadow bit is always valid in ExecutionState struct
755*bb4ee6a4SAndroid Build Coastguard Worker         let shadow = unsafe {
756*bb4ee6a4SAndroid Build Coastguard Worker             self.last_exit_context
757*bb4ee6a4SAndroid Build Coastguard Worker                 .VpContext
758*bb4ee6a4SAndroid Build Coastguard Worker                 .ExecutionState
759*bb4ee6a4SAndroid Build Coastguard Worker                 .__bindgen_anon_1
760*bb4ee6a4SAndroid Build Coastguard Worker                 .InterruptShadow()
761*bb4ee6a4SAndroid Build Coastguard Worker         };
762*bb4ee6a4SAndroid Build Coastguard Worker 
763*bb4ee6a4SAndroid Build Coastguard Worker         let eflags = self.last_exit_context.VpContext.Rflags;
764*bb4ee6a4SAndroid Build Coastguard Worker         const IF_MASK: u64 = 0x00000200;
765*bb4ee6a4SAndroid Build Coastguard Worker 
766*bb4ee6a4SAndroid Build Coastguard Worker         // can't inject an interrupt if InterruptShadow or InterruptPending bits are set, or if
767*bb4ee6a4SAndroid Build Coastguard Worker         // the IF flag is clear
768*bb4ee6a4SAndroid Build Coastguard Worker         shadow == 0 && pending == 0 && (eflags & IF_MASK) != 0
769*bb4ee6a4SAndroid Build Coastguard Worker     }
770*bb4ee6a4SAndroid Build Coastguard Worker 
771*bb4ee6a4SAndroid Build Coastguard Worker     /// Injects interrupt vector `irq` into the VCPU.
interrupt(&self, irq: u8) -> Result<()>772*bb4ee6a4SAndroid Build Coastguard Worker     fn interrupt(&self, irq: u8) -> Result<()> {
773*bb4ee6a4SAndroid Build Coastguard Worker         const REG_NAMES: [WHV_REGISTER_NAME; 1] =
774*bb4ee6a4SAndroid Build Coastguard Worker             [WHV_REGISTER_NAME_WHvRegisterPendingInterruption];
775*bb4ee6a4SAndroid Build Coastguard Worker         let mut pending_interrupt: WHV_X64_PENDING_INTERRUPTION_REGISTER__bindgen_ty_1 =
776*bb4ee6a4SAndroid Build Coastguard Worker             Default::default();
777*bb4ee6a4SAndroid Build Coastguard Worker         pending_interrupt.set_InterruptionPending(1);
778*bb4ee6a4SAndroid Build Coastguard Worker         pending_interrupt
779*bb4ee6a4SAndroid Build Coastguard Worker             .set_InterruptionType(WHV_X64_PENDING_INTERRUPTION_TYPE_WHvX64PendingInterrupt as u32);
780*bb4ee6a4SAndroid Build Coastguard Worker         pending_interrupt.set_InterruptionVector(irq.into());
781*bb4ee6a4SAndroid Build Coastguard Worker         let interrupt = WHV_REGISTER_VALUE {
782*bb4ee6a4SAndroid Build Coastguard Worker             PendingInterruption: WHV_X64_PENDING_INTERRUPTION_REGISTER {
783*bb4ee6a4SAndroid Build Coastguard Worker                 __bindgen_anon_1: pending_interrupt,
784*bb4ee6a4SAndroid Build Coastguard Worker             },
785*bb4ee6a4SAndroid Build Coastguard Worker         };
786*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
787*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
788*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
789*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
790*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
791*bb4ee6a4SAndroid Build Coastguard Worker                 &REG_NAMES as *const WHV_REGISTER_NAME,
792*bb4ee6a4SAndroid Build Coastguard Worker                 REG_NAMES.len() as u32,
793*bb4ee6a4SAndroid Build Coastguard Worker                 &interrupt as *const WHV_REGISTER_VALUE,
794*bb4ee6a4SAndroid Build Coastguard Worker             )
795*bb4ee6a4SAndroid Build Coastguard Worker         })
796*bb4ee6a4SAndroid Build Coastguard Worker     }
797*bb4ee6a4SAndroid Build Coastguard Worker 
798*bb4ee6a4SAndroid Build Coastguard Worker     /// Injects a non-maskable interrupt into the VCPU.
inject_nmi(&self) -> Result<()>799*bb4ee6a4SAndroid Build Coastguard Worker     fn inject_nmi(&self) -> Result<()> {
800*bb4ee6a4SAndroid Build Coastguard Worker         const REG_NAMES: [WHV_REGISTER_NAME; 1] =
801*bb4ee6a4SAndroid Build Coastguard Worker             [WHV_REGISTER_NAME_WHvRegisterPendingInterruption];
802*bb4ee6a4SAndroid Build Coastguard Worker         let mut pending_interrupt: WHV_X64_PENDING_INTERRUPTION_REGISTER__bindgen_ty_1 =
803*bb4ee6a4SAndroid Build Coastguard Worker             Default::default();
804*bb4ee6a4SAndroid Build Coastguard Worker         pending_interrupt.set_InterruptionPending(1);
805*bb4ee6a4SAndroid Build Coastguard Worker         pending_interrupt
806*bb4ee6a4SAndroid Build Coastguard Worker             .set_InterruptionType(WHV_X64_PENDING_INTERRUPTION_TYPE_WHvX64PendingNmi as u32);
807*bb4ee6a4SAndroid Build Coastguard Worker         const NMI_VECTOR: u32 = 2; // 2 is the NMI vector.
808*bb4ee6a4SAndroid Build Coastguard Worker         pending_interrupt.set_InterruptionVector(NMI_VECTOR);
809*bb4ee6a4SAndroid Build Coastguard Worker         let interrupt = WHV_REGISTER_VALUE {
810*bb4ee6a4SAndroid Build Coastguard Worker             PendingInterruption: WHV_X64_PENDING_INTERRUPTION_REGISTER {
811*bb4ee6a4SAndroid Build Coastguard Worker                 __bindgen_anon_1: pending_interrupt,
812*bb4ee6a4SAndroid Build Coastguard Worker             },
813*bb4ee6a4SAndroid Build Coastguard Worker         };
814*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
815*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
816*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
817*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
818*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
819*bb4ee6a4SAndroid Build Coastguard Worker                 &REG_NAMES as *const WHV_REGISTER_NAME,
820*bb4ee6a4SAndroid Build Coastguard Worker                 REG_NAMES.len() as u32,
821*bb4ee6a4SAndroid Build Coastguard Worker                 &interrupt as *const WHV_REGISTER_VALUE,
822*bb4ee6a4SAndroid Build Coastguard Worker             )
823*bb4ee6a4SAndroid Build Coastguard Worker         })
824*bb4ee6a4SAndroid Build Coastguard Worker     }
825*bb4ee6a4SAndroid Build Coastguard Worker 
826*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the VCPU general purpose registers.
get_regs(&self) -> Result<Regs>827*bb4ee6a4SAndroid Build Coastguard Worker     fn get_regs(&self) -> Result<Regs> {
828*bb4ee6a4SAndroid Build Coastguard Worker         let mut whpx_regs: WhpxRegs = Default::default();
829*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxRegs::get_register_names();
830*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
831*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
832*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorRegisters(
833*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
834*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
835*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
836*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
837*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_regs.as_mut_ptr(),
838*bb4ee6a4SAndroid Build Coastguard Worker             )
839*bb4ee6a4SAndroid Build Coastguard Worker         })?;
840*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Regs::from(&whpx_regs))
841*bb4ee6a4SAndroid Build Coastguard Worker     }
842*bb4ee6a4SAndroid Build Coastguard Worker 
843*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the VCPU general purpose registers.
set_regs(&self, regs: &Regs) -> Result<()>844*bb4ee6a4SAndroid Build Coastguard Worker     fn set_regs(&self, regs: &Regs) -> Result<()> {
845*bb4ee6a4SAndroid Build Coastguard Worker         let whpx_regs = WhpxRegs::from(regs);
846*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxRegs::get_register_names();
847*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
848*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
849*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
850*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
851*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
852*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
853*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
854*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_regs.as_ptr(),
855*bb4ee6a4SAndroid Build Coastguard Worker             )
856*bb4ee6a4SAndroid Build Coastguard Worker         })
857*bb4ee6a4SAndroid Build Coastguard Worker     }
858*bb4ee6a4SAndroid Build Coastguard Worker 
859*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the VCPU special registers.
get_sregs(&self) -> Result<Sregs>860*bb4ee6a4SAndroid Build Coastguard Worker     fn get_sregs(&self) -> Result<Sregs> {
861*bb4ee6a4SAndroid Build Coastguard Worker         let mut whpx_sregs: WhpxSregs = Default::default();
862*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxSregs::get_register_names();
863*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
864*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
865*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorRegisters(
866*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
867*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
868*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
869*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
870*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_sregs.as_mut_ptr(),
871*bb4ee6a4SAndroid Build Coastguard Worker             )
872*bb4ee6a4SAndroid Build Coastguard Worker         })?;
873*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Sregs::from(&whpx_sregs))
874*bb4ee6a4SAndroid Build Coastguard Worker     }
875*bb4ee6a4SAndroid Build Coastguard Worker 
876*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the VCPU special registers.
set_sregs(&self, sregs: &Sregs) -> Result<()>877*bb4ee6a4SAndroid Build Coastguard Worker     fn set_sregs(&self, sregs: &Sregs) -> Result<()> {
878*bb4ee6a4SAndroid Build Coastguard Worker         let whpx_sregs = WhpxSregs::from(sregs);
879*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxSregs::get_register_names();
880*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
881*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
882*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
883*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
884*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
885*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
886*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
887*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_sregs.as_ptr(),
888*bb4ee6a4SAndroid Build Coastguard Worker             )
889*bb4ee6a4SAndroid Build Coastguard Worker         })
890*bb4ee6a4SAndroid Build Coastguard Worker     }
891*bb4ee6a4SAndroid Build Coastguard Worker 
892*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the VCPU FPU registers.
get_fpu(&self) -> Result<Fpu>893*bb4ee6a4SAndroid Build Coastguard Worker     fn get_fpu(&self) -> Result<Fpu> {
894*bb4ee6a4SAndroid Build Coastguard Worker         let mut whpx_fpu: WhpxFpu = Default::default();
895*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxFpu::get_register_names();
896*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
897*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
898*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorRegisters(
899*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
900*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
901*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
902*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
903*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_fpu.as_mut_ptr(),
904*bb4ee6a4SAndroid Build Coastguard Worker             )
905*bb4ee6a4SAndroid Build Coastguard Worker         })?;
906*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Fpu::from(&whpx_fpu))
907*bb4ee6a4SAndroid Build Coastguard Worker     }
908*bb4ee6a4SAndroid Build Coastguard Worker 
909*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the VCPU FPU registers.
set_fpu(&self, fpu: &Fpu) -> Result<()>910*bb4ee6a4SAndroid Build Coastguard Worker     fn set_fpu(&self, fpu: &Fpu) -> Result<()> {
911*bb4ee6a4SAndroid Build Coastguard Worker         let whpx_fpu = WhpxFpu::from(fpu);
912*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxFpu::get_register_names();
913*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
914*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
915*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
916*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
917*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
918*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
919*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
920*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_fpu.as_ptr(),
921*bb4ee6a4SAndroid Build Coastguard Worker             )
922*bb4ee6a4SAndroid Build Coastguard Worker         })
923*bb4ee6a4SAndroid Build Coastguard Worker     }
924*bb4ee6a4SAndroid Build Coastguard Worker 
925*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the VCPU XSAVE.
get_xsave(&self) -> Result<Xsave>926*bb4ee6a4SAndroid Build Coastguard Worker     fn get_xsave(&self) -> Result<Xsave> {
927*bb4ee6a4SAndroid Build Coastguard Worker         let mut empty_buffer = [0u8; 1];
928*bb4ee6a4SAndroid Build Coastguard Worker         let mut needed_buf_size: u32 = 0;
929*bb4ee6a4SAndroid Build Coastguard Worker 
930*bb4ee6a4SAndroid Build Coastguard Worker         // Find out how much space is needed for XSAVEs.
931*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe {
932*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorXsaveState(
933*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
934*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
935*bb4ee6a4SAndroid Build Coastguard Worker                 empty_buffer.as_mut_ptr() as *mut _,
936*bb4ee6a4SAndroid Build Coastguard Worker                 0,
937*bb4ee6a4SAndroid Build Coastguard Worker                 &mut needed_buf_size,
938*bb4ee6a4SAndroid Build Coastguard Worker             )
939*bb4ee6a4SAndroid Build Coastguard Worker         };
940*bb4ee6a4SAndroid Build Coastguard Worker         if res != WHV_E_INSUFFICIENT_BUFFER.0 {
941*bb4ee6a4SAndroid Build Coastguard Worker             // This should always work, so if it doesn't, we'll return unsupported.
942*bb4ee6a4SAndroid Build Coastguard Worker             error!("failed to get size of vcpu xsave");
943*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(EIO));
944*bb4ee6a4SAndroid Build Coastguard Worker         }
945*bb4ee6a4SAndroid Build Coastguard Worker 
946*bb4ee6a4SAndroid Build Coastguard Worker         let mut xsave = Xsave::new(needed_buf_size as usize);
947*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: xsave_data is valid for the duration of the FFI call, and we pass its length in
948*bb4ee6a4SAndroid Build Coastguard Worker         // bytes so writes are bounded within the buffer.
949*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
950*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorXsaveState(
951*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
952*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
953*bb4ee6a4SAndroid Build Coastguard Worker                 xsave.as_mut_ptr(),
954*bb4ee6a4SAndroid Build Coastguard Worker                 xsave.len() as u32,
955*bb4ee6a4SAndroid Build Coastguard Worker                 &mut needed_buf_size,
956*bb4ee6a4SAndroid Build Coastguard Worker             )
957*bb4ee6a4SAndroid Build Coastguard Worker         })?;
958*bb4ee6a4SAndroid Build Coastguard Worker         Ok(xsave)
959*bb4ee6a4SAndroid Build Coastguard Worker     }
960*bb4ee6a4SAndroid Build Coastguard Worker 
961*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the VCPU XSAVE.
set_xsave(&self, xsave: &Xsave) -> Result<()>962*bb4ee6a4SAndroid Build Coastguard Worker     fn set_xsave(&self, xsave: &Xsave) -> Result<()> {
963*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: the xsave buffer is valid for the duration of the FFI call, and we pass its
964*bb4ee6a4SAndroid Build Coastguard Worker         // length in bytes so reads are bounded within the buffer.
965*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
966*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorXsaveState(
967*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
968*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
969*bb4ee6a4SAndroid Build Coastguard Worker                 xsave.as_ptr(),
970*bb4ee6a4SAndroid Build Coastguard Worker                 xsave.len() as u32,
971*bb4ee6a4SAndroid Build Coastguard Worker             )
972*bb4ee6a4SAndroid Build Coastguard Worker         })
973*bb4ee6a4SAndroid Build Coastguard Worker     }
974*bb4ee6a4SAndroid Build Coastguard Worker 
get_interrupt_state(&self) -> Result<serde_json::Value>975*bb4ee6a4SAndroid Build Coastguard Worker     fn get_interrupt_state(&self) -> Result<serde_json::Value> {
976*bb4ee6a4SAndroid Build Coastguard Worker         let mut whpx_interrupt_regs: WhpxInterruptRegs = Default::default();
977*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxInterruptRegs::get_register_names();
978*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: we have enough space for all the registers & the memory lives for the duration
979*bb4ee6a4SAndroid Build Coastguard Worker         // of the FFI call.
980*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
981*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorRegisters(
982*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
983*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
984*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
985*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
986*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_interrupt_regs.as_mut_ptr(),
987*bb4ee6a4SAndroid Build Coastguard Worker             )
988*bb4ee6a4SAndroid Build Coastguard Worker         })?;
989*bb4ee6a4SAndroid Build Coastguard Worker 
990*bb4ee6a4SAndroid Build Coastguard Worker         serde_json::to_value(whpx_interrupt_regs.into_serializable()).map_err(|e| {
991*bb4ee6a4SAndroid Build Coastguard Worker             error!("failed to serialize interrupt state: {:?}", e);
992*bb4ee6a4SAndroid Build Coastguard Worker             Error::new(EIO)
993*bb4ee6a4SAndroid Build Coastguard Worker         })
994*bb4ee6a4SAndroid Build Coastguard Worker     }
995*bb4ee6a4SAndroid Build Coastguard Worker 
set_interrupt_state(&self, data: serde_json::Value) -> Result<()>996*bb4ee6a4SAndroid Build Coastguard Worker     fn set_interrupt_state(&self, data: serde_json::Value) -> Result<()> {
997*bb4ee6a4SAndroid Build Coastguard Worker         let whpx_interrupt_regs =
998*bb4ee6a4SAndroid Build Coastguard Worker             WhpxInterruptRegs::from_serializable(serde_json::from_value(data).map_err(|e| {
999*bb4ee6a4SAndroid Build Coastguard Worker                 error!("failed to serialize interrupt state: {:?}", e);
1000*bb4ee6a4SAndroid Build Coastguard Worker                 Error::new(EIO)
1001*bb4ee6a4SAndroid Build Coastguard Worker             })?);
1002*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxInterruptRegs::get_register_names();
1003*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: we have enough space for all the registers & the memory lives for the duration
1004*bb4ee6a4SAndroid Build Coastguard Worker         // of the FFI call.
1005*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
1006*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
1007*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
1008*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
1009*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
1010*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
1011*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_interrupt_regs.as_ptr(),
1012*bb4ee6a4SAndroid Build Coastguard Worker             )
1013*bb4ee6a4SAndroid Build Coastguard Worker         })
1014*bb4ee6a4SAndroid Build Coastguard Worker     }
1015*bb4ee6a4SAndroid Build Coastguard Worker 
1016*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the VCPU debug registers.
get_debugregs(&self) -> Result<DebugRegs>1017*bb4ee6a4SAndroid Build Coastguard Worker     fn get_debugregs(&self) -> Result<DebugRegs> {
1018*bb4ee6a4SAndroid Build Coastguard Worker         let mut whpx_debugregs: WhpxDebugRegs = Default::default();
1019*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxDebugRegs::get_register_names();
1020*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
1021*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
1022*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorRegisters(
1023*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
1024*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
1025*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
1026*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
1027*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_debugregs.as_mut_ptr(),
1028*bb4ee6a4SAndroid Build Coastguard Worker             )
1029*bb4ee6a4SAndroid Build Coastguard Worker         })?;
1030*bb4ee6a4SAndroid Build Coastguard Worker         Ok(DebugRegs::from(&whpx_debugregs))
1031*bb4ee6a4SAndroid Build Coastguard Worker     }
1032*bb4ee6a4SAndroid Build Coastguard Worker 
1033*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the VCPU debug registers.
set_debugregs(&self, debugregs: &DebugRegs) -> Result<()>1034*bb4ee6a4SAndroid Build Coastguard Worker     fn set_debugregs(&self, debugregs: &DebugRegs) -> Result<()> {
1035*bb4ee6a4SAndroid Build Coastguard Worker         let whpx_debugregs = WhpxDebugRegs::from(debugregs);
1036*bb4ee6a4SAndroid Build Coastguard Worker         let reg_names = WhpxDebugRegs::get_register_names();
1037*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
1038*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
1039*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
1040*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
1041*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
1042*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names as *const WHV_REGISTER_NAME,
1043*bb4ee6a4SAndroid Build Coastguard Worker                 reg_names.len() as u32,
1044*bb4ee6a4SAndroid Build Coastguard Worker                 whpx_debugregs.as_ptr(),
1045*bb4ee6a4SAndroid Build Coastguard Worker             )
1046*bb4ee6a4SAndroid Build Coastguard Worker         })
1047*bb4ee6a4SAndroid Build Coastguard Worker     }
1048*bb4ee6a4SAndroid Build Coastguard Worker 
1049*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the VCPU extended control registers.
get_xcrs(&self) -> Result<BTreeMap<u32, u64>>1050*bb4ee6a4SAndroid Build Coastguard Worker     fn get_xcrs(&self) -> Result<BTreeMap<u32, u64>> {
1051*bb4ee6a4SAndroid Build Coastguard Worker         const REG_NAME: WHV_REGISTER_NAME = WHV_REGISTER_NAME_WHvX64RegisterXCr0;
1052*bb4ee6a4SAndroid Build Coastguard Worker         let mut reg_value = WHV_REGISTER_VALUE::default();
1053*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers in whpx_regs
1054*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
1055*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorRegisters(
1056*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
1057*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
1058*bb4ee6a4SAndroid Build Coastguard Worker                 &REG_NAME,
1059*bb4ee6a4SAndroid Build Coastguard Worker                 /* RegisterCount */ 1,
1060*bb4ee6a4SAndroid Build Coastguard Worker                 &mut reg_value,
1061*bb4ee6a4SAndroid Build Coastguard Worker             )
1062*bb4ee6a4SAndroid Build Coastguard Worker         })?;
1063*bb4ee6a4SAndroid Build Coastguard Worker 
1064*bb4ee6a4SAndroid Build Coastguard Worker         // safe because the union value, reg64, is safe to pull out assuming
1065*bb4ee6a4SAndroid Build Coastguard Worker         // kernel filled in the xcrs properly.
1066*bb4ee6a4SAndroid Build Coastguard Worker         let xcr0 = unsafe { reg_value.Reg64 };
1067*bb4ee6a4SAndroid Build Coastguard Worker 
1068*bb4ee6a4SAndroid Build Coastguard Worker         // whpx only supports xcr0
1069*bb4ee6a4SAndroid Build Coastguard Worker         let xcrs = BTreeMap::from([(0, xcr0)]);
1070*bb4ee6a4SAndroid Build Coastguard Worker         Ok(xcrs)
1071*bb4ee6a4SAndroid Build Coastguard Worker     }
1072*bb4ee6a4SAndroid Build Coastguard Worker 
1073*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets a VCPU extended control register.
set_xcr(&self, xcr_index: u32, value: u64) -> Result<()>1074*bb4ee6a4SAndroid Build Coastguard Worker     fn set_xcr(&self, xcr_index: u32, value: u64) -> Result<()> {
1075*bb4ee6a4SAndroid Build Coastguard Worker         if xcr_index != 0 {
1076*bb4ee6a4SAndroid Build Coastguard Worker             // invalid xcr register provided
1077*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(EINVAL));
1078*bb4ee6a4SAndroid Build Coastguard Worker         }
1079*bb4ee6a4SAndroid Build Coastguard Worker 
1080*bb4ee6a4SAndroid Build Coastguard Worker         const REG_NAME: WHV_REGISTER_NAME = WHV_REGISTER_NAME_WHvX64RegisterXCr0;
1081*bb4ee6a4SAndroid Build Coastguard Worker         let reg_value = WHV_REGISTER_VALUE { Reg64: value };
1082*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers in whpx_xcrs
1083*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
1084*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
1085*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
1086*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
1087*bb4ee6a4SAndroid Build Coastguard Worker                 &REG_NAME,
1088*bb4ee6a4SAndroid Build Coastguard Worker                 /* RegisterCount */ 1,
1089*bb4ee6a4SAndroid Build Coastguard Worker                 &reg_value,
1090*bb4ee6a4SAndroid Build Coastguard Worker             )
1091*bb4ee6a4SAndroid Build Coastguard Worker         })
1092*bb4ee6a4SAndroid Build Coastguard Worker     }
1093*bb4ee6a4SAndroid Build Coastguard Worker 
1094*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the value of a single model-specific register.
get_msr(&self, msr_index: u32) -> Result<u64>1095*bb4ee6a4SAndroid Build Coastguard Worker     fn get_msr(&self, msr_index: u32) -> Result<u64> {
1096*bb4ee6a4SAndroid Build Coastguard Worker         let msr_name = get_msr_name(msr_index).ok_or(Error::new(libc::ENOENT))?;
1097*bb4ee6a4SAndroid Build Coastguard Worker         let mut msr_value = WHV_REGISTER_VALUE::default();
1098*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers in whpx_regs
1099*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
1100*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetVirtualProcessorRegisters(
1101*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
1102*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
1103*bb4ee6a4SAndroid Build Coastguard Worker                 &msr_name,
1104*bb4ee6a4SAndroid Build Coastguard Worker                 /* RegisterCount */ 1,
1105*bb4ee6a4SAndroid Build Coastguard Worker                 &mut msr_value,
1106*bb4ee6a4SAndroid Build Coastguard Worker             )
1107*bb4ee6a4SAndroid Build Coastguard Worker         })?;
1108*bb4ee6a4SAndroid Build Coastguard Worker 
1109*bb4ee6a4SAndroid Build Coastguard Worker         // safe because Reg64 will be a valid union value
1110*bb4ee6a4SAndroid Build Coastguard Worker         let value = unsafe { msr_value.Reg64 };
1111*bb4ee6a4SAndroid Build Coastguard Worker         Ok(value)
1112*bb4ee6a4SAndroid Build Coastguard Worker     }
1113*bb4ee6a4SAndroid Build Coastguard Worker 
get_all_msrs(&self) -> Result<BTreeMap<u32, u64>>1114*bb4ee6a4SAndroid Build Coastguard Worker     fn get_all_msrs(&self) -> Result<BTreeMap<u32, u64>> {
1115*bb4ee6a4SAndroid Build Coastguard Worker         // Note that some members of VALID_MSRS cannot be fetched from WHPX with
1116*bb4ee6a4SAndroid Build Coastguard Worker         // WHvGetVirtualProcessorRegisters per the HTLFS, so we enumerate all of
1117*bb4ee6a4SAndroid Build Coastguard Worker         // permitted MSRs here.
1118*bb4ee6a4SAndroid Build Coastguard Worker         //
1119*bb4ee6a4SAndroid Build Coastguard Worker         // We intentionally exclude WHvRegisterPendingInterruption and
1120*bb4ee6a4SAndroid Build Coastguard Worker         // WHvRegisterInterruptState because they are included in
1121*bb4ee6a4SAndroid Build Coastguard Worker         // get_interrupt_state.
1122*bb4ee6a4SAndroid Build Coastguard Worker         //
1123*bb4ee6a4SAndroid Build Coastguard Worker         // We intentionally exclude MSR_TSC because in snapshotting it is
1124*bb4ee6a4SAndroid Build Coastguard Worker         // handled by the generic x86_64 VCPU snapshot/restore. Non snapshot
1125*bb4ee6a4SAndroid Build Coastguard Worker         // consumers should use get/set_tsc_adjust to access the adjust register
1126*bb4ee6a4SAndroid Build Coastguard Worker         // if needed.
1127*bb4ee6a4SAndroid Build Coastguard Worker         const MSRS_TO_SAVE: &[u32] = &[
1128*bb4ee6a4SAndroid Build Coastguard Worker             MSR_EFER,
1129*bb4ee6a4SAndroid Build Coastguard Worker             MSR_KERNEL_GS_BASE,
1130*bb4ee6a4SAndroid Build Coastguard Worker             MSR_APIC_BASE,
1131*bb4ee6a4SAndroid Build Coastguard Worker             MSR_SYSENTER_CS,
1132*bb4ee6a4SAndroid Build Coastguard Worker             MSR_SYSENTER_EIP,
1133*bb4ee6a4SAndroid Build Coastguard Worker             MSR_SYSENTER_ESP,
1134*bb4ee6a4SAndroid Build Coastguard Worker             MSR_STAR,
1135*bb4ee6a4SAndroid Build Coastguard Worker             MSR_LSTAR,
1136*bb4ee6a4SAndroid Build Coastguard Worker             MSR_CSTAR,
1137*bb4ee6a4SAndroid Build Coastguard Worker             MSR_SFMASK,
1138*bb4ee6a4SAndroid Build Coastguard Worker         ];
1139*bb4ee6a4SAndroid Build Coastguard Worker 
1140*bb4ee6a4SAndroid Build Coastguard Worker         let registers = MSRS_TO_SAVE
1141*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1142*bb4ee6a4SAndroid Build Coastguard Worker             .map(|msr_index| {
1143*bb4ee6a4SAndroid Build Coastguard Worker                 let value = self.get_msr(*msr_index)?;
1144*bb4ee6a4SAndroid Build Coastguard Worker                 Ok((*msr_index, value))
1145*bb4ee6a4SAndroid Build Coastguard Worker             })
1146*bb4ee6a4SAndroid Build Coastguard Worker             .collect::<Result<BTreeMap<u32, u64>>>()?;
1147*bb4ee6a4SAndroid Build Coastguard Worker 
1148*bb4ee6a4SAndroid Build Coastguard Worker         Ok(registers)
1149*bb4ee6a4SAndroid Build Coastguard Worker     }
1150*bb4ee6a4SAndroid Build Coastguard Worker 
1151*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the value of a single model-specific register.
set_msr(&self, msr_index: u32, value: u64) -> Result<()>1152*bb4ee6a4SAndroid Build Coastguard Worker     fn set_msr(&self, msr_index: u32, value: u64) -> Result<()> {
1153*bb4ee6a4SAndroid Build Coastguard Worker         match get_msr_name(msr_index) {
1154*bb4ee6a4SAndroid Build Coastguard Worker             Some(msr_name) => {
1155*bb4ee6a4SAndroid Build Coastguard Worker                 let msr_value = WHV_REGISTER_VALUE { Reg64: value };
1156*bb4ee6a4SAndroid Build Coastguard Worker                 check_whpx!(unsafe {
1157*bb4ee6a4SAndroid Build Coastguard Worker                     WHvSetVirtualProcessorRegisters(
1158*bb4ee6a4SAndroid Build Coastguard Worker                         self.vm_partition.partition,
1159*bb4ee6a4SAndroid Build Coastguard Worker                         self.index,
1160*bb4ee6a4SAndroid Build Coastguard Worker                         &msr_name,
1161*bb4ee6a4SAndroid Build Coastguard Worker                         /* RegisterCount */ 1,
1162*bb4ee6a4SAndroid Build Coastguard Worker                         &msr_value,
1163*bb4ee6a4SAndroid Build Coastguard Worker                     )
1164*bb4ee6a4SAndroid Build Coastguard Worker                 })
1165*bb4ee6a4SAndroid Build Coastguard Worker             }
1166*bb4ee6a4SAndroid Build Coastguard Worker             None => {
1167*bb4ee6a4SAndroid Build Coastguard Worker                 warn!("msr 0x{msr_index:X} write unsupported by WHPX, dropping");
1168*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(())
1169*bb4ee6a4SAndroid Build Coastguard Worker             }
1170*bb4ee6a4SAndroid Build Coastguard Worker         }
1171*bb4ee6a4SAndroid Build Coastguard Worker     }
1172*bb4ee6a4SAndroid Build Coastguard Worker 
1173*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets up the data returned by the CPUID instruction.
1174*bb4ee6a4SAndroid Build Coastguard Worker     /// For WHPX, this is not valid on the vcpu, and needs to be setup on the vm.
set_cpuid(&self, _cpuid: &CpuId) -> Result<()>1175*bb4ee6a4SAndroid Build Coastguard Worker     fn set_cpuid(&self, _cpuid: &CpuId) -> Result<()> {
1176*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::new(ENXIO))
1177*bb4ee6a4SAndroid Build Coastguard Worker     }
1178*bb4ee6a4SAndroid Build Coastguard Worker 
1179*bb4ee6a4SAndroid Build Coastguard Worker     /// This function should be called after `Vcpu::run` returns `VcpuExit::Cpuid`, and `entry`
1180*bb4ee6a4SAndroid Build Coastguard Worker     /// should represent the result of emulating the CPUID instruction. The `handle_cpuid` function
1181*bb4ee6a4SAndroid Build Coastguard Worker     /// will then set the appropriate registers on the vcpu.
handle_cpuid(&mut self, entry: &CpuIdEntry) -> Result<()>1182*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_cpuid(&mut self, entry: &CpuIdEntry) -> Result<()> {
1183*bb4ee6a4SAndroid Build Coastguard Worker         // Verify that we're only being called in a situation where the last exit reason was
1184*bb4ee6a4SAndroid Build Coastguard Worker         // ExitReasonX64Cpuid
1185*bb4ee6a4SAndroid Build Coastguard Worker         if self.last_exit_context.ExitReason != WHV_RUN_VP_EXIT_REASON_WHvRunVpExitReasonX64Cpuid {
1186*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(EINVAL));
1187*bb4ee6a4SAndroid Build Coastguard Worker         }
1188*bb4ee6a4SAndroid Build Coastguard Worker 
1189*bb4ee6a4SAndroid Build Coastguard Worker         // Get the next rip from the exit context
1190*bb4ee6a4SAndroid Build Coastguard Worker         let rip = self.last_exit_context.VpContext.Rip
1191*bb4ee6a4SAndroid Build Coastguard Worker             + self.last_exit_context.VpContext.InstructionLength() as u64;
1192*bb4ee6a4SAndroid Build Coastguard Worker 
1193*bb4ee6a4SAndroid Build Coastguard Worker         const REG_NAMES: [WHV_REGISTER_NAME; 5] = [
1194*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_NAME_WHvX64RegisterRip,
1195*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_NAME_WHvX64RegisterRax,
1196*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_NAME_WHvX64RegisterRbx,
1197*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_NAME_WHvX64RegisterRcx,
1198*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_NAME_WHvX64RegisterRdx,
1199*bb4ee6a4SAndroid Build Coastguard Worker         ];
1200*bb4ee6a4SAndroid Build Coastguard Worker 
1201*bb4ee6a4SAndroid Build Coastguard Worker         let values = vec![
1202*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_VALUE { Reg64: rip },
1203*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_VALUE {
1204*bb4ee6a4SAndroid Build Coastguard Worker                 Reg64: entry.cpuid.eax as u64,
1205*bb4ee6a4SAndroid Build Coastguard Worker             },
1206*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_VALUE {
1207*bb4ee6a4SAndroid Build Coastguard Worker                 Reg64: entry.cpuid.ebx as u64,
1208*bb4ee6a4SAndroid Build Coastguard Worker             },
1209*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_VALUE {
1210*bb4ee6a4SAndroid Build Coastguard Worker                 Reg64: entry.cpuid.ecx as u64,
1211*bb4ee6a4SAndroid Build Coastguard Worker             },
1212*bb4ee6a4SAndroid Build Coastguard Worker             WHV_REGISTER_VALUE {
1213*bb4ee6a4SAndroid Build Coastguard Worker                 Reg64: entry.cpuid.edx as u64,
1214*bb4ee6a4SAndroid Build Coastguard Worker             },
1215*bb4ee6a4SAndroid Build Coastguard Worker         ];
1216*bb4ee6a4SAndroid Build Coastguard Worker 
1217*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we have enough space for all the registers
1218*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
1219*bb4ee6a4SAndroid Build Coastguard Worker             WHvSetVirtualProcessorRegisters(
1220*bb4ee6a4SAndroid Build Coastguard Worker                 self.vm_partition.partition,
1221*bb4ee6a4SAndroid Build Coastguard Worker                 self.index,
1222*bb4ee6a4SAndroid Build Coastguard Worker                 &REG_NAMES as *const WHV_REGISTER_NAME,
1223*bb4ee6a4SAndroid Build Coastguard Worker                 REG_NAMES.len() as u32,
1224*bb4ee6a4SAndroid Build Coastguard Worker                 values.as_ptr() as *const WHV_REGISTER_VALUE,
1225*bb4ee6a4SAndroid Build Coastguard Worker             )
1226*bb4ee6a4SAndroid Build Coastguard Worker         })
1227*bb4ee6a4SAndroid Build Coastguard Worker     }
1228*bb4ee6a4SAndroid Build Coastguard Worker 
1229*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets up debug registers and configure vcpu for handling guest debug events.
set_guest_debug(&self, _addrs: &[GuestAddress], _enable_singlestep: bool) -> Result<()>1230*bb4ee6a4SAndroid Build Coastguard Worker     fn set_guest_debug(&self, _addrs: &[GuestAddress], _enable_singlestep: bool) -> Result<()> {
1231*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/173807302): Implement this
1232*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::new(ENOENT))
1233*bb4ee6a4SAndroid Build Coastguard Worker     }
1234*bb4ee6a4SAndroid Build Coastguard Worker 
restore_timekeeping(&self, host_tsc_reference_moment: u64, tsc_offset: u64) -> Result<()>1235*bb4ee6a4SAndroid Build Coastguard Worker     fn restore_timekeeping(&self, host_tsc_reference_moment: u64, tsc_offset: u64) -> Result<()> {
1236*bb4ee6a4SAndroid Build Coastguard Worker         // Set the guest TSC such that it has the same TSC_OFFSET as it did at
1237*bb4ee6a4SAndroid Build Coastguard Worker         // the moment it was snapshotted. This is required for virtio-pvclock
1238*bb4ee6a4SAndroid Build Coastguard Worker         // to function correctly. (virtio-pvclock assumes the offset is fixed,
1239*bb4ee6a4SAndroid Build Coastguard Worker         // and adjusts CLOCK_BOOTTIME accordingly. It also hides the TSC jump
1240*bb4ee6a4SAndroid Build Coastguard Worker         // from CLOCK_MONOTONIC by setting the timebase.)
1241*bb4ee6a4SAndroid Build Coastguard Worker         self.set_tsc_value(host_tsc_reference_moment.wrapping_add(tsc_offset))
1242*bb4ee6a4SAndroid Build Coastguard Worker     }
1243*bb4ee6a4SAndroid Build Coastguard Worker }
1244*bb4ee6a4SAndroid Build Coastguard Worker 
get_msr_name(msr_index: u32) -> Option<WHV_REGISTER_NAME>1245*bb4ee6a4SAndroid Build Coastguard Worker fn get_msr_name(msr_index: u32) -> Option<WHV_REGISTER_NAME> {
1246*bb4ee6a4SAndroid Build Coastguard Worker     VALID_MSRS.get(&msr_index).copied()
1247*bb4ee6a4SAndroid Build Coastguard Worker }
1248*bb4ee6a4SAndroid Build Coastguard Worker 
1249*bb4ee6a4SAndroid Build Coastguard Worker // run calls are tested with the integration tests since the full vcpu needs to be setup for it.
1250*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
1251*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
1252*bb4ee6a4SAndroid Build Coastguard Worker     use vm_memory::GuestAddress;
1253*bb4ee6a4SAndroid Build Coastguard Worker     use vm_memory::GuestMemory;
1254*bb4ee6a4SAndroid Build Coastguard Worker 
1255*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
1256*bb4ee6a4SAndroid Build Coastguard Worker     use crate::VmX86_64;
1257*bb4ee6a4SAndroid Build Coastguard Worker 
new_vm(cpu_count: usize, mem: GuestMemory) -> WhpxVm1258*bb4ee6a4SAndroid Build Coastguard Worker     fn new_vm(cpu_count: usize, mem: GuestMemory) -> WhpxVm {
1259*bb4ee6a4SAndroid Build Coastguard Worker         let whpx = Whpx::new().expect("failed to instantiate whpx");
1260*bb4ee6a4SAndroid Build Coastguard Worker         let local_apic_supported = Whpx::check_whpx_feature(WhpxFeature::LocalApicEmulation)
1261*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to get whpx features");
1262*bb4ee6a4SAndroid Build Coastguard Worker         WhpxVm::new(
1263*bb4ee6a4SAndroid Build Coastguard Worker             &whpx,
1264*bb4ee6a4SAndroid Build Coastguard Worker             cpu_count,
1265*bb4ee6a4SAndroid Build Coastguard Worker             mem,
1266*bb4ee6a4SAndroid Build Coastguard Worker             CpuId::new(0),
1267*bb4ee6a4SAndroid Build Coastguard Worker             local_apic_supported,
1268*bb4ee6a4SAndroid Build Coastguard Worker             None,
1269*bb4ee6a4SAndroid Build Coastguard Worker         )
1270*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to create whpx vm")
1271*bb4ee6a4SAndroid Build Coastguard Worker     }
1272*bb4ee6a4SAndroid Build Coastguard Worker 
1273*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
try_clone()1274*bb4ee6a4SAndroid Build Coastguard Worker     fn try_clone() {
1275*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1276*bb4ee6a4SAndroid Build Coastguard Worker             return;
1277*bb4ee6a4SAndroid Build Coastguard Worker         }
1278*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1279*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1280*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1281*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1282*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1283*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu: &WhpxVcpu = vcpu.downcast_ref().expect("Expected a WhpxVcpu");
1284*bb4ee6a4SAndroid Build Coastguard Worker         let _vcpu_clone = vcpu.try_clone().expect("failed to clone whpx vcpu");
1285*bb4ee6a4SAndroid Build Coastguard Worker     }
1286*bb4ee6a4SAndroid Build Coastguard Worker 
1287*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
index()1288*bb4ee6a4SAndroid Build Coastguard Worker     fn index() {
1289*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1290*bb4ee6a4SAndroid Build Coastguard Worker             return;
1291*bb4ee6a4SAndroid Build Coastguard Worker         }
1292*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 2;
1293*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1294*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1295*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1296*bb4ee6a4SAndroid Build Coastguard Worker         let mut vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1297*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu0: &WhpxVcpu = vcpu.downcast_ref().expect("Expected a WhpxVcpu");
1298*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(vcpu0.index, 0);
1299*bb4ee6a4SAndroid Build Coastguard Worker         vcpu = vm.create_vcpu(1).expect("failed to create vcpu");
1300*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu1: &WhpxVcpu = vcpu.downcast_ref().expect("Expected a WhpxVcpu");
1301*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(vcpu1.index, 1);
1302*bb4ee6a4SAndroid Build Coastguard Worker     }
1303*bb4ee6a4SAndroid Build Coastguard Worker 
1304*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
get_regs()1305*bb4ee6a4SAndroid Build Coastguard Worker     fn get_regs() {
1306*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1307*bb4ee6a4SAndroid Build Coastguard Worker             return;
1308*bb4ee6a4SAndroid Build Coastguard Worker         }
1309*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1310*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1311*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1312*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1313*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1314*bb4ee6a4SAndroid Build Coastguard Worker 
1315*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.get_regs().expect("failed to get regs");
1316*bb4ee6a4SAndroid Build Coastguard Worker     }
1317*bb4ee6a4SAndroid Build Coastguard Worker 
1318*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
set_regs()1319*bb4ee6a4SAndroid Build Coastguard Worker     fn set_regs() {
1320*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1321*bb4ee6a4SAndroid Build Coastguard Worker             return;
1322*bb4ee6a4SAndroid Build Coastguard Worker         }
1323*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1324*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1325*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1326*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1327*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1328*bb4ee6a4SAndroid Build Coastguard Worker 
1329*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = vcpu.get_regs().expect("failed to get regs");
1330*bb4ee6a4SAndroid Build Coastguard Worker         let new_val = regs.rax + 2;
1331*bb4ee6a4SAndroid Build Coastguard Worker         regs.rax = new_val;
1332*bb4ee6a4SAndroid Build Coastguard Worker 
1333*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_regs(&regs).expect("failed to set regs");
1334*bb4ee6a4SAndroid Build Coastguard Worker         let new_regs = vcpu.get_regs().expect("failed to get regs");
1335*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(new_regs.rax, new_val);
1336*bb4ee6a4SAndroid Build Coastguard Worker     }
1337*bb4ee6a4SAndroid Build Coastguard Worker 
1338*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
debugregs()1339*bb4ee6a4SAndroid Build Coastguard Worker     fn debugregs() {
1340*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1341*bb4ee6a4SAndroid Build Coastguard Worker             return;
1342*bb4ee6a4SAndroid Build Coastguard Worker         }
1343*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1344*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1345*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1346*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1347*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1348*bb4ee6a4SAndroid Build Coastguard Worker 
1349*bb4ee6a4SAndroid Build Coastguard Worker         let mut dregs = vcpu.get_debugregs().unwrap();
1350*bb4ee6a4SAndroid Build Coastguard Worker         dregs.dr7 += 13;
1351*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_debugregs(&dregs).unwrap();
1352*bb4ee6a4SAndroid Build Coastguard Worker         let dregs2 = vcpu.get_debugregs().unwrap();
1353*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(dregs.dr7, dregs2.dr7);
1354*bb4ee6a4SAndroid Build Coastguard Worker     }
1355*bb4ee6a4SAndroid Build Coastguard Worker 
1356*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
sregs()1357*bb4ee6a4SAndroid Build Coastguard Worker     fn sregs() {
1358*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1359*bb4ee6a4SAndroid Build Coastguard Worker             return;
1360*bb4ee6a4SAndroid Build Coastguard Worker         }
1361*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1362*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1363*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1364*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1365*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1366*bb4ee6a4SAndroid Build Coastguard Worker 
1367*bb4ee6a4SAndroid Build Coastguard Worker         let mut sregs = vcpu.get_sregs().unwrap();
1368*bb4ee6a4SAndroid Build Coastguard Worker         sregs.cs.base += 7;
1369*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_sregs(&sregs).unwrap();
1370*bb4ee6a4SAndroid Build Coastguard Worker         let sregs2 = vcpu.get_sregs().unwrap();
1371*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sregs.cs.base, sregs2.cs.base);
1372*bb4ee6a4SAndroid Build Coastguard Worker     }
1373*bb4ee6a4SAndroid Build Coastguard Worker 
1374*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
fpu()1375*bb4ee6a4SAndroid Build Coastguard Worker     fn fpu() {
1376*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1377*bb4ee6a4SAndroid Build Coastguard Worker             return;
1378*bb4ee6a4SAndroid Build Coastguard Worker         }
1379*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1380*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1381*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1382*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1383*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1384*bb4ee6a4SAndroid Build Coastguard Worker 
1385*bb4ee6a4SAndroid Build Coastguard Worker         let mut fpu = vcpu.get_fpu().unwrap();
1386*bb4ee6a4SAndroid Build Coastguard Worker         fpu.fpr[0].significand += 3;
1387*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_fpu(&fpu).unwrap();
1388*bb4ee6a4SAndroid Build Coastguard Worker         let fpu2 = vcpu.get_fpu().unwrap();
1389*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(fpu.fpr, fpu2.fpr);
1390*bb4ee6a4SAndroid Build Coastguard Worker     }
1391*bb4ee6a4SAndroid Build Coastguard Worker 
1392*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
xcrs()1393*bb4ee6a4SAndroid Build Coastguard Worker     fn xcrs() {
1394*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1395*bb4ee6a4SAndroid Build Coastguard Worker             return;
1396*bb4ee6a4SAndroid Build Coastguard Worker         }
1397*bb4ee6a4SAndroid Build Coastguard Worker         let whpx = Whpx::new().expect("failed to instantiate whpx");
1398*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1399*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1400*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1401*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1402*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1403*bb4ee6a4SAndroid Build Coastguard Worker         // check xsave support
1404*bb4ee6a4SAndroid Build Coastguard Worker         if !whpx.check_capability(HypervisorCap::Xcrs) {
1405*bb4ee6a4SAndroid Build Coastguard Worker             return;
1406*bb4ee6a4SAndroid Build Coastguard Worker         }
1407*bb4ee6a4SAndroid Build Coastguard Worker 
1408*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_xcr(0, 1).unwrap();
1409*bb4ee6a4SAndroid Build Coastguard Worker         let xcrs = vcpu.get_xcrs().unwrap();
1410*bb4ee6a4SAndroid Build Coastguard Worker         let xcr0 = xcrs.get(&0).unwrap();
1411*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*xcr0, 1);
1412*bb4ee6a4SAndroid Build Coastguard Worker     }
1413*bb4ee6a4SAndroid Build Coastguard Worker 
1414*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
set_msr()1415*bb4ee6a4SAndroid Build Coastguard Worker     fn set_msr() {
1416*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1417*bb4ee6a4SAndroid Build Coastguard Worker             return;
1418*bb4ee6a4SAndroid Build Coastguard Worker         }
1419*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1420*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1421*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1422*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1423*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1424*bb4ee6a4SAndroid Build Coastguard Worker 
1425*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_msr(MSR_KERNEL_GS_BASE, 42).unwrap();
1426*bb4ee6a4SAndroid Build Coastguard Worker 
1427*bb4ee6a4SAndroid Build Coastguard Worker         let gs_base = vcpu.get_msr(MSR_KERNEL_GS_BASE).unwrap();
1428*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(gs_base, 42);
1429*bb4ee6a4SAndroid Build Coastguard Worker     }
1430*bb4ee6a4SAndroid Build Coastguard Worker 
1431*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
get_msr()1432*bb4ee6a4SAndroid Build Coastguard Worker     fn get_msr() {
1433*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1434*bb4ee6a4SAndroid Build Coastguard Worker             return;
1435*bb4ee6a4SAndroid Build Coastguard Worker         }
1436*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1437*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1438*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1439*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1440*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1441*bb4ee6a4SAndroid Build Coastguard Worker 
1442*bb4ee6a4SAndroid Build Coastguard Worker         // This one should succeed
1443*bb4ee6a4SAndroid Build Coastguard Worker         let _value = vcpu.get_msr(MSR_TSC).unwrap();
1444*bb4ee6a4SAndroid Build Coastguard Worker 
1445*bb4ee6a4SAndroid Build Coastguard Worker         // This one will fail to fetch
1446*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.get_msr(MSR_TSC + 1)
1447*bb4ee6a4SAndroid Build Coastguard Worker             .expect_err("invalid MSR index should fail");
1448*bb4ee6a4SAndroid Build Coastguard Worker     }
1449*bb4ee6a4SAndroid Build Coastguard Worker 
1450*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
set_efer()1451*bb4ee6a4SAndroid Build Coastguard Worker     fn set_efer() {
1452*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1453*bb4ee6a4SAndroid Build Coastguard Worker             return;
1454*bb4ee6a4SAndroid Build Coastguard Worker         }
1455*bb4ee6a4SAndroid Build Coastguard Worker         // EFER Bits
1456*bb4ee6a4SAndroid Build Coastguard Worker         const EFER_SCE: u64 = 0x00000001;
1457*bb4ee6a4SAndroid Build Coastguard Worker         const EFER_LME: u64 = 0x00000100;
1458*bb4ee6a4SAndroid Build Coastguard Worker         const EFER_LMA: u64 = 0x00000400;
1459*bb4ee6a4SAndroid Build Coastguard Worker         const X86_CR0_PE: u64 = 0x1;
1460*bb4ee6a4SAndroid Build Coastguard Worker         const X86_CR0_PG: u64 = 0x80000000;
1461*bb4ee6a4SAndroid Build Coastguard Worker         const X86_CR4_PAE: u64 = 0x20;
1462*bb4ee6a4SAndroid Build Coastguard Worker 
1463*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1464*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1465*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1466*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1467*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1468*bb4ee6a4SAndroid Build Coastguard Worker 
1469*bb4ee6a4SAndroid Build Coastguard Worker         let mut sregs = vcpu.get_sregs().expect("failed to get sregs");
1470*bb4ee6a4SAndroid Build Coastguard Worker         // Initial value should be 0
1471*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sregs.efer, 0);
1472*bb4ee6a4SAndroid Build Coastguard Worker 
1473*bb4ee6a4SAndroid Build Coastguard Worker         // Enable and activate long mode
1474*bb4ee6a4SAndroid Build Coastguard Worker         sregs.cr0 |= X86_CR0_PE; // enable protected mode
1475*bb4ee6a4SAndroid Build Coastguard Worker         sregs.cr0 |= X86_CR0_PG; // enable paging
1476*bb4ee6a4SAndroid Build Coastguard Worker         sregs.cr4 |= X86_CR4_PAE; // enable physical address extension
1477*bb4ee6a4SAndroid Build Coastguard Worker         sregs.efer = EFER_LMA | EFER_LME;
1478*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_sregs(&sregs).expect("failed to set sregs");
1479*bb4ee6a4SAndroid Build Coastguard Worker 
1480*bb4ee6a4SAndroid Build Coastguard Worker         // Verify that setting stuck
1481*bb4ee6a4SAndroid Build Coastguard Worker         let sregs = vcpu.get_sregs().expect("failed to get sregs");
1482*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sregs.efer, EFER_LMA | EFER_LME);
1483*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sregs.cr0 & X86_CR0_PE, X86_CR0_PE);
1484*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sregs.cr0 & X86_CR0_PG, X86_CR0_PG);
1485*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sregs.cr4 & X86_CR4_PAE, X86_CR4_PAE);
1486*bb4ee6a4SAndroid Build Coastguard Worker 
1487*bb4ee6a4SAndroid Build Coastguard Worker         let efer = vcpu.get_msr(MSR_EFER).expect("failed to get msr");
1488*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(efer, EFER_LMA | EFER_LME);
1489*bb4ee6a4SAndroid Build Coastguard Worker 
1490*bb4ee6a4SAndroid Build Coastguard Worker         // Enable SCE via set_msrs
1491*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_msr(MSR_EFER, efer | EFER_SCE)
1492*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to set msr");
1493*bb4ee6a4SAndroid Build Coastguard Worker 
1494*bb4ee6a4SAndroid Build Coastguard Worker         // Verify that setting stuck
1495*bb4ee6a4SAndroid Build Coastguard Worker         let sregs = vcpu.get_sregs().expect("failed to get sregs");
1496*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sregs.efer, EFER_SCE | EFER_LME | EFER_LMA);
1497*bb4ee6a4SAndroid Build Coastguard Worker         let new_efer = vcpu.get_msr(MSR_EFER).expect("failed to get msr");
1498*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(new_efer, EFER_SCE | EFER_LME | EFER_LMA);
1499*bb4ee6a4SAndroid Build Coastguard Worker     }
1500*bb4ee6a4SAndroid Build Coastguard Worker 
1501*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
get_and_set_xsave_smoke()1502*bb4ee6a4SAndroid Build Coastguard Worker     fn get_and_set_xsave_smoke() {
1503*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1504*bb4ee6a4SAndroid Build Coastguard Worker             return;
1505*bb4ee6a4SAndroid Build Coastguard Worker         }
1506*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1507*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1508*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1509*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1510*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1511*bb4ee6a4SAndroid Build Coastguard Worker 
1512*bb4ee6a4SAndroid Build Coastguard Worker         // XSAVE is essentially opaque for our purposes. We just want to make sure our syscalls
1513*bb4ee6a4SAndroid Build Coastguard Worker         // succeed.
1514*bb4ee6a4SAndroid Build Coastguard Worker         let xsave = vcpu.get_xsave().unwrap();
1515*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_xsave(&xsave).unwrap();
1516*bb4ee6a4SAndroid Build Coastguard Worker     }
1517*bb4ee6a4SAndroid Build Coastguard Worker 
1518*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
get_and_set_interrupt_state_smoke()1519*bb4ee6a4SAndroid Build Coastguard Worker     fn get_and_set_interrupt_state_smoke() {
1520*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1521*bb4ee6a4SAndroid Build Coastguard Worker             return;
1522*bb4ee6a4SAndroid Build Coastguard Worker         }
1523*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1524*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1525*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1526*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1527*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1528*bb4ee6a4SAndroid Build Coastguard Worker 
1529*bb4ee6a4SAndroid Build Coastguard Worker         // For the sake of snapshotting, interrupt state is essentially opaque. We just want to make
1530*bb4ee6a4SAndroid Build Coastguard Worker         // sure our syscalls succeed.
1531*bb4ee6a4SAndroid Build Coastguard Worker         let interrupt_state = vcpu.get_interrupt_state().unwrap();
1532*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_interrupt_state(interrupt_state).unwrap();
1533*bb4ee6a4SAndroid Build Coastguard Worker     }
1534*bb4ee6a4SAndroid Build Coastguard Worker 
1535*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
get_all_msrs()1536*bb4ee6a4SAndroid Build Coastguard Worker     fn get_all_msrs() {
1537*bb4ee6a4SAndroid Build Coastguard Worker         if !Whpx::is_enabled() {
1538*bb4ee6a4SAndroid Build Coastguard Worker             return;
1539*bb4ee6a4SAndroid Build Coastguard Worker         }
1540*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_count = 1;
1541*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
1542*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
1543*bb4ee6a4SAndroid Build Coastguard Worker         let vm = new_vm(cpu_count, mem);
1544*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
1545*bb4ee6a4SAndroid Build Coastguard Worker 
1546*bb4ee6a4SAndroid Build Coastguard Worker         let all_msrs = vcpu.get_all_msrs().unwrap();
1547*bb4ee6a4SAndroid Build Coastguard Worker 
1548*bb4ee6a4SAndroid Build Coastguard Worker         // Our MSR buffer is init'ed to zeros in the registers. The APIC base will be non-zero, so
1549*bb4ee6a4SAndroid Build Coastguard Worker         // by asserting that we know the MSR fetch actually did get us data.
1550*bb4ee6a4SAndroid Build Coastguard Worker         let apic_base = all_msrs.get(&MSR_APIC_BASE).unwrap();
1551*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(*apic_base, 0);
1552*bb4ee6a4SAndroid Build Coastguard Worker     }
1553*bb4ee6a4SAndroid Build Coastguard Worker }
1554