···349349 depends on SMP350350 default "4"351351352352+config HOTPLUG_CPU353353+ bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"354354+ depends on SMP && HOTPLUG && EXPERIMENTAL355355+ help356356+ Say Y here to experiment with turning CPUs off and on. CPUs357357+ can be controlled through /sys/devices/system/cpu.358358+352359config PREEMPT353360 bool "Preemptible Kernel (EXPERIMENTAL)"354361 depends on EXPERIMENTAL
+31
arch/arm/kernel/irq.c
···10501050}1051105110521052__setup("noirqdebug", noirqdebug_setup);10531053+10541054+#ifdef CONFIG_HOTPLUG_CPU10551055+/*10561056+ * The CPU has been marked offline. Migrate IRQs off this CPU. If10571057+ * the affinity settings do not allow other CPUs, force them onto any10581058+ * available CPU.10591059+ */10601060+void migrate_irqs(void)10611061+{10621062+ unsigned int i, cpu = smp_processor_id();10631063+10641064+ for (i = 0; i < NR_IRQS; i++) {10651065+ struct irqdesc *desc = irq_desc + i;10661066+10671067+ if (desc->cpu == cpu) {10681068+ unsigned int newcpu = any_online_cpu(desc->affinity);10691069+10701070+ if (newcpu == NR_CPUS) {10711071+ if (printk_ratelimit())10721072+ printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n",10731073+ i, cpu);10741074+10751075+ cpus_setall(desc->affinity);10761076+ newcpu = any_online_cpu(desc->affinity);10771077+ }10781078+10791079+ route_irq(desc, i, newcpu);10801080+ }10811081+ }10821082+}10831083+#endif /* CONFIG_HOTPLUG_CPU */
+9
arch/arm/kernel/process.c
···2626#include <linux/interrupt.h>2727#include <linux/kallsyms.h>2828#include <linux/init.h>2929+#include <linux/cpu.h>29303031#include <asm/system.h>3132#include <asm/io.h>···106105 /* endless idle loop with no priority at all */107106 while (1) {108107 void (*idle)(void) = pm_idle;108108+109109+#ifdef CONFIG_HOTPLUG_CPU110110+ if (cpu_is_offline(smp_processor_id())) {111111+ leds_event(led_idle_start);112112+ cpu_die();113113+ }114114+#endif115115+109116 if (!idle)110117 idle = default_idle;111118 preempt_disable();
+85
arch/arm/kernel/smp.c
···159159 return ret;160160}161161162162+#ifdef CONFIG_HOTPLUG_CPU163163+/*164164+ * __cpu_disable runs on the processor to be shutdown.165165+ */166166+int __cpuexit __cpu_disable(void)167167+{168168+ unsigned int cpu = smp_processor_id();169169+ struct task_struct *p;170170+ int ret;171171+172172+ ret = mach_cpu_disable(cpu);173173+ if (ret)174174+ return ret;175175+176176+ /*177177+ * Take this CPU offline. Once we clear this, we can't return,178178+ * and we must not schedule until we're ready to give up the cpu.179179+ */180180+ cpu_clear(cpu, cpu_online_map);181181+182182+ /*183183+ * OK - migrate IRQs away from this CPU184184+ */185185+ migrate_irqs();186186+187187+ /*188188+ * Flush user cache and TLB mappings, and then remove this CPU189189+ * from the vm mask set of all processes.190190+ */191191+ flush_cache_all();192192+ local_flush_tlb_all();193193+194194+ read_lock(&tasklist_lock);195195+ for_each_process(p) {196196+ if (p->mm)197197+ cpu_clear(cpu, p->mm->cpu_vm_mask);198198+ }199199+ read_unlock(&tasklist_lock);200200+201201+ return 0;202202+}203203+204204+/*205205+ * called on the thread which is asking for a CPU to be shutdown -206206+ * waits until shutdown has completed, or it is timed out.207207+ */208208+void __cpuexit __cpu_die(unsigned int cpu)209209+{210210+ if (!platform_cpu_kill(cpu))211211+ printk("CPU%u: unable to kill\n", cpu);212212+}213213+214214+/*215215+ * Called from the idle thread for the CPU which has been shutdown.216216+ *217217+ * Note that we disable IRQs here, but do not re-enable them218218+ * before returning to the caller. This is also the behaviour219219+ * of the other hotplug-cpu capable cores, so presumably coming220220+ * out of idle fixes this.221221+ */222222+void __cpuexit cpu_die(void)223223+{224224+ unsigned int cpu = smp_processor_id();225225+226226+ local_irq_disable();227227+ idle_task_exit();228228+229229+ /*230230+ * actual CPU shutdown procedure is at least platform (if not231231+ * CPU) specific232232+ */233233+ platform_cpu_die(cpu);234234+235235+ /*236236+ * Do not return to the idle loop - jump back to the secondary237237+ * cpu initialisation. There's some initialisation which needs238238+ * to be repeated to undo the effects of taking the CPU offline.239239+ */240240+ __asm__("mov sp, %0\n"241241+ " b secondary_start_kernel"242242+ :243243+ : "r" ((void *)current->thread_info + THREAD_SIZE - 8));244244+}245245+#endif /* CONFIG_HOTPLUG_CPU */246246+162247/*163248 * This is the secondary CPU boot entry. We're using this CPUs164249 * idle thread stack, but a set of temporary page tables.
···6666};6767extern struct secondary_data secondary_data;68686969+extern int __cpu_disable(void);7070+extern int mach_cpu_disable(unsigned int cpu);7171+7272+extern void __cpu_die(unsigned int cpu);7373+extern void cpu_die(void);7474+7575+extern void platform_cpu_die(unsigned int cpu);7676+extern int platform_cpu_kill(unsigned int cpu);7777+extern void platform_cpu_enable(unsigned int cpu);7878+6979#endif /* ifndef __ASM_ARM_SMP_H */