diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index 437b43a44..1eba6b53a 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -9,9 +9,7 @@ // #[cfg(target_arch = "aarch64")] -use crate::aarch64::VcpuInit; -#[cfg(target_arch = "aarch64")] -use crate::aarch64::{RegList, Register, StandardRegisters}; +use crate::aarch64::{RegList, StandardRegisters, VcpuInit}; #[cfg(target_arch = "x86_64")] use crate::arch::x86::{ CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters, @@ -378,16 +376,6 @@ pub trait Vcpu: Send + Sync { #[cfg(target_arch = "aarch64")] 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>; - /// - /// 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. /// #[cfg(target_arch = "aarch64")] diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index bbb71c913..7fd1667e9 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -1654,53 +1654,6 @@ impl cpu::Vcpu for KvmVcpu { .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> { - // Call KVM_GET_REG_LIST to get all registers available to the guest. For ArmV8 there are - // around 500 registers. - let mut state: Vec = 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. /// #[cfg(target_arch = "aarch64")] @@ -1886,8 +1839,41 @@ impl cpu::Vcpu for KvmVcpu { mpidr: self.read_mpidr()?, ..Default::default() }; + // Get core registers 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 = 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()) } @@ -1983,8 +1969,15 @@ impl cpu::Vcpu for KvmVcpu { #[cfg(target_arch = "aarch64")] fn set_state(&self, state: &CpuState) -> cpu::Result<()> { let state: VcpuKvmState = state.clone().into(); + // Set core registers 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())?; Ok(()) diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 2e73037ae..8302b2ea3 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -2411,9 +2411,9 @@ mod tests { #[cfg(test)] mod tests { use arch::layout; - use hypervisor::kvm::aarch64::{is_system_register, MPIDR_EL1}; + use hypervisor::kvm::aarch64::is_system_register; 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, }; use hypervisor::{arm64_core_reg_id, offset__of}; @@ -2498,50 +2498,6 @@ mod tests { 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 = 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] fn test_get_set_mpstate() { let hv = hypervisor::new().unwrap();