diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/smp.h | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/smp.c | 46 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 12 |
3 files changed, 64 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index ebc24dc5b1a1..b625a1a9ad16 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h | |||
@@ -66,6 +66,14 @@ void generic_cpu_die(unsigned int cpu); | |||
66 | void generic_mach_cpu_die(void); | 66 | void generic_mach_cpu_die(void); |
67 | void generic_set_cpu_dead(unsigned int cpu); | 67 | void generic_set_cpu_dead(unsigned int cpu); |
68 | int generic_check_cpu_restart(unsigned int cpu); | 68 | int generic_check_cpu_restart(unsigned int cpu); |
69 | |||
70 | extern void inhibit_secondary_onlining(void); | ||
71 | extern void uninhibit_secondary_onlining(void); | ||
72 | |||
73 | #else /* HOTPLUG_CPU */ | ||
74 | static inline void inhibit_secondary_onlining(void) {} | ||
75 | static inline void uninhibit_secondary_onlining(void) {} | ||
76 | |||
69 | #endif | 77 | #endif |
70 | 78 | ||
71 | #ifdef CONFIG_PPC64 | 79 | #ifdef CONFIG_PPC64 |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 8d4214afc21d..c4f420c5fc1b 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -417,6 +417,45 @@ int generic_check_cpu_restart(unsigned int cpu) | |||
417 | { | 417 | { |
418 | return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; | 418 | return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; |
419 | } | 419 | } |
420 | |||
421 | static atomic_t secondary_inhibit_count; | ||
422 | |||
423 | /* | ||
424 | * Don't allow secondary CPU threads to come online | ||
425 | */ | ||
426 | void inhibit_secondary_onlining(void) | ||
427 | { | ||
428 | /* | ||
429 | * This makes secondary_inhibit_count stable during cpu | ||
430 | * online/offline operations. | ||
431 | */ | ||
432 | get_online_cpus(); | ||
433 | |||
434 | atomic_inc(&secondary_inhibit_count); | ||
435 | put_online_cpus(); | ||
436 | } | ||
437 | EXPORT_SYMBOL_GPL(inhibit_secondary_onlining); | ||
438 | |||
439 | /* | ||
440 | * Allow secondary CPU threads to come online again | ||
441 | */ | ||
442 | void uninhibit_secondary_onlining(void) | ||
443 | { | ||
444 | get_online_cpus(); | ||
445 | atomic_dec(&secondary_inhibit_count); | ||
446 | put_online_cpus(); | ||
447 | } | ||
448 | EXPORT_SYMBOL_GPL(uninhibit_secondary_onlining); | ||
449 | |||
450 | static int secondaries_inhibited(void) | ||
451 | { | ||
452 | return atomic_read(&secondary_inhibit_count); | ||
453 | } | ||
454 | |||
455 | #else /* HOTPLUG_CPU */ | ||
456 | |||
457 | #define secondaries_inhibited() 0 | ||
458 | |||
420 | #endif | 459 | #endif |
421 | 460 | ||
422 | static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle) | 461 | static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle) |
@@ -435,6 +474,13 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) | |||
435 | { | 474 | { |
436 | int rc, c; | 475 | int rc, c; |
437 | 476 | ||
477 | /* | ||
478 | * Don't allow secondary threads to come online if inhibited | ||
479 | */ | ||
480 | if (threads_per_core > 1 && secondaries_inhibited() && | ||
481 | cpu % threads_per_core != 0) | ||
482 | return -EBUSY; | ||
483 | |||
438 | if (smp_ops == NULL || | 484 | if (smp_ops == NULL || |
439 | (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))) | 485 | (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))) |
440 | return -EINVAL; | 486 | return -EINVAL; |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 9a15da76e56b..c5ddf048e19e 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <asm/page.h> | 47 | #include <asm/page.h> |
48 | #include <asm/hvcall.h> | 48 | #include <asm/hvcall.h> |
49 | #include <asm/switch_to.h> | 49 | #include <asm/switch_to.h> |
50 | #include <asm/smp.h> | ||
50 | #include <linux/gfp.h> | 51 | #include <linux/gfp.h> |
51 | #include <linux/vmalloc.h> | 52 | #include <linux/vmalloc.h> |
52 | #include <linux/highmem.h> | 53 | #include <linux/highmem.h> |
@@ -1016,8 +1017,6 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc) | |||
1016 | /* | 1017 | /* |
1017 | * Make sure we are running on thread 0, and that | 1018 | * Make sure we are running on thread 0, and that |
1018 | * secondary threads are offline. | 1019 | * secondary threads are offline. |
1019 | * XXX we should also block attempts to bring any | ||
1020 | * secondary threads online. | ||
1021 | */ | 1020 | */ |
1022 | if (threads_per_core > 1 && !on_primary_thread()) { | 1021 | if (threads_per_core > 1 && !on_primary_thread()) { |
1023 | list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) | 1022 | list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) |
@@ -1730,11 +1729,20 @@ int kvmppc_core_init_vm(struct kvm *kvm) | |||
1730 | 1729 | ||
1731 | kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206); | 1730 | kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206); |
1732 | spin_lock_init(&kvm->arch.slot_phys_lock); | 1731 | spin_lock_init(&kvm->arch.slot_phys_lock); |
1732 | |||
1733 | /* | ||
1734 | * Don't allow secondary CPU threads to come online | ||
1735 | * while any KVM VMs exist. | ||
1736 | */ | ||
1737 | inhibit_secondary_onlining(); | ||
1738 | |||
1733 | return 0; | 1739 | return 0; |
1734 | } | 1740 | } |
1735 | 1741 | ||
1736 | void kvmppc_core_destroy_vm(struct kvm *kvm) | 1742 | void kvmppc_core_destroy_vm(struct kvm *kvm) |
1737 | { | 1743 | { |
1744 | uninhibit_secondary_onlining(); | ||
1745 | |||
1738 | if (kvm->arch.rma) { | 1746 | if (kvm->arch.rma) { |
1739 | kvm_release_rma(kvm->arch.rma); | 1747 | kvm_release_rma(kvm->arch.rma); |
1740 | kvm->arch.rma = NULL; | 1748 | kvm->arch.rma = NULL; |