[patch 2/4]Enable CMCI for Intel CPUs -- change stopmachine_run interface We change the interface because when do cpu hotplug, CMCI owner change algorithm need to execute on each of the CPUs instead of one designated CPU. Signed-off-by Yunhong Jiang Signed-off-by Liping Ke diff -r 7d46a8eb30d0 xen/common/stop_machine.c --- a/xen/common/stop_machine.c Thu Dec 18 14:18:41 2008 +0800 +++ b/xen/common/stop_machine.c Sun Jan 02 00:30:38 2005 +0800 @@ -45,7 +45,7 @@ enum stopmachine_state state; atomic_t done; - unsigned int fn_cpu; + cpumask_t fn_cpus; int fn_result; int (*fn)(void *); void *fn_data; @@ -63,21 +63,22 @@ cpu_relax(); } -int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) +int stop_machine_run(int (*fn)(void *), void *data, cpumask_t cpus) { cpumask_t allbutself; unsigned int i, nr_cpus; - int ret; + int cur_cpu, ret; BUG_ON(!local_irq_is_enabled()); allbutself = cpu_online_map; - cpu_clear(smp_processor_id(), allbutself); + cur_cpu = smp_processor_id(); + cpu_clear(cur_cpu, allbutself); nr_cpus = cpus_weight(allbutself); if ( nr_cpus == 0 ) { - BUG_ON(cpu != smp_processor_id()); + BUG_ON(!cpu_isset(cur_cpu, cpus)); return (*fn)(data); } @@ -91,7 +92,8 @@ stopmachine_data.fn = fn; stopmachine_data.fn_data = data; stopmachine_data.nr_cpus = nr_cpus; - stopmachine_data.fn_cpu = cpu; + stopmachine_data.fn_cpus = cpus; + stopmachine_data.fn_result = 0; atomic_set(&stopmachine_data.done, 0); stopmachine_data.state = STOPMACHINE_START; @@ -105,8 +107,13 @@ local_irq_disable(); stopmachine_set_state(STOPMACHINE_DISABLE_IRQ); - if ( cpu == smp_processor_id() ) - stopmachine_data.fn_result = (*fn)(data); + /* callback will run on each cpu of the input map. + * If callback fails on any CPU, the stop_machine_run + * will return the *ORed* the failure + */ + if ( cpu_isset(cur_cpu, cpus) ){ + stopmachine_data.fn_result |= (*fn)(data); + } stopmachine_set_state(STOPMACHINE_INVOKE); ret = stopmachine_data.fn_result; @@ -121,7 +128,6 @@ static void stopmachine_softirq(void) { enum stopmachine_state state = STOPMACHINE_START; - smp_mb(); while ( state != STOPMACHINE_EXIT ) @@ -136,10 +142,11 @@ local_irq_disable(); break; case STOPMACHINE_INVOKE: - if ( stopmachine_data.fn_cpu == smp_processor_id() ) - stopmachine_data.fn_result = + if ( cpu_isset(smp_processor_id(), stopmachine_data.fn_cpus )) { + stopmachine_data.fn_result |= stopmachine_data.fn(stopmachine_data.fn_data); - break; + } + break; default: break; } diff -r 7d46a8eb30d0 xen/include/xen/stop_machine.h --- a/xen/include/xen/stop_machine.h Thu Dec 18 14:18:41 2008 +0800 +++ b/xen/include/xen/stop_machine.h Sun Jan 02 00:30:38 2005 +0800 @@ -5,7 +5,7 @@ * stop_machine_run: freeze the machine on all CPUs and run this function * @fn: the function to run * @data: the data ptr for the @fn() - * @cpu: the cpu to run @fn() on (or any, if @cpu == NR_CPUS). + * @cpus: cpus to run @fn() on. * * Description: This causes every other cpu to enter a safe point, with * each of which disables interrupts, and finally interrupts are disabled @@ -14,6 +14,6 @@ * * This can be thought of as a very heavy write lock, equivalent to * grabbing every spinlock in the kernel. */ -int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu); +int stop_machine_run(int (*fn)(void *), void *data, cpumask_t cpu); #endif /* __XEN_STOP_MACHINE_H__ */