This commit is contained in:
Jinank Jain 2024-04-06 21:26:59 +08:00 committed by GitHub
commit 890309853e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 164 additions and 45 deletions

View File

@ -1,3 +1,36 @@
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
pub mod gic;
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
pub struct StandardRegisters {
pub gpr: [u64; 31usize], // 31 General Purpose Registers
pub sp: u64, // Stack Pointer
pub pc: u64, // Program Counter
pub pstate: u64, // Program Status Register
pub sp_el1: u64, // Stack Pointer for EL1
pub elr_el1: u64, // Exception Link Register for EL1
pub spsr: [u64; 5usize], // Saved Program Status Registers
pub vregs: [u128; 32usize], // 32 Floating Point Registers
pub fpsr: u64, // Floating point status register
pub fpcr: u64, // Floating point control register
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
pub struct Register {
pub id: u64,
pub addr: u64,
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
pub struct VcpuInit {
pub target: u32,
pub features: [u32; 7usize],
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
pub struct RegList(pub Vec<u64>);

View File

@ -9,7 +9,7 @@
//
#[cfg(target_arch = "aarch64")]
use crate::aarch64::{RegList, StandardRegisters, VcpuInit};
use crate::arch::aarch64::{RegList, StandardRegisters, VcpuInit};
#[cfg(target_arch = "x86_64")]
use crate::arch::x86::{
CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters,

View File

@ -206,6 +206,7 @@ pub fn construct_gicr_typers(vcpu_states: &[CpuState]) -> Vec<u64> {
.sys_regs
.into_iter()
.filter(|reg| reg.id == KVM_ARM64_SYSREG_MPIDR_EL1)
.map(|reg| reg.into())
.collect();
//calculate affinity
let mut cpu_affid = mpidr[0].addr & 1095233437695;

View File

@ -10,14 +10,13 @@
pub mod gic;
use crate::arch::aarch64::{Register, StandardRegisters, VcpuInit};
use crate::kvm::{KvmError, KvmResult};
use kvm_bindings::{
kvm_mp_state, kvm_one_reg, kvm_regs, KVM_REG_ARM_COPROC_MASK, KVM_REG_ARM_CORE,
KVM_REG_SIZE_MASK, KVM_REG_SIZE_U32, KVM_REG_SIZE_U64,
};
pub use kvm_bindings::{
kvm_one_reg as Register, kvm_regs as StandardRegisters, kvm_vcpu_init as VcpuInit, RegList,
};
pub use kvm_bindings::{kvm_vcpu_init, user_fpsimd_state, user_pt_regs};
use serde::{Deserialize, Serialize};
pub use {kvm_ioctls::Cap, kvm_ioctls::Kvm};
@ -121,3 +120,79 @@ pub struct VcpuKvmState {
pub core_regs: kvm_regs,
pub sys_regs: Vec<kvm_one_reg>,
}
impl From<StandardRegisters> for kvm_regs {
fn from(regs: StandardRegisters) -> Self {
Self {
regs: user_pt_regs {
regs: regs.gpr,
sp: regs.sp,
pc: regs.pc,
pstate: regs.pstate,
},
sp_el1: regs.sp_el1,
elr_el1: regs.elr_el1,
spsr: regs.spsr,
fp_regs: user_fpsimd_state {
vregs: regs.vregs,
fpsr: regs.fpsr as u32,
fpcr: regs.fpcr as u32,
..Default::default()
},
..Default::default()
}
}
}
impl From<kvm_regs> for StandardRegisters {
fn from(regs: kvm_regs) -> Self {
Self {
gpr: regs.regs.regs,
sp: regs.regs.sp,
pc: regs.regs.pc,
pstate: regs.regs.pstate,
sp_el1: regs.sp_el1,
elr_el1: regs.elr_el1,
spsr: regs.spsr,
vregs: regs.fp_regs.vregs,
fpsr: regs.fp_regs.fpsr as u64,
fpcr: regs.fp_regs.fpcr as u64,
}
}
}
impl From<Register> for kvm_one_reg {
fn from(reg: Register) -> Self {
Self {
id: reg.id,
addr: reg.addr,
}
}
}
impl From<kvm_one_reg> for Register {
fn from(reg: kvm_one_reg) -> Self {
Self {
id: reg.id,
addr: reg.addr,
}
}
}
impl From<VcpuInit> for kvm_vcpu_init {
fn from(vcpu_init: VcpuInit) -> Self {
Self {
target: vcpu_init.target,
features: vcpu_init.features,
}
}
}
impl From<kvm_vcpu_init> for VcpuInit {
fn from(vcpu_init: kvm_vcpu_init) -> Self {
Self {
target: vcpu_init.target,
features: vcpu_init.features,
}
}
}

View File

@ -12,8 +12,7 @@
use crate::aarch64::gic::KvmGicV3Its;
#[cfg(target_arch = "aarch64")]
pub use crate::aarch64::{
check_required_kvm_extensions, gic::Gicv3ItsState as GicState, is_system_register, VcpuInit,
VcpuKvmState,
check_required_kvm_extensions, gic::Gicv3ItsState as GicState, is_system_register, VcpuKvmState,
};
#[cfg(target_arch = "aarch64")]
use crate::arch::aarch64::gic::{Vgic, VgicConfig};
@ -43,6 +42,8 @@ use vmm_sys_util::eventfd::EventFd;
// x86_64 dependencies
#[cfg(target_arch = "x86_64")]
pub mod x86_64;
#[cfg(target_arch = "aarch64")]
use crate::arch::aarch64::{RegList, Register, StandardRegisters, VcpuInit};
#[cfg(target_arch = "x86_64")]
use crate::arch::x86::{
CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters, XsaveState,
@ -54,8 +55,6 @@ use crate::{
CpuState, IoEventAddress, IrqRoutingEntry, MpState, UserMemoryRegion,
USER_MEMORY_REGION_LOG_DIRTY, USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE,
};
#[cfg(target_arch = "aarch64")]
use aarch64::{RegList, Register, StandardRegisters};
#[cfg(target_arch = "x86_64")]
use kvm_bindings::{
kvm_enable_cap, kvm_msr_entry, MsrList, KVM_CAP_HYPERV_SYNIC, KVM_CAP_SPLIT_IRQCHIP,
@ -77,10 +76,11 @@ pub use kvm_bindings::{
};
#[cfg(target_arch = "aarch64")]
use kvm_bindings::{
kvm_regs, user_fpsimd_state, user_pt_regs, KVM_GUESTDBG_USE_HW, KVM_NR_SPSR, KVM_REG_ARM64,
KVM_REG_ARM64_SYSREG, KVM_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRN_MASK,
KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP1_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK,
KVM_REG_ARM_CORE, KVM_REG_SIZE_U128, KVM_REG_SIZE_U32, KVM_REG_SIZE_U64,
kvm_regs, user_fpsimd_state, user_pt_regs, RegList as KvmRegList, KVM_GUESTDBG_USE_HW,
KVM_NR_SPSR, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM64_SYSREG_CRM_MASK,
KVM_REG_ARM64_SYSREG_CRN_MASK, KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP1_MASK,
KVM_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM_CORE, KVM_REG_SIZE_U128, KVM_REG_SIZE_U32,
KVM_REG_SIZE_U64,
};
#[cfg(feature = "tdx")]
use kvm_bindings::{kvm_run__bindgen_ty_1, KVMIO};
@ -691,8 +691,9 @@ impl vm::Vm for KvmVm {
///
#[cfg(target_arch = "aarch64")]
fn get_preferred_target(&self, kvi: &mut VcpuInit) -> vm::Result<()> {
let mut kvi = (*kvi).into();
self.fd
.get_preferred_target(kvi)
.get_preferred_target(&mut kvi)
.map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into()))
}
@ -1210,7 +1211,7 @@ impl cpu::Vcpu for KvmVcpu {
///
#[cfg(target_arch = "aarch64")]
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
let mut state: StandardRegisters = kvm_regs::default();
let mut state = kvm_regs::default();
let mut off = offset_of!(user_pt_regs, regs);
// There are 31 user_pt_regs:
// https://elixir.free-electrons.com/linux/v4.14.174/source/arch/arm64/include/uapi/asm/ptrace.h#L72
@ -1305,7 +1306,7 @@ impl cpu::Vcpu for KvmVcpu {
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.fp_regs.fpcr = u32::from_le_bytes(bytes);
Ok(state)
Ok(state.into())
}
#[cfg(target_arch = "x86_64")]
@ -1328,6 +1329,7 @@ impl cpu::Vcpu for KvmVcpu {
fn set_regs(&self, state: &StandardRegisters) -> cpu::Result<()> {
// The function follows the exact identical order from `state`. Look there
// for some additional info on registers.
let state: kvm_regs = (*state).into();
let mut off = offset_of!(user_pt_regs, regs);
for i in 0..31 {
self.fd
@ -1776,8 +1778,9 @@ impl cpu::Vcpu for KvmVcpu {
#[cfg(target_arch = "aarch64")]
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
let kvi = (*kvi).into();
self.fd
.vcpu_init(kvi)
.vcpu_init(&kvi)
.map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into()))
}
@ -1787,8 +1790,10 @@ impl cpu::Vcpu for KvmVcpu {
///
#[cfg(target_arch = "aarch64")]
fn get_reg_list(&self, reg_list: &mut RegList) -> cpu::Result<()> {
let mut kvm_reg_list: KvmRegList = KvmRegList::from_entries(reg_list.0.as_slice())
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))?;
self.fd
.get_reg_list(reg_list)
.get_reg_list(&mut kvm_reg_list)
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
}
@ -2013,13 +2018,13 @@ impl cpu::Vcpu for KvmVcpu {
..Default::default()
};
// Get core registers
state.core_regs = self.get_regs()?;
state.core_regs = self.get_regs()?.into();
// Get systerm register
// Call KVM_GET_REG_LIST to get all registers available to the guest.
// For ArmV8 there are around 500 registers.
let mut sys_regs: Vec<Register> = Vec::new();
let mut reg_list = RegList::new(500).unwrap();
let mut reg_list = KvmRegList::new(500).unwrap();
self.fd
.get_reg_list(&mut reg_list)
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))?;
@ -2041,13 +2046,16 @@ impl cpu::Vcpu for KvmVcpu {
self.fd
.get_one_reg(*index, &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?;
sys_regs.push(kvm_bindings::kvm_one_reg {
id: *index,
addr: u64::from_le_bytes(bytes),
});
sys_regs.push(
kvm_bindings::kvm_one_reg {
id: *index,
addr: u64::from_le_bytes(bytes),
}
.into(),
);
}
state.sys_regs = sys_regs;
state.sys_regs = sys_regs.into_iter().map(|reg| reg.into()).collect();
Ok(state.into())
}
@ -2149,7 +2157,7 @@ impl cpu::Vcpu for KvmVcpu {
fn set_state(&self, state: &CpuState) -> cpu::Result<()> {
let state: VcpuKvmState = state.clone().into();
// Set core registers
self.set_regs(&state.core_regs)?;
self.set_regs(&state.core_regs.into())?;
// Set system registers
for reg in &state.sys_regs {
self.fd

View File

@ -1191,12 +1191,12 @@ impl cpu::Vcpu for MshvVcpu {
}
#[cfg(target_arch = "aarch64")]
fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> {
fn set_regs(&self, regs: &crate::arch::aarch64::StandardRegisters) -> cpu::Result<()> {
unimplemented!()
}
#[cfg(target_arch = "aarch64")]
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
fn get_regs(&self) -> cpu::Result<crate::arch::aarch64::StandardRegisters> {
unimplemented!()
}

View File

@ -8,10 +8,10 @@
//
//
#[cfg(target_arch = "aarch64")]
use crate::aarch64::VcpuInit;
#[cfg(target_arch = "aarch64")]
use crate::arch::aarch64::gic::{Vgic, VgicConfig};
#[cfg(target_arch = "aarch64")]
use crate::arch::aarch64::VcpuInit;
#[cfg(feature = "tdx")]
use crate::arch::x86::CpuIdEntry;
use crate::cpu::Vcpu;

View File

@ -43,7 +43,9 @@ use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs;
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
use gdbstub_arch::x86::reg::{X86SegmentRegs, X86_64CoreRegs as CoreRegs};
#[cfg(all(target_arch = "aarch64", feature = "guest_debug"))]
use hypervisor::aarch64::StandardRegisters;
use hypervisor::arch::aarch64::StandardRegisters;
#[cfg(target_arch = "aarch64")]
use hypervisor::arch::aarch64::VcpuInit;
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
use hypervisor::arch::x86::msr_index;
#[cfg(target_arch = "x86_64")]
@ -413,7 +415,7 @@ impl Vcpu {
/// Initializes an aarch64 specific vcpu for booting Linux.
#[cfg(target_arch = "aarch64")]
pub fn init(&self, vm: &Arc<dyn hypervisor::Vm>) -> Result<()> {
let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default();
let mut kvi = VcpuInit::default();
// This reads back the kernel's preferred target type.
vm.get_preferred_target(&mut kvi)
@ -2383,9 +2385,9 @@ impl Debuggable for CpuManager {
.get_regs(cpu_id as u8)
.map_err(DebuggableError::ReadRegs)?;
Ok(CoreRegs {
x: gregs.regs.regs,
sp: gregs.regs.sp,
pc: gregs.regs.pc,
x: gregs.gpr,
sp: gregs.sp,
pc: gregs.pc,
..Default::default()
})
}
@ -2454,9 +2456,9 @@ impl Debuggable for CpuManager {
.get_regs(cpu_id as u8)
.map_err(DebuggableError::ReadRegs)?;
gregs.regs.regs = regs.x;
gregs.regs.sp = regs.sp;
gregs.regs.pc = regs.pc;
gregs.gpr = regs.x;
gregs.sp = regs.sp;
gregs.pc = regs.pc;
self.set_regs(cpu_id as u8, &gregs)
.map_err(DebuggableError::WriteRegs)?;
@ -2889,10 +2891,10 @@ mod tests {
#[cfg(test)]
mod tests {
use arch::{aarch64::regs, layout};
use hypervisor::arch::aarch64::{StandardRegisters, VcpuInit};
use hypervisor::kvm::aarch64::is_system_register;
use hypervisor::kvm::kvm_bindings::{
kvm_regs, kvm_vcpu_init, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG,
KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
};
use hypervisor::{arm64_core_reg_id, offset_of};
use std::mem;
@ -2907,7 +2909,7 @@ mod tests {
// Must fail when vcpu is not initialized yet.
assert!(res.is_err());
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
let mut kvi = VcpuInit::default();
vm.get_preferred_target(&mut kvi).unwrap();
vcpu.vcpu_init(&kvi).unwrap();
@ -2919,7 +2921,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let vcpu = vm.create_vcpu(0, None).unwrap();
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
let mut kvi = VcpuInit::default();
vm.get_preferred_target(&mut kvi).unwrap();
// Must fail when vcpu is not initialized yet.
@ -2943,7 +2945,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let vcpu = vm.create_vcpu(0, None).unwrap();
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
let mut kvi = VcpuInit::default();
vm.get_preferred_target(&mut kvi).unwrap();
// Must fail when vcpu is not initialized yet.
@ -2954,7 +2956,7 @@ mod tests {
"Failed to get core register: Exec format error (os error 8)"
);
let mut state = kvm_regs::default();
let mut state = StandardRegisters::default();
let res = vcpu.set_regs(&state);
assert!(res.is_err());
assert_eq!(
@ -2966,7 +2968,7 @@ mod tests {
let res = vcpu.get_regs();
assert!(res.is_ok());
state = res.unwrap();
assert_eq!(state.regs.pstate, 0x3C5);
assert_eq!(state.pstate, 0x3C5);
assert!(vcpu.set_regs(&state).is_ok());
}
@ -2976,7 +2978,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let vcpu = vm.create_vcpu(0, None).unwrap();
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
let mut kvi = VcpuInit::default();
vm.get_preferred_target(&mut kvi).unwrap();
let res = vcpu.get_mp_state();