diff --git a/alioth/src/hv/hv.rs b/alioth/src/hv/hv.rs index 037d3d6a..6858d0ad 100644 --- a/alioth/src/hv/hv.rs +++ b/alioth/src/hv/hv.rs @@ -87,6 +87,12 @@ pub enum Error { #[cfg(target_arch = "x86_64")] #[snafu(display("Failed to configure guest MSRs"))] GuestMsr { error: std::io::Error }, + #[cfg(target_arch = "x86_64")] + #[snafu(display("Failed to configure guest XSAVE"))] + GuestXsave { error: std::io::Error }, + #[cfg(target_arch = "x86_64")] + #[snafu(display("Failed to configure guest local APIC"))] + GuestLapic { error: std::io::Error }, #[snafu(display("Failed to configure memory encryption"))] MemEncrypt { error: std::io::Error }, #[snafu(display("Failed to configure an IrqFd"))] @@ -210,6 +216,16 @@ pub trait Vcpu { #[cfg(target_arch = "x86_64")] fn set_msrs(&mut self, msrs: &[(Msr, u64)]) -> Result<()>; + #[cfg(target_arch = "x86_64")] + fn get_xsave(&self, xsave: &mut [u32; 1024]) -> Result<()>; + #[cfg(target_arch = "x86_64")] + fn set_xsave(&mut self, xsave: &[u32; 1024]) -> Result<()>; + + #[cfg(target_arch = "x86_64")] + fn get_lapic(&self, lapic: &mut [u32; 256]) -> Result<()>; + #[cfg(target_arch = "x86_64")] + fn set_lapic(&mut self, lapic: &[u32; 256]) -> Result<()>; + fn dump(&self) -> Result<(), Error>; #[cfg(target_arch = "aarch64")] diff --git a/alioth/src/hv/kvm/vcpu/vcpu.rs b/alioth/src/hv/kvm/vcpu/vcpu.rs index 825f0c8a..934621a4 100644 --- a/alioth/src/hv/kvm/vcpu/vcpu.rs +++ b/alioth/src/hv/kvm/vcpu/vcpu.rs @@ -233,6 +233,26 @@ impl Vcpu for KvmVcpu { self.kvm_set_msrs(msrs) } + #[cfg(target_arch = "x86_64")] + fn get_xsave(&self, xsave: &mut [u32; 1024]) -> Result<()> { + self.kvm_get_xsave(xsave) + } + + #[cfg(target_arch = "x86_64")] + fn set_xsave(&mut self, xsave: &[u32; 1024]) -> Result<()> { + self.kvm_set_xsave(xsave) + } + + #[cfg(target_arch = "x86_64")] + fn get_lapic(&self, lapic: &mut [u32; 256]) -> Result<()> { + self.kvm_get_lapic(lapic) + } + + #[cfg(target_arch = "x86_64")] + fn set_lapic(&mut self, lapic: &[u32; 256]) -> Result<()> { + self.kvm_set_lapic(lapic) + } + fn dump(&self) -> Result<(), Error> { Ok(()) } diff --git a/alioth/src/hv/kvm/vcpu/vcpu_amd64/vcpu_amd64.rs b/alioth/src/hv/kvm/vcpu/vcpu_amd64/vcpu_amd64.rs index 77081eca..74499df1 100644 --- a/alioth/src/hv/kvm/vcpu/vcpu_amd64/vcpu_amd64.rs +++ b/alioth/src/hv/kvm/vcpu/vcpu_amd64/vcpu_amd64.rs @@ -20,6 +20,7 @@ use std::iter::zip; use std::os::fd::{FromRawFd, OwnedFd}; use snafu::ResultExt; +use zerocopy::{transmute_mut, transmute_ref}; use crate::arch::cpuid::CpuidIn; use crate::arch::msr::{Efer, Msr}; @@ -30,8 +31,9 @@ use crate::hv::kvm::vm::KvmVm; use crate::hv::{Error, Result, error}; use crate::sys::kvm::{ KVM_MAX_CPUID_ENTRIES, KvmCpuid2, KvmCpuid2Flag, KvmCpuidEntry2, KvmMsrEntry, KvmMsrs, KvmRegs, - MAX_IO_MSRS, kvm_create_vcpu, kvm_get_regs, kvm_get_sregs, kvm_kvmclock_ctrl, kvm_set_cpuid2, - kvm_set_msrs, kvm_set_regs, kvm_set_sregs, + MAX_IO_MSRS, kvm_create_vcpu, kvm_get_lapic, kvm_get_regs, kvm_get_sregs, kvm_get_xsave, + kvm_kvmclock_ctrl, kvm_set_cpuid2, kvm_set_lapic, kvm_set_msrs, kvm_set_regs, kvm_set_sregs, + kvm_set_xsave, }; #[derive(Debug)] @@ -312,6 +314,30 @@ impl KvmVcpu { unsafe { kvm_set_msrs(&self.fd, &kvm_msrs) }.context(error::GuestMsr)?; Ok(()) } + + pub fn kvm_get_xsave(&self, xsave: &mut [u32; 1024]) -> Result<()> { + let buf = transmute_mut!(xsave); + unsafe { kvm_get_xsave(&self.fd, buf) }.context(error::GuestXsave)?; + Ok(()) + } + + pub fn kvm_set_xsave(&mut self, xsave: &[u32; 1024]) -> Result<()> { + let buf = transmute_ref!(xsave); + unsafe { kvm_set_xsave(&self.fd, buf) }.context(error::GuestXsave)?; + Ok(()) + } + + pub fn kvm_get_lapic(&self, lapic: &mut [u32; 256]) -> Result<()> { + let buf = transmute_mut!(lapic); + unsafe { kvm_get_lapic(&self.fd, buf) }.context(error::GuestLapic)?; + Ok(()) + } + + pub fn kvm_set_lapic(&mut self, lapic: &[u32; 256]) -> Result<()> { + let buf = transmute_ref!(lapic); + unsafe { kvm_set_lapic(&self.fd, buf) }.context(error::GuestLapic)?; + Ok(()) + } } #[cfg(test)] diff --git a/alioth/src/sys/linux/kvm.rs b/alioth/src/sys/linux/kvm.rs index b8e0e42f..1ecdc953 100644 --- a/alioth/src/sys/linux/kvm.rs +++ b/alioth/src/sys/linux/kvm.rs @@ -15,6 +15,7 @@ use std::fmt::{Debug, Formatter, Result}; use bitfield::bitfield; +use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::arch::x86_64::msr::{ApicBase, Efer}; use crate::arch::x86_64::reg::{Cr0, Cr3, Cr4}; @@ -561,6 +562,18 @@ pub struct KvmEnableCap { pub pad: [u8; 64], } +#[repr(C)] +#[derive(Debug, Clone, FromBytes, KnownLayout, Immutable, IntoBytes)] +pub struct KvmXsave { + pub region: [u32; 1024], +} + +#[repr(C)] +#[derive(Debug, Clone, FromBytes, KnownLayout, Immutable, IntoBytes)] +pub struct KvmLapicState { + pub regs: [u32; 0x100], +} + #[repr(C)] #[derive(Debug, Copy, Clone, Default)] pub struct KvmOneReg { @@ -686,12 +699,20 @@ ioctl_write_ptr!(kvm_set_regs, KVMIO, 0x82, KvmRegs); ioctl_read!(kvm_get_sregs, KVMIO, 0x83, KvmSregs); ioctl_write_ptr!(kvm_set_sregs, KVMIO, 0x84, KvmSregs); ioctl_write_buf!(kvm_set_msrs, KVMIO, 0x89, KvmMsrs); - +ioctl_writeread!( + kvm_get_lapic, + ioctl_ior::(KVMIO, 0x8e), + KvmLapicState +); +ioctl_write_ptr!(kvm_set_lapic, KVMIO, 0x8f, KvmLapicState); ioctl_write_buf!(kvm_set_cpuid2, KVMIO, 0x90, KvmCpuid2); ioctl_write_ptr!(kvm_enable_cap, KVMIO, 0xa3, KvmEnableCap); ioctl_write_ptr!(kvm_signal_msi, KVMIO, 0xa5, KvmMsi); +ioctl_writeread!(kvm_get_xsave, ioctl_ior::(KVMIO, 0xa4), KvmXsave); +ioctl_write_ptr!(kvm_set_xsave, KVMIO, 0xa5, KvmXsave); + ioctl_write_ptr!(kvm_get_one_reg, KVMIO, 0xab, KvmOneReg); ioctl_write_ptr!(kvm_set_one_reg, KVMIO, 0xac, KvmOneReg);