mirror of
https://github.com/obhq/obliteration.git
synced 2024-10-07 00:13:24 +00:00
Implements CPU states for AArch64 KVM (#1009)
This commit is contained in:
parent
c8ce13a7bf
commit
b66b4fe5d5
@ -1,16 +1,53 @@
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
use super::ffi::{KvmOneReg, ARM64_SYS_REG, KVM_SET_ONE_REG};
|
||||
use crate::vmm::hv::{CpuStates, Pstate, Sctlr, Tcr};
|
||||
use std::os::fd::OwnedFd;
|
||||
use libc::ioctl;
|
||||
use std::io::Error;
|
||||
use std::os::fd::{AsRawFd, OwnedFd};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Implementation of [`Cpu::States`] for KVM.
|
||||
pub struct KvmStates<'a> {
|
||||
cpu: &'a mut OwnedFd,
|
||||
pstate: State<u64>,
|
||||
sctlr: State<u64>,
|
||||
mair: State<u64>,
|
||||
tcr: State<u64>,
|
||||
ttbr0: State<u64>,
|
||||
ttbr1: State<u64>,
|
||||
sp: State<u64>,
|
||||
pc: State<u64>,
|
||||
x0: State<u64>,
|
||||
x1: State<u64>,
|
||||
}
|
||||
|
||||
impl<'a> KvmStates<'a> {
|
||||
pub fn from_cpu(cpu: &'a mut OwnedFd) -> Result<Self, StatesError> {
|
||||
Ok(KvmStates { cpu })
|
||||
Ok(KvmStates {
|
||||
cpu,
|
||||
pstate: State::None,
|
||||
sctlr: State::None,
|
||||
mair: State::None,
|
||||
tcr: State::None,
|
||||
ttbr0: State::None,
|
||||
ttbr1: State::None,
|
||||
sp: State::None,
|
||||
pc: State::None,
|
||||
x0: State::None,
|
||||
x1: State::None,
|
||||
})
|
||||
}
|
||||
|
||||
fn set_reg<T>(&mut self, reg: u64, mut val: T) -> Result<(), Error> {
|
||||
let reg = KvmOneReg {
|
||||
id: reg,
|
||||
addr: &mut val,
|
||||
};
|
||||
|
||||
match unsafe { ioctl(self.cpu.as_raw_fd(), KVM_SET_ONE_REG, ®) } {
|
||||
0 => Ok(()),
|
||||
_ => Err(Error::last_os_error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,50 +55,145 @@ impl<'a> CpuStates for KvmStates<'a> {
|
||||
type Err = StatesError;
|
||||
|
||||
fn set_pstate(&mut self, v: Pstate) {
|
||||
todo!()
|
||||
self.pstate = State::Dirty(v.into_bits());
|
||||
}
|
||||
|
||||
fn set_sctlr(&mut self, v: Sctlr) {
|
||||
todo!()
|
||||
self.sctlr = State::Dirty(v.into_bits());
|
||||
}
|
||||
|
||||
fn set_mair_el1(&mut self, attrs: u64) {
|
||||
todo!()
|
||||
self.mair = State::Dirty(attrs);
|
||||
}
|
||||
|
||||
fn set_tcr(&mut self, v: Tcr) {
|
||||
todo!()
|
||||
self.tcr = State::Dirty(v.into_bits());
|
||||
}
|
||||
|
||||
fn set_ttbr0_el1(&mut self, baddr: usize) {
|
||||
todo!()
|
||||
self.ttbr0 = State::Dirty(baddr.try_into().unwrap());
|
||||
}
|
||||
|
||||
fn set_ttbr1_el1(&mut self, baddr: usize) {
|
||||
todo!()
|
||||
self.ttbr1 = State::Dirty(baddr.try_into().unwrap());
|
||||
}
|
||||
|
||||
fn set_sp_el1(&mut self, v: usize) {
|
||||
todo!()
|
||||
self.sp = State::Dirty(v.try_into().unwrap());
|
||||
}
|
||||
|
||||
fn set_pc(&mut self, v: usize) {
|
||||
todo!()
|
||||
self.pc = State::Dirty(v.try_into().unwrap());
|
||||
}
|
||||
|
||||
fn set_x0(&mut self, v: usize) {
|
||||
todo!()
|
||||
self.x0 = State::Dirty(v.try_into().unwrap());
|
||||
}
|
||||
|
||||
fn set_x1(&mut self, v: usize) {
|
||||
todo!()
|
||||
self.x1 = State::Dirty(v.try_into().unwrap());
|
||||
}
|
||||
|
||||
fn commit(self) -> Result<(), Self::Err> {
|
||||
todo!()
|
||||
fn commit(mut self) -> Result<(), Self::Err> {
|
||||
// PSTATE.
|
||||
if let State::Dirty(v) = self.pstate {
|
||||
self.set_reg(0x6030000000100042, v)
|
||||
.map_err(StatesError::SetPstateFailed)?;
|
||||
}
|
||||
|
||||
// SCTLR_EL1.
|
||||
if let State::Dirty(v) = self.sctlr {
|
||||
self.set_reg(ARM64_SYS_REG(0b11, 0b000, 0b0001, 0b0000, 0b000), v)
|
||||
.map_err(StatesError::SetSctlrFailed)?;
|
||||
}
|
||||
|
||||
// MAIR_EL1.
|
||||
if let State::Dirty(v) = self.mair {
|
||||
self.set_reg(ARM64_SYS_REG(0b11, 0b000, 0b1010, 0b0010, 0b000), v)
|
||||
.map_err(StatesError::SetMairFailed)?;
|
||||
}
|
||||
|
||||
// TCR_EL1.
|
||||
if let State::Dirty(v) = self.tcr {
|
||||
self.set_reg(ARM64_SYS_REG(0b11, 0b000, 0b0010, 0b0000, 0b010), v)
|
||||
.map_err(StatesError::SetTcrFailed)?;
|
||||
}
|
||||
|
||||
// TTBR0_EL1.
|
||||
if let State::Dirty(v) = self.ttbr0 {
|
||||
self.set_reg(ARM64_SYS_REG(0b11, 0b000, 0b0010, 0b0000, 0b000), v)
|
||||
.map_err(StatesError::SetTtbr0Failed)?;
|
||||
}
|
||||
|
||||
// TTBR1_EL1.
|
||||
if let State::Dirty(v) = self.ttbr1 {
|
||||
self.set_reg(ARM64_SYS_REG(0b11, 0b000, 0b0010, 0b0000, 0b001), v)
|
||||
.map_err(StatesError::SetTtbr1Failed)?;
|
||||
}
|
||||
|
||||
// SP_EL1.
|
||||
if let State::Dirty(v) = self.sp {
|
||||
self.set_reg(0x6030000000100044, v)
|
||||
.map_err(StatesError::SetSpFailed)?;
|
||||
}
|
||||
|
||||
// PC.
|
||||
if let State::Dirty(v) = self.pc {
|
||||
self.set_reg(0x6030000000100040, v)
|
||||
.map_err(StatesError::SetPcFailed)?;
|
||||
}
|
||||
|
||||
// X0.
|
||||
if let State::Dirty(v) = self.x0 {
|
||||
self.set_reg(0x6030000000100000, v)
|
||||
.map_err(StatesError::SetX0Failed)?;
|
||||
}
|
||||
|
||||
// X1.
|
||||
if let State::Dirty(v) = self.x1 {
|
||||
self.set_reg(0x6030000000100002, v)
|
||||
.map_err(StatesError::SetX1Failed)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
enum State<T> {
|
||||
None,
|
||||
Dirty(T),
|
||||
}
|
||||
|
||||
/// Implementation of [`CpuStates::Err`].
|
||||
#[derive(Debug, Error)]
|
||||
pub enum StatesError {}
|
||||
pub enum StatesError {
|
||||
#[error("couldn't set PSTATE")]
|
||||
SetPstateFailed(#[source] Error),
|
||||
|
||||
#[error("couldn't set SCTLR_EL1")]
|
||||
SetSctlrFailed(#[source] Error),
|
||||
|
||||
#[error("couldn't set MAIR_EL1")]
|
||||
SetMairFailed(#[source] Error),
|
||||
|
||||
#[error("couldn't set TCR_EL1")]
|
||||
SetTcrFailed(#[source] Error),
|
||||
|
||||
#[error("couldn't set TTBR0_EL1")]
|
||||
SetTtbr0Failed(#[source] Error),
|
||||
|
||||
#[error("couldn't set TTBR1_EL1")]
|
||||
SetTtbr1Failed(#[source] Error),
|
||||
|
||||
#[error("couldn't set SP_EL1")]
|
||||
SetSpFailed(#[source] Error),
|
||||
|
||||
#[error("couldn't set PC")]
|
||||
SetPcFailed(#[source] Error),
|
||||
|
||||
#[error("couldn't set X0")]
|
||||
SetX0Failed(#[source] Error),
|
||||
|
||||
#[error("couldn't set X1")]
|
||||
SetX1Failed(#[source] Error),
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ pub const KVM_CREATE_VCPU: c_ulong = _IO(KVMIO, 0x41);
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub const KVM_GET_ONE_REG: c_ulong = _IOW::<KvmOneReg<()>>(KVMIO, 0xab);
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub const KVM_SET_ONE_REG: c_ulong = _IOW::<KvmOneReg<()>>(KVMIO, 0xac);
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub const KVM_ARM_VCPU_INIT: c_ulong = _IOW::<KvmVcpuInit>(KVMIO, 0xae);
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub const KVM_ARM_PREFERRED_TARGET: c_ulong = _IOR::<KvmVcpuInit>(KVMIO, 0xaf);
|
||||
|
Loading…
Reference in New Issue
Block a user