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")]