diff options
author | Dmitry Torokhov <dtor@chromium.org> | 2018-05-14 12:21:31 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-05-16 05:08:21 -0700 |
commit | 6051e7593a612d45549662b84a74c131b95c1af6 (patch) | |
tree | 33eaad4e7a82890d604fb760516906d08f124358 /kvm/src/lib.rs | |
parent | 6526fbfd4f352294b42835536cf8c784aea668c0 (diff) | |
download | crosvm-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.rs | 47 |
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(); |