Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions alioth/src/arch/x86_64/msr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::{bitflags, consts};

// Intel Vol.4, Table 2-2.
consts! {
#[derive(Default)]
pub struct Msr(u32) {
EFER = 0xc000_0080;
STAR = 0xc000_0081;
Expand Down
12 changes: 12 additions & 0 deletions alioth/src/hv/hv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ 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 },
#[snafu(display("Failed to configure memory encryption"))]
MemEncrypt { error: std::io::Error },
#[snafu(display("Cannot create multiple VM memories"))]
Expand Down Expand Up @@ -205,12 +208,21 @@ pub trait Vcpu {

fn run(&mut self, entry: VmEntry) -> Result<VmExit, Error>;

#[cfg(target_arch = "x86_64")]
fn get_cpuids(&self) -> Result<HashMap<CpuidIn, CpuidResult>>;
#[cfg(target_arch = "x86_64")]
fn set_cpuids(&mut self, cpuids: HashMap<CpuidIn, CpuidResult>) -> Result<(), Error>;

#[cfg(target_arch = "x86_64")]
fn get_msrs(&self, msrs: &[Msr]) -> Result<Vec<u64>>;
#[cfg(target_arch = "x86_64")]
fn set_msrs(&mut self, msrs: &[(Msr, u64)]) -> Result<()>;

#[cfg(target_arch = "x86_64")]
fn get_xsave(&self) -> Result<[u32; 1024]>;
#[cfg(target_arch = "x86_64")]
fn set_xsave(&mut self, xsave: &[u32; 1024]) -> Result<()>;

fn dump(&self) -> Result<(), Error>;

#[cfg(target_arch = "aarch64")]
Expand Down
20 changes: 20 additions & 0 deletions alioth/src/hv/kvm/vcpu/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,36 @@ impl Vcpu for KvmVcpu {
}
}

#[cfg(target_arch = "x86_64")]
fn get_cpuids(&self) -> Result<HashMap<CpuidIn, CpuidResult>> {
self.kvm_get_cpuids()
}

#[cfg(target_arch = "x86_64")]
fn set_cpuids(&mut self, cpuids: HashMap<CpuidIn, CpuidResult>) -> Result<(), Error> {
self.kvm_set_cpuids(&cpuids)
}

#[cfg(target_arch = "x86_64")]
fn get_msrs(&self, msrs: &[Msr]) -> Result<Vec<u64>> {
self.kvm_get_msrs(msrs)
}

#[cfg(target_arch = "x86_64")]
fn set_msrs(&mut self, msrs: &[(Msr, u64)]) -> Result<()> {
self.kvm_set_msrs(msrs)
}

#[cfg(target_arch = "x86_64")]
fn get_xsave(&self) -> Result<[u32; 1024]> {
self.kvm_get_xsave()
}

#[cfg(target_arch = "x86_64")]
fn set_xsave(&mut self, xsave: &[u32; 1024]) -> Result<()> {
self.kvm_set_xsave(xsave)
}

fn dump(&self) -> Result<(), Error> {
Ok(())
}
Expand Down
67 changes: 64 additions & 3 deletions alioth/src/hv/kvm/vcpu/vcpu_x86_64/vcpu_x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use std::iter::zip;
use std::os::fd::{FromRawFd, OwnedFd};

use snafu::ResultExt;
use zerocopy::{FromBytes, IntoBytes, transmute};

use crate::arch::cpuid::CpuidIn;
use crate::arch::msr::{Efer, Msr};
Expand All @@ -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_get_sregs2, kvm_kvmclock_ctrl,
kvm_set_cpuid2, kvm_set_msrs, kvm_set_regs, kvm_set_sregs, kvm_set_sregs2,
KvmXsave, MAX_IO_MSRS, kvm_create_vcpu, kvm_get_cpuid2, kvm_get_msrs, kvm_get_regs,
kvm_get_sregs, kvm_get_sregs2, kvm_get_xsave, kvm_kvmclock_ctrl, kvm_set_cpuid2, kvm_set_msrs,
kvm_set_regs, kvm_set_sregs, kvm_set_sregs2, kvm_set_xsave,
};

#[derive(Debug)]
Expand Down Expand Up @@ -312,6 +314,38 @@ impl KvmVcpu {
Ok(val)
}

pub fn kvm_get_cpuids(&self) -> Result<HashMap<CpuidIn, CpuidResult>> {
let mut kvm_cpuid2 = KvmCpuid2 {
nent: KVM_MAX_CPUID_ENTRIES as u32,
padding: 0,
entries: [KvmCpuidEntry2::default(); KVM_MAX_CPUID_ENTRIES],
};
unsafe { kvm_get_cpuid2(&self.fd, &mut kvm_cpuid2) }.context(error::GuestCpuid)?;
let cpuids: HashMap<CpuidIn, CpuidResult> = kvm_cpuid2
.entries
.iter()
.take(kvm_cpuid2.nent as usize)
.map(|e| {
let in_ = CpuidIn {
func: e.function,
index: if e.flags.contains(KvmCpuid2Flag::SIGNIFCANT_INDEX) {
Some(e.index)
} else {
None
},
};
let out = CpuidResult {
eax: e.eax,
ebx: e.ebx,
ecx: e.ecx,
edx: e.edx,
};
(in_, out)
})
.collect();
Ok(cpuids)
}

pub fn kvm_set_cpuids(&mut self, cpuids: &HashMap<CpuidIn, CpuidResult>) -> Result<(), Error> {
if cpuids.len() > KVM_MAX_CPUID_ENTRIES {
return kvm_error::CpuidTableTooLong.fail()?;
Expand All @@ -338,19 +372,46 @@ impl KvmVcpu {
Ok(())
}

pub fn kvm_get_msrs(&self, msrs: &[Msr]) -> Result<Vec<u64>> {
let mut kvm_msrs = KvmMsrs {
nmsrs: msrs.len() as u32,
_pad: 0,
entries: [KvmMsrEntry::default(); MAX_IO_MSRS],
};
for (i, index) in msrs.iter().enumerate() {
kvm_msrs.entries[i].index = *index;
}
unsafe { kvm_get_msrs(&self.fd, &mut kvm_msrs) }.context(error::GuestMsr)?;
Ok(kvm_msrs.entries[..msrs.len()]
.iter()
.map(|e| e.data)
.collect())
}

pub fn kvm_set_msrs(&mut self, msrs: &[(Msr, u64)]) -> Result<()> {
let mut kvm_msrs = KvmMsrs {
nmsrs: msrs.len() as u32,
_pad: 0,
entries: [KvmMsrEntry::default(); MAX_IO_MSRS],
};
for (i, (index, data)) in msrs.iter().enumerate() {
kvm_msrs.entries[i].index = index.raw();
kvm_msrs.entries[i].index = *index;
kvm_msrs.entries[i].data = *data;
}
unsafe { kvm_set_msrs(&self.fd, &kvm_msrs) }.context(error::GuestMsr)?;
Ok(())
}

pub fn kvm_get_xsave(&self) -> Result<[u32; 1024]> {
let kvm_xsave = unsafe { kvm_get_xsave(&self.fd) }.context(error::GuestXsave)?;
Ok(transmute!(kvm_xsave.region))
}

pub fn kvm_set_xsave(&mut self, xsave: &[u32; 1024]) -> Result<()> {
let kvm_xsave = KvmXsave::ref_from_bytes(xsave.as_bytes()).unwrap();
unsafe { kvm_set_xsave(&self.fd, kvm_xsave) }.context(error::GuestXsave)?;
Ok(())
}
}

#[cfg(test)]
Expand Down
16 changes: 14 additions & 2 deletions alioth/src/sys/linux/kvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
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::msr::{ApicBase, Efer, Msr};
use crate::arch::x86_64::reg::{Cr0, Cr3, Cr4};
use crate::sys::ioctl::{ioctl_ior, ioctl_iowr};
use crate::{
Expand Down Expand Up @@ -99,7 +100,7 @@ bitflags! {
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct KvmMsrEntry {
pub index: u32,
pub index: Msr,
pub _reserved: u32,
pub data: u64,
}
Expand Down Expand Up @@ -567,6 +568,12 @@ pub struct KvmEnableCap {
pub pad: [u8; 64],
}

#[repr(C, align(16))]
#[derive(Debug, Clone, FromBytes, KnownLayout, Immutable, IntoBytes)]
pub struct KvmXsave {
pub region: [u32; 1024],
}

#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct KvmOneReg {
Expand Down Expand Up @@ -691,13 +698,18 @@ ioctl_read!(kvm_get_regs, KVMIO, 0x81, KvmRegs);
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_writeread_buf!(kvm_get_msrs, KVMIO, 0x88, KvmMsrs);
ioctl_write_buf!(kvm_set_msrs, KVMIO, 0x89, KvmMsrs);

ioctl_write_buf!(kvm_set_cpuid2, KVMIO, 0x90, KvmCpuid2);
ioctl_writeread_buf!(kvm_get_cpuid2, KVMIO, 0x91, KvmCpuid2);

ioctl_write_ptr!(kvm_enable_cap, KVMIO, 0xa3, KvmEnableCap);
ioctl_write_ptr!(kvm_signal_msi, KVMIO, 0xa5, KvmMsi);

ioctl_read!(kvm_get_xsave, 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);

Expand Down
Loading