From 1719d707216c919ac0d453bbfccf210c7104b31c Mon Sep 17 00:00:00 2001 From: Nuno Das Neves Date: Thu, 11 Jan 2024 00:46:28 +0000 Subject: [PATCH] ioctls/vcpu: Introduce hvcall_ version of set/get vp registers Signed-off-by: Nuno Das Neves --- mshv-ioctls/src/ioctls/vcpu.rs | 66 ++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/mshv-ioctls/src/ioctls/vcpu.rs b/mshv-ioctls/src/ioctls/vcpu.rs index aedf3de6..6b0cbea6 100644 --- a/mshv-ioctls/src/ioctls/vcpu.rs +++ b/mshv-ioctls/src/ioctls/vcpu.rs @@ -80,12 +80,45 @@ impl VcpuFd { } Ok(()) } - /// Sets a vCPU register to input value. - /// - /// # Arguments - /// - /// * `reg_name` - general purpose register name. - /// * `reg_value` - register value. + /// Generic hvcall version of get_reg + pub fn hvcall_get_reg(&self, reg_assocs: &mut [hv_register_assoc]) -> Result<()> { + if reg_assocs.is_empty() { + return Err(libc::EINVAL.into()); + } + let reg_names: Vec = reg_assocs.iter().map(|assoc| assoc.name).collect(); + let input = make_rep_input!( + hv_input_get_vp_registers { + vp_index: self.index, + ..Default::default() + }, + names, + reg_names.as_slice() + ); + let mut output: Vec = reg_names + .iter() + .map(|_| hv_register_value { + reg128: hv_u128 { + ..Default::default() + }, + }) + .collect(); + let output_slice = output.as_mut_slice(); + + let mut args = make_rep_args!(HVCALL_GET_VP_REGISTERS, input, output_slice); + self.hvcall(&mut args)?; + + if args.reps as usize != reg_assocs.len() { + // TODO better handling? partial success? + return Err(libc::EINTR.into()); + } + + for (assoc, value) in reg_assocs.iter_mut().zip(output.iter()) { + assoc.value = *value; + } + + Ok(()) + } + /// Set vcpu register values by providing an array of register assocs #[cfg(not(target_arch = "aarch64"))] pub fn set_reg(&self, regs: &[hv_register_assoc]) -> Result<()> { let hv_vp_register_args = mshv_vp_registers { @@ -97,6 +130,27 @@ impl VcpuFd { if ret != 0 { return Err(MshvError::from_last_errno()); } + + Ok(()) + } + /// Generic hypercall version of set_reg + pub fn hvcall_set_reg(&self, reg_assocs: &[hv_register_assoc]) -> Result<()> { + let input = make_rep_input!( + hv_input_set_vp_registers { + vp_index: self.index, + ..Default::default() + }, + elements, + reg_assocs + ); + let mut args = make_rep_args!(HVCALL_SET_VP_REGISTERS, input); + self.hvcall(&mut args)?; + + if args.reps as usize != reg_assocs.len() { + // TODO better handling? partial success? + return Err(libc::EINTR.into()); + } + Ok(()) } /// Sets the vCPU general purpose registers