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

[Xen-changelog] [xen master] x86/vpt: add support for level interrupts



commit 0bcbc971feaa7d9ef6d92b5b39a37819d449a821
Author:     Roger Pau Monné <roger.pau@xxxxxxxxxx>
AuthorDate: Tue Jul 24 15:52:47 2018 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Jul 24 15:52:47 2018 +0200

    x86/vpt: add support for level interrupts
    
    Level trigger interrupts will be asserted regardless of whether the
    interrupt is masked, and thus the callback will also be executed.
    
    Add a new 'level' parameter to create_periodic_time in order to create
    level triggered timers. None of the current users of vpt are switched
    to use level triggered interrupts yet.
    
    Note that periodic level triggered interrupts are not supported. This
    is because level triggered interrupts always require a deassert of the
    IO-APIC pin, which should be done by the caller of vpt at which point
    the caller should also reset the timer if required.
    
    Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/hvm/hpet.c       |  2 +-
 xen/arch/x86/hvm/i8254.c      |  4 ++--
 xen/arch/x86/hvm/rtc.c        |  2 +-
 xen/arch/x86/hvm/vlapic.c     |  8 ++++----
 xen/arch/x86/hvm/vpt.c        | 48 +++++++++++++++++++++++++++++++++++--------
 xen/include/asm-x86/hvm/vpt.h |  3 ++-
 6 files changed, 49 insertions(+), 18 deletions(-)

diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index 171afe9ac2..b7dcfa8af9 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -292,7 +292,7 @@ static void hpet_set_timer(HPETState *h, unsigned int tn,
     create_periodic_time(vhpet_vcpu(h), &h->pt[tn],
                          hpet_tick_to_ns(h, diff),
                          oneshot ? 0 : hpet_tick_to_ns(h, h->hpet.period[tn]),
-                         irq, NULL, NULL);
+                         irq, NULL, NULL, false);
 }
 
 static inline uint64_t hpet_fixup_reg(
diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c
index 992f08dd6c..b8ec56f8d3 100644
--- a/xen/arch/x86/hvm/i8254.c
+++ b/xen/arch/x86/hvm/i8254.c
@@ -191,14 +191,14 @@ static void pit_load_count(PITState *pit, int channel, 
int val)
         /* Periodic timer. */
         TRACE_2D(TRC_HVM_EMUL_PIT_START_TIMER, period, period);
         create_periodic_time(v, &pit->pt0, period, period, 0, pit_time_fired, 
-                             &pit->count_load_time[channel]);
+                             &pit->count_load_time[channel], false);
         break;
     case 1:
     case 4:
         /* One-shot timer. */
         TRACE_2D(TRC_HVM_EMUL_PIT_START_TIMER, period, 0);
         create_periodic_time(v, &pit->pt0, period, 0, 0, pit_time_fired,
-                             &pit->count_load_time[channel]);
+                             &pit->count_load_time[channel], false);
         break;
     default:
         TRACE_0D(TRC_HVM_EMUL_PIT_STOP_TIMER);
diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
index cb75b99ed1..96921bb5b5 100644
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -156,7 +156,7 @@ static void rtc_timer_update(RTCState *s)
                 {
                     TRACE_2D(TRC_HVM_EMUL_RTC_START_TIMER, delta, period);
                     create_periodic_time(v, &s->pt, delta, period,
-                                         RTC_IRQ, rtc_pf_callback, s);
+                                         RTC_IRQ, rtc_pf_callback, s, false);
                 }
                 else
                     s->check_ticks_since = now;
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index e79ff84f0c..fa43d8f133 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -762,7 +762,7 @@ static void vlapic_update_timer(struct vlapic *vlapic, 
uint32_t lvtt,
         create_periodic_time(current, &vlapic->pt, delta,
                              is_periodic ? period : 0, vlapic->pt.irq,
                              is_periodic ? vlapic_pt_cb : NULL,
-                             &vlapic->timer_last_update);
+                             &vlapic->timer_last_update, false);
 
         vlapic->timer_last_update = vlapic->pt.last_plt_gtime;
         if ( !tmict_updated )
@@ -1166,7 +1166,7 @@ void vlapic_tdt_msr_set(struct vlapic *vlapic, uint64_t 
value)
                         TRC_PAR_LONG(0LL), vlapic->pt.irq);
         create_periodic_time(v, &vlapic->pt, delta, 0,
                              vlapic->pt.irq, vlapic_tdt_pt_cb,
-                             &vlapic->timer_last_update);
+                             &vlapic->timer_last_update, false);
         vlapic->timer_last_update = vlapic->pt.last_plt_gtime;
     }
     else
@@ -1180,7 +1180,7 @@ void vlapic_tdt_msr_set(struct vlapic *vlapic, uint64_t 
value)
                             TRC_PAR_LONG(0LL), vlapic->pt.irq);
             create_periodic_time(v, &vlapic->pt, 0, 0,
                                  vlapic->pt.irq, vlapic_tdt_pt_cb,
-                                 &vlapic->timer_last_update);
+                                 &vlapic->timer_last_update, false);
             vlapic->timer_last_update = vlapic->pt.last_plt_gtime;
         }
         else
@@ -1423,7 +1423,7 @@ static void lapic_rearm(struct vlapic *s)
                          vlapic_lvtt_period(s) ? period : 0,
                          s->pt.irq,
                          vlapic_lvtt_period(s) ? vlapic_pt_cb : NULL,
-                         &s->timer_last_update);
+                         &s->timer_last_update, false);
     s->timer_last_update = s->pt.last_plt_gtime;
 }
 
diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c
index f655457e03..6ac4c913bb 100644
--- a/xen/arch/x86/hvm/vpt.c
+++ b/xen/arch/x86/hvm/vpt.c
@@ -306,6 +306,7 @@ int pt_update_irq(struct vcpu *v)
     struct periodic_time *pt, *temp, *earliest_pt;
     uint64_t max_lag;
     int irq, pt_vector = -1;
+    bool level;
 
     spin_lock(&v->arch.hvm_vcpu.tm_lock);
 
@@ -316,7 +317,9 @@ int pt_update_irq(struct vcpu *v)
         if ( pt->pending_intr_nr )
         {
             /* RTC code takes care of disabling the timer itself. */
-            if ( (pt->irq != RTC_IRQ || !pt->priv) && pt_irq_masked(pt) )
+            if ( (pt->irq != RTC_IRQ || !pt->priv) && pt_irq_masked(pt) &&
+                 /* Level interrupts should be asserted even if masked. */
+                 !pt->level )
             {
                 /* suspend timer emulation */
                 list_del(&pt->list);
@@ -341,6 +344,7 @@ int pt_update_irq(struct vcpu *v)
 
     earliest_pt->irq_issued = 1;
     irq = earliest_pt->irq;
+    level = earliest_pt->level;
 
     spin_unlock(&v->arch.hvm_vcpu.tm_lock);
 
@@ -374,13 +378,37 @@ int pt_update_irq(struct vcpu *v)
         break;
 
     case PTSRC_ioapic:
-        /*
-         * NB: At the moment IO-APIC routed interrupts generated by vpt devices
-         * (HPET) are edge-triggered.
-         */
-        pt_vector = hvm_ioapic_assert(v->domain, irq, false);
+        pt_vector = hvm_ioapic_assert(v->domain, irq, level);
         if ( pt_vector < 0 || !vlapic_test_irq(vcpu_vlapic(v), pt_vector) )
+        {
             pt_vector = -1;
+            if ( level )
+            {
+                /*
+                 * Level interrupts are always asserted because the pin assert
+                 * count is incremented regardless of whether the pin is masked
+                 * or the vector latched in IRR, so also execute the callback
+                 * associated with the timer.
+                 */
+                time_cb *cb = NULL;
+                void *cb_priv;
+
+                spin_lock(&v->arch.hvm_vcpu.tm_lock);
+                /* Make sure the timer is still on the list. */
+                list_for_each_entry ( pt, &v->arch.hvm_vcpu.tm_list, list )
+                    if ( pt == earliest_pt )
+                    {
+                        pt_irq_fired(v, pt);
+                        cb = pt->cb;
+                        cb_priv = pt->priv;
+                        break;
+                    }
+                spin_unlock(&v->arch.hvm_vcpu.tm_lock);
+
+                if ( cb != NULL )
+                    cb(v, cb_priv);
+            }
+        }
         break;
     }
 
@@ -447,12 +475,13 @@ void pt_migrate(struct vcpu *v)
 
 void create_periodic_time(
     struct vcpu *v, struct periodic_time *pt, uint64_t delta,
-    uint64_t period, uint8_t irq, time_cb *cb, void *data)
+    uint64_t period, uint8_t irq, time_cb *cb, void *data, bool level)
 {
     if ( !pt->source ||
          (irq >= NR_ISAIRQS && pt->source == PTSRC_isa) ||
-         (irq >= hvm_domain_irq(v->domain)->nr_gsis &&
-          pt->source == PTSRC_ioapic) )
+         (level && period) ||
+         (pt->source == PTSRC_ioapic ? irq >= 
hvm_domain_irq(v->domain)->nr_gsis
+                                     : level) )
     {
         ASSERT_UNREACHABLE();
         return;
@@ -480,6 +509,7 @@ void create_periodic_time(
     pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
     pt->irq = irq;
     pt->one_shot = !period;
+    pt->level = level;
     pt->scheduled = NOW() + delta;
 
     if ( !pt->one_shot )
diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h
index f693c0bcf1..61c26ed8b2 100644
--- a/xen/include/asm-x86/hvm/vpt.h
+++ b/xen/include/asm-x86/hvm/vpt.h
@@ -42,6 +42,7 @@ struct periodic_time {
     bool do_not_freeze;
     bool irq_issued;
     bool warned_timeout_too_short;
+    bool level;
 #define PTSRC_isa    1 /* ISA time source */
 #define PTSRC_lapic  2 /* LAPIC time source */
 #define PTSRC_ioapic 3 /* IOAPIC time source */
@@ -169,7 +170,7 @@ void pt_may_unmask_irq(struct domain *d, struct 
periodic_time *vlapic_pt);
  */
 void create_periodic_time(
     struct vcpu *v, struct periodic_time *pt, uint64_t delta,
-    uint64_t period, uint8_t irq, time_cb *cb, void *data);
+    uint64_t period, uint8_t irq, time_cb *cb, void *data, bool level);
 void destroy_periodic_time(struct periodic_time *pt);
 
 int pv_pit_handler(int port, int data, int write);
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
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®.