mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-09-28 17:45:44 +00:00
hypervisor: Remove get/set_sys_regs()
on AArch64
`hypervisor::Vcpu::get/set_sys_regs()` are only used in Vcpu internally. Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
parent
e1a70f676a
commit
f7b6d99c2d
@ -9,9 +9,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use crate::aarch64::VcpuInit;
|
use crate::aarch64::{RegList, StandardRegisters, VcpuInit};
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
use crate::aarch64::{RegList, Register, StandardRegisters};
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::arch::x86::{
|
use crate::arch::x86::{
|
||||||
CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters,
|
CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters,
|
||||||
@ -378,16 +376,6 @@ pub trait Vcpu: Send + Sync {
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>;
|
fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>;
|
||||||
///
|
///
|
||||||
/// Save the state of the system registers.
|
|
||||||
///
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
fn get_sys_regs(&self) -> Result<Vec<Register>>;
|
|
||||||
///
|
|
||||||
/// Restore the state of the system registers.
|
|
||||||
///
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
fn set_sys_regs(&self, state: &[Register]) -> Result<()>;
|
|
||||||
///
|
|
||||||
/// Read the MPIDR - Multiprocessor Affinity Register.
|
/// Read the MPIDR - Multiprocessor Affinity Register.
|
||||||
///
|
///
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
@ -1654,53 +1654,6 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
|
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
|
||||||
}
|
}
|
||||||
///
|
///
|
||||||
/// Save the state of the system registers.
|
|
||||||
///
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
fn get_sys_regs(&self) -> cpu::Result<Vec<Register>> {
|
|
||||||
// Call KVM_GET_REG_LIST to get all registers available to the guest. For ArmV8 there are
|
|
||||||
// around 500 registers.
|
|
||||||
let mut state: Vec<Register> = Vec::new();
|
|
||||||
let mut reg_list = RegList::new(500).unwrap();
|
|
||||||
self.fd
|
|
||||||
.get_reg_list(&mut reg_list)
|
|
||||||
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))?;
|
|
||||||
|
|
||||||
// At this point reg_list should contain: core registers and system registers.
|
|
||||||
// The register list contains the number of registers and their ids. We will be needing to
|
|
||||||
// call KVM_GET_ONE_REG on each id in order to save all of them. We carve out from the list
|
|
||||||
// the core registers which are represented in the kernel by kvm_regs structure and for which
|
|
||||||
// we can calculate the id based on the offset in the structure.
|
|
||||||
reg_list.retain(|regid| is_system_register(*regid));
|
|
||||||
|
|
||||||
// Now, for the rest of the registers left in the previously fetched register list, we are
|
|
||||||
// simply calling KVM_GET_ONE_REG.
|
|
||||||
let indices = reg_list.as_slice();
|
|
||||||
for index in indices.iter() {
|
|
||||||
state.push(kvm_bindings::kvm_one_reg {
|
|
||||||
id: *index,
|
|
||||||
addr: self
|
|
||||||
.fd
|
|
||||||
.get_one_reg(*index)
|
|
||||||
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(state)
|
|
||||||
}
|
|
||||||
///
|
|
||||||
/// Restore the state of the system registers.
|
|
||||||
///
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
fn set_sys_regs(&self, state: &[Register]) -> cpu::Result<()> {
|
|
||||||
for reg in state {
|
|
||||||
self.fd
|
|
||||||
.set_one_reg(reg.id, reg.addr)
|
|
||||||
.map_err(|e| cpu::HypervisorCpuError::SetSysRegister(e.into()))?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
///
|
|
||||||
/// Read the MPIDR - Multiprocessor Affinity Register.
|
/// Read the MPIDR - Multiprocessor Affinity Register.
|
||||||
///
|
///
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
@ -1886,8 +1839,41 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
mpidr: self.read_mpidr()?,
|
mpidr: self.read_mpidr()?,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
// Get core registers
|
||||||
state.core_regs = self.get_regs()?;
|
state.core_regs = self.get_regs()?;
|
||||||
state.sys_regs = self.get_sys_regs()?;
|
|
||||||
|
// 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();
|
||||||
|
self.fd
|
||||||
|
.get_reg_list(&mut reg_list)
|
||||||
|
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))?;
|
||||||
|
|
||||||
|
// At this point reg_list should contain: core registers and system
|
||||||
|
// registers.
|
||||||
|
// The register list contains the number of registers and their ids. We
|
||||||
|
// will be needing to call KVM_GET_ONE_REG on each id in order to save
|
||||||
|
// all of them. We carve out from the list the core registers which are
|
||||||
|
// represented in the kernel by kvm_regs structure and for which we can
|
||||||
|
// calculate the id based on the offset in the structure.
|
||||||
|
reg_list.retain(|regid| is_system_register(*regid));
|
||||||
|
|
||||||
|
// Now, for the rest of the registers left in the previously fetched
|
||||||
|
// register list, we are simply calling KVM_GET_ONE_REG.
|
||||||
|
let indices = reg_list.as_slice();
|
||||||
|
for index in indices.iter() {
|
||||||
|
sys_regs.push(kvm_bindings::kvm_one_reg {
|
||||||
|
id: *index,
|
||||||
|
addr: self
|
||||||
|
.fd
|
||||||
|
.get_one_reg(*index)
|
||||||
|
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
state.sys_regs = sys_regs;
|
||||||
|
|
||||||
Ok(state.into())
|
Ok(state.into())
|
||||||
}
|
}
|
||||||
@ -1983,8 +1969,15 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
fn set_state(&self, state: &CpuState) -> cpu::Result<()> {
|
fn set_state(&self, state: &CpuState) -> cpu::Result<()> {
|
||||||
let state: VcpuKvmState = state.clone().into();
|
let state: VcpuKvmState = state.clone().into();
|
||||||
|
// Set core registers
|
||||||
self.set_regs(&state.core_regs)?;
|
self.set_regs(&state.core_regs)?;
|
||||||
self.set_sys_regs(&state.sys_regs)?;
|
// Set system registers
|
||||||
|
for reg in &state.sys_regs {
|
||||||
|
self.fd
|
||||||
|
.set_one_reg(reg.id, reg.addr)
|
||||||
|
.map_err(|e| cpu::HypervisorCpuError::SetSysRegister(e.into()))?;
|
||||||
|
}
|
||||||
|
|
||||||
self.set_mp_state(state.mp_state.into())?;
|
self.set_mp_state(state.mp_state.into())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2411,9 +2411,9 @@ mod tests {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use arch::layout;
|
use arch::layout;
|
||||||
use hypervisor::kvm::aarch64::{is_system_register, MPIDR_EL1};
|
use hypervisor::kvm::aarch64::is_system_register;
|
||||||
use hypervisor::kvm::kvm_bindings::{
|
use hypervisor::kvm::kvm_bindings::{
|
||||||
kvm_one_reg, kvm_regs, kvm_vcpu_init, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG,
|
kvm_regs, kvm_vcpu_init, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG,
|
||||||
KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
||||||
};
|
};
|
||||||
use hypervisor::{arm64_core_reg_id, offset__of};
|
use hypervisor::{arm64_core_reg_id, offset__of};
|
||||||
@ -2498,50 +2498,6 @@ mod tests {
|
|||||||
assert_eq!(state.regs.pstate, pstate);
|
assert_eq!(state.regs.pstate, pstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_save_restore_system_regs() {
|
|
||||||
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();
|
|
||||||
vm.get_preferred_target(&mut kvi).unwrap();
|
|
||||||
|
|
||||||
// Must fail when vcpu is not initialized yet.
|
|
||||||
let mut state: Vec<kvm_one_reg> = Vec::new();
|
|
||||||
let res = vcpu.get_sys_regs();
|
|
||||||
assert!(res.is_err());
|
|
||||||
assert_eq!(
|
|
||||||
format!("{}", res.as_ref().unwrap_err()),
|
|
||||||
"Failed to retrieve list of registers: Exec format error (os error 8)"
|
|
||||||
);
|
|
||||||
|
|
||||||
state.push(kvm_one_reg {
|
|
||||||
id: MPIDR_EL1,
|
|
||||||
addr: 0x00,
|
|
||||||
});
|
|
||||||
let res = vcpu.set_sys_regs(&state);
|
|
||||||
assert!(res.is_err());
|
|
||||||
assert_eq!(
|
|
||||||
format!("{}", res.unwrap_err()),
|
|
||||||
"Failed to set system register: Exec format error (os error 8)"
|
|
||||||
);
|
|
||||||
|
|
||||||
vcpu.vcpu_init(&kvi).unwrap();
|
|
||||||
let res = vcpu.get_sys_regs();
|
|
||||||
assert!(res.is_ok());
|
|
||||||
state = res.unwrap();
|
|
||||||
|
|
||||||
let initial_mpidr: u64 = vcpu.read_mpidr().expect("Fail to read mpidr");
|
|
||||||
assert!(state.contains(&kvm_one_reg {
|
|
||||||
id: MPIDR_EL1,
|
|
||||||
addr: initial_mpidr
|
|
||||||
}));
|
|
||||||
|
|
||||||
assert!(vcpu.set_sys_regs(&state).is_ok());
|
|
||||||
let mpidr: u64 = vcpu.read_mpidr().expect("Fail to read mpidr");
|
|
||||||
assert_eq!(initial_mpidr, mpidr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_set_mpstate() {
|
fn test_get_set_mpstate() {
|
||||||
let hv = hypervisor::new().unwrap();
|
let hv = hypervisor::new().unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user