summary refs log tree commit diff
path: root/kvm/src/lib.rs
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@chromium.org>2018-05-14 12:21:31 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-05-16 05:08:21 -0700
commit6051e7593a612d45549662b84a74c131b95c1af6 (patch)
tree33eaad4e7a82890d604fb760516906d08f124358 /kvm/src/lib.rs
parent6526fbfd4f352294b42835536cf8c784aea668c0 (diff)
downloadcrosvm-6051e7593a612d45549662b84a74c131b95c1af6.tar
crosvm-6051e7593a612d45549662b84a74c131b95c1af6.tar.gz
crosvm-6051e7593a612d45549662b84a74c131b95c1af6.tar.bz2
crosvm-6051e7593a612d45549662b84a74c131b95c1af6.tar.lz
crosvm-6051e7593a612d45549662b84a74c131b95c1af6.tar.xz
crosvm-6051e7593a612d45549662b84a74c131b95c1af6.tar.zst
crosvm-6051e7593a612d45549662b84a74c131b95c1af6.zip
kvm: plumb accessors for VCPU XCR state
Plumb in KVM_GET_XCRS and KVM_SET_XCRS to allow saving and restoring
extended control registers of VCPUs.

BUG=b:79692549
TEST=cargo test -p kvm

Change-Id: I77dcb2ac488bf73b7503f49875d91e7c0cb21003
Signed-off-by: Dmitry Torokhov <dtor@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1060613
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'kvm/src/lib.rs')
-rw-r--r--kvm/src/lib.rs47
1 files changed, 47 insertions, 0 deletions
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs
index 5f321f2..2fdac43 100644
--- a/kvm/src/lib.rs
+++ b/kvm/src/lib.rs
@@ -1007,6 +1007,32 @@ impl Vcpu {
         Ok(())
     }
 
+    /// Gets the VCPU extended control registers
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    pub fn get_xcrs(&self) -> Result<kvm_xcrs> {
+        // Safe because we know that our file is a VCPU fd, we know the kernel will only write the
+        // correct amount of memory to our pointer, and we verify the return result.
+        let mut regs = unsafe { std::mem::zeroed() };
+        let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_XCRS(), &mut regs) };
+        if ret != 0 {
+            return errno_result();
+        }
+        Ok(regs)
+    }
+
+    /// Sets the VCPU extended control registers
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    pub fn set_xcrs(&self, xcrs: &kvm_xcrs) -> Result<()> {
+        let ret = unsafe {
+            // Here we trust the kernel not to read past the end of the kvm_xcrs struct.
+            ioctl_with_ref(self, KVM_SET_XCRS(), xcrs)
+        };
+        if ret < 0 {
+            return errno_result();
+        }
+        Ok(())
+    }
+
     /// X86 specific call to get the MSRS
     ///
     /// See the documentation for KVM_SET_MSRS.
@@ -1559,6 +1585,27 @@ mod tests {
 
     #[test]
     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    fn xcrs() {
+        let kvm = Kvm::new().unwrap();
+        if kvm.check_extension(Cap::Xcrs) {
+            return;
+        }
+
+        let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();
+        let vm = Vm::new(&kvm, gm).unwrap();
+        let vcpu = Vcpu::new(0, &kvm, &vm).unwrap();
+        let mut xcrs = vcpu.get_xcrs().unwrap();
+        xcrs.nr_xcrs = 1;
+        xcrs.flags = 0;
+        // We assume anything we run on has SSE (bit 1). FP bit (bit 0) must always be set.
+        xcrs.xcrs[0].value |= 3;
+        vcpu.set_xcrs(&xcrs).unwrap();
+        let xcrs2 = vcpu.get_xcrs().unwrap();
+        assert_eq!(xcrs.xcrs[0].value, xcrs2.xcrs[0].value);
+    }
+
+    #[test]
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
     fn get_msrs() {
         let kvm = Kvm::new().unwrap();
         let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();