aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-04-07 08:09:00 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-04-07 08:09:00 +0100
commitf2dcefdc7bbebb44b09f2c4abaa8e731b4959fcf (patch)
treeda359fcee6e22e2eb0ac3e45ad0d7d46ee97bf58
parent0273e627ed1c8d6ed3a3494b3b670192e15c56f3 (diff)
downloadxen-f2dcefdc7bbebb44b09f2c4abaa8e731b4959fcf.tar.gz
xen-f2dcefdc7bbebb44b09f2c4abaa8e731b4959fcf.tar.bz2
xen-f2dcefdc7bbebb44b09f2c4abaa8e731b4959fcf.zip
x86, cpu hotplug: Synchronise vcpu state earlier during cpu offline.
Needs to happen before non-idle VCPU is fully descheduled after CPU is removed from cpu_online_map. Else sync_vcpu_execstate() doesn't work properly. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/x86/domain.c3
-rw-r--r--xen/arch/x86/smpboot.c17
2 files changed, 12 insertions, 8 deletions
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 6321e56bfb..1ed5c9e73f 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1442,7 +1442,8 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
set_current(next);
- if ( (per_cpu(curr_vcpu, cpu) == next) || is_idle_vcpu(next) )
+ if ( (per_cpu(curr_vcpu, cpu) == next) ||
+ (is_idle_vcpu(next) && cpu_online(cpu)) )
{
local_irq_enable();
}
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index 0fb829028e..96db89fc54 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -997,17 +997,13 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
return boot_error;
}
-static void idle_task_exit(void)
-{
- /* Give up lazy state borrowed by this idle vcpu */
- __sync_lazy_execstate();
-}
-
void cpu_exit_clear(void)
{
int cpu = raw_smp_processor_id();
- idle_task_exit();
+ /* Previous non-idle state should be synchronised already. */
+ if (__sync_lazy_execstate())
+ BUG();
cpucount --;
cpu_uninit();
@@ -1302,6 +1298,13 @@ int __cpu_disable(void)
remove_siblinginfo(cpu);
+ /*
+ * If we are running the idle vcpu, sync last non-idle vcpu's state
+ * before changing cpu_online_map. If we are running non-idle vcpu,
+ * we will synchronously sync the state in context_switch() later.
+ */
+ __sync_lazy_execstate();
+
/* It's now safe to remove this processor from the online map */
cpu_clear(cpu, cpu_online_map);
fixup_irqs();