mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Some cleanups to cpu offline handling.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
This commit is contained in:
1 parent
c1bc99b8a7
commit
06111bb25b
16 files changed
+61
-45
No files matched your search
@@ -721,16 +721,10 @@ remove_siblinginfo(int cpu)
|
||||
|
||||
extern void fixup_irqs(void);
|
||||
/* must be called with cpucontrol mutex held */
|
||||
int __cpu_disable(void)
|
||||
void __cpu_disable(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
/*
|
||||
* dont permit boot processor for now
|
||||
*/
|
||||
if (cpu == 0)
|
||||
return -EBUSY;
|
||||
|
||||
remove_siblinginfo(cpu);
|
||||
cpu_clear(cpu, cpu_online_map);
|
||||
#ifndef XEN
|
||||
@@ -738,12 +732,11 @@ int __cpu_disable(void)
|
||||
#endif
|
||||
local_flush_tlb_all();
|
||||
cpu_clear(cpu, cpu_callin_map);
|
||||
return 0;
|
||||
}
|
||||
#else /* !CONFIG_HOTPLUG_CPU */
|
||||
int __cpu_disable(void)
|
||||
void __cpu_disable(void)
|
||||
{
|
||||
return -ENOSYS;
|
||||
BUG();
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
|
||||
@@ -98,15 +98,8 @@ static void default_dead_idle(void)
|
||||
|
||||
static void play_dead(void)
|
||||
{
|
||||
/*
|
||||
* Flush pending softirqs if any. They can be queued up before this CPU
|
||||
* was taken out of cpu_online_map in __cpu_disable().
|
||||
*/
|
||||
do_softirq();
|
||||
|
||||
/* This must be done before dead CPU ack */
|
||||
cpu_exit_clear();
|
||||
hvm_cpu_down();
|
||||
wbinvd();
|
||||
mb();
|
||||
/* Ack it */
|
||||
|
||||
@@ -80,7 +80,13 @@ static int cpu_callback(
|
||||
switch ( action )
|
||||
{
|
||||
case CPU_UP_PREPARE:
|
||||
rc = hvm_funcs.cpu_prepare(cpu);
|
||||
rc = hvm_funcs.cpu_up_prepare(cpu);
|
||||
break;
|
||||
case CPU_DYING:
|
||||
hvm_cpu_down();
|
||||
break;
|
||||
case CPU_DEAD:
|
||||
hvm_funcs.cpu_dead(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -818,13 +818,25 @@ static int svm_do_pmu_interrupt(struct cpu_user_regs *regs)
|
||||
return vpmu_do_interrupt(regs);
|
||||
}
|
||||
|
||||
static int svm_cpu_prepare(unsigned int cpu)
|
||||
static void svm_cpu_dead(unsigned int cpu)
|
||||
{
|
||||
free_xenheap_page(hsa[cpu]);
|
||||
hsa[cpu] = NULL;
|
||||
free_vmcb(root_vmcb[cpu]);
|
||||
root_vmcb[cpu] = NULL;
|
||||
}
|
||||
|
||||
static int svm_cpu_up_prepare(unsigned int cpu)
|
||||
{
|
||||
if ( ((hsa[cpu] == NULL) &&
|
||||
((hsa[cpu] = alloc_host_save_area()) == NULL)) ||
|
||||
((root_vmcb[cpu] == NULL) &&
|
||||
((root_vmcb[cpu] = alloc_vmcb()) == NULL)) )
|
||||
{
|
||||
svm_cpu_dead(cpu);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -842,7 +854,7 @@ static int svm_cpu_up(struct cpuinfo_x86 *c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( svm_cpu_prepare(cpu) != 0 )
|
||||
if ( svm_cpu_up_prepare(cpu) != 0 )
|
||||
return 0;
|
||||
|
||||
write_efer(read_efer() | EFER_SVME);
|
||||
@@ -1328,7 +1340,8 @@ static void svm_invlpg_intercept(unsigned long vaddr)
|
||||
|
||||
static struct hvm_function_table __read_mostly svm_function_table = {
|
||||
.name = "SVM",
|
||||
.cpu_prepare = svm_cpu_prepare,
|
||||
.cpu_up_prepare = svm_cpu_up_prepare,
|
||||
.cpu_dead = svm_cpu_dead,
|
||||
.cpu_down = svm_cpu_down,
|
||||
.domain_initialise = svm_domain_initialise,
|
||||
.domain_destroy = svm_domain_destroy,
|
||||
|
||||
@@ -337,7 +337,7 @@ static void vmx_load_vmcs(struct vcpu *v)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
int vmx_cpu_prepare(unsigned int cpu)
|
||||
int vmx_cpu_up_prepare(unsigned int cpu)
|
||||
{
|
||||
if ( per_cpu(host_vmcs, cpu) != NULL )
|
||||
return 0;
|
||||
@@ -350,6 +350,12 @@ int vmx_cpu_prepare(unsigned int cpu)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void vmx_cpu_dead(unsigned int cpu)
|
||||
{
|
||||
vmx_free_vmcs(per_cpu(host_vmcs, cpu));
|
||||
per_cpu(host_vmcs, cpu) = NULL;
|
||||
}
|
||||
|
||||
int vmx_cpu_up(void)
|
||||
{
|
||||
u32 eax, edx;
|
||||
@@ -398,7 +404,7 @@ int vmx_cpu_up(void)
|
||||
|
||||
INIT_LIST_HEAD(&this_cpu(active_vmcs_list));
|
||||
|
||||
if ( vmx_cpu_prepare(cpu) != 0 )
|
||||
if ( vmx_cpu_up_prepare(cpu) != 0 )
|
||||
return 0;
|
||||
|
||||
switch ( __vmxon(virt_to_maddr(this_cpu(host_vmcs))) )
|
||||
|
||||
@@ -1379,7 +1379,8 @@ static void vmx_set_info_guest(struct vcpu *v)
|
||||
|
||||
static struct hvm_function_table __read_mostly vmx_function_table = {
|
||||
.name = "VMX",
|
||||
.cpu_prepare = vmx_cpu_prepare,
|
||||
.cpu_up_prepare = vmx_cpu_up_prepare,
|
||||
.cpu_dead = vmx_cpu_dead,
|
||||
.domain_initialise = vmx_domain_initialise,
|
||||
.domain_destroy = vmx_domain_destroy,
|
||||
.vcpu_initialise = vmx_vcpu_initialise,
|
||||
|
||||
@@ -1265,9 +1265,9 @@ remove_siblinginfo(int cpu)
|
||||
cpu_clear(cpu, cpu_sibling_setup_map);
|
||||
}
|
||||
|
||||
extern void fixup_irqs(void);
|
||||
int __cpu_disable(void)
|
||||
void __cpu_disable(void)
|
||||
{
|
||||
extern void fixup_irqs(void);
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
local_irq_disable();
|
||||
@@ -1287,8 +1287,6 @@ int __cpu_disable(void)
|
||||
fixup_irqs();
|
||||
|
||||
cpu_disable_scheduler(cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __cpu_die(unsigned int cpu)
|
||||
|
||||
+2
-1
@@ -68,7 +68,8 @@ static int take_cpu_down(void *unused)
|
||||
void *hcpu = (void *)(long)smp_processor_id();
|
||||
if ( raw_notifier_call_chain(&cpu_chain, CPU_DYING, hcpu) != NOTIFY_DONE )
|
||||
BUG();
|
||||
return __cpu_disable();
|
||||
__cpu_disable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_down(unsigned int cpu)
|
||||
|
||||
@@ -38,7 +38,8 @@ static void __do_softirq(unsigned long ignore_mask)
|
||||
if ( rcu_pending(cpu) )
|
||||
rcu_check_callbacks(cpu);
|
||||
|
||||
if ( (pending = (softirq_pending(cpu) & ~ignore_mask)) == 0 )
|
||||
if ( ((pending = (softirq_pending(cpu) & ~ignore_mask)) == 0)
|
||||
|| cpu_is_offline(cpu) )
|
||||
break;
|
||||
|
||||
i = find_first_set_bit(pending);
|
||||
|
||||
@@ -78,7 +78,7 @@ void do_tasklet(void)
|
||||
|
||||
spin_lock_irq(&tasklet_lock);
|
||||
|
||||
if ( unlikely(list_empty(list)) )
|
||||
if ( unlikely(list_empty(list) || cpu_is_offline(cpu)) )
|
||||
goto out;
|
||||
|
||||
t = list_entry(list->next, struct tasklet, list);
|
||||
|
||||
@@ -118,10 +118,7 @@ max_xtp (void)
|
||||
#define hard_smp_processor_id() ia64_get_lid()
|
||||
|
||||
/* Upping and downing of CPUs */
|
||||
extern int __cpu_disable (void);
|
||||
extern void __cpu_die (unsigned int cpu);
|
||||
extern void cpu_die (void) __attribute__ ((noreturn));
|
||||
extern int __cpu_up (unsigned int cpu);
|
||||
extern void __init smp_build_cpu_map(void);
|
||||
|
||||
extern void __init init_smp_config (void);
|
||||
|
||||
@@ -115,7 +115,9 @@ struct hvm_function_table {
|
||||
int (*event_pending)(struct vcpu *v);
|
||||
int (*do_pmu_interrupt)(struct cpu_user_regs *regs);
|
||||
|
||||
int (*cpu_prepare)(unsigned int cpu);
|
||||
int (*cpu_up_prepare)(unsigned int cpu);
|
||||
void (*cpu_dead)(unsigned int cpu);
|
||||
|
||||
int (*cpu_up)(void);
|
||||
void (*cpu_down)(void);
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
extern void start_vmx(void);
|
||||
extern void vmcs_dump_vcpu(struct vcpu *v);
|
||||
extern void setup_vmcs_dump(void);
|
||||
extern int vmx_cpu_prepare(unsigned int cpu);
|
||||
extern int vmx_cpu_up_prepare(unsigned int cpu);
|
||||
extern void vmx_cpu_dead(unsigned int cpu);
|
||||
extern int vmx_cpu_up(void);
|
||||
extern void vmx_cpu_down(void);
|
||||
|
||||
|
||||
@@ -93,8 +93,6 @@ static __inline int logical_smp_processor_id(void)
|
||||
|
||||
#endif
|
||||
|
||||
extern int __cpu_disable(void);
|
||||
extern void __cpu_die(unsigned int cpu);
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#else /* CONFIG_SMP */
|
||||
|
||||
+13
-2
@@ -17,8 +17,14 @@ void cpu_hotplug_done(void);
|
||||
int register_cpu_notifier(struct notifier_block *nb);
|
||||
|
||||
/*
|
||||
* Notification actions: note that only CPU_{UP,DOWN}_PREPARE may fail ---
|
||||
* all other handlers *must* return NOTIFY_DONE.
|
||||
* Possible event sequences for a given CPU:
|
||||
* CPU_UP_PREPARE -> CPU_UP_CANCELLED -- failed CPU up
|
||||
* CPU_UP_PREPARE -> CPU_ONLINE -- successful CPU up
|
||||
* CPU_DOWN_PREPARE -> CPU_DOWN_FAILED -- failed CPU down
|
||||
* CPU_DOWN_PREPARE -> CPU_DYING -> CPU_DEAD -- successful CPU down
|
||||
*
|
||||
* Hence note that only CPU_*_PREPARE handlers are allowed to fail. Also note
|
||||
* that once CPU_DYING is delivered, an offline action can no longer fail.
|
||||
*/
|
||||
#define CPU_UP_PREPARE 0x0002 /* CPU is coming up */
|
||||
#define CPU_UP_CANCELED 0x0003 /* CPU is no longer coming up */
|
||||
@@ -36,4 +42,9 @@ int cpu_up(unsigned int cpu);
|
||||
int disable_nonboot_cpus(void);
|
||||
void enable_nonboot_cpus(void);
|
||||
|
||||
/* Private arch-dependent helpers for CPU hotplug. */
|
||||
int __cpu_up(unsigned int cpunum);
|
||||
void __cpu_disable(void);
|
||||
void __cpu_die(unsigned int cpu);
|
||||
|
||||
#endif /* __XEN_CPU_H__ */
|
||||
@@ -20,11 +20,6 @@ extern void smp_send_state_dump(unsigned int cpu);
|
||||
*/
|
||||
extern void smp_prepare_cpus(unsigned int max_cpus);
|
||||
|
||||
/*
|
||||
* Bring a CPU up
|
||||
*/
|
||||
extern int __cpu_up(unsigned int cpunum);
|
||||
|
||||
/*
|
||||
* Final polishing of CPUs
|
||||
*/
|
||||
|
||||