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

[Xen-changelog] [xen-unstable] x86 hvm: Clean up vlapic/vioapic/vmsi delivery.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1250687632 -3600
# Node ID 017762c75beb46eae8996cce9c0761959a793f2b
# Parent  902f4ae65123813aaf660d3b8cf81eb5ba0fa6ff
x86 hvm: Clean up vlapic/vioapic/vmsi delivery.

In particular, avoid intermediate delivery bitmaps which restrict
number of vcpus supported.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/vioapic.c        |  106 ++++++++------------------------------
 xen/arch/x86/hvm/vlapic.c         |   81 +++++++++++------------------
 xen/arch/x86/hvm/vmsi.c           |   75 +++-----------------------
 xen/include/asm-ia64/hvm/vlapic.h |    2 
 xen/include/asm-x86/hvm/vlapic.h  |   12 ++--
 5 files changed, 72 insertions(+), 204 deletions(-)

diff -r 902f4ae65123 -r 017762c75beb xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c        Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/arch/x86/hvm/vioapic.c        Wed Aug 19 14:13:52 2009 +0100
@@ -263,46 +263,6 @@ static void ioapic_inj_irq(
         vcpu_kick(vlapic_vcpu(target));
 }
 
-static uint32_t ioapic_get_delivery_bitmask(
-    struct hvm_hw_vioapic *vioapic, uint16_t dest, uint8_t dest_mode)
-{
-    uint32_t mask = 0;
-    struct vcpu *v;
-
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "dest %d dest_mode %d",
-                dest, dest_mode);
-
-    if ( dest_mode == 0 ) /* Physical mode. */
-    {
-        if ( dest == 0xFF ) /* Broadcast. */
-        {
-            for_each_vcpu ( vioapic_domain(vioapic), v )
-                mask |= 1 << v->vcpu_id;
-            goto out;
-        }
-
-        for_each_vcpu ( vioapic_domain(vioapic), v )
-        {
-            if ( VLAPIC_ID(vcpu_vlapic(v)) == dest )
-            {
-                mask = 1 << v->vcpu_id;
-                break;
-            }
-        }
-    }
-    else if ( dest != 0 ) /* Logical mode, MDA non-zero. */
-    {
-        for_each_vcpu ( vioapic_domain(vioapic), v )
-            if ( vlapic_match_logical_addr(vcpu_vlapic(v), dest) )
-                mask |= 1 << v->vcpu_id;
-    }
-
- out:
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "mask %x",
-                mask);
-    return mask;
-}
-
 static inline int pit_channel0_enabled(void)
 {
     PITState *pit = &current->domain->arch.hvm_domain.pl_time.vpit;
@@ -316,24 +276,17 @@ static void vioapic_deliver(struct hvm_h
     uint8_t delivery_mode = vioapic->redirtbl[irq].fields.delivery_mode;
     uint8_t vector = vioapic->redirtbl[irq].fields.vector;
     uint8_t trig_mode = vioapic->redirtbl[irq].fields.trig_mode;
-    uint32_t deliver_bitmask;
+    struct domain *d = vioapic_domain(vioapic);
     struct vlapic *target;
     struct vcpu *v;
 
-    ASSERT(spin_is_locked(&vioapic_domain(vioapic)->arch.hvm_domain.irq_lock));
+    ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock));
 
     HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
                 "dest=%x dest_mode=%x delivery_mode=%x "
                 "vector=%x trig_mode=%x",
                 dest, dest_mode, delivery_mode, vector, trig_mode);
 
-    deliver_bitmask = ioapic_get_delivery_bitmask(vioapic, dest, dest_mode);
-    if ( !deliver_bitmask )
-    {
-        HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "no target on destination");
-        return;
-    }
-
     switch ( delivery_mode )
     {
     case dest_LowestPrio:
@@ -342,14 +295,12 @@ static void vioapic_deliver(struct hvm_h
         /* Force round-robin to pick VCPU 0 */
         if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
         {
-            v = vioapic_domain(vioapic)->vcpu ?
-                vioapic_domain(vioapic)->vcpu[0] : NULL;
+            v = d->vcpu ? d->vcpu[0] : NULL;
             target = v ? vcpu_vlapic(v) : NULL;
         }
         else
 #endif
-            target = apic_lowest_prio(vioapic_domain(vioapic),
-                                      deliver_bitmask);
+            target = vlapic_lowest_prio(d, NULL, 0, dest, dest_mode);
         if ( target != NULL )
         {
             ioapic_inj_irq(vioapic, target, vector, trig_mode, delivery_mode);
@@ -357,52 +308,41 @@ static void vioapic_deliver(struct hvm_h
         else
         {
             HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin: "
-                        "mask=%x vector=%x delivery_mode=%x",
-                        deliver_bitmask, vector, dest_LowestPrio);
+                        "vector=%x delivery_mode=%x",
+                        vector, dest_LowestPrio);
         }
         break;
     }
 
     case dest_Fixed:
     {
-        uint8_t bit;
-        for ( bit = 0; deliver_bitmask != 0; bit++ )
-        {
-            if ( !(deliver_bitmask & (1 << bit)) )
-                continue;
-            deliver_bitmask &= ~(1 << bit);
-            if ( vioapic_domain(vioapic)->vcpu == NULL )
-                v = NULL;
 #ifdef IRQ0_SPECIAL_ROUTING
-            /* Do not deliver timer interrupts to VCPU != 0 */
-            else if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() 
)
-                v = vioapic_domain(vioapic)->vcpu[0];
-#endif
-            else
-                v = vioapic_domain(vioapic)->vcpu[bit];
-            if ( v != NULL )
-            {
-                target = vcpu_vlapic(v);
-                ioapic_inj_irq(vioapic, target, vector,
+        /* Do not deliver timer interrupts to VCPU != 0 */
+        if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
+        {
+            if ( (v = d->vcpu ? d->vcpu[0] : NULL) != NULL )
+                ioapic_inj_irq(vioapic, vcpu_vlapic(v), vector,
                                trig_mode, delivery_mode);
-            }
+        }
+        else
+#endif
+        {
+            for_each_vcpu ( d, v )
+                if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
+                                       0, dest, dest_mode) )
+                    ioapic_inj_irq(vioapic, vcpu_vlapic(v), vector,
+                                   trig_mode, delivery_mode);
         }
         break;
     }
 
     case dest_NMI:
     {
-        uint8_t bit;
-        for ( bit = 0; deliver_bitmask != 0; bit++ )
-        {
-            if ( !(deliver_bitmask & (1 << bit)) )
-                continue;
-            deliver_bitmask &= ~(1 << bit);
-            if ( (vioapic_domain(vioapic)->vcpu != NULL) &&
-                 ((v = vioapic_domain(vioapic)->vcpu[bit]) != NULL) &&
+        for_each_vcpu ( d, v )
+            if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
+                                   0, dest, dest_mode) &&
                  !test_and_set_bool(v->nmi_pending) )
                 vcpu_kick(v);
-        }
         break;
     }
 
diff -r 902f4ae65123 -r 017762c75beb xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/arch/x86/hvm/vlapic.c Wed Aug 19 14:13:52 2009 +0100
@@ -167,7 +167,7 @@ uint32_t vlapic_get_ppr(struct vlapic *v
     return ppr;
 }
 
-int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda)
+static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda)
 {
     int result = 0;
     uint8_t logical_id;
@@ -194,12 +194,10 @@ int vlapic_match_logical_addr(struct vla
     return result;
 }
 
-static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
-                             int short_hand, int dest, int dest_mode)
-{
-    int result = 0;
-    struct vlapic *target = vcpu_vlapic(v);
-
+bool_t vlapic_match_dest(
+    struct vlapic *target, struct vlapic *source,
+    int short_hand, uint8_t dest, uint8_t dest_mode)
+{
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "target %p, source %p, dest 0x%x, "
                 "dest_mode 0x%x, short_hand 0x%x",
                 target, source, dest, dest_mode, short_hand);
@@ -207,39 +205,25 @@ static int vlapic_match_dest(struct vcpu
     switch ( short_hand )
     {
     case APIC_DEST_NOSHORT:
-        if ( dest_mode == 0 )
-        {
-            /* Physical mode. */
-            if ( (dest == 0xFF) || (dest == VLAPIC_ID(target)) )
-                result = 1;
-        }
-        else
-        {
-            /* Logical mode. */
-            result = vlapic_match_logical_addr(target, dest);
-        }
-        break;
+        if ( dest_mode )
+            return vlapic_match_logical_addr(target, dest);
+        return ((dest == 0xFF) || (dest == VLAPIC_ID(target)));
 
     case APIC_DEST_SELF:
-        if ( target == source )
-            result = 1;
-        break;
+        return (target == source);
 
     case APIC_DEST_ALLINC:
-        result = 1;
-        break;
+        return 1;
 
     case APIC_DEST_ALLBUT:
-        if ( target != source )
-            result = 1;
-        break;
+        return (target != source);
 
     default:
         gdprintk(XENLOG_WARNING, "Bad dest shorthand value %x\n", short_hand);
         break;
     }
 
-    return result;
+    return 0;
 }
 
 static int vlapic_vcpu_pause_async(struct vcpu *v)
@@ -376,8 +360,9 @@ static int vlapic_accept_irq(struct vcpu
     return rc;
 }
 
-/* This function is used by both ioapic and lapic.The bitmap is for vcpu_id. */
-struct vlapic *apic_lowest_prio(struct domain *d, uint32_t bitmap)
+struct vlapic *vlapic_lowest_prio(
+    struct domain *d, struct vlapic *source,
+    int short_hand, uint8_t dest, uint8_t dest_mode)
 {
     int old = d->arch.hvm_domain.irq.round_robin_prev_vcpu;
     uint32_t ppr, target_ppr = UINT_MAX;
@@ -390,7 +375,8 @@ struct vlapic *apic_lowest_prio(struct d
     do {
         v = v->next_in_list ? : d->vcpu[0];
         vlapic = vcpu_vlapic(v);
-        if ( test_bit(v->vcpu_id, &bitmap) && vlapic_enabled(vlapic) &&
+        if ( vlapic_match_dest(vlapic, source, short_hand, dest, dest_mode) &&
+             vlapic_enabled(vlapic) &&
              ((ppr = vlapic_get_ppr(vlapic)) < target_ppr) )
         {
             target = vlapic;
@@ -434,36 +420,33 @@ int vlapic_ipi(
 
     struct vlapic *target;
     struct vcpu *v;
-    uint32_t lpr_map = 0;
     int rc = X86EMUL_OKAY;
 
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr_high 0x%x, icr_low 0x%x, "
                 "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
                 "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x",
                 icr_high, icr_low, short_hand, dest,
-                trig_mode, level, dest_mode, delivery_mode, vector);
-
-    for_each_vcpu ( vlapic_domain(vlapic), v )
-    {
-        if ( vlapic_match_dest(v, vlapic, short_hand, dest, dest_mode) )
-        {
-            if ( delivery_mode == APIC_DM_LOWEST )
-                __set_bit(v->vcpu_id, &lpr_map);
-            else
-                rc = vlapic_accept_irq(v, delivery_mode,
-                                       vector, level, trig_mode);
-        }
-
-        if ( rc != X86EMUL_OKAY )
-            break;
-    }
+                trig_mode, level, dest_mode, delivery_mode, vector);    
 
     if ( delivery_mode == APIC_DM_LOWEST )
     {
-        target = apic_lowest_prio(vlapic_domain(vlapic), lpr_map);
+        target = vlapic_lowest_prio(vlapic_domain(vlapic), vlapic,
+                                    short_hand, dest, dest_mode);
         if ( target != NULL )
             rc = vlapic_accept_irq(vlapic_vcpu(target), delivery_mode,
                                    vector, level, trig_mode);
+        return rc;
+    }
+
+    for_each_vcpu ( vlapic_domain(vlapic), v )
+    {
+        if ( vlapic_match_dest(vcpu_vlapic(v), vlapic,
+                               short_hand, dest, dest_mode) )
+                rc = vlapic_accept_irq(v, delivery_mode,
+                                       vector, level, trig_mode);
+
+        if ( rc != X86EMUL_OKAY )
+            break;
     }
 
     return rc;
diff -r 902f4ae65123 -r 017762c75beb xen/arch/x86/hvm/vmsi.c
--- a/xen/arch/x86/hvm/vmsi.c   Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/arch/x86/hvm/vmsi.c   Wed Aug 19 14:13:52 2009 +0100
@@ -40,46 +40,6 @@
 #include <asm/current.h>
 #include <asm/event.h>
 
-static uint32_t vmsi_get_delivery_bitmask(
-    struct domain *d, uint16_t dest, uint8_t dest_mode)
-{
-    uint32_t mask = 0;
-    struct vcpu *v;
-
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
-                "dest %d dest_mode %d\n", dest, dest_mode);
-
-    if ( dest_mode == 0 ) /* Physical mode. */
-    {
-        if ( dest == 0xFF ) /* Broadcast. */
-        {
-            for_each_vcpu ( d, v )
-                mask |= 1 << v->vcpu_id;
-            goto out;
-        }
-
-        for_each_vcpu ( d, v )
-        {
-            if ( VLAPIC_ID(vcpu_vlapic(v)) == dest )
-            {
-                mask = 1 << v->vcpu_id;
-                break;
-            }
-        }
-    }
-    else if ( dest != 0 ) /* Logical mode, MDA non-zero. */
-    {
-        for_each_vcpu ( d, v )
-            if ( vlapic_match_logical_addr(vcpu_vlapic(v), dest) )
-                mask |= 1 << v->vcpu_id;
-    }
-
- out:
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask mask %x\n",
-                mask);
-    return mask;
-}
-
 static void vmsi_inj_irq(
     struct domain *d,
     struct vlapic *target,
@@ -87,7 +47,7 @@ static void vmsi_inj_irq(
     uint8_t trig_mode,
     uint8_t delivery_mode)
 {
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_inj_irq "
+    HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vmsi_inj_irq "
                 "irq %d trig %d delive mode %d\n",
                 vector, trig_mode, delivery_mode);
 
@@ -125,7 +85,6 @@ int vmsi_deliver(struct domain *d, int p
     uint8_t dest_mode = (flags & VMSI_DM_MASK) >> GFLAGS_SHIFT_DM;
     uint8_t delivery_mode = (flags & VMSI_DELIV_MASK) >> 
GLFAGS_SHIFT_DELIV_MODE;
     uint8_t trig_mode = (flags & VMSI_TRIG_MODE) >> GLFAGS_SHIFT_TRG_MODE;
-    uint32_t deliver_bitmask;
     struct vlapic *target;
     struct vcpu *v;
 
@@ -140,44 +99,28 @@ int vmsi_deliver(struct domain *d, int p
         return 0;
     }
 
-    deliver_bitmask = vmsi_get_delivery_bitmask(d, dest, dest_mode);
-    if ( !deliver_bitmask )
-    {
-        HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
-                    "no target on destination\n");
-        return 0;
-    }
-
     switch ( delivery_mode )
     {
     case dest_LowestPrio:
     {
-        target = apic_lowest_prio(d, deliver_bitmask);
+        target = vlapic_lowest_prio(d, NULL, 0, dest, dest_mode);
         if ( target != NULL )
             vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
         else
             HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin: "
-                        "mask=%x vector=%x delivery_mode=%x\n",
-                        deliver_bitmask, vector, dest_LowestPrio);
+                        "vector=%x delivery_mode=%x\n",
+                        vector, dest_LowestPrio);
         break;
     }
 
     case dest_Fixed:
     case dest_ExtINT:
     {
-        uint8_t bit;
-        for ( bit = 0; deliver_bitmask != 0; bit++ )
-        {
-            if ( !(deliver_bitmask & (1 << bit)) )
-                continue;
-            deliver_bitmask &= ~(1 << bit);
-            v = d->vcpu[bit];
-            if ( v != NULL )
-            {
-                target = vcpu_vlapic(v);
-                vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
-            }
-        }
+        for_each_vcpu ( d, v )
+            if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
+                                   0, dest, dest_mode) )
+                vmsi_inj_irq(d, vcpu_vlapic(v),
+                             vector, trig_mode, delivery_mode);
         break;
     }
 
diff -r 902f4ae65123 -r 017762c75beb xen/include/asm-ia64/hvm/vlapic.h
--- a/xen/include/asm-ia64/hvm/vlapic.h Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/include/asm-ia64/hvm/vlapic.h Wed Aug 19 14:13:52 2009 +0100
@@ -1,6 +1,4 @@
 #ifndef __ASM_IA64_HVM_VLAPIC_H__
 #define __ASM_IA64_HVM_VLAPIC_H__
 
-int vlapic_match_logical_addr(struct vlapic *vlapic, uint16_t dest);
-
 #endif /* __ASM_IA64_HVM_VLAPIC_H__ */
diff -r 902f4ae65123 -r 017762c75beb xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/include/asm-x86/hvm/vlapic.h  Wed Aug 19 14:13:52 2009 +0100
@@ -94,12 +94,16 @@ int vlapic_accept_pic_intr(struct vcpu *
 
 void vlapic_adjust_i8259_target(struct domain *d);
 
-struct vlapic *apic_lowest_prio(struct domain *d, uint32_t bitmap);
-
-int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
-
 void vlapic_EOI_set(struct vlapic *vlapic);
 
 int vlapic_ipi(struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high);
 
+struct vlapic *vlapic_lowest_prio(
+    struct domain *d, struct vlapic *source,
+    int short_hand, uint8_t dest, uint8_t dest_mode);
+
+bool_t vlapic_match_dest(
+    struct vlapic *target, struct vlapic *source,
+    int short_hand, uint8_t dest, uint8_t dest_mode);
+
 #endif /* __ASM_X86_HVM_VLAPIC_H__ */

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


 


Rackspace

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