From c350eee33b7a95dc1ff690be8a99af2caf2722de Mon Sep 17 00:00:00 2001 From: Noah Gold Date: Fri, 19 May 2023 11:44:33 -0700 Subject: [PATCH] hypervisor: implement blanket MSR fetch for WHPX. For snapshotting, we want to save/restore *all* MSRs rather than a one or two specific MSRs. To accomplish this, we're implementing get_all_msrs for WHPX. BUG=b:269705560 TEST=unit tests Change-Id: I706c3bd1d9d11ca58c709e1a19e0184dc560f193 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4546271 Commit-Queue: Noah Gold Reviewed-by: Richard Zhang Reviewed-by: Frederick Mayle --- hypervisor/src/whpx/vcpu.rs | 60 +++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/hypervisor/src/whpx/vcpu.rs b/hypervisor/src/whpx/vcpu.rs index 61c27e9af8..738e86a13c 100644 --- a/hypervisor/src/whpx/vcpu.rs +++ b/hypervisor/src/whpx/vcpu.rs @@ -14,7 +14,6 @@ use libc::EINVAL; use libc::EIO; use libc::ENOENT; use libc::ENXIO; -use libc::EOPNOTSUPP; use vm_memory::GuestAddress; use winapi::shared::winerror::E_UNEXPECTED; use windows::Win32::Foundation::WHV_E_INSUFFICIENT_BUFFER; @@ -1157,9 +1156,64 @@ impl VcpuX86_64 for WhpxVcpu { Ok(()) } - // TODO: b/270734340 implement fn get_all_msrs(&self) -> Result> { - Err(Error::new(EOPNOTSUPP)) + // Note that some members of VALID_MSRS cannot be fetched from WHPX with + // WHvGetVirtualProcessorRegisters per the HTLFS, so we enumerate all of + // permitted MSRs here. + // + // We intentionally exclude WHvRegisterPendingInterruption and + // WHvRegisterInterruptState because they are included in + // get_interrupt_state. + // + // We also exclude MSR_TSC, because on WHPX, we will use virtio-pvclock + // to restore the guest clocks. Note that this will be *guest aware* + // snapshotting. We may in the future add guest unaware snapshotting + // for Windows, in which case we will want to save/restore TSC such that + // the guest does not observe any change. + let mut registers = vec![ + Register { + id: MSR_EFER, + ..Default::default() + }, + Register { + id: MSR_KERNEL_GS_BASE, + ..Default::default() + }, + Register { + id: MSR_APIC_BASE, + ..Default::default() + }, + Register { + id: MSR_SYSENTER_CS, + ..Default::default() + }, + Register { + id: MSR_SYSENTER_EIP, + ..Default::default() + }, + Register { + id: MSR_SYSENTER_ESP, + ..Default::default() + }, + Register { + id: MSR_STAR, + ..Default::default() + }, + Register { + id: MSR_LSTAR, + ..Default::default() + }, + Register { + id: MSR_CSTAR, + ..Default::default() + }, + Register { + id: MSR_SFMASK, + ..Default::default() + }, + ]; + self.get_msrs(&mut registers)?; + Ok(registers) } /// Sets the model-specific registers.