# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1176376198 -3600
# Node ID 4c06bcd83c902cf9851e8ad7ada5c09207da3e91
# Parent 9e9eb5b3dab7d2a09c0ba157c0fea628bbcac957
PV-on-HVM: More carefully synchronise with APs when putting them to
sleep in a spin loop.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c | 34 ++++++++++---
1 files changed, 27 insertions(+), 7 deletions(-)
diff -r 9e9eb5b3dab7 -r 4c06bcd83c90
unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c
--- a/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c Thu Apr
12 11:44:26 2007 +0100
+++ b/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c Thu Apr
12 12:09:58 2007 +0100
@@ -6,21 +6,32 @@
#include "platform-pci.h"
#include <asm/hypervisor.h>
+struct ap_suspend_info {
+ int do_spin;
+ atomic_t nr_spinning;
+};
+
/*
* Spinning prevents, for example, APs touching grant table entries while
* the shared grant table is not mapped into the address space imemdiately
* after resume.
*/
-static void ap_suspend(void *_ap_spin)
+static void ap_suspend(void *_info)
{
- int *ap_spin = _ap_spin;
+ struct ap_suspend_info *info = _info;
BUG_ON(!irqs_disabled());
- while (*ap_spin) {
+ atomic_inc(&info->nr_spinning);
+ mb();
+
+ while (info->do_spin) {
cpu_relax();
HYPERVISOR_yield();
}
+
+ mb();
+ atomic_dec(&info->nr_spinning);
}
static int bp_suspend(void)
@@ -42,7 +53,8 @@ static int bp_suspend(void)
int __xen_suspend(int fast_suspend)
{
- int err, suspend_cancelled, ap_spin;
+ int err, suspend_cancelled, nr_cpus;
+ struct ap_suspend_info info;
xenbus_suspend();
@@ -51,22 +63,30 @@ int __xen_suspend(int fast_suspend)
/* Prevent any races with evtchn_interrupt() handler. */
disable_irq(xen_platform_pdev->irq);
- ap_spin = 1;
+ info.do_spin = 1;
+ atomic_set(&info.nr_spinning, 0);
smp_mb();
- err = smp_call_function(ap_suspend, &ap_spin, 0, 0);
+ nr_cpus = num_online_cpus() - 1;
+
+ err = smp_call_function(ap_suspend, &info, 0, 0);
if (err < 0) {
preempt_enable();
xenbus_suspend_cancel();
return err;
}
+ while (atomic_read(&info.nr_spinning) != nr_cpus)
+ cpu_relax();
+
local_irq_disable();
suspend_cancelled = bp_suspend();
local_irq_enable();
smp_mb();
- ap_spin = 0;
+ info.do_spin = 0;
+ while (atomic_read(&info.nr_spinning) != 0)
+ cpu_relax();
enable_irq(xen_platform_pdev->irq);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|