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 ®_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 ®_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 ®_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 ®_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 ®_NAMES as *const WHV_REGISTER_NAME,
737*bb4ee6a4SAndroid Build Coastguard Worker REG_NAMES.len() as u32,
738*bb4ee6a4SAndroid Build Coastguard Worker ¬ify_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 ®_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 ®_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 ®_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 ®_NAME,
1088*bb4ee6a4SAndroid Build Coastguard Worker /* RegisterCount */ 1,
1089*bb4ee6a4SAndroid Build Coastguard Worker ®_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 ®_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(®s).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