ia64/xen-unstable

changeset 14823:4c06bcd83c90

PV-on-HVM: More carefully synchronise with APs when putting them to
sleep in a spin loop.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Apr 12 12:09:58 2007 +0100 (2007-04-12)
parents 9e9eb5b3dab7
children 95a9998ede92
files unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c
line diff
     1.1 --- a/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c	Thu Apr 12 11:44:26 2007 +0100
     1.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c	Thu Apr 12 12:09:58 2007 +0100
     1.3 @@ -6,21 +6,32 @@
     1.4  #include "platform-pci.h"
     1.5  #include <asm/hypervisor.h>
     1.6  
     1.7 +struct ap_suspend_info {
     1.8 +	int      do_spin;
     1.9 +	atomic_t nr_spinning;
    1.10 +};
    1.11 +
    1.12  /*
    1.13   * Spinning prevents, for example, APs touching grant table entries while
    1.14   * the shared grant table is not mapped into the address space imemdiately
    1.15   * after resume.
    1.16   */
    1.17 -static void ap_suspend(void *_ap_spin)
    1.18 +static void ap_suspend(void *_info)
    1.19  {
    1.20 -	int *ap_spin = _ap_spin;
    1.21 +	struct ap_suspend_info *info = _info;
    1.22  
    1.23  	BUG_ON(!irqs_disabled());
    1.24  
    1.25 -	while (*ap_spin) {
    1.26 +	atomic_inc(&info->nr_spinning);
    1.27 +	mb();
    1.28 +
    1.29 +	while (info->do_spin) {
    1.30  		cpu_relax();
    1.31  		HYPERVISOR_yield();
    1.32  	}
    1.33 +
    1.34 +	mb();
    1.35 +	atomic_dec(&info->nr_spinning);
    1.36  }
    1.37  
    1.38  static int bp_suspend(void)
    1.39 @@ -42,7 +53,8 @@ static int bp_suspend(void)
    1.40  
    1.41  int __xen_suspend(int fast_suspend)
    1.42  {
    1.43 -	int err, suspend_cancelled, ap_spin;
    1.44 +	int err, suspend_cancelled, nr_cpus;
    1.45 +	struct ap_suspend_info info;
    1.46  
    1.47  	xenbus_suspend();
    1.48  
    1.49 @@ -51,22 +63,30 @@ int __xen_suspend(int fast_suspend)
    1.50  	/* Prevent any races with evtchn_interrupt() handler. */
    1.51  	disable_irq(xen_platform_pdev->irq);
    1.52  
    1.53 -	ap_spin = 1;
    1.54 +	info.do_spin = 1;
    1.55 +	atomic_set(&info.nr_spinning, 0);
    1.56  	smp_mb();
    1.57  
    1.58 -	err = smp_call_function(ap_suspend, &ap_spin, 0, 0);
    1.59 +	nr_cpus = num_online_cpus() - 1;
    1.60 +
    1.61 +	err = smp_call_function(ap_suspend, &info, 0, 0);
    1.62  	if (err < 0) {
    1.63  		preempt_enable();
    1.64  		xenbus_suspend_cancel();
    1.65  		return err;
    1.66  	}
    1.67  
    1.68 +	while (atomic_read(&info.nr_spinning) != nr_cpus)
    1.69 +		cpu_relax();
    1.70 +
    1.71  	local_irq_disable();
    1.72  	suspend_cancelled = bp_suspend();
    1.73  	local_irq_enable();
    1.74  
    1.75  	smp_mb();
    1.76 -	ap_spin = 0;
    1.77 +	info.do_spin = 0;
    1.78 +	while (atomic_read(&info.nr_spinning) != 0)
    1.79 +		cpu_relax();
    1.80  
    1.81  	enable_irq(xen_platform_pdev->irq);
    1.82