@@ -14,6 +14,7 @@ use log::warn;
1414
1515use  super :: get_fdt_addr; 
1616use  super :: regs:: * ; 
17+ use  crate :: vstate:: kvm:: OptionalCapabilities ; 
1718use  crate :: vstate:: memory:: GuestMemoryMmap ; 
1819
1920/// Errors thrown while setting aarch64 registers. 
@@ -79,6 +80,7 @@ pub fn setup_boot_regs(
7980    cpu_id :  u8 , 
8081    boot_ip :  u64 , 
8182    mem :  & GuestMemoryMmap , 
83+     optional_capabilities :  & OptionalCapabilities , 
8284)  -> Result < ( ) ,  VcpuError >  { 
8385    let  kreg_off = offset_of ! ( kvm_regs,  regs) ; 
8486
@@ -113,17 +115,16 @@ pub fn setup_boot_regs(
113115        // Resetting KVM_REG_ARM_PTIMER_CNT for single vcpu is enough because there is only 
114116        // one timer struct with offsets per VM. 
115117        // Because the access to KVM_REG_ARM_PTIMER_CNT is only present starting 6.4 kernel, 
116-         // we don't fail if ioctl returns an error. 
118+         // we only do the reset if KVM_CAP_COUNTER_OFFSET is present as it was added 
119+         // in the same patch series as the ability to set the KVM_REG_ARM_PTIMER_CNT register. 
117120        // Path series which introduced the needed changes: 
118121        // https://lore.kernel.org/all/[email protected] /  119122        // Note: the value observed by the guest will still be above 0, because there is a delta 
120123        // time between this resetting and first call to KVM_RUN. 
121-         let  zero:  u64  = 0 ; 
122-         if  vcpufd
123-             . set_one_reg ( KVM_REG_ARM_PTIMER_CNT ,  & zero. to_le_bytes ( ) ) 
124-             . is_err ( ) 
125-         { 
126-             warn ! ( "Unable to reset VM physical counter. VM will use host value instead." ) ; 
124+         if  optional_capabilities. counter_offset  { 
125+             vcpufd
126+                 . set_one_reg ( KVM_REG_ARM_PTIMER_CNT ,  & [ 0 ;  8 ] ) 
127+                 . map_err ( |err| VcpuError :: SetOneReg ( id,  err) ) ?; 
127128        } 
128129    } 
129130    Ok ( ( ) ) 
@@ -245,8 +246,9 @@ mod tests {
245246        let  vm = kvm. fd . create_vm ( ) . unwrap ( ) ; 
246247        let  vcpu = vm. create_vcpu ( 0 ) . unwrap ( ) ; 
247248        let  mem = arch_mem ( layout:: FDT_MAX_SIZE  + 0x1000 ) ; 
249+         let  optional_capabilities = kvm. optional_capabilities ( ) ; 
248250
249-         let  res = setup_boot_regs ( & vcpu,  0 ,  0x0 ,  & mem) ; 
251+         let  res = setup_boot_regs ( & vcpu,  0 ,  0x0 ,  & mem,   & optional_capabilities ) ; 
250252        assert ! ( matches!( 
251253            res. unwrap_err( ) , 
252254            VcpuError :: SetOneReg ( 0x6030000000100042 ,  _) 
@@ -256,14 +258,17 @@ mod tests {
256258        vm. get_preferred_target ( & mut  kvi) . unwrap ( ) ; 
257259        vcpu. vcpu_init ( & kvi) . unwrap ( ) ; 
258260
259-         setup_boot_regs ( & vcpu,  0 ,  0x0 ,  & mem) . unwrap ( ) ; 
261+         setup_boot_regs ( & vcpu,  0 ,  0x0 ,  & mem,   & optional_capabilities ) . unwrap ( ) ; 
260262
261263        // Check that the register is reset on compatible kernels. 
262264        // Because there is a delta in time between we reset the register and time we 
263265        // read it, we cannot compare with 0. Instead we read CNTVNT_EL0 (Virtual counter) 
264266        // from the host. The host value should be much bigger than the VM physical counter. 
265-         let  mut  reg_bytes = [ 0_u8 ;  8 ] ; 
266-         if  vcpu. get_one_reg ( SYS_CNTPCT_EL0 ,  & mut  reg_bytes) . is_ok ( )  { 
267+         if  optional_capabilities. counter_offset  { 
268+             let  mut  reg_bytes = [ 0_u8 ;  8 ] ; 
269+             vcpu. get_one_reg ( SYS_CNTPCT_EL0 ,  & mut  reg_bytes) . unwrap ( ) ; 
270+             let  counter_value = u64:: from_le_bytes ( reg_bytes) ; 
271+ 
267272            let  virt_count = unsafe  { 
268273                // Rust is so smart, it cannot figure out that `virt_count` 
269274                // is read later in the assert!, so it complains about unused assignment. 
@@ -276,7 +281,7 @@ mod tests {
276281                ) ; 
277282                virt_count
278283            } ; 
279-              let  counter_value = u64 :: from_le_bytes ( reg_bytes ) ; 
284+ 
280285            assert ! ( counter_value < virt_count) ; 
281286        } 
282287    } 
0 commit comments