From 7199119bb2ebce56874b4c4a08535ea1fb468caf Mon Sep 17 00:00:00 2001 From: Michael Zhao Date: Thu, 28 Jul 2022 16:51:58 +0800 Subject: [PATCH] hypervisor: Remove `Vcpu::read_mpidr()` on AArch64 Replaced `read_mpidr()` with `get_sys_reg()`. Signed-off-by: Michael Zhao --- arch/src/aarch64/mod.rs | 4 +- hypervisor/src/cpu.rs | 5 --- hypervisor/src/kvm/aarch64/gic/redist_regs.rs | 21 +++++++++- hypervisor/src/kvm/aarch64/mod.rs | 38 +------------------ hypervisor/src/kvm/mod.rs | 12 +----- vmm/src/cpu.rs | 6 +-- 6 files changed, 28 insertions(+), 58 deletions(-) diff --git a/arch/src/aarch64/mod.rs b/arch/src/aarch64/mod.rs index 0f4194d1c..f160f986a 100644 --- a/arch/src/aarch64/mod.rs +++ b/arch/src/aarch64/mod.rs @@ -75,7 +75,9 @@ pub fn configure_vcpu( .map_err(Error::RegsConfiguration)?; } - let mpidr = vcpu.read_mpidr().map_err(Error::VcpuRegMpidr)?; + let mpidr = vcpu + .get_sys_reg(regs::MPIDR_EL1) + .map_err(Error::VcpuRegMpidr)?; Ok(mpidr) } diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index 366aa7e62..2a35e0e16 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -366,11 +366,6 @@ pub trait Vcpu: Send + Sync { #[cfg(target_arch = "aarch64")] fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>; /// - /// Read the MPIDR - Multiprocessor Affinity Register. - /// - #[cfg(target_arch = "aarch64")] - fn read_mpidr(&self) -> Result; - /// /// Gets the value of a system register /// #[cfg(target_arch = "aarch64")] diff --git a/hypervisor/src/kvm/aarch64/gic/redist_regs.rs b/hypervisor/src/kvm/aarch64/gic/redist_regs.rs index b036d3701..70759595f 100644 --- a/hypervisor/src/kvm/aarch64/gic/redist_regs.rs +++ b/hypervisor/src/kvm/aarch64/gic/redist_regs.rs @@ -4,7 +4,12 @@ use crate::arch::aarch64::gic::{Error, Result}; use crate::device::HypervisorDeviceError; -use crate::kvm::kvm_bindings::{kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS}; +use crate::kvm::kvm_bindings::{ + kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, + KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP0_SHIFT, KVM_REG_ARM64_SYSREG_OP2_MASK, + KVM_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_SIZE_U64, +}; +use crate::kvm::Register; use crate::kvm::VcpuKvmState; use crate::CpuState; use kvm_ioctls::DeviceFd; @@ -34,6 +39,12 @@ const GICR_ICFGR0: u32 = GICR_SGI_OFFSET + 0x0C00; const KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT: u32 = 32; const KVM_DEV_ARM_VGIC_V3_MPIDR_MASK: u64 = 0xffffffff << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT as u64; +const KVM_ARM64_SYSREG_MPIDR_EL1: u64 = KVM_REG_ARM64 as u64 + | KVM_REG_SIZE_U64 as u64 + | KVM_REG_ARM64_SYSREG as u64 + | (((3_u64) << KVM_REG_ARM64_SYSREG_OP0_SHIFT) & KVM_REG_ARM64_SYSREG_OP0_MASK as u64) + | (((5_u64) << KVM_REG_ARM64_SYSREG_OP2_SHIFT) & KVM_REG_ARM64_SYSREG_OP2_MASK as u64); + /// This is how we represent the registers of a distributor. /// It is relrvant their offset from the base address of the /// distributor. @@ -196,8 +207,14 @@ pub fn construct_gicr_typers(vcpu_states: &[CpuState]) -> Vec { 0 } }; + // state.sys_regs is a big collection of system registers, including MIPDR_EL1 + let mpidr: Vec = state + .sys_regs + .into_iter() + .filter(|reg| reg.id == KVM_ARM64_SYSREG_MPIDR_EL1) + .collect(); //calculate affinity - let mut cpu_affid = state.mpidr & 1095233437695; + let mut cpu_affid = mpidr[0].addr & 1095233437695; cpu_affid = ((cpu_affid & 0xFF00000000) >> 8) | (cpu_affid & 0xFFFFFF); gicr_typers.push((cpu_affid << 32) | (1 << 24) | (index as u64) << 8 | (last << 4)); } diff --git a/hypervisor/src/kvm/aarch64/mod.rs b/hypervisor/src/kvm/aarch64/mod.rs index 903cdc052..7712508ec 100644 --- a/hypervisor/src/kvm/aarch64/mod.rs +++ b/hypervisor/src/kvm/aarch64/mod.rs @@ -12,12 +12,8 @@ pub mod gic; use crate::kvm::{KvmError, KvmResult}; use kvm_bindings::{ - kvm_mp_state, kvm_one_reg, kvm_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, - KVM_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRN_MASK, - KVM_REG_ARM64_SYSREG_CRN_SHIFT, KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP0_SHIFT, - KVM_REG_ARM64_SYSREG_OP1_MASK, KVM_REG_ARM64_SYSREG_OP1_SHIFT, KVM_REG_ARM64_SYSREG_OP2_MASK, - KVM_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_ARM_COPROC_MASK, KVM_REG_ARM_CORE, KVM_REG_SIZE_MASK, - KVM_REG_SIZE_U32, KVM_REG_SIZE_U64, + 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, @@ -85,32 +81,6 @@ macro_rules! arm64_core_reg_id { }; } -// This macro computes the ID of a specific ARM64 system register similar to how -// the kernel C macro does. -// https://elixir.bootlin.com/linux/v4.20.17/source/arch/arm64/include/uapi/asm/kvm.h#L203 -#[macro_export] -macro_rules! arm64_sys_reg { - ($name: tt, $op0: tt, $op1: tt, $crn: tt, $crm: tt, $op2: tt) => { - pub const $name: u64 = KVM_REG_ARM64 as u64 - | KVM_REG_SIZE_U64 as u64 - | KVM_REG_ARM64_SYSREG as u64 - | ((($op0 as u64) << KVM_REG_ARM64_SYSREG_OP0_SHIFT) - & KVM_REG_ARM64_SYSREG_OP0_MASK as u64) - | ((($op1 as u64) << KVM_REG_ARM64_SYSREG_OP1_SHIFT) - & KVM_REG_ARM64_SYSREG_OP1_MASK as u64) - | ((($crn as u64) << KVM_REG_ARM64_SYSREG_CRN_SHIFT) - & KVM_REG_ARM64_SYSREG_CRN_MASK as u64) - | ((($crm as u64) << KVM_REG_ARM64_SYSREG_CRM_SHIFT) - & KVM_REG_ARM64_SYSREG_CRM_MASK as u64) - | ((($op2 as u64) << KVM_REG_ARM64_SYSREG_OP2_SHIFT) - & KVM_REG_ARM64_SYSREG_OP2_MASK as u64); - }; -} - -// Constant imported from the Linux kernel: -// https://elixir.bootlin.com/linux/v4.20.17/source/arch/arm64/include/asm/sysreg.h#L135 -arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5); - /// Specifies whether a particular register is a system register or not. /// The kernel splits the registers on aarch64 in core registers and system registers. /// So, below we get the system registers by checking that they are not core registers. @@ -149,8 +119,4 @@ pub struct VcpuKvmState { pub mp_state: kvm_mp_state, pub core_regs: kvm_regs, pub sys_regs: Vec, - // We will be using the mpidr for passing it to the VmState. - // The VmState will give this away for saving restoring the icc and redistributor - // registers. - pub mpidr: u64, } diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 9c927a895..08e06afdf 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -13,7 +13,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, MPIDR_EL1, + VcpuKvmState, }; #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::gic::Vgic; @@ -1638,15 +1638,6 @@ impl cpu::Vcpu for KvmVcpu { .map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into())) } /// - /// Read the MPIDR - Multiprocessor Affinity Register. - /// - #[cfg(target_arch = "aarch64")] - fn read_mpidr(&self) -> cpu::Result { - self.fd - .get_one_reg(MPIDR_EL1) - .map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into())) - } - /// /// Gets the value of a system register /// #[cfg(target_arch = "aarch64")] @@ -1853,7 +1844,6 @@ impl cpu::Vcpu for KvmVcpu { fn state(&self) -> cpu::Result { let mut state = VcpuKvmState { mp_state: self.get_mp_state()?.into(), - mpidr: self.read_mpidr()?, ..Default::default() }; // Get core registers diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 6942c2d5e..945851d2c 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -2410,7 +2410,7 @@ mod tests { #[cfg(target_arch = "aarch64")] #[cfg(test)] mod tests { - use arch::layout; + use arch::{aarch64::regs, layout}; 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, @@ -2445,10 +2445,10 @@ mod tests { vm.get_preferred_target(&mut kvi).unwrap(); // Must fail when vcpu is not initialized yet. - assert!(vcpu.read_mpidr().is_err()); + assert!(vcpu.get_sys_reg(regs::MPIDR_EL1).is_err()); vcpu.vcpu_init(&kvi).unwrap(); - assert_eq!(vcpu.read_mpidr().unwrap(), 0x80000000); + assert_eq!(vcpu.get_sys_reg(regs::MPIDR_EL1).unwrap(), 0x80000000); } #[test]