hypervisor: Add Vcpu::get_sys_reg() on AArch64

Added function `Vcpu::get_sys_reg()` to get single system register.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
Michael Zhao 2022-07-28 14:52:34 +08:00 committed by Rob Bradford
parent ecb66b5e94
commit 5b54dc60aa
2 changed files with 38 additions and 1 deletions

View File

@ -371,6 +371,11 @@ pub trait Vcpu: Send + Sync {
#[cfg(target_arch = "aarch64")]
fn read_mpidr(&self) -> Result<u64>;
///
/// Gets the value of a system register
///
#[cfg(target_arch = "aarch64")]
fn get_sys_reg(&self, sys_reg: u32) -> Result<u64>;
///
/// Configure core registers for a given CPU.
///
#[cfg(target_arch = "aarch64")]

View File

@ -80,7 +80,9 @@ pub use kvm_bindings::{
};
#[cfg(target_arch = "aarch64")]
use kvm_bindings::{
kvm_regs, user_fpsimd_state, user_pt_regs, KVM_NR_SPSR, KVM_REG_ARM64, KVM_REG_ARM_CORE,
kvm_regs, user_fpsimd_state, user_pt_regs, 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,
};
pub use kvm_ioctls;
@ -1645,6 +1647,36 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))
}
///
/// Gets the value of a system register
///
#[cfg(target_arch = "aarch64")]
fn get_sys_reg(&self, sys_reg: u32) -> cpu::Result<u64> {
//
// Arm Architecture Reference Manual defines the encoding of
// AArch64 system registers, see
// https://developer.arm.com/documentation/ddi0487 (chapter D12).
// While KVM defines another ID for each AArch64 system register,
// which is used in calling `KVM_G/SET_ONE_REG` to access a system
// register of a guest.
// A mapping exists between the Arm standard encoding and the KVM ID.
// This function takes the standard u32 ID as input parameter, converts
// it to the corresponding KVM ID, and call `KVM_GET_ONE_REG` API to
// get the value of the system parameter.
//
let id: u64 = KVM_REG_ARM64 as u64
| KVM_REG_SIZE_U64 as u64
| KVM_REG_ARM64_SYSREG as u64
| ((((sys_reg) >> 5)
& (KVM_REG_ARM64_SYSREG_OP0_MASK
| KVM_REG_ARM64_SYSREG_OP1_MASK
| KVM_REG_ARM64_SYSREG_CRN_MASK
| KVM_REG_ARM64_SYSREG_CRM_MASK
| KVM_REG_ARM64_SYSREG_OP2_MASK)) as u64);
self.fd
.get_one_reg(id)
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))
}
///
/// Configure core registers for a given CPU.
///
#[cfg(target_arch = "aarch64")]