mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 10:10:41 +00:00
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>
This commit is contained in:
parent
6526fbfd4f
commit
6051e7593a
1 changed files with 47 additions and 0 deletions
|
@ -1007,6 +1007,32 @@ impl Vcpu {
|
||||||
Ok(())
|
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
|
/// X86 specific call to get the MSRS
|
||||||
///
|
///
|
||||||
/// See the documentation for KVM_SET_MSRS.
|
/// See the documentation for KVM_SET_MSRS.
|
||||||
|
@ -1557,6 +1583,27 @@ mod tests {
|
||||||
assert_eq!(dregs.dr7, dregs2.dr7);
|
assert_eq!(dregs.dr7, dregs2.dr7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[test]
|
||||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
fn get_msrs() {
|
fn get_msrs() {
|
||||||
|
|
Loading…
Reference in a new issue