Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2828

kernel-2.6.18-128.1.10.el5.src.rpm

From: Tetsu Yamamoto <tyamamot@redhat.com>
Date: Thu, 16 Oct 2008 11:44:24 -0400
Subject: [xen] ia64: make viosapic SMP-safe by adding lock/unlock
Message-id: 48F76158.1010802@redhat.com
O-Subject: [RHEL5.3 PATCH] xen-ia64: Make viosapic SMP-safe adding lock/unlock similar to x86 vioapic
Bugzilla: 466552
RH-Acked-by: Bill Burns <bburns@redhat.com>
RH-Acked-by: Rik van Riel <riel@redhat.com>

BZ466552
https://bugzilla.redhat.com/show_bug.cgi?id=466552

[Description]
Windows guest on ia64/xen hangs during network performance test.  The
cause is that viosapic is not SMP-safe.

This is fixed by the patch in the upstream.
- [IA64] Make viosapic SMP-safe adding lock/unlock similar to x86 vioapic
   http://xenbits.xensource.com/xen-unstable.hg?rev/764d33505b98

[Upstream Status]
The patch was applied in the upstream a year ago.

[brew ID]
http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1517140

[Test Status]
I tested this patch with kernel-119 on ia64 box running network
performance test (ttcp) on a Windows guest for more than 48 hours.  The
guest did not hang.

Please review and ACK.

Regards,

Tetsu Yamamoto

# HG changeset patch
# User Alex Williamson <alex.williamson@hp.com>
# Date 1190905706 21600
# Node ID 764d33505b98f43c1c265a07a2b2ae3c252a5388
# Parent  b658296982eeee313f36460a4f575f0a4dde0116
[IA64] Make viosapic SMP-safe adding lock/unlock similar to x86 vioapic

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

diff --git a/arch/ia64/vmx/viosapic.c b/arch/ia64/vmx/viosapic.c
index f951aa0..fe16600 100644
--- a/arch/ia64/vmx/viosapic.c
+++ b/arch/ia64/vmx/viosapic.c
@@ -23,6 +23,10 @@
  *
  *  Yunhong Jiang <yunhong.jiang@intel.com>
  *  Ported to xen by using virtual IRQ line.
+ * 
+ *  Copyright (C) 2007 VA Linux Systems Japan K.K.
+ *  Isaku Yamahata <yamahata at valinux co jp>
+ *  SMP support
  */
 
 #include <xen/config.h>
@@ -44,6 +48,7 @@ static void viosapic_deliver(struct viosapic *viosapic, int irq)
     uint8_t vector = viosapic->redirtbl[irq].vector;
     struct vcpu *v;
 
+    ASSERT(spin_is_locked(&viosapic->lock));
     switch ( delivery_mode )
     {
     case SAPIC_FIXED:
@@ -90,6 +95,7 @@ static int get_redir_num(struct viosapic *viosapic, int vector)
 {
     int i;
 
+    ASSERT(spin_is_locked(&viosapic->lock));
     for ( i = 0; i < VIOSAPIC_NUM_PINS; i++ )
         if ( viosapic->redirtbl[i].vector == vector )
             return i;
@@ -118,20 +124,24 @@ static void viosapic_update_EOI(struct viosapic *viosapic, int vector)
 {
     int redir_num;
 
+    spin_lock(&viosapic->lock);
     if ( (redir_num = get_redir_num(viosapic, vector)) == -1 )
     {
+        spin_unlock(&viosapic->lock);
         gdprintk(XENLOG_WARNING, "Can't find redir item for %d EOI\n", vector);
         return;
     }
 
     if ( !test_and_clear_bit(redir_num, &viosapic->isr) )
     {
+        spin_unlock(&viosapic->lock);
         if ( viosapic->redirtbl[redir_num].trig_mode == SAPIC_LEVEL )
             gdprintk(XENLOG_WARNING, "redir %d not set for %d EOI\n",
                      redir_num, vector);
         return;
     }
     service_iosapic(viosapic);
+    spin_unlock(&viosapic->lock);
 }
 
 
@@ -150,18 +160,21 @@ static unsigned long viosapic_read_indirect(struct viosapic *viosapic,
 
     default:
     {
-        uint32_t redir_index = (viosapic->ioregsel - 0x10) >> 1;
+        /* ioregsel might be written at the same time. copy it before use. */
+        uint32_t ioregsel = viosapic->ioregsel;
+        uint32_t redir_index;
         uint64_t redir_content;
 
+        redir_index = (ioregsel - 0x10) >> 1;
         if ( redir_index >= VIOSAPIC_NUM_PINS )
         {
             gdprintk(XENLOG_WARNING, "viosapic_read_indirect:undefined "
-                     "ioregsel %x\n", viosapic->ioregsel);
+                     "ioregsel %x\n", ioregsel);
             break;
         }
 
         redir_content = viosapic->redirtbl[redir_index].bits;
-        result = (viosapic->ioregsel & 0x1) ?
+        result = (ioregsel & 0x1) ?
                  (redir_content >> 32) & 0xffffffff :
                  redir_content & 0xffffffff;
         break;
@@ -213,9 +226,12 @@ static void viosapic_write_indirect(struct viosapic *viosapic,
 
     default:
     {
-        uint32_t redir_index = (viosapic->ioregsel - 0x10) >> 1;
+        /* ioregsel might be written at the same time. copy it before use. */
+        uint32_t ioregsel = viosapic->ioregsel;
+        uint32_t redir_index;
         uint64_t redir_content;
 
+        redir_index = (ioregsel - 0x10) >> 1;
         if ( redir_index >= VIOSAPIC_NUM_PINS )
         {
             gdprintk(XENLOG_WARNING, "viosapic_write_indirect "
@@ -223,9 +239,10 @@ static void viosapic_write_indirect(struct viosapic *viosapic,
             break;
         }
 
+        spin_lock(&viosapic->lock);
         redir_content = viosapic->redirtbl[redir_index].bits;
 
-        if ( viosapic->ioregsel & 0x1 )
+        if ( ioregsel & 0x1 )
         {
             redir_content = (((uint64_t)val & 0xffffffff) << 32) |
                             (redir_content & 0xffffffff);
@@ -236,6 +253,7 @@ static void viosapic_write_indirect(struct viosapic *viosapic,
                             (val & 0xffffffff);
         }
         viosapic->redirtbl[redir_index].bits = redir_content;
+        spin_unlock(&viosapic->lock);
         break;
     }
     } /* switch */
diff --git a/arch/ia64/vmx/vlsapic.c b/arch/ia64/vmx/vlsapic.c
index 70ef86f..077f75a 100644
--- a/arch/ia64/vmx/vlsapic.c
+++ b/arch/ia64/vmx/vlsapic.c
@@ -771,6 +771,8 @@ static void vlsapic_write_xtp(struct vcpu *v, uint8_t val)
     struct viosapic * viosapic;
     struct vcpu *lvcpu, *vcpu;
     viosapic = vcpu_viosapic(v); 
+
+    spin_lock(&viosapic->lock);
     lvcpu = viosapic->lowest_vcpu;
     VLSAPIC_XTP(v) = val;
     
@@ -783,6 +785,7 @@ static void vlsapic_write_xtp(struct vcpu *v, uint8_t val)
         lvcpu = NULL;
 
     viosapic->lowest_vcpu = lvcpu;
+    spin_unlock(&viosapic->lock);
 }
 
 void vlsapic_write(struct vcpu *v,