From 6a8c0fc88734d07cda142d4bfb88b0fb4e3964f6 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 15 Jul 2022 12:35:10 +0000 Subject: [PATCH] hypervisor: provide a generic FpuState structure Signed-off-by: Wei Liu --- arch/src/x86_64/regs.rs | 3 +-- hypervisor/src/arch/x86/mod.rs | 13 +++++++++++ hypervisor/src/cpu.rs | 4 ++-- hypervisor/src/kvm/mod.rs | 15 ++++++++----- hypervisor/src/kvm/x86_64/mod.rs | 37 +++++++++++++++++++++++++++++-- hypervisor/src/mshv/mod.rs | 11 +++++---- hypervisor/src/mshv/x86_64/mod.rs | 37 +++++++++++++++++++++++++++++-- vmm/src/cpu.rs | 4 ++-- 8 files changed, 105 insertions(+), 19 deletions(-) diff --git a/arch/src/x86_64/regs.rs b/arch/src/x86_64/regs.rs index f4ea570c6..1bb2af994 100644 --- a/arch/src/x86_64/regs.rs +++ b/arch/src/x86_64/regs.rs @@ -10,8 +10,7 @@ use crate::layout::{BOOT_GDT_START, BOOT_IDT_START, PVH_INFO_START}; use crate::GuestMemoryMmap; use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt}; use hypervisor::arch::x86::regs::CR0_PE; -use hypervisor::arch::x86::{SpecialRegisters, StandardRegisters}; -use hypervisor::x86_64::FpuState; +use hypervisor::arch::x86::{FpuState, SpecialRegisters, StandardRegisters}; use std::sync::Arc; use std::{mem, result}; use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError}; diff --git a/hypervisor/src/arch/x86/mod.rs b/hypervisor/src/arch/x86/mod.rs index 034edd759..32751715f 100644 --- a/hypervisor/src/arch/x86/mod.rs +++ b/hypervisor/src/arch/x86/mod.rs @@ -241,3 +241,16 @@ pub struct CpuIdEntry { } pub const CPUID_FLAG_VALID_INDEX: u32 = 1; + +#[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct FpuState { + pub fpr: [[u8; 16usize]; 8usize], + pub fcw: u16, + pub fsw: u16, + pub ftwx: u8, + pub last_opcode: u16, + pub last_ip: u64, + pub last_dp: u64, + pub xmm: [[u8; 16usize]; 16usize], + pub mxcsr: u32, +} diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index 6ec8cf2cd..251a2bc46 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -13,7 +13,7 @@ use crate::aarch64::VcpuInit; #[cfg(target_arch = "aarch64")] use crate::aarch64::{RegList, Register, StandardRegisters}; #[cfg(target_arch = "x86_64")] -use crate::arch::x86::{CpuIdEntry, SpecialRegisters, StandardRegisters}; +use crate::arch::x86::{CpuIdEntry, FpuState, SpecialRegisters, StandardRegisters}; #[cfg(feature = "tdx")] use crate::kvm::{TdxExitDetails, TdxExitStatus}; #[cfg(target_arch = "x86_64")] @@ -21,7 +21,7 @@ use crate::x86_64::LapicState; #[cfg(target_arch = "x86_64")] use crate::x86_64::Xsave; #[cfg(target_arch = "x86_64")] -use crate::x86_64::{ExtendedControlRegisters, FpuState, MsrEntries, VcpuEvents}; +use crate::x86_64::{ExtendedControlRegisters, MsrEntries, VcpuEvents}; use crate::CpuState; #[cfg(target_arch = "aarch64")] use crate::DeviceAttr; diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index ca547f009..19c328456 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -46,7 +46,9 @@ use vmm_sys_util::eventfd::EventFd; #[cfg(target_arch = "x86_64")] pub mod x86_64; #[cfg(target_arch = "x86_64")] -use crate::arch::x86::{CpuIdEntry, SpecialRegisters, StandardRegisters, NUM_IOAPIC_PINS}; +use crate::arch::x86::{ + CpuIdEntry, FpuState, SpecialRegisters, StandardRegisters, NUM_IOAPIC_PINS, +}; #[cfg(target_arch = "x86_64")] use crate::ClockData; use crate::{ @@ -61,7 +63,7 @@ use kvm_bindings::{ KVM_CAP_SPLIT_IRQCHIP, KVM_GUESTDBG_ENABLE, KVM_GUESTDBG_SINGLESTEP, KVM_GUESTDBG_USE_HW_BP, }; #[cfg(target_arch = "x86_64")] -use x86_64::{check_required_kvm_extensions, FpuState}; +use x86_64::check_required_kvm_extensions; #[cfg(target_arch = "x86_64")] pub use x86_64::{CpuId, ExtendedControlRegisters, LapicState, MsrEntries, VcpuKvmState, Xsave}; // aarch64 dependencies @@ -1306,17 +1308,20 @@ impl cpu::Vcpu for KvmVcpu { /// Returns the floating point state (FPU) from the vCPU. /// fn get_fpu(&self) -> cpu::Result { - self.fd + Ok(self + .fd .get_fpu() - .map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into())) + .map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))? + .into()) } #[cfg(target_arch = "x86_64")] /// /// Set the floating point state (FPU) of a vCPU using the `KVM_SET_FPU` ioct. /// fn set_fpu(&self, fpu: &FpuState) -> cpu::Result<()> { + let fpu: kvm_bindings::kvm_fpu = (*fpu).clone().into(); self.fd - .set_fpu(fpu) + .set_fpu(&fpu) .map_err(|e| cpu::HypervisorCpuError::SetFloatingPointRegs(e.into())) } #[cfg(target_arch = "x86_64")] diff --git a/hypervisor/src/kvm/x86_64/mod.rs b/hypervisor/src/kvm/x86_64/mod.rs index 83befa195..12df38771 100644 --- a/hypervisor/src/kvm/x86_64/mod.rs +++ b/hypervisor/src/kvm/x86_64/mod.rs @@ -9,7 +9,7 @@ // use crate::arch::x86::{ - CpuIdEntry, DescriptorTable, SegmentRegister, SpecialRegisters, StandardRegisters, + CpuIdEntry, DescriptorTable, FpuState, SegmentRegister, SpecialRegisters, StandardRegisters, CPUID_FLAG_VALID_INDEX, }; use crate::kvm::{Cap, Kvm, KvmError, KvmResult}; @@ -19,7 +19,7 @@ use serde::{Deserialize, Serialize}; /// Export generically-named wrappers of kvm-bindings for Unix-based platforms /// pub use { - kvm_bindings::kvm_cpuid_entry2, kvm_bindings::kvm_dtable, kvm_bindings::kvm_fpu as FpuState, + kvm_bindings::kvm_cpuid_entry2, kvm_bindings::kvm_dtable, kvm_bindings::kvm_fpu, kvm_bindings::kvm_lapic_state as LapicState, kvm_bindings::kvm_mp_state as MpState, kvm_bindings::kvm_msr_entry as MsrEntry, kvm_bindings::kvm_regs, kvm_bindings::kvm_segment, kvm_bindings::kvm_sregs, kvm_bindings::kvm_vcpu_events as VcpuEvents, @@ -262,3 +262,36 @@ impl From for CpuIdEntry { } } } + +impl From for FpuState { + fn from(s: kvm_fpu) -> Self { + Self { + fpr: s.fpr, + fcw: s.fcw, + fsw: s.fsw, + ftwx: s.ftwx, + last_opcode: s.last_opcode, + last_ip: s.last_ip, + last_dp: s.last_dp, + xmm: s.xmm, + mxcsr: s.mxcsr, + } + } +} + +impl From for kvm_fpu { + fn from(s: FpuState) -> Self { + Self { + fpr: s.fpr, + fcw: s.fcw, + fsw: s.fsw, + ftwx: s.ftwx, + last_opcode: s.last_opcode, + last_ip: s.last_ip, + last_dp: s.last_dp, + xmm: s.xmm, + mxcsr: s.mxcsr, + ..Default::default() + } + } +} diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index f9571189f..84d48f6c8 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -37,7 +37,7 @@ use std::fs::File; use std::os::unix::io::AsRawFd; #[cfg(target_arch = "x86_64")] -use crate::arch::x86::{CpuIdEntry, SpecialRegisters, StandardRegisters}; +use crate::arch::x86::{CpuIdEntry, FpuState, SpecialRegisters, StandardRegisters}; const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4; const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8; @@ -317,17 +317,20 @@ impl cpu::Vcpu for MshvVcpu { /// Returns the floating point state (FPU) from the vCPU. /// fn get_fpu(&self) -> cpu::Result { - self.fd + Ok(self + .fd .get_fpu() - .map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into())) + .map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))? + .into()) } #[cfg(target_arch = "x86_64")] /// /// Set the floating point state (FPU) of a vCPU. /// fn set_fpu(&self, fpu: &FpuState) -> cpu::Result<()> { + let fpu: mshv_bindings::FloatingPointUnit = (*fpu).clone().into(); self.fd - .set_fpu(fpu) + .set_fpu(&fpu) .map_err(|e| cpu::HypervisorCpuError::SetFloatingPointRegs(e.into())) } diff --git a/hypervisor/src/mshv/x86_64/mod.rs b/hypervisor/src/mshv/x86_64/mod.rs index 19f53ca8b..d1cc9b0ba 100644 --- a/hypervisor/src/mshv/x86_64/mod.rs +++ b/hypervisor/src/mshv/x86_64/mod.rs @@ -8,7 +8,7 @@ // // use crate::arch::x86::{ - CpuIdEntry, DescriptorTable, SegmentRegister, SpecialRegisters, StandardRegisters, + CpuIdEntry, DescriptorTable, FpuState, SegmentRegister, SpecialRegisters, StandardRegisters, }; use serde::{Deserialize, Serialize}; use std::fmt; @@ -19,7 +19,7 @@ use std::fmt; pub use { mshv_bindings::hv_cpuid_entry, mshv_bindings::mshv_user_mem_region as MemoryRegion, mshv_bindings::msr_entry as MsrEntry, mshv_bindings::CpuId, mshv_bindings::DebugRegisters, - mshv_bindings::FloatingPointUnit as FpuState, mshv_bindings::LapicState, + mshv_bindings::FloatingPointUnit, mshv_bindings::LapicState, mshv_bindings::MiscRegs as MiscRegisters, mshv_bindings::MsrList, mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs, mshv_bindings::SegmentRegister as MshvSegmentRegister, @@ -252,3 +252,36 @@ impl From for CpuIdEntry { } } } + +impl From for FpuState { + fn from(s: FloatingPointUnit) -> Self { + Self { + fpr: s.fpr, + fcw: s.fcw, + fsw: s.fsw, + ftwx: s.ftwx, + last_opcode: s.last_opcode, + last_ip: s.last_ip, + last_dp: s.last_dp, + xmm: s.xmm, + mxcsr: s.mxcsr, + } + } +} + +impl From for FloatingPointUnit { + fn from(s: FpuState) -> Self { + Self { + fpr: s.fpr, + fcw: s.fcw, + fsw: s.fsw, + ftwx: s.ftwx, + last_opcode: s.last_opcode, + last_ip: s.last_ip, + last_dp: s.last_dp, + xmm: s.xmm, + mxcsr: s.mxcsr, + ..Default::default() + } + } +} diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index c0aa1f9f5..a80a36c57 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -2336,8 +2336,8 @@ impl CpuElf64Writable for CpuManager { mod tests { use arch::x86_64::interrupts::*; use arch::x86_64::regs::*; - use hypervisor::arch::x86::StandardRegisters; - use hypervisor::x86_64::{FpuState, LapicState}; + use hypervisor::arch::x86::{FpuState, StandardRegisters}; + use hypervisor::x86_64::LapicState; #[test] fn test_setlint() {