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

[Xen-changelog] [xen staging] x86/vhpet: check that the set interrupt route is valid



commit ec40d3fe2147d7671d512d22b1dd418eff0124b1
Author:     Roger Pau Monné <roger.pau@xxxxxxxxxx>
AuthorDate: Thu Jul 5 15:43:28 2018 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu Jul 5 15:43:28 2018 +0200

    x86/vhpet: check that the set interrupt route is valid
    
    The value written by the guest must be valid according to the mask
    provided in the interrupt routing capabilities register. If the
    interrupt is not valid set it to the first valid IRQ in the
    capabilities field if the timer is enabled, else just clear the field.
    
    Also refuse to start any timer that has an invalid interrupt route.
    
    Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/hvm/hpet.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index 28377091ca..f7ef4f7514 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -73,6 +73,9 @@
     ((timer_config(h, n) & HPET_TN_INT_ROUTE_CAP_MASK) \
         >> HPET_TN_INT_ROUTE_CAP_SHIFT)
 
+#define timer_int_route_valid(h, n) \
+    ((1u << timer_int_route(h, n)) & timer_int_route_cap(h, n))
+
 static inline uint64_t hpet_read_maincounter(HPETState *h, uint64_t guest_time)
 {
     ASSERT(rw_is_locked(&h->lock));
@@ -244,6 +247,12 @@ static void hpet_set_timer(HPETState *h, unsigned int tn,
     if ( !timer_enabled(h, tn) )
         return;
 
+    if ( !timer_int_route_valid(h, tn) )
+    {
+        ASSERT_UNREACHABLE();
+        return;
+    }
+
     tn_cmp   = hpet_get_comparator(h, tn, guest_time);
     cur_tick = hpet_read_maincounter(h, guest_time);
     if ( timer_is_32bit(h, tn) )
@@ -304,6 +313,24 @@ static inline uint64_t hpet_fixup_reg(
     return new;
 }
 
+static void timer_sanitize_int_route(HPETState *h, unsigned int tn)
+{
+    if ( timer_int_route_valid(h, tn) )
+        return;
+
+    timer_config(h, tn) &= ~HPET_TN_ROUTE;
+    if ( !timer_enabled(h, tn) )
+        return;
+
+    /*
+     * If the requested interrupt is not valid and the timer is
+     * enabled pick the first irq.
+     */
+    timer_config(h, tn) |=
+        MASK_INSR(find_first_set_bit(timer_int_route_cap(h, tn)),
+                  HPET_TN_ROUTE);
+}
+
 static int hpet_write(
     struct vcpu *v, unsigned long addr,
     unsigned int length, unsigned long val)
@@ -386,6 +413,8 @@ static int hpet_write(
 
         h->hpet.timers[tn].config = hpet_fixup_reg(new_val, old_val, 0x3f4e);
 
+        timer_sanitize_int_route(h, tn);
+
         if ( timer_level(h, tn) )
         {
             gdprintk(XENLOG_ERR,
@@ -621,6 +650,7 @@ static int hpet_load(struct domain *d, hvm_domain_context_t 
*h)
         if ( timer_is_32bit(hp, i) )
             cmp = (uint32_t)cmp;
         hp->hpet.timers[i].cmp = cmp;
+        timer_sanitize_int_route(hp, i);
     }
 #undef C
 
--
generated by git-patchbot for /home/xen/git/xen.git#staging

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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