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

[Xen-changelog] Fix IPI handling before vcpu launched



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID bee09e2200ab0386437e8824c152ad2ae7541f68
# Parent  de41f5e24cf1b39a57ad343c84e2221ad62b9afa
Fix IPI handling before vcpu launched

When sending IPI, the target vcpu may not be launched (like
INIT/Start-Up IPI), and the local apic is not initialized. Fix handling
on such case.

Also fix one bug in apic_round_robin function.

Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Xin Li <xin.b.li@xxxxxxxxx>

diff -r de41f5e24cf1 -r bee09e2200ab xen/arch/x86/vmx_vlapic.c
--- a/xen/arch/x86/vmx_vlapic.c Thu Nov 10 11:09:17 2005
+++ b/xen/arch/x86/vmx_vlapic.c Thu Nov 10 11:11:39 2005
@@ -119,22 +119,35 @@
 }
 
 /* This only for fixed delivery mode */
-int vlapic_match_dest(struct vlapic *target, struct vlapic *source,
-                      int short_hand, int dest, int dest_mode,
-                      int delivery_mode)
+static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
+                             int short_hand, int dest, int dest_mode,
+                             int delivery_mode)
 {
     int result = 0;
+    struct vlapic *target = VLAPIC(v);
 
     VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: "
                 "target %p source %p dest %x dest_mode %x short_hand %x "
                 "delivery_mode %x",
                 target, source, dest, dest_mode, short_hand, delivery_mode);
 
+    if ( unlikely(!target) &&
+         ( (delivery_mode != VLAPIC_DELIV_MODE_INIT) &&
+           (delivery_mode != VLAPIC_DELIV_MODE_STARTUP) &&
+           (delivery_mode != VLAPIC_DELIV_MODE_NMI) )) {
+        VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest "
+                    "uninitialized target v %p delivery_mode %x dest %x\n",
+                    v, delivery_mode, dest);
+        return result;
+    }
+
     switch (short_hand) {
     case VLAPIC_NO_SHORTHAND:
         if (!dest_mode) {   /* Physical */
-            result = (target->id == dest);
+            result = ((target ? target->id : v->vcpu_id ) == dest);
         } else {            /* Logical */
+            if (!target)
+                break;
             if (((target->dest_format >> 28) & 0xf) == 0xf) {   /* Flat mode */
                 result = (target->logical_dest >> 24) & dest;
             } else {
@@ -176,17 +189,18 @@
  * Add a pending IRQ into lapic.
  * Return 1 if successfully added and 0 if discarded.
  */
-int vlapic_accept_irq(struct vlapic *vlapic, int delivery_mode,
-                      int vector, int level, int trig_mode)
-{
-    int        result = 1;
+static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
+                             int vector, int level, int trig_mode)
+{
+    int        result = 0;
+    struct vlapic *vlapic = VLAPIC(v);
 
     switch (delivery_mode) {
     case VLAPIC_DELIV_MODE_FIXED:
     case VLAPIC_DELIV_MODE_LPRI:
         /* FIXME add logic for vcpu on reset */
-        if (!vlapic->vcpu || !vlapic_enabled(vlapic))
-            return 0;
+        if (unlikely(!vlapic || !vlapic_enabled(vlapic)))
+            return result;
 
         if (test_and_set_bit(vector, &vlapic->irr[0])) {
             printk("<vlapic_accept_irq>"
@@ -199,6 +213,7 @@
             }
         }
         evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain));
+        result = 1;
         break;
 
     case VLAPIC_DELIV_MODE_RESERVED:
@@ -269,15 +284,12 @@
 
     old = next = d->arch.vmx_platform.round_info[vector];
 
-    next++;
-    if (next == MAX_VIRT_CPUS || !d->vcpu[next])
-        next = 0;
-
     do {
         /* the vcpu array is arranged according to vcpu_id */
         if (test_bit(next, &bitmap)) {
             target = d->vcpu[next]->arch.arch_vmx.vlapic;
-            if (!vlapic_enabled(target)) {
+
+            if (!target || !vlapic_enabled(target)) {
                 printk("warning: targe round robin local apic disabled\n");
                 /* XXX should we domain crash?? Or should we return NULL */
             }
@@ -285,7 +297,9 @@
         }
 
         next ++;
-        if (next == MAX_VIRT_CPUS || !d->vcpu[next])
+        if (!d->vcpu[next] ||
+            !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) ||
+            next == MAX_VIRT_CPUS)
             next = 0;
     }while(next != old);
 
@@ -319,7 +333,7 @@
 {
     if ((dm == VLAPIC_DELIV_MODE_FIXED) && (vector < 16)) {
         vlapic->err_status |= 0x40;
-        vlapic_accept_irq(vlapic, VLAPIC_DELIV_MODE_FIXED,
+        vlapic_accept_irq(vlapic->vcpu, VLAPIC_DELIV_MODE_FIXED,
           vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 0, 0);
         printk("<vlapic_check_vector>: check fail\n");
         return 0;
@@ -340,7 +354,6 @@
 
     struct vlapic *target;
     struct vcpu *v = NULL;
-    int result = 0;
     uint32_t lpr_map;
 
     VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: "
@@ -352,32 +365,27 @@
                 delivery_mode, vector);
 
     for_each_vcpu ( vlapic->domain, v ) {
-        target = VLAPIC(v);
-        if (vlapic_match_dest(target, vlapic, short_hand,
+        if (vlapic_match_dest(v, vlapic, short_hand,
                               dest, dest_mode, delivery_mode)) {
             if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
                 set_bit(v->vcpu_id, &lpr_map);
-            }else
-                result = vlapic_accept_irq(target, delivery_mode,
-                  vector, level, trig_mode);
+            } else
+                vlapic_accept_irq(v, delivery_mode,
+                                  vector, level, trig_mode);
         }
     }
 
     if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
-        extern struct vlapic*
-          apic_round_robin(struct domain *d,
-            uint8_t dest_mode, uint8_t vector, uint32_t bitmap);
-
         v = vlapic->vcpu;
         target = apic_round_robin(v->domain, dest_mode, vector, lpr_map);
 
         if (target)
-            vlapic_accept_irq(target, delivery_mode,
-              vector, level, trig_mode);
-    }
-}
-
-void vlapic_begin_timer(struct vlapic *vlapic)
+            vlapic_accept_irq(target->vcpu, delivery_mode,
+                              vector, level, trig_mode);
+    }
+}
+
+static void vlapic_begin_timer(struct vlapic *vlapic)
 {
     s_time_t cur = NOW(), offset;
 
@@ -737,12 +745,13 @@
         vlapic->timer_current = val;
         vlapic->timer_current_update = NOW();
 
+        vlapic_begin_timer(vlapic);
+
         VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "timer_init %x timer_current %x"
                     "timer_current_update %08x%08x",
                     vlapic->timer_initial, vlapic->timer_current,
                     (uint32_t)(vlapic->timer_current_update >> 32),
                     (uint32_t)vlapic->timer_current_update);
-                    vlapic_begin_timer(vlapic);
         break;
 
     case APIC_TDCR:
@@ -827,6 +836,7 @@
         }
         else
             vlapic->intr_pending_count[vlapic_lvt_vector(vlapic, 
VLAPIC_LVT_TIMER)]++;
+        evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain));
     }
 
     vlapic->timer_current_update = NOW();

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