WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] hvm: Re-jig event delivery logic to bette

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] hvm: Re-jig event delivery logic to better integrate TPR management.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 01 Oct 2007 14:00:09 -0700
Delivery-date: Mon, 01 Oct 2007 14:01:09 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1191244275 -3600
# Node ID 9eff4c97053b866a1803ce1a85a231e2821ea598
# Parent  69a74ac976cbc900ec0b26ba99d1e621ffa46953
hvm: Re-jig event delivery logic to better integrate TPR management.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/hvm.c           |    2 
 xen/arch/x86/hvm/irq.c           |   84 ++++++++++++++++------------
 xen/arch/x86/hvm/svm/intr.c      |   91 +++++++++---------------------
 xen/arch/x86/hvm/svm/svm.c       |  115 +++++++++++++--------------------------
 xen/arch/x86/hvm/svm/vmcb.c      |    9 +--
 xen/arch/x86/hvm/vlapic.c        |   31 +++++-----
 xen/arch/x86/hvm/vmx/intr.c      |   88 ++++++++++-------------------
 xen/arch/x86/hvm/vmx/vmx.c       |   34 ++++++++---
 xen/arch/x86/hvm/vpic.c          |    2 
 xen/arch/x86/hvm/vpt.c           |   15 ++---
 xen/include/asm-x86/hvm/hvm.h    |   33 ++++++++---
 xen/include/asm-x86/hvm/irq.h    |    8 +-
 xen/include/asm-x86/hvm/vlapic.h |    4 -
 xen/include/asm-x86/hvm/vpic.h   |    2 
 xen/include/asm-x86/hvm/vpt.h    |    2 
 15 files changed, 233 insertions(+), 287 deletions(-)

diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Mon Oct 01 14:11:15 2007 +0100
@@ -737,7 +737,7 @@ int hvm_set_cr4(unsigned long value)
     old_cr = v->arch.hvm_vcpu.guest_cr[4];
     v->arch.hvm_vcpu.guest_cr[4] = value;
     hvm_update_guest_cr(v, 4);
-  
+
     /* Modifying CR4.{PSE,PAE,PGE} invalidates all TLB entries, inc. Global. */
     if ( (old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE) )
         paging_update_paging_modes(v);
diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/irq.c    Mon Oct 01 14:11:15 2007 +0100
@@ -285,49 +285,63 @@ void hvm_set_callback_via(struct domain 
     }
 }
 
-enum hvm_intack hvm_vcpu_has_pending_irq(struct vcpu *v)
+struct hvm_intack hvm_vcpu_has_pending_irq(struct vcpu *v)
 {
     struct hvm_domain *plat = &v->domain->arch.hvm_domain;
+    int vector;
 
     if ( unlikely(v->nmi_pending) )
         return hvm_intack_nmi;
 
-    if ( vlapic_has_interrupt(v) != -1 )
-        return hvm_intack_lapic;
-
-    if ( !vlapic_accept_pic_intr(v) )
-        return hvm_intack_none;
-
-    return plat->vpic[0].int_output ? hvm_intack_pic : hvm_intack_none;
-}
-
-int hvm_vcpu_ack_pending_irq(struct vcpu *v, enum hvm_intack type, int *vector)
-{
-    switch ( type )
-    {
-    case hvm_intack_nmi:
-        return test_and_clear_bool(v->nmi_pending);
-    case hvm_intack_lapic:
-        return ((*vector = cpu_get_apic_interrupt(v)) != -1);
-    case hvm_intack_pic:
+    if ( vlapic_accept_pic_intr(v) && plat->vpic[0].int_output )
+        return hvm_intack_pic(0);
+
+    vector = vlapic_has_pending_irq(v);
+    if ( vector != -1 )
+        return hvm_intack_lapic(vector);
+
+    return hvm_intack_none;
+}
+
+struct hvm_intack hvm_vcpu_ack_pending_irq(
+    struct vcpu *v, struct hvm_intack intack)
+{
+    int vector;
+
+    switch ( intack.source )
+    {
+    case hvm_intsrc_nmi:
+        if ( !test_and_clear_bool(v->nmi_pending) )
+            intack = hvm_intack_none;
+        break;
+    case hvm_intsrc_pic:
         ASSERT(v->vcpu_id == 0);
-        return ((*vector = cpu_get_pic_interrupt(v)) != -1);
+        if ( (vector = vpic_ack_pending_irq(v)) == -1 )
+            intack = hvm_intack_none;
+        else
+            intack.vector = (uint8_t)vector;
+        break;
+    case hvm_intsrc_lapic:
+        if ( !vlapic_ack_pending_irq(v, intack.vector) )
+            intack = hvm_intack_none;
+        break;
     default:
-        break;
-    }
-
-    return 0;
-}
-
-int get_isa_irq_vector(struct vcpu *v, int isa_irq, enum hvm_intack src)
+        intack = hvm_intack_none;
+        break;
+    }
+
+    return intack;
+}
+
+int get_isa_irq_vector(struct vcpu *v, int isa_irq, enum hvm_intsrc src)
 {
     unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
 
-    if ( src == hvm_intack_pic )
+    if ( src == hvm_intsrc_pic )
         return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base
                 + (isa_irq & 7));
 
-    ASSERT(src == hvm_intack_lapic);
+    ASSERT(src == hvm_intsrc_lapic);
     return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector;
 }
 
@@ -345,18 +359,18 @@ int is_isa_irq_masked(struct vcpu *v, in
 
 int hvm_local_events_need_delivery(struct vcpu *v)
 {
-    enum hvm_intack type;
+    struct hvm_intack intack;
 
     /* TODO: Get rid of event-channel special case. */
     if ( vcpu_info(v, evtchn_upcall_pending) )
-        type = hvm_intack_pic;
+        intack = hvm_intack_pic(0);
     else
-        type = hvm_vcpu_has_pending_irq(v);
-
-    if ( likely(type == hvm_intack_none) )
+        intack = hvm_vcpu_has_pending_irq(v);
+
+    if ( likely(intack.source == hvm_intsrc_none) )
         return 0;
 
-    return hvm_interrupts_enabled(v, type);
+    return !hvm_interrupt_blocked(v, intack);
 }
 
 #if 0 /* Keep for debugging */
diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c       Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/svm/intr.c       Mon Oct 01 14:11:15 2007 +0100
@@ -39,19 +39,6 @@
 #include <xen/domain_page.h>
 #include <asm/hvm/trace.h>
 
-static void svm_inject_dummy_vintr(struct vcpu *v)
-{
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    vintr_t intr = vmcb->vintr;
-
-    intr.fields.irq = 1;
-    intr.fields.intr_masking = 1;
-    intr.fields.vector = 0;
-    intr.fields.prio = 0xF;
-    intr.fields.ign_tpr = 1;
-    vmcb->vintr = intr;
-}
-    
 static void svm_inject_nmi(struct vcpu *v)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -80,11 +67,14 @@ static void svm_inject_extint(struct vcp
     vmcb->eventinj = event;
 }
     
-static void enable_intr_window(struct vcpu *v, enum hvm_intack intr_source)
+static void enable_intr_window(struct vcpu *v, struct hvm_intack intack)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    vintr_t intr;
 
-    ASSERT(intr_source != hvm_intack_none);
+    ASSERT(intack.source != hvm_intsrc_none);
+
+    HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);
 
     /*
      * Create a dummy virtual interrupt to intercept as soon as the
@@ -95,53 +85,29 @@ static void enable_intr_window(struct vc
      * track 'NMI blocking' from NMI injection until IRET. This can be done
      * quite easily in software by intercepting the unblocking IRET.
      */
+    intr = vmcb->vintr;
+    intr.fields.irq     = 1;
+    intr.fields.vector  = 0;
+    intr.fields.prio    = intack.vector >> 4;
+    intr.fields.ign_tpr = (intack.source != hvm_intsrc_lapic);
+    vmcb->vintr = intr;
     vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
-    HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);
-    svm_inject_dummy_vintr(v);
-}
-
-static void update_cr8_intercept(
-    struct vcpu *v, enum hvm_intack masked_intr_source)
-{
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    struct vlapic *vlapic = vcpu_vlapic(v);
-    int max_irr;
-
-    vmcb->cr_intercepts &= ~CR_INTERCEPT_CR8_WRITE;
-
-    /*
-     * If ExtInts are masked then that dominates the TPR --- the 'interrupt
-     * window' has already been enabled in this case.
-     */
-    if ( (masked_intr_source == hvm_intack_lapic) ||
-         (masked_intr_source == hvm_intack_pic) )
-        return;
-
-    /* Is there an interrupt pending at the LAPIC? Nothing to do if not. */
-    if ( !vlapic_enabled(vlapic) || 
-         ((max_irr = vlapic_find_highest_irr(vlapic)) == -1) )
-        return;
-
-    /* Highest-priority pending interrupt is masked by the TPR? */
-    if ( (vmcb->vintr.fields.tpr & 0xf) >= (max_irr >> 4) )
-        vmcb->cr_intercepts |= CR_INTERCEPT_CR8_WRITE;
 }
 
 asmlinkage void svm_intr_assist(void) 
 {
     struct vcpu *v = current;
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    enum hvm_intack intr_source;
-    int intr_vector;
+    struct hvm_intack intack;
 
     /* Crank the handle on interrupt state. */
     pt_update_irq(v);
     hvm_set_callback_irq_level();
 
     do {
-        intr_source = hvm_vcpu_has_pending_irq(v);
-        if ( likely(intr_source == hvm_intack_none) )
-            goto out;
+        intack = hvm_vcpu_has_pending_irq(v);
+        if ( likely(intack.source == hvm_intsrc_none) )
+            return;
 
         /*
          * Pending IRQs must be delayed if:
@@ -158,31 +124,30 @@ asmlinkage void svm_intr_assist(void)
          * 2. The IRQ is masked.
          */
         if ( unlikely(vmcb->eventinj.fields.v) ||
-             !hvm_interrupts_enabled(v, intr_source) )
+             hvm_interrupt_blocked(v, intack) )
         {
-            enable_intr_window(v, intr_source);
-            goto out;
+            enable_intr_window(v, intack);
+            return;
         }
-    } while ( !hvm_vcpu_ack_pending_irq(v, intr_source, &intr_vector) );
 
-    if ( intr_source == hvm_intack_nmi )
+        intack = hvm_vcpu_ack_pending_irq(v, intack);
+    } while ( intack.source == hvm_intsrc_none );
+
+    if ( intack.source == hvm_intsrc_nmi )
     {
         svm_inject_nmi(v);
     }
     else
     {
-        HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0);
-        svm_inject_extint(v, intr_vector);
-        pt_intr_post(v, intr_vector, intr_source);
+        HVMTRACE_2D(INJ_VIRQ, v, intack.vector, /*fake=*/ 0);
+        svm_inject_extint(v, intack.vector);
+        pt_intr_post(v, intack);
     }
 
     /* Is there another IRQ to queue up behind this one? */
-    intr_source = hvm_vcpu_has_pending_irq(v);
-    if ( unlikely(intr_source != hvm_intack_none) )
-        enable_intr_window(v, intr_source);
-
- out:
-    update_cr8_intercept(v, intr_source);
+    intack = hvm_vcpu_has_pending_irq(v);
+    if ( unlikely(intack.source != hvm_intsrc_none) )
+        enable_intr_window(v, intack);
 }
 
 /*
diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Oct 01 14:11:15 2007 +0100
@@ -425,16 +425,28 @@ static void svm_restore_dr(struct vcpu *
         __restore_debug_registers(v);
 }
 
-static int svm_interrupts_enabled(struct vcpu *v, enum hvm_intack type)
-{
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-
-    if ( type == hvm_intack_nmi )
-        return !vmcb->interrupt_shadow;
-
-    ASSERT((type == hvm_intack_pic) || (type == hvm_intack_lapic));
-    return (!irq_masked(guest_cpu_user_regs()->eflags) &&
-            !vmcb->interrupt_shadow);
+static enum hvm_intblk svm_interrupt_blocked(
+    struct vcpu *v, struct hvm_intack intack)
+{
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+    if ( vmcb->interrupt_shadow )
+        return hvm_intblk_shadow;
+
+    if ( intack.source == hvm_intsrc_nmi )
+        return hvm_intblk_none;
+
+    ASSERT((intack.source == hvm_intsrc_pic) ||
+           (intack.source == hvm_intsrc_lapic));
+
+    if ( irq_masked(guest_cpu_user_regs()->eflags) )
+        return hvm_intblk_rflags_ie;
+
+    if ( (intack.source == hvm_intsrc_lapic) &&
+         ((vmcb->vintr.fields.tpr & 0xf) >= (intack.vector >> 4)) )
+        return hvm_intblk_tpr;
+
+    return hvm_intblk_none;
 }
 
 static int svm_guest_x86_mode(struct vcpu *v)
@@ -855,7 +867,7 @@ static struct hvm_function_table svm_fun
     .vcpu_destroy         = svm_vcpu_destroy,
     .save_cpu_ctxt        = svm_save_vmcb_ctxt,
     .load_cpu_ctxt        = svm_load_vmcb_ctxt,
-    .interrupts_enabled   = svm_interrupts_enabled,
+    .interrupt_blocked    = svm_interrupt_blocked,
     .guest_x86_mode       = svm_guest_x86_mode,
     .get_segment_base     = svm_get_segment_base,
     .get_segment_register = svm_get_segment_register,
@@ -1552,7 +1564,6 @@ static void mov_from_cr(int cr, int gp, 
 {
     unsigned long value = 0;
     struct vcpu *v = current;
-    struct vlapic *vlapic = vcpu_vlapic(v);
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
 
     switch ( cr )
@@ -1560,21 +1571,14 @@ static void mov_from_cr(int cr, int gp, 
     case 0:
         value = v->arch.hvm_vcpu.guest_cr[0];
         break;
-    case 2:
-        value = vmcb->cr2;
-        break;
     case 3:
         value = (unsigned long)v->arch.hvm_vcpu.guest_cr[3];
         break;
     case 4:
         value = (unsigned long)v->arch.hvm_vcpu.guest_cr[4];
         break;
-    case 8:
-        value = (unsigned long)vlapic_get_reg(vlapic, APIC_TASKPRI);
-        value = (value & 0xF0) >> 4;
-        break;
-        
     default:
+        gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr);
         domain_crash(v->domain);
         return;
     }
@@ -1590,7 +1594,6 @@ static int mov_to_cr(int gpreg, int cr, 
 {
     unsigned long value;
     struct vcpu *v = current;
-    struct vlapic *vlapic = vcpu_vlapic(v);
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
 
     value = get_reg(gpreg, regs, vmcb);
@@ -1604,18 +1607,10 @@ static int mov_to_cr(int gpreg, int cr, 
     {
     case 0: 
         return svm_set_cr0(value);
-
     case 3:
         return hvm_set_cr3(value);
-
     case 4:
         return hvm_set_cr4(value);
-
-    case 8:
-        vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4));
-        vmcb->vintr.fields.tpr = value & 0x0F;
-        break;
-
     default:
         gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr);
         domain_crash(v->domain);
@@ -1894,13 +1889,14 @@ static void svm_vmexit_do_hlt(struct vmc
 static void svm_vmexit_do_hlt(struct vmcb_struct *vmcb,
                               struct cpu_user_regs *regs)
 {
-    enum hvm_intack type = hvm_vcpu_has_pending_irq(current);
+    struct hvm_intack intack = hvm_vcpu_has_pending_irq(current);
 
     __update_guest_eip(regs, 1);
 
     /* Check for interrupt not handled or new interrupt. */
     if ( vmcb->eventinj.fields.v ||
-         ((type != hvm_intack_none) && svm_interrupts_enabled(current, type)) )
+         ((intack.source != hvm_intsrc_none) &&
+          !svm_interrupt_blocked(current, intack)) )
     {
         HVMTRACE_1D(HLT, current, /*int pending=*/ 1);
         return;
@@ -2080,13 +2076,11 @@ asmlinkage void svm_vmexit_handler(struc
 
     /*
      * Before doing anything else, we need to sync up the VLAPIC's TPR with
-     * SVM's vTPR if CR8 writes are currently disabled.  It's OK if the 
-     * guest doesn't touch the CR8 (e.g. 32-bit Windows) because we update
-     * the vTPR on MMIO writes to the TPR
+     * SVM's vTPR. It's OK if the guest doesn't touch CR8 (e.g. 32-bit Windows)
+     * because we update the vTPR on MMIO writes to the TPR.
      */
-    if ( !(vmcb->cr_intercepts & CR_INTERCEPT_CR8_WRITE) )
-        vlapic_set_reg(vcpu_vlapic(v), APIC_TASKPRI,
-                       (vmcb->vintr.fields.tpr & 0x0F) << 4);
+    vlapic_set_reg(vcpu_vlapic(v), APIC_TASKPRI,
+                   (vmcb->vintr.fields.tpr & 0x0F) << 4);
 
     exit_reason = vmcb->exitcode;
 
@@ -2222,45 +2216,14 @@ asmlinkage void svm_vmexit_handler(struc
         }
         break;
 
-    case VMEXIT_CR0_READ:
-        svm_cr_access(v, 0, TYPE_MOV_FROM_CR, regs);
-        break;
-
-    case VMEXIT_CR2_READ:
-        svm_cr_access(v, 2, TYPE_MOV_FROM_CR, regs);
-        break;
-
-    case VMEXIT_CR3_READ:
-        svm_cr_access(v, 3, TYPE_MOV_FROM_CR, regs);
-        break;
-
-    case VMEXIT_CR4_READ:
-        svm_cr_access(v, 4, TYPE_MOV_FROM_CR, regs);
-        break;
-
-    case VMEXIT_CR8_READ:
-        svm_cr_access(v, 8, TYPE_MOV_FROM_CR, regs);
-        break;
-
-    case VMEXIT_CR0_WRITE:
-        svm_cr_access(v, 0, TYPE_MOV_TO_CR, regs);
-        break;
-
-    case VMEXIT_CR2_WRITE:
-        svm_cr_access(v, 2, TYPE_MOV_TO_CR, regs);
-        break;
-
-    case VMEXIT_CR3_WRITE:
-        svm_cr_access(v, 3, TYPE_MOV_TO_CR, regs);
-        local_flush_tlb();
-        break;
-
-    case VMEXIT_CR4_WRITE:
-        svm_cr_access(v, 4, TYPE_MOV_TO_CR, regs);
-        break;
-
-    case VMEXIT_CR8_WRITE:
-        svm_cr_access(v, 8, TYPE_MOV_TO_CR, regs);
+    case VMEXIT_CR0_READ ... VMEXIT_CR15_READ:
+        svm_cr_access(v, exit_reason - VMEXIT_CR0_READ,
+                      TYPE_MOV_FROM_CR, regs);
+        break;
+
+    case VMEXIT_CR0_WRITE ... VMEXIT_CR15_WRITE:
+        svm_cr_access(v, exit_reason - VMEXIT_CR0_WRITE,
+                      TYPE_MOV_TO_CR, regs);
         break;
 
     case VMEXIT_DR0_WRITE ... VMEXIT_DR7_WRITE:
diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Mon Oct 01 14:11:15 2007 +0100
@@ -130,14 +130,11 @@ static int construct_vmcb(struct vcpu *v
     /* Intercept all debug-register writes. */
     vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES;
 
-    /*
-     * Intercept all control-register accesses except for CR2 reads/writes
-     * and CR8 reads (and actually CR8 writes, but that's a special case
-     * that's handled in svm/intr.c). 
-     */
+    /* Intercept all control-register accesses except for CR2 and CR8. */
     vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ |
                             CR_INTERCEPT_CR2_WRITE |
-                            CR_INTERCEPT_CR8_READ);
+                            CR_INTERCEPT_CR8_READ |
+                            CR_INTERCEPT_CR8_WRITE);
 
     /* I/O and MSR permission bitmaps. */
     arch_svm->msrpm = alloc_xenheap_pages(get_order_from_bytes(MSRPM_SIZE));
diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/vlapic.c Mon Oct 01 14:11:15 2007 +0100
@@ -732,33 +732,34 @@ int vlapic_accept_pic_intr(struct vcpu *
              vlapic_hw_disabled(vlapic)));
 }
 
-int vlapic_has_interrupt(struct vcpu *v)
+int vlapic_has_pending_irq(struct vcpu *v)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
-    int highest_irr;
+    int irr, isr;
 
     if ( !vlapic_enabled(vlapic) )
         return -1;
 
-    highest_irr = vlapic_find_highest_irr(vlapic);
-    if ( (highest_irr == -1) ||
-         ((highest_irr & 0xF0) <= vlapic_get_ppr(vlapic)) )
+    irr = vlapic_find_highest_irr(vlapic);
+    if ( irr == -1 )
         return -1;
 
-    return highest_irr;
-}
-
-int cpu_get_apic_interrupt(struct vcpu *v)
-{
-    int vector = vlapic_has_interrupt(v);
+    isr = vlapic_find_highest_isr(vlapic);
+    isr = (isr != -1) ? isr : 0;
+    if ( (isr & 0xf0) >= (irr & 0xf0) )
+        return -1;
+
+    return irr;
+}
+
+int vlapic_ack_pending_irq(struct vcpu *v, int vector)
+{
     struct vlapic *vlapic = vcpu_vlapic(v);
 
-    if ( vector == -1 )
-        return -1;
- 
     vlapic_set_vector(vector, &vlapic->regs->data[APIC_ISR]);
     vlapic_clear_irr(vector, vlapic);
-    return vector;
+
+    return 1;
 }
 
 /* Reset the VLPAIC back to its power-on/reset state. */
diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c       Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/intr.c       Mon Oct 01 14:11:15 2007 +0100
@@ -71,14 +71,14 @@
  * the effect is cleared. (i.e., MOV-SS-blocking 'dominates' STI-blocking).
  */
 
-static void enable_intr_window(struct vcpu *v, enum hvm_intack intr_source)
+static void enable_intr_window(struct vcpu *v, struct hvm_intack intack)
 {
     u32 *cpu_exec_control = &v->arch.hvm_vmx.exec_control;
     u32 ctl = CPU_BASED_VIRTUAL_INTR_PENDING;
 
-    ASSERT(intr_source != hvm_intack_none);
+    ASSERT(intack.source != hvm_intsrc_none);
 
-    if ( (intr_source == hvm_intack_nmi) && cpu_has_vmx_vnmi )
+    if ( (intack.source == hvm_intsrc_nmi) && cpu_has_vmx_vnmi )
     {
         /*
          * We set MOV-SS blocking in lieu of STI blocking when delivering an
@@ -107,37 +107,6 @@ static void enable_intr_window(struct vc
     }
 }
 
-static void update_tpr_threshold(
-    struct vcpu *v, enum hvm_intack masked_intr_source)
-{
-    struct vlapic *vlapic = vcpu_vlapic(v);
-    int max_irr, tpr, threshold = 0;
-
-    if ( !cpu_has_vmx_tpr_shadow )
-        return;
-
-    /*
-     * If ExtInts are masked then that dominates the TPR --- the 'interrupt
-     * window' has already been enabled in this case.
-     */
-    if ( (masked_intr_source == hvm_intack_lapic) ||
-         (masked_intr_source == hvm_intack_pic) )
-        goto out;
-
-    /* Is there an interrupt pending at the LAPIC? Nothing to do if not. */
-    if ( !vlapic_enabled(vlapic) || 
-         ((max_irr = vlapic_find_highest_irr(vlapic)) == -1) )
-        goto out;
-
-    /* Highest-priority pending interrupt is masked by the TPR? */
-    tpr = vlapic_get_reg(vlapic, APIC_TASKPRI) & 0xF0;
-    if ( (tpr >> 4) >= (max_irr >> 4) )
-        threshold = max_irr >> 4;
-
- out:
-    __vmwrite(TPR_THRESHOLD, threshold);
-}
-
 static void vmx_dirq_assist(struct domain *d)
 {
     unsigned int irq;
@@ -157,10 +126,10 @@ static void vmx_dirq_assist(struct domai
 
 asmlinkage void vmx_intr_assist(void)
 {
-    int intr_vector;
-    enum hvm_intack intr_source;
+    struct hvm_intack intack;
     struct vcpu *v = current;
-    unsigned int intr_info;
+    unsigned int tpr_threshold = 0;
+    enum hvm_intblk intblk;
 
     /* Crank the handle on interrupt state. */
     pt_update_irq(v);
@@ -171,41 +140,48 @@ asmlinkage void vmx_intr_assist(void)
     hvm_set_callback_irq_level();
 
     do {
-        intr_source = hvm_vcpu_has_pending_irq(v);
-        if ( likely(intr_source == hvm_intack_none) )
+        intack = hvm_vcpu_has_pending_irq(v);
+        if ( likely(intack.source == hvm_intsrc_none) )
             goto out;
 
-        /*
-         * An event is already pending or the pending interrupt is masked?
-         * Then the pending interrupt must be delayed.
-         */
-        intr_info = __vmread(VM_ENTRY_INTR_INFO);
-        if ( unlikely(intr_info & INTR_INFO_VALID_MASK) ||
-             !hvm_interrupts_enabled(v, intr_source) )
+        intblk = hvm_interrupt_blocked(v, intack);
+        if ( intblk == hvm_intblk_tpr )
         {
-            enable_intr_window(v, intr_source);
+            ASSERT(vlapic_enabled(vcpu_vlapic(v)));
+            ASSERT(intack.source == hvm_intsrc_lapic);
+            tpr_threshold = intack.vector >> 4;
             goto out;
         }
-    } while ( !hvm_vcpu_ack_pending_irq(v, intr_source, &intr_vector) );
 
-    if ( intr_source == hvm_intack_nmi )
+        if ( (intblk != hvm_intblk_none) ||
+             (__vmread(VM_ENTRY_INTR_INFO) & INTR_INFO_VALID_MASK) )
+        {
+            enable_intr_window(v, intack);
+            goto out;
+        }
+
+        intack = hvm_vcpu_ack_pending_irq(v, intack);
+    } while ( intack.source == hvm_intsrc_none );
+
+    if ( intack.source == hvm_intsrc_nmi )
     {
         vmx_inject_nmi(v);
     }
     else
     {
-        HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0);
-        vmx_inject_extint(v, intr_vector);
-        pt_intr_post(v, intr_vector, intr_source);
+        HVMTRACE_2D(INJ_VIRQ, v, intack.vector, /*fake=*/ 0);
+        vmx_inject_extint(v, intack.vector);
+        pt_intr_post(v, intack);
     }
 
     /* Is there another IRQ to queue up behind this one? */
-    intr_source = hvm_vcpu_has_pending_irq(v);
-    if ( unlikely(intr_source != hvm_intack_none) )
-        enable_intr_window(v, intr_source);
+    intack = hvm_vcpu_has_pending_irq(v);
+    if ( unlikely(intack.source != hvm_intsrc_none) )
+        enable_intr_window(v, intack);
 
  out:
-    update_tpr_threshold(v, intr_source);
+    if ( cpu_has_vmx_tpr_shadow )
+        __vmwrite(TPR_THRESHOLD, tpr_threshold);
 }
 
 /*
diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Mon Oct 01 14:11:15 2007 +0100
@@ -975,20 +975,34 @@ static void vmx_init_hypercall_page(stru
     *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */
 }
 
-static int vmx_interrupts_enabled(struct vcpu *v, enum hvm_intack type)
+static enum hvm_intblk vmx_interrupt_blocked(
+    struct vcpu *v, struct hvm_intack intack)
 {
     unsigned long intr_shadow;
 
     intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
 
-    if ( type == hvm_intack_nmi )
-        return !(intr_shadow & (VMX_INTR_SHADOW_STI|
-                                VMX_INTR_SHADOW_MOV_SS|
-                                VMX_INTR_SHADOW_NMI));
-
-    ASSERT((type == hvm_intack_pic) || (type == hvm_intack_lapic));
-    return (!irq_masked(guest_cpu_user_regs()->eflags) &&
-            !(intr_shadow & (VMX_INTR_SHADOW_STI|VMX_INTR_SHADOW_MOV_SS)));
+    if ( intr_shadow & (VMX_INTR_SHADOW_STI|VMX_INTR_SHADOW_MOV_SS) )
+        return hvm_intblk_shadow;
+
+    if ( intack.source == hvm_intsrc_nmi )
+        return ((intr_shadow & VMX_INTR_SHADOW_NMI) ?
+                hvm_intblk_nmi_iret : hvm_intblk_none);
+
+    ASSERT((intack.source == hvm_intsrc_pic) ||
+           (intack.source == hvm_intsrc_lapic));
+
+    if ( irq_masked(guest_cpu_user_regs()->eflags) )
+        return hvm_intblk_rflags_ie;
+
+    if ( intack.source == hvm_intsrc_lapic )
+    {
+        uint32_t tpr = vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xF0;
+        if ( (tpr >> 4) >= (intack.vector >> 4) )
+            return hvm_intblk_tpr;
+    }
+
+    return hvm_intblk_none;
 }
 
 static void vmx_update_host_cr3(struct vcpu *v)
@@ -1112,7 +1126,7 @@ static struct hvm_function_table vmx_fun
     .vcpu_destroy         = vmx_vcpu_destroy,
     .save_cpu_ctxt        = vmx_save_vmcs_ctxt,
     .load_cpu_ctxt        = vmx_load_vmcs_ctxt,
-    .interrupts_enabled   = vmx_interrupts_enabled,
+    .interrupt_blocked    = vmx_interrupt_blocked,
     .guest_x86_mode       = vmx_guest_x86_mode,
     .get_segment_base     = vmx_get_segment_base,
     .get_segment_register = vmx_get_segment_register,
diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/vpic.c
--- a/xen/arch/x86/hvm/vpic.c   Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/vpic.c   Mon Oct 01 14:11:15 2007 +0100
@@ -503,7 +503,7 @@ void vpic_irq_negative_edge(struct domai
         vpic_update_int_output(vpic);
 }
 
-int cpu_get_pic_interrupt(struct vcpu *v)
+int vpic_ack_pending_irq(struct vcpu *v)
 {
     int irq, vector;
     struct hvm_hw_vpic *vpic = &v->domain->arch.hvm_domain.vpic[0];
diff -r 69a74ac976cb -r 9eff4c97053b xen/arch/x86/hvm/vpt.c
--- a/xen/arch/x86/hvm/vpt.c    Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/arch/x86/hvm/vpt.c    Mon Oct 01 14:11:15 2007 +0100
@@ -165,12 +165,12 @@ void pt_update_irq(struct vcpu *v)
 }
 
 static struct periodic_time *is_pt_irq(
-    struct vcpu *v, int vector, enum hvm_intack src)
+    struct vcpu *v, struct hvm_intack intack)
 {
     struct list_head *head = &v->arch.hvm_vcpu.tm_list;
     struct periodic_time *pt;
     struct RTCState *rtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
-    int vec;
+    int vector;
 
     list_for_each_entry ( pt, head, list )
     {
@@ -179,15 +179,16 @@ static struct periodic_time *is_pt_irq(
 
         if ( is_lvtt(v, pt->irq) )
         {
-            if ( pt->irq != vector )
+            if ( pt->irq != intack.vector )
                 continue;
             return pt;
         }
 
-        vec = get_isa_irq_vector(v, pt->irq, src);
+        vector = get_isa_irq_vector(v, pt->irq, intack.source);
 
         /* RTC irq need special care */
-        if ( (vector != vec) || (pt->irq == 8 && !is_rtc_periodic_irq(rtc)) )
+        if ( (intack.vector != vector) ||
+             ((pt->irq == 8) && !is_rtc_periodic_irq(rtc)) )
             continue;
 
         return pt;
@@ -196,7 +197,7 @@ static struct periodic_time *is_pt_irq(
     return NULL;
 }
 
-void pt_intr_post(struct vcpu *v, int vector, enum hvm_intack src)
+void pt_intr_post(struct vcpu *v, struct hvm_intack intack)
 {
     struct periodic_time *pt;
     time_cb *cb;
@@ -204,7 +205,7 @@ void pt_intr_post(struct vcpu *v, int ve
 
     spin_lock(&v->arch.hvm_vcpu.tm_lock);
 
-    pt = is_pt_irq(v, vector, src);
+    pt = is_pt_irq(v, intack);
     if ( pt == NULL )
     {
         spin_unlock(&v->arch.hvm_vcpu.tm_lock);
diff -r 69a74ac976cb -r 9eff4c97053b xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/include/asm-x86/hvm/hvm.h     Mon Oct 01 14:11:15 2007 +0100
@@ -57,11 +57,26 @@ typedef struct segment_register {
 } __attribute__ ((packed)) segment_register_t;
 
 /* Interrupt acknowledgement sources. */
-enum hvm_intack {
-    hvm_intack_none,
-    hvm_intack_pic,
-    hvm_intack_lapic,
-    hvm_intack_nmi
+enum hvm_intsrc {
+    hvm_intsrc_none,
+    hvm_intsrc_pic,
+    hvm_intsrc_lapic,
+    hvm_intsrc_nmi
+};
+struct hvm_intack {
+    uint8_t source; /* enum hvm_intsrc */
+    uint8_t vector;
+};
+#define hvm_intack_none       ( (struct hvm_intack) { hvm_intsrc_none,  0 } )
+#define hvm_intack_pic(vec)   ( (struct hvm_intack) { hvm_intsrc_pic,   vec } )
+#define hvm_intack_lapic(vec) ( (struct hvm_intack) { hvm_intsrc_lapic, vec } )
+#define hvm_intack_nmi        ( (struct hvm_intack) { hvm_intsrc_nmi,   2 } )
+enum hvm_intblk {
+    hvm_intblk_none,      /* not blocked (deliverable) */
+    hvm_intblk_shadow,    /* MOV-SS or STI shadow */
+    hvm_intblk_rflags_ie, /* RFLAGS.IE == 0 */
+    hvm_intblk_tpr,       /* LAPIC TPR too high */
+    hvm_intblk_nmi_iret   /* NMI blocked until IRET */
 };
 
 /*
@@ -94,7 +109,7 @@ struct hvm_function_table {
      * 3) return the current guest segment descriptor base
      * 4) return the current guest segment descriptor
      */
-    int (*interrupts_enabled)(struct vcpu *v, enum hvm_intack);
+    enum hvm_intblk (*interrupt_blocked)(struct vcpu *v, struct hvm_intack);
     int (*guest_x86_mode)(struct vcpu *v);
     unsigned long (*get_segment_base)(struct vcpu *v, enum x86_segment seg);
     void (*get_segment_register)(struct vcpu *v, enum x86_segment seg,
@@ -177,11 +192,11 @@ u64 hvm_get_guest_time(struct vcpu *v);
 #define hvm_long_mode_enabled(v) (v,0)
 #endif
 
-static inline int
-hvm_interrupts_enabled(struct vcpu *v, enum hvm_intack type)
+static inline enum hvm_intblk
+hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack)
 {
     ASSERT(v == current);
-    return hvm_funcs.interrupts_enabled(v, type);
+    return hvm_funcs.interrupt_blocked(v, intack);
 }
 
 static inline int
diff -r 69a74ac976cb -r 9eff4c97053b xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h     Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/include/asm-x86/hvm/irq.h     Mon Oct 01 14:11:15 2007 +0100
@@ -135,11 +135,11 @@ void hvm_set_callback_via(struct domain 
 void hvm_set_callback_via(struct domain *d, uint64_t via);
 
 /* Check/Acknowledge next pending interrupt. */
-enum hvm_intack hvm_vcpu_has_pending_irq(struct vcpu *v);
-int hvm_vcpu_ack_pending_irq(
-    struct vcpu *v, enum hvm_intack type, int *vector);
+struct hvm_intack hvm_vcpu_has_pending_irq(struct vcpu *v);
+struct hvm_intack hvm_vcpu_ack_pending_irq(struct vcpu *v,
+                                           struct hvm_intack intack);
 
-int get_isa_irq_vector(struct vcpu *vcpu, int irq, enum hvm_intack src);
+int get_isa_irq_vector(struct vcpu *vcpu, int irq, enum hvm_intsrc src);
 int is_isa_irq_masked(struct vcpu *v, int isa_irq);
 
 #endif /* __ASM_X86_HVM_IRQ_H__ */
diff -r 69a74ac976cb -r 9eff4c97053b xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/include/asm-x86/hvm/vlapic.h  Mon Oct 01 14:11:15 2007 +0100
@@ -75,8 +75,8 @@ int vlapic_set_irq(struct vlapic *vlapic
 
 int vlapic_find_highest_irr(struct vlapic *vlapic);
 
-int vlapic_has_interrupt(struct vcpu *v);
-int cpu_get_apic_interrupt(struct vcpu *v);
+int vlapic_has_pending_irq(struct vcpu *v);
+int vlapic_ack_pending_irq(struct vcpu *v, int vector);
 
 int  vlapic_init(struct vcpu *v);
 void vlapic_destroy(struct vcpu *v);
diff -r 69a74ac976cb -r 9eff4c97053b xen/include/asm-x86/hvm/vpic.h
--- a/xen/include/asm-x86/hvm/vpic.h    Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/include/asm-x86/hvm/vpic.h    Mon Oct 01 14:11:15 2007 +0100
@@ -32,7 +32,7 @@ void vpic_irq_positive_edge(struct domai
 void vpic_irq_positive_edge(struct domain *d, int irq);
 void vpic_irq_negative_edge(struct domain *d, int irq);
 void vpic_init(struct domain *d);
-int cpu_get_pic_interrupt(struct vcpu *v);
+int vpic_ack_pending_irq(struct vcpu *v);
 int is_periodic_irq(struct vcpu *v, int irq, int type);
 
 #endif  /* __ASM_X86_HVM_VPIC_H__ */  
diff -r 69a74ac976cb -r 9eff4c97053b xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h     Mon Oct 01 13:18:19 2007 +0100
+++ b/xen/include/asm-x86/hvm/vpt.h     Mon Oct 01 14:11:15 2007 +0100
@@ -120,7 +120,7 @@ void pt_freeze_time(struct vcpu *v);
 void pt_freeze_time(struct vcpu *v);
 void pt_thaw_time(struct vcpu *v);
 void pt_update_irq(struct vcpu *v);
-void pt_intr_post(struct vcpu *v, int vector, enum hvm_intack src);
+void pt_intr_post(struct vcpu *v, struct hvm_intack intack);
 void pt_reset(struct vcpu *v);
 void pt_migrate(struct vcpu *v);
 void create_periodic_time(

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] hvm: Re-jig event delivery logic to better integrate TPR management., Xen patchbot-unstable <=