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-devel

[Xen-devel] [PATCH]CPUFREQ: Fix two racing issues during cpu hotplug

To: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH]CPUFREQ: Fix two racing issues during cpu hotplug
From: "Wei, Gang" <gang.wei@xxxxxxxxx>
Date: Mon, 12 Apr 2010 12:45:39 +0800
Accept-language: zh-CN, en-US
Acceptlanguage: zh-CN, en-US
Cc: Keir Fraser <keir.fraser@xxxxxxxxxxxxx>
Delivery-date: Sun, 11 Apr 2010 21:46:49 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Thread-index: AcrZ+wAOQtQIXlCDQjCnYThDbZTKrg==
Thread-topic: [PATCH]CPUFREQ: Fix two racing issues during cpu hotplug
CPUFREQ: Fix two racing issues during cpu hotplug

Move cpufreq_del_cpu() call into __cpu_disable to eliminate racing with dbs 
timer handler on policy & drv_data. Put it after local_irq_enable because 
xmalloc/xfree in cpufreq_del_cpu assert for this.

Change access to cpufreq_statistic_lock from spin_lock to spin_lock_irqsave to 
avoid statistic data access racing between cpufreq_statistic_exit and dbs timer 
handler.

Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx>

diff -r adce8bc43fcc xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Tue Apr 06 07:16:47 2010 +0100
+++ b/xen/arch/x86/smpboot.c    Fri Apr 09 11:54:42 2010 +0800
@@ -1293,6 +1293,7 @@ int __cpu_disable(void)
        clear_local_APIC();
        /* Allow any queued timer interrupts to get serviced */
        local_irq_enable();
+       cpufreq_del_cpu(cpu);
        mdelay(1);
        local_irq_disable();
 
@@ -1362,8 +1363,6 @@ int cpu_down(unsigned int cpu)
        }
 
        printk("Prepare to bring CPU%d down...\n", cpu);
-
-       cpufreq_del_cpu(cpu);
 
        err = stop_machine_run(take_cpu_down, NULL, cpu);
        if (err < 0)
diff -r adce8bc43fcc xen/drivers/acpi/pmstat.c
--- a/xen/drivers/acpi/pmstat.c Tue Apr 06 07:16:47 2010 +0100
+++ b/xen/drivers/acpi/pmstat.c Fri Apr 09 11:39:27 2010 +0800
@@ -86,15 +86,17 @@ int do_get_pm_info(struct xen_sysctl_get
     case PMSTAT_get_pxstat:
     {
         uint32_t ct;
-        struct pm_px *pxpt = cpufreq_statistic_data[op->cpuid];
+        struct pm_px *pxpt;
         spinlock_t *cpufreq_statistic_lock = 
                    &per_cpu(cpufreq_statistic_lock, op->cpuid);
-
-        spin_lock(cpufreq_statistic_lock);
-
+        unsigned long flags;
+
+        spin_lock_irqsave(cpufreq_statistic_lock, flags);
+
+        pxpt = cpufreq_statistic_data[op->cpuid];
         if ( !pxpt || !pxpt->u.pt || !pxpt->u.trans_pt )
         {
-            spin_unlock(cpufreq_statistic_lock);
+            spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
             return -ENODATA;
         }
 
@@ -105,14 +107,14 @@ int do_get_pm_info(struct xen_sysctl_get
         ct = pmpt->perf.state_count;
         if ( copy_to_guest(op->u.getpx.trans_pt, pxpt->u.trans_pt, ct*ct) )
         {
-            spin_unlock(cpufreq_statistic_lock);
+            spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
             ret = -EFAULT;
             break;
         }
 
         if ( copy_to_guest(op->u.getpx.pt, pxpt->u.pt, ct) )
         {
-            spin_unlock(cpufreq_statistic_lock);
+            spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
             ret = -EFAULT;
             break;
         }
@@ -122,7 +124,7 @@ int do_get_pm_info(struct xen_sysctl_get
         op->u.getpx.last = pxpt->u.last;
         op->u.getpx.cur = pxpt->u.cur;
 
-        spin_unlock(cpufreq_statistic_lock);
+        spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
 
         break;
     }
diff -r adce8bc43fcc xen/drivers/cpufreq/utility.c
--- a/xen/drivers/cpufreq/utility.c     Tue Apr 06 07:16:47 2010 +0100
+++ b/xen/drivers/cpufreq/utility.c     Fri Apr 09 11:39:27 2010 +0800
@@ -67,12 +67,13 @@ void cpufreq_statistic_update(unsigned i
     struct processor_pminfo *pmpt = processor_pminfo[cpu];
     spinlock_t *cpufreq_statistic_lock = 
                &per_cpu(cpufreq_statistic_lock, cpu);
-
-    spin_lock(cpufreq_statistic_lock);
+    unsigned long flags;
+
+    spin_lock_irqsave(cpufreq_statistic_lock, flags);
 
     pxpt = cpufreq_statistic_data[cpu];
     if ( !pxpt || !pmpt ) {
-        spin_unlock(cpufreq_statistic_lock);
+        spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
         return;
     }
 
@@ -84,7 +85,7 @@ void cpufreq_statistic_update(unsigned i
 
     (*(pxpt->u.trans_pt + from * pmpt->perf.state_count + to))++;
 
-    spin_unlock(cpufreq_statistic_lock);
+    spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
 }
 
 int cpufreq_statistic_init(unsigned int cpuid)
@@ -94,15 +95,16 @@ int cpufreq_statistic_init(unsigned int 
     const struct processor_pminfo *pmpt = processor_pminfo[cpuid];
     spinlock_t *cpufreq_statistic_lock = 
                           &per_cpu(cpufreq_statistic_lock, cpuid);
+    unsigned long flags;
 
     if ( !pmpt )
         return -EINVAL;
 
-    spin_lock(cpufreq_statistic_lock);
-
+    spin_lock_irqsave(cpufreq_statistic_lock, flags);
     pxpt = cpufreq_statistic_data[cpuid];
+    spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
+
     if ( pxpt ) {
-        spin_unlock(cpufreq_statistic_lock);
         return 0;
     }
 
@@ -110,16 +112,13 @@ int cpufreq_statistic_init(unsigned int 
 
     pxpt = xmalloc(struct pm_px);
     if ( !pxpt ) {
-        spin_unlock(cpufreq_statistic_lock);
         return -ENOMEM;
     }
     memset(pxpt, 0, sizeof(*pxpt));
-    cpufreq_statistic_data[cpuid] = pxpt;
 
     pxpt->u.trans_pt = xmalloc_array(uint64_t, count * count);
     if (!pxpt->u.trans_pt) {
         xfree(pxpt);
-        spin_unlock(cpufreq_statistic_lock);
         return -ENOMEM;
     }
 
@@ -127,7 +126,6 @@ int cpufreq_statistic_init(unsigned int 
     if (!pxpt->u.pt) {
         xfree(pxpt->u.trans_pt);
         xfree(pxpt);
-        spin_unlock(cpufreq_statistic_lock);
         return -ENOMEM;
     }
 
@@ -143,8 +141,18 @@ int cpufreq_statistic_init(unsigned int 
     pxpt->prev_state_wall = NOW();
     pxpt->prev_idle_wall = get_cpu_idle_time(cpuid);
 
-    spin_unlock(cpufreq_statistic_lock);
-
+    spin_lock_irqsave(cpufreq_statistic_lock, flags);
+    if ( !cpufreq_statistic_data[cpuid] ) {
+        cpufreq_statistic_data[cpuid] = pxpt;
+        pxpt = NULL;
+    }
+    spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
+
+    if (pxpt) {
+        xfree(pxpt->u.trans_pt);
+        xfree(pxpt->u.pt);
+        xfree(pxpt);
+    }
     return 0;
 }
 
@@ -153,21 +161,18 @@ void cpufreq_statistic_exit(unsigned int
     struct pm_px *pxpt;
     spinlock_t *cpufreq_statistic_lock = 
                &per_cpu(cpufreq_statistic_lock, cpuid);
-
-    spin_lock(cpufreq_statistic_lock);
-
+    unsigned long flags;
+
+    spin_lock_irqsave(cpufreq_statistic_lock, flags);
     pxpt = cpufreq_statistic_data[cpuid];
-    if (!pxpt) {
-        spin_unlock(cpufreq_statistic_lock);
-        return;
-    }
-
-    xfree(pxpt->u.trans_pt);
-    xfree(pxpt->u.pt);
-    xfree(pxpt);
     cpufreq_statistic_data[cpuid] = NULL;
-
-    spin_unlock(cpufreq_statistic_lock);
+    spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
+
+    if (pxpt) {
+        xfree(pxpt->u.trans_pt);
+        xfree(pxpt->u.pt);
+        xfree(pxpt);
+    }
 }
 
 void cpufreq_statistic_reset(unsigned int cpuid)
@@ -177,12 +182,13 @@ void cpufreq_statistic_reset(unsigned in
     const struct processor_pminfo *pmpt = processor_pminfo[cpuid];
     spinlock_t *cpufreq_statistic_lock = 
                &per_cpu(cpufreq_statistic_lock, cpuid);
-
-    spin_lock(cpufreq_statistic_lock);
+    unsigned long flags;
+
+    spin_lock_irqsave(cpufreq_statistic_lock, flags);
 
     pxpt = cpufreq_statistic_data[cpuid];
     if ( !pmpt || !pxpt || !pxpt->u.pt || !pxpt->u.trans_pt ) {
-        spin_unlock(cpufreq_statistic_lock);
+        spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
         return;
     }
 
@@ -199,7 +205,7 @@ void cpufreq_statistic_reset(unsigned in
     pxpt->prev_state_wall = NOW();
     pxpt->prev_idle_wall = get_cpu_idle_time(cpuid);
 
-    spin_unlock(cpufreq_statistic_lock);
+    spin_unlock_irqrestore(cpufreq_statistic_lock, flags);
 }
 
 

Attachment: dbs-timer-fix.patch
Description: dbs-timer-fix.patch

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