From 177d8b80e2e0c2aae1b8ca870838c98b0f8bfbca Mon Sep 17 00:00:00 2001 From: Ruben Hakobyan Date: Thu, 21 May 2026 19:01:08 -0700 Subject: [PATCH] hypervisor: Extract FPSIMD register access into helper methods Move the inline FPSIMD register read/write code from `get_regs()` and `set_regs()` into dedicated `get_fpsimd_regs()` and `set_fpsimd_regs()` methods on `KvmVcpu`. This helps keep the larger `{get,set}_regs()` easier to understand and prepares them for a subsequent commit that needs to conditionally skip FPSIMD access when SVE registers are used instead. Signed-off-by: Ruben Hakobyan --- hypervisor/src/kvm/mod.rs | 125 ++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 53 deletions(-) diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 39f76dca3..a7fa74ca6 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -1895,33 +1895,7 @@ impl cpu::Vcpu for KvmVcpu { off += std::mem::size_of::(); } - // Now moving on to floating point registers which are stored in the user_fpsimd_state in the kernel: - // https://elixir.bootlin.com/linux/v4.9.62/source/arch/arm64/include/uapi/asm/kvm.h#L53 - let mut off = offset_of!(kvm_regs, fp_regs.vregs); - for i in 0..32 { - let mut bytes = [0_u8; 16]; - self.fd - .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U128, off), &mut bytes) - .map_err(|e| cpu::HypervisorCpuError::GetAarchCoreRegister(e.into()))?; - state.fp_regs.vregs[i] = u128::from_le_bytes(bytes); - off += mem::size_of::(); - } - - // Floating-point Status Register - let off = offset_of!(kvm_regs, fp_regs.fpsr); - let mut bytes = [0_u8; 4]; - self.fd - .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes) - .map_err(|e| cpu::HypervisorCpuError::GetAarchCoreRegister(e.into()))?; - state.fp_regs.fpsr = u32::from_le_bytes(bytes); - - // Floating-point Control Register - let off = offset_of!(kvm_regs, fp_regs.fpcr); - let mut bytes = [0_u8; 4]; - self.fd - .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes) - .map_err(|e| cpu::HypervisorCpuError::GetAarchCoreRegister(e.into()))?; - state.fp_regs.fpcr = u32::from_le_bytes(bytes); + self.get_fpsimd_regs(&mut state)?; Ok(state.into()) } @@ -2075,32 +2049,7 @@ impl cpu::Vcpu for KvmVcpu { off += std::mem::size_of::(); } - let mut off = offset_of!(kvm_regs, fp_regs.vregs); - for i in 0..32 { - self.fd - .set_one_reg( - arm64_core_reg_id!(KVM_REG_SIZE_U128, off), - &kvm_regs_state.fp_regs.vregs[i].to_le_bytes(), - ) - .map_err(|e| cpu::HypervisorCpuError::SetAarchCoreRegister(e.into()))?; - off += mem::size_of::(); - } - - let off = offset_of!(kvm_regs, fp_regs.fpsr); - self.fd - .set_one_reg( - arm64_core_reg_id!(KVM_REG_SIZE_U32, off), - &kvm_regs_state.fp_regs.fpsr.to_le_bytes(), - ) - .map_err(|e| cpu::HypervisorCpuError::SetAarchCoreRegister(e.into()))?; - - let off = offset_of!(kvm_regs, fp_regs.fpcr); - self.fd - .set_one_reg( - arm64_core_reg_id!(KVM_REG_SIZE_U32, off), - &kvm_regs_state.fp_regs.fpcr.to_le_bytes(), - ) - .map_err(|e| cpu::HypervisorCpuError::SetAarchCoreRegister(e.into()))?; + self.set_fpsimd_regs(&kvm_regs_state)?; Ok(()) } @@ -3454,6 +3403,76 @@ impl cpu::Vcpu for KvmVcpu { } } +#[cfg(target_arch = "aarch64")] +impl KvmVcpu { + fn get_fpsimd_regs(&self, regs: &mut kvm_regs) -> cpu::Result<()> { + // Floating point registers are stored in the user_fpsimd_state in the kernel: + // https://elixir.bootlin.com/linux/v4.9.62/source/arch/arm64/include/uapi/asm/kvm.h#L53 + let mut off = offset_of!(kvm_regs, fp_regs.vregs); + for i in 0..32 { + let mut bytes = [0_u8; 16]; + self.fd + .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U128, off), &mut bytes) + .map_err(|e| cpu::HypervisorCpuError::GetAarchCoreRegister(e.into()))?; + regs.fp_regs.vregs[i] = u128::from_le_bytes(bytes); + off += mem::size_of::(); + } + + // Floating-point Status Register + let off = offset_of!(kvm_regs, fp_regs.fpsr); + let mut bytes = [0_u8; 4]; + self.fd + .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes) + .map_err(|e| cpu::HypervisorCpuError::GetAarchCoreRegister(e.into()))?; + regs.fp_regs.fpsr = u32::from_le_bytes(bytes); + + // Floating-point Control Register + let off = offset_of!(kvm_regs, fp_regs.fpcr); + let mut bytes = [0_u8; 4]; + self.fd + .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes) + .map_err(|e| cpu::HypervisorCpuError::GetAarchCoreRegister(e.into()))?; + regs.fp_regs.fpcr = u32::from_le_bytes(bytes); + + Ok(()) + } + + fn set_fpsimd_regs(&self, regs: &kvm_regs) -> cpu::Result<()> { + // Floating point registers are stored in the user_fpsimd_state in the kernel: + // https://elixir.bootlin.com/linux/v4.9.62/source/arch/arm64/include/uapi/asm/kvm.h#L53 + let mut off = offset_of!(kvm_regs, fp_regs.vregs); + for i in 0..32 { + self.fd + .set_one_reg( + arm64_core_reg_id!(KVM_REG_SIZE_U128, off), + ®s.fp_regs.vregs[i].to_le_bytes(), + ) + .map_err(|e| cpu::HypervisorCpuError::SetAarchCoreRegister(e.into()))?; + off += mem::size_of::(); + } + + // Floating-point Status Register + let off = offset_of!(kvm_regs, fp_regs.fpsr); + self.fd + .set_one_reg( + arm64_core_reg_id!(KVM_REG_SIZE_U32, off), + ®s.fp_regs.fpsr.to_le_bytes(), + ) + .map_err(|e| cpu::HypervisorCpuError::SetAarchCoreRegister(e.into()))?; + + // Floating-point Control Register + let off = offset_of!(kvm_regs, fp_regs.fpcr); + self.fd + .set_one_reg( + arm64_core_reg_id!(KVM_REG_SIZE_U32, off), + ®s.fp_regs.fpcr.to_le_bytes(), + ) + .map_err(|e| cpu::HypervisorCpuError::SetAarchCoreRegister(e.into()))?; + + Ok(()) + } +} + impl KvmVcpu { #[cfg(target_arch = "x86_64")] ///