diff --git a/xen/common/timer.c b/xen/common/timer.c index 376581bd54..12fcd952fd 100644 --- a/xen/common/timer.c +++ b/xen/common/timer.c @@ -601,6 +601,20 @@ static void migrate_timers_from_cpu(unsigned int old_cpu) static struct timer *dummy_heap; +static void free_percpu_timers(unsigned int cpu) +{ + struct timers *ts = &per_cpu(timers, cpu); + + ASSERT(GET_HEAP_SIZE(ts->heap) == 0); + if ( GET_HEAP_LIMIT(ts->heap) ) + { + xfree(ts->heap); + ts->heap = &dummy_heap; + } + else + ASSERT(ts->heap == &dummy_heap); +} + static int cpu_callback( struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -610,14 +624,28 @@ static int cpu_callback( switch ( action ) { case CPU_UP_PREPARE: - INIT_LIST_HEAD(&ts->inactive); - spin_lock_init(&ts->lock); - ts->heap = &dummy_heap; + /* Only initialise ts once. */ + if ( !ts->heap ) + { + INIT_LIST_HEAD(&ts->inactive); + spin_lock_init(&ts->lock); + ts->heap = &dummy_heap; + } break; + case CPU_UP_CANCELED: case CPU_DEAD: migrate_timers_from_cpu(cpu); + + if ( !park_offline_cpus && system_state != SYS_STATE_suspend ) + free_percpu_timers(cpu); break; + + case CPU_REMOVE: + if ( park_offline_cpus ) + free_percpu_timers(cpu); + break; + default: break; } diff --git a/xen/include/asm-arm/smp.h b/xen/include/asm-arm/smp.h index 3c122681d7..fdbcefa241 100644 --- a/xen/include/asm-arm/smp.h +++ b/xen/include/asm-arm/smp.h @@ -14,6 +14,12 @@ DECLARE_PER_CPU(cpumask_var_t, cpu_core_mask); #define raw_smp_processor_id() (get_processor_id()) +/* + * Do we, for platform reasons, need to actually keep CPUs online when we + * would otherwise prefer them to be off? + */ +#define park_offline_cpus false + extern void noreturn stop_cpu(void); extern int arch_smp_init(void); diff --git a/xen/include/asm-x86/smp.h b/xen/include/asm-x86/smp.h index 09c55458df..9f533f9072 100644 --- a/xen/include/asm-x86/smp.h +++ b/xen/include/asm-x86/smp.h @@ -26,6 +26,10 @@ DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_mask); DECLARE_PER_CPU(cpumask_var_t, cpu_core_mask); DECLARE_PER_CPU(cpumask_var_t, scratch_cpumask); +/* + * Do we, for platform reasons, need to actually keep CPUs online when we + * would otherwise prefer them to be off? + */ extern bool park_offline_cpus; void smp_send_nmi_allbutself(void);