[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging-4.16] xen/arm: avoid overflow when setting vtimer in context switch



commit 48e7440ec6eb6eb99011a549a649c44632f69edb
Author:     Jiamei Xie <jiamei.xie@xxxxxxx>
AuthorDate: Wed Jul 6 16:25:58 2022 +0800
Commit:     Stefano Stabellini <stefano.stabellini@xxxxxxx>
CommitDate: Wed Aug 3 14:58:04 2022 -0700

    xen/arm: avoid overflow when setting vtimer in context switch
    
    virt_vtimer_save() will calculate the next deadline when the vCPU is
    scheduled out. At the moment, Xen will use the following equation:
    
      virt_timer.cval + virt_time_base.offset - boot_count
    
    The three values are 64-bit and one (cval) is controlled by domain. In
    theory, it would be possible that the domain has started a long time
    after the system boot. So virt_time_base.offset - boot_count may be a
    large numbers.
    
    This means a domain may inadvertently set a cval so the result would
    overflow. Consequently, the deadline would be set very far in the
    future. This could result to loss of timer interrupts or the vCPU
    getting block "forever".
    
    One way to solve the problem, would be to separately
       1) compute when the domain was created in ns
       2) convert cval to ns
       3) Add 1 and 2 together
    
    The first part of the equation never change (the value is set/known at
    domain creation). So take the opportunity to store it in domain structure.
    
    Signed-off-by: Jiamei Xie <jiamei.xie@xxxxxxx>
    Reviewed-by: Julien Grall <jgrall@xxxxxxxxxx>
    Reviewed-by: Bertrand Marquis <bertrand.marquis@xxxxxxx>
    (cherry picked from commit 6655eb81092a94e065fdcd0b47a1b1d69dc4e54c)
---
 xen/arch/arm/vtimer.c        | 9 ++++++---
 xen/include/asm-arm/domain.h | 1 +
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c
index 0196951af4..23198d0396 100644
--- a/xen/arch/arm/vtimer.c
+++ b/xen/arch/arm/vtimer.c
@@ -63,7 +63,9 @@ static void virt_timer_expired(void *data)
 int domain_vtimer_init(struct domain *d, struct xen_arch_domainconfig *config)
 {
     d->arch.virt_timer_base.offset = get_cycles();
-    d->time_offset.seconds = ticks_to_ns(d->arch.virt_timer_base.offset - 
boot_count);
+    d->arch.virt_timer_base.nanoseconds =
+        ticks_to_ns(d->arch.virt_timer_base.offset - boot_count);
+    d->time_offset.seconds = d->arch.virt_timer_base.nanoseconds;
     do_div(d->time_offset.seconds, 1000000000);
 
     config->clock_frequency = timer_dt_clock_frequency;
@@ -144,8 +146,9 @@ void virt_timer_save(struct vcpu *v)
     if ( (v->arch.virt_timer.ctl & CNTx_CTL_ENABLE) &&
          !(v->arch.virt_timer.ctl & CNTx_CTL_MASK))
     {
-        set_timer(&v->arch.virt_timer.timer, 
ticks_to_ns(v->arch.virt_timer.cval +
-                  v->domain->arch.virt_timer_base.offset - boot_count));
+        set_timer(&v->arch.virt_timer.timer,
+                  v->domain->arch.virt_timer_base.nanoseconds +
+                  ticks_to_ns(v->arch.virt_timer.cval));
     }
 }
 
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 9b3647587a..7f8ddd3f5c 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -58,6 +58,7 @@ struct arch_domain
 
     struct {
         uint64_t offset;
+        s_time_t nanoseconds;
     } virt_timer_base;
 
     struct vgic_dist vgic;
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.16



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.