From 58f71b0c44106358c6d93eb526a8aeb153f09049 Mon Sep 17 00:00:00 2001 From: Jinank Jain Date: Wed, 23 Apr 2025 09:14:12 +0000 Subject: [PATCH] hypervisor: arch: Move common regs from arch to hypervisor crate There are other potential users of these registers definitions in the hypervisor crate. And hypervisor crate cannot use definitions from arch crate because it creates cyclic dependency. Signed-off-by: Jinank Jain --- arch/src/aarch64/mod.rs | 7 ++--- arch/src/aarch64/regs.rs | 43 ----------------------------- hypervisor/src/arch/aarch64/regs.rs | 41 +++++++++++++++++++++++++++ vmm/src/cpu.rs | 16 +++++------ 4 files changed, 51 insertions(+), 56 deletions(-) delete mode 100644 arch/src/aarch64/regs.rs diff --git a/arch/src/aarch64/mod.rs b/arch/src/aarch64/mod.rs index 00d3984ce..78f44e89d 100644 --- a/arch/src/aarch64/mod.rs +++ b/arch/src/aarch64/mod.rs @@ -6,8 +6,6 @@ pub mod fdt; /// Layout for this aarch64 system. pub mod layout; -/// Module for system registers definition -pub mod regs; /// Module for loading UEFI binary. pub mod uefi; @@ -16,6 +14,7 @@ use std::fmt::Debug; use std::sync::{Arc, Mutex}; use hypervisor::arch::aarch64::gic::Vgic; +use hypervisor::arch::aarch64::regs::MPIDR_EL1; use log::{log_enabled, Level}; use thiserror::Error; use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic}; @@ -86,9 +85,7 @@ pub fn configure_vcpu( .map_err(Error::RegsConfiguration)?; } - let mpidr = vcpu - .get_sys_reg(regs::MPIDR_EL1) - .map_err(Error::VcpuRegMpidr)?; + let mpidr = vcpu.get_sys_reg(MPIDR_EL1).map_err(Error::VcpuRegMpidr)?; Ok(mpidr) } diff --git a/arch/src/aarch64/regs.rs b/arch/src/aarch64/regs.rs deleted file mode 100644 index 17294d6c0..000000000 --- a/arch/src/aarch64/regs.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2022 Arm Limited (or its affiliates). All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -// AArch64 system register encoding: -// See https://developer.arm.com/documentation/ddi0487 (chapter D12) -// -// 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0 -// +----------+---+-----+-----+-----+-----+-----+----+ -// |1101010100| L | op0 | op1 | CRn | CRm | op2 | Rt | -// +----------+---+-----+-----+-----+-----+-----+----+ -// -// Notes: -// - L and Rt are reserved as implementation defined fields, ignored. - -const SYSREG_HEAD: u32 = 0b1101010100u32 << 22; -const SYSREG_OP0_SHIFT: u32 = 19; -const SYSREG_OP0_MASK: u32 = 0b11u32 << 19; -const SYSREG_OP1_SHIFT: u32 = 16; -const SYSREG_OP1_MASK: u32 = 0b111u32 << 16; -const SYSREG_CRN_SHIFT: u32 = 12; -const SYSREG_CRN_MASK: u32 = 0b1111u32 << 12; -const SYSREG_CRM_SHIFT: u32 = 8; -const SYSREG_CRM_MASK: u32 = 0b1111u32 << 8; -const SYSREG_OP2_SHIFT: u32 = 5; -const SYSREG_OP2_MASK: u32 = 0b111u32 << 5; - -/// Define the ID of system registers -#[macro_export] -macro_rules! arm64_sys_reg { - ($name: tt, $op0: tt, $op1: tt, $crn: tt, $crm: tt, $op2: tt) => { - pub const $name: u32 = SYSREG_HEAD - | ((($op0 as u32) << SYSREG_OP0_SHIFT) & SYSREG_OP0_MASK as u32) - | ((($op1 as u32) << SYSREG_OP1_SHIFT) & SYSREG_OP1_MASK as u32) - | ((($crn as u32) << SYSREG_CRN_SHIFT) & SYSREG_CRN_MASK as u32) - | ((($crm as u32) << SYSREG_CRM_SHIFT) & SYSREG_CRM_MASK as u32) - | ((($op2 as u32) << SYSREG_OP2_SHIFT) & SYSREG_OP2_MASK as u32); - }; -} - -arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5); -arm64_sys_reg!(ID_AA64MMFR0_EL1, 3, 0, 0, 7, 0); -arm64_sys_reg!(TTBR1_EL1, 3, 0, 2, 0, 1); -arm64_sys_reg!(TCR_EL1, 3, 0, 2, 0, 2); diff --git a/hypervisor/src/arch/aarch64/regs.rs b/hypervisor/src/arch/aarch64/regs.rs index 73eab69bb..e1a51a848 100644 --- a/hypervisor/src/arch/aarch64/regs.rs +++ b/hypervisor/src/arch/aarch64/regs.rs @@ -175,3 +175,44 @@ const PSR_A_BIT: u64 = 0x0000_0100; const PSR_D_BIT: u64 = 0x0000_0200; // Taken from arch/arm64/kvm/inject_fault.c. pub const PSTATE_FAULT_BITS_64: u64 = PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | PSR_I_BIT | PSR_D_BIT; + +// AArch64 system register encoding: +// See https://developer.arm.com/documentation/ddi0487 (chapter D12) +// +// 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0 +// +----------+---+-----+-----+-----+-----+-----+----+ +// |1101010100| L | op0 | op1 | CRn | CRm | op2 | Rt | +// +----------+---+-----+-----+-----+-----+-----+----+ +// +// Notes: +// - L and Rt are reserved as implementation defined fields, ignored. + +const SYSREG_HEAD: u32 = 0b1101010100u32 << 22; +const SYSREG_OP0_SHIFT: u32 = 19; +const SYSREG_OP0_MASK: u32 = 0b11u32 << 19; +const SYSREG_OP1_SHIFT: u32 = 16; +const SYSREG_OP1_MASK: u32 = 0b111u32 << 16; +const SYSREG_CRN_SHIFT: u32 = 12; +const SYSREG_CRN_MASK: u32 = 0b1111u32 << 12; +const SYSREG_CRM_SHIFT: u32 = 8; +const SYSREG_CRM_MASK: u32 = 0b1111u32 << 8; +const SYSREG_OP2_SHIFT: u32 = 5; +const SYSREG_OP2_MASK: u32 = 0b111u32 << 5; + +/// Define the ID of system registers +#[macro_export] +macro_rules! arm64_sys_reg { + ($name: tt, $op0: tt, $op1: tt, $crn: tt, $crm: tt, $op2: tt) => { + pub const $name: u32 = SYSREG_HEAD + | ((($op0 as u32) << SYSREG_OP0_SHIFT) & SYSREG_OP0_MASK as u32) + | ((($op1 as u32) << SYSREG_OP1_SHIFT) & SYSREG_OP1_MASK as u32) + | ((($crn as u32) << SYSREG_CRN_SHIFT) & SYSREG_CRN_MASK as u32) + | ((($crm as u32) << SYSREG_CRM_SHIFT) & SYSREG_CRM_MASK as u32) + | ((($op2 as u32) << SYSREG_OP2_SHIFT) & SYSREG_OP2_MASK as u32); + }; +} + +arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5); +arm64_sys_reg!(ID_AA64MMFR0_EL1, 3, 0, 0, 7, 0); +arm64_sys_reg!(TTBR1_EL1, 3, 0, 2, 0, 1); +arm64_sys_reg!(TCR_EL1, 3, 0, 2, 0, 2); diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 70ad93c54..663119e2d 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -25,8 +25,6 @@ use std::{cmp, io, result, thread}; use acpi_tables::sdt::Sdt; use acpi_tables::{aml, Aml}; use anyhow::anyhow; -#[cfg(all(target_arch = "aarch64", feature = "guest_debug"))] -use arch::aarch64::regs; #[cfg(target_arch = "x86_64")] use arch::x86_64::get_x2apic_id; use arch::{EntryPoint, NumaNodes}; @@ -37,6 +35,8 @@ use devices::interrupt_controller::InterruptController; 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::arch::aarch64::regs::{ID_AA64MMFR0_EL1, TCR_EL1, TTBR1_EL1}; #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))] use hypervisor::arch::x86::msr_index; #[cfg(target_arch = "x86_64")] @@ -1703,19 +1703,19 @@ impl CpuManager { .lock() .unwrap() .vcpu - .get_sys_reg(regs::TCR_EL1) + .get_sys_reg(TCR_EL1) .map_err(|e| Error::TranslateVirtualAddress(e.into()))?; let ttbr1_el1: u64 = self.vcpus[usize::from(cpu_id)] .lock() .unwrap() .vcpu - .get_sys_reg(regs::TTBR1_EL1) + .get_sys_reg(TTBR1_EL1) .map_err(|e| Error::TranslateVirtualAddress(e.into()))?; let id_aa64mmfr0_el1: u64 = self.vcpus[usize::from(cpu_id)] .lock() .unwrap() .vcpu - .get_sys_reg(regs::ID_AA64MMFR0_EL1) + .get_sys_reg(ID_AA64MMFR0_EL1) .map_err(|e| Error::TranslateVirtualAddress(e.into()))?; // Bit 55 of the VA determines the range, high (0xFFFxxx...) @@ -2937,8 +2937,8 @@ mod tests { #[cfg(feature = "kvm")] use std::mem; - use arch::aarch64::regs; use arch::layout; + use hypervisor::arch::aarch64::regs::MPIDR_EL1; #[cfg(feature = "kvm")] use hypervisor::kvm::aarch64::is_system_register; #[cfg(feature = "kvm")] @@ -2973,10 +2973,10 @@ mod tests { vm.get_preferred_target(&mut kvi).unwrap(); // Must fail when vcpu is not initialized yet. - vcpu.get_sys_reg(regs::MPIDR_EL1).unwrap_err(); + vcpu.get_sys_reg(MPIDR_EL1).unwrap_err(); vcpu.vcpu_init(&kvi).unwrap(); - assert_eq!(vcpu.get_sys_reg(regs::MPIDR_EL1).unwrap(), 0x80000000); + assert_eq!(vcpu.get_sys_reg(MPIDR_EL1).unwrap(), 0x80000000); } #[cfg(feature = "kvm")]