ia64/xen-unstable

changeset 14184:c3c03089c59e

linux: More save/restore fixes. Fix deadlock of cpu_hotplug_lock vs
workqueue_mutex. This is a new deadlock since the workqueue_mutex is
acquired in the workqueue_cpu_calbback() function across
CPU_UP_PREPARE->CPU_ONLINE.

The fix is for us not to rudely grab the cpu_hotplug_lock() during
save/restore -- it's really not necessary.

This patch is applicable to any of our 2.6 kernels, but is absolutely
required from 2.6.18 onwards.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Feb 28 17:55:19 2007 +0000 (2007-02-28)
parents 8ba425b640b3
children d2646466e0a7
files linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c linux-2.6-xen-sparse/drivers/xen/core/smpboot.c linux-2.6-xen-sparse/include/xen/cpu_hotplug.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c	Wed Feb 28 11:13:49 2007 -0500
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c	Wed Feb 28 17:55:19 2007 +0000
     1.3 @@ -121,29 +121,19 @@ arch_initcall(setup_vcpu_hotplug_event);
     1.4  
     1.5  int smp_suspend(void)
     1.6  {
     1.7 -	int i, err;
     1.8 -
     1.9 -	lock_cpu_hotplug();
    1.10 +	int cpu, err;
    1.11  
    1.12 -	/*
    1.13 -	 * Take all other CPUs offline. We hold the hotplug mutex to
    1.14 -	 * avoid other processes bringing up CPUs under our feet.
    1.15 -	 */
    1.16 -	while (num_online_cpus() > 1) {
    1.17 -		unlock_cpu_hotplug();
    1.18 -		for_each_online_cpu(i) {
    1.19 -			if (i == 0)
    1.20 -				continue;
    1.21 -			err = cpu_down(i);
    1.22 -			if (err) {
    1.23 -				printk(KERN_CRIT "Failed to take all CPUs "
    1.24 -				       "down: %d.\n", err);
    1.25 -				for_each_possible_cpu(i)
    1.26 -					vcpu_hotplug(i);
    1.27 -				return err;
    1.28 -			}
    1.29 +	for_each_online_cpu(cpu) {
    1.30 +		if (cpu == 0)
    1.31 +			continue;
    1.32 +		err = cpu_down(cpu);
    1.33 +		if (err) {
    1.34 +			printk(KERN_CRIT "Failed to take all CPUs "
    1.35 +			       "down: %d.\n", err);
    1.36 +			for_each_possible_cpu(cpu)
    1.37 +				vcpu_hotplug(cpu);
    1.38 +			return err;
    1.39  		}
    1.40 -		lock_cpu_hotplug();
    1.41  	}
    1.42  
    1.43  	return 0;
    1.44 @@ -154,11 +144,6 @@ void smp_resume(void)
    1.45  	int cpu;
    1.46  
    1.47  	for_each_possible_cpu(cpu)
    1.48 -		cpu_initialize_context(cpu);
    1.49 -
    1.50 -	unlock_cpu_hotplug();
    1.51 -
    1.52 -	for_each_possible_cpu(cpu)
    1.53  		vcpu_hotplug(cpu);
    1.54  }
    1.55  
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c	Wed Feb 28 11:13:49 2007 -0500
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c	Wed Feb 28 17:55:19 2007 +0000
     2.3 @@ -97,6 +97,9 @@ static void post_suspend(int suspend_can
     2.4  			pfn_to_mfn(xen_start_info->store_mfn);
     2.5  		xen_start_info->console.domU.mfn =
     2.6  			pfn_to_mfn(xen_start_info->console.domU.mfn);
     2.7 +	} else {
     2.8 +		extern cpumask_t cpu_initialized_map;
     2.9 +		cpu_initialized_map = cpumask_of_cpu(0);
    2.10  	}
    2.11  	
    2.12  	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
    2.13 @@ -147,13 +150,20 @@ int __xen_suspend(void)
    2.14  	}
    2.15  #endif
    2.16  
    2.17 -	err = smp_suspend();
    2.18 -	if (err)
    2.19 -		return err;
    2.20 +	for (;;) {
    2.21 +		err = smp_suspend();
    2.22 +		if (err)
    2.23 +			return err;
    2.24  
    2.25 -	xenbus_suspend();
    2.26 +		xenbus_suspend();
    2.27 +		preempt_disable();
    2.28  
    2.29 -	preempt_disable();
    2.30 +		if (num_online_cpus() == 1)
    2.31 +			break;
    2.32 +
    2.33 +		preempt_enable();
    2.34 +		xenbus_suspend_cancel();
    2.35 +	}
    2.36  
    2.37  	mm_pin_all();
    2.38  	local_irq_disable();
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c	Wed Feb 28 11:13:49 2007 -0500
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c	Wed Feb 28 17:55:19 2007 +0000
     3.3 @@ -47,7 +47,7 @@ cpumask_t cpu_online_map;
     3.4  EXPORT_SYMBOL(cpu_online_map);
     3.5  cpumask_t cpu_possible_map;
     3.6  EXPORT_SYMBOL(cpu_possible_map);
     3.7 -static cpumask_t cpu_initialized_map;
     3.8 +cpumask_t cpu_initialized_map;
     3.9  
    3.10  struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
    3.11  EXPORT_SYMBOL(cpu_data);
    3.12 @@ -185,7 +185,7 @@ static void cpu_bringup_and_idle(void)
    3.13  	cpu_idle();
    3.14  }
    3.15  
    3.16 -void cpu_initialize_context(unsigned int cpu)
    3.17 +static void cpu_initialize_context(unsigned int cpu)
    3.18  {
    3.19  	vcpu_guest_context_t ctxt;
    3.20  	struct task_struct *idle = idle_task(cpu);
    3.21 @@ -195,7 +195,7 @@ void cpu_initialize_context(unsigned int
    3.22  	struct Xgt_desc_struct *gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
    3.23  #endif
    3.24  
    3.25 -	if (cpu == 0)
    3.26 +	if (cpu_test_and_set(cpu, cpu_initialized_map))
    3.27  		return;
    3.28  
    3.29  	memset(&ctxt, 0, sizeof(ctxt));
    3.30 @@ -417,10 +417,7 @@ int __devinit __cpu_up(unsigned int cpu)
    3.31  	if (rc)
    3.32  		return rc;
    3.33  
    3.34 -	if (!cpu_isset(cpu, cpu_initialized_map)) {
    3.35 -		cpu_set(cpu, cpu_initialized_map);
    3.36 -		cpu_initialize_context(cpu);
    3.37 -	}
    3.38 +	cpu_initialize_context(cpu);
    3.39  
    3.40  	if (num_online_cpus() == 1)
    3.41  		alternatives_smp_switch(1);
     4.1 --- a/linux-2.6-xen-sparse/include/xen/cpu_hotplug.h	Wed Feb 28 11:13:49 2007 -0500
     4.2 +++ b/linux-2.6-xen-sparse/include/xen/cpu_hotplug.h	Wed Feb 28 17:55:19 2007 +0000
     4.3 @@ -6,12 +6,6 @@
     4.4  
     4.5  #if defined(CONFIG_HOTPLUG_CPU)
     4.6  
     4.7 -#if defined(CONFIG_X86)
     4.8 -void cpu_initialize_context(unsigned int cpu);
     4.9 -#else
    4.10 -#define cpu_initialize_context(cpu)	((void)0)
    4.11 -#endif
    4.12 -
    4.13  int cpu_up_check(unsigned int cpu);
    4.14  void init_xenbus_allowed_cpumask(void);
    4.15  int smp_suspend(void);