···140140 range 2 32141141 default "4"142142143143+config HOTPLUG_CPU144144+ bool "Enable CPU hotplug support"145145+ depends on SMP146146+ help147147+ Say Y here to allow turning CPUs off and on. CPUs can be148148+ controlled through /sys/devices/system/cpu.149149+150150+ Say N if you want to disable CPU hotplug.151151+143152config MATH_EMULATION144153 bool "Math emulation"145154 help
+1
arch/xtensa/include/asm/irq.h
···4545struct irqaction;4646struct irq_domain;47474848+void migrate_irqs(void);4849int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize,4950 unsigned long int_irq, unsigned long ext_irq,5051 unsigned long *out_hwirq, unsigned int *out_type);
···153153#endif154154 variant_init_irq();155155}156156+157157+#ifdef CONFIG_HOTPLUG_CPU158158+static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu)159159+{160160+ struct irq_desc *desc = irq_to_desc(irq);161161+ struct irq_chip *chip = irq_data_get_irq_chip(data);162162+ unsigned long flags;163163+164164+ raw_spin_lock_irqsave(&desc->lock, flags);165165+ if (chip->irq_set_affinity)166166+ chip->irq_set_affinity(data, cpumask_of(cpu), false);167167+ raw_spin_unlock_irqrestore(&desc->lock, flags);168168+}169169+170170+/*171171+ * The CPU has been marked offline. Migrate IRQs off this CPU. If172172+ * the affinity settings do not allow other CPUs, force them onto any173173+ * available CPU.174174+ */175175+void migrate_irqs(void)176176+{177177+ unsigned int i, cpu = smp_processor_id();178178+ struct irq_desc *desc;179179+180180+ for_each_irq_desc(i, desc) {181181+ struct irq_data *data = irq_desc_get_irq_data(desc);182182+ unsigned int newcpu;183183+184184+ if (irqd_is_per_cpu(data))185185+ continue;186186+187187+ if (!cpumask_test_cpu(cpu, data->affinity))188188+ continue;189189+190190+ newcpu = cpumask_any_and(data->affinity, cpu_online_mask);191191+192192+ if (newcpu >= nr_cpu_ids) {193193+ pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n",194194+ i, cpu);195195+196196+ cpumask_setall(data->affinity);197197+ newcpu = cpumask_any_and(data->affinity,198198+ cpu_online_mask);199199+ }200200+201201+ route_irq(data, i, newcpu);202202+ }203203+}204204+#endif /* CONFIG_HOTPLUG_CPU */
···4040# endif4141#endif42424343+static void system_invalidate_dcache_range(unsigned long start,4444+ unsigned long size);4545+static void system_flush_invalidate_dcache_range(unsigned long start,4646+ unsigned long size);4747+4348/* IPI (Inter Process Interrupt) */44494550#define IPI_IRQ 0···111106static int boot_secondary_processors = 1; /* Set with xt-gdb via .xt-gdb */112107static DECLARE_COMPLETION(cpu_running);113108114114-void __init secondary_start_kernel(void)109109+void secondary_start_kernel(void)115110{116111 struct mm_struct *mm = &init_mm;117112 unsigned int cpu = smp_processor_id();···179174 __func__, cpu, run_stall_mask, get_er(MPSCORE));180175}181176177177+#ifdef CONFIG_HOTPLUG_CPU178178+unsigned long cpu_start_id __cacheline_aligned;179179+#endif182180unsigned long cpu_start_ccount;183181184182static int boot_secondary(unsigned int cpu, struct task_struct *ts)···190182 unsigned long ccount;191183 int i;192184185185+#ifdef CONFIG_HOTPLUG_CPU186186+ cpu_start_id = cpu;187187+ system_flush_invalidate_dcache_range(188188+ (unsigned long)&cpu_start_id, sizeof(cpu_start_id));189189+#endif193190 smp_call_function_single(0, mx_cpu_start, (void *)cpu, 1);194191195192 for (i = 0; i < 2; ++i) {···246233247234 return ret;248235}236236+237237+#ifdef CONFIG_HOTPLUG_CPU238238+239239+/*240240+ * __cpu_disable runs on the processor to be shutdown.241241+ */242242+int __cpu_disable(void)243243+{244244+ unsigned int cpu = smp_processor_id();245245+246246+ /*247247+ * Take this CPU offline. Once we clear this, we can't return,248248+ * and we must not schedule until we're ready to give up the cpu.249249+ */250250+ set_cpu_online(cpu, false);251251+252252+ /*253253+ * OK - migrate IRQs away from this CPU254254+ */255255+ migrate_irqs();256256+257257+ /*258258+ * Flush user cache and TLB mappings, and then remove this CPU259259+ * from the vm mask set of all processes.260260+ */261261+ local_flush_cache_all();262262+ local_flush_tlb_all();263263+ invalidate_page_directory();264264+265265+ clear_tasks_mm_cpumask(cpu);266266+267267+ return 0;268268+}269269+270270+static void platform_cpu_kill(unsigned int cpu)271271+{272272+ smp_call_function_single(0, mx_cpu_stop, (void *)cpu, true);273273+}274274+275275+/*276276+ * called on the thread which is asking for a CPU to be shutdown -277277+ * waits until shutdown has completed, or it is timed out.278278+ */279279+void __cpu_die(unsigned int cpu)280280+{281281+ unsigned long timeout = jiffies + msecs_to_jiffies(1000);282282+ while (time_before(jiffies, timeout)) {283283+ system_invalidate_dcache_range((unsigned long)&cpu_start_id,284284+ sizeof(cpu_start_id));285285+ if (cpu_start_id == -cpu) {286286+ platform_cpu_kill(cpu);287287+ return;288288+ }289289+ }290290+ pr_err("CPU%u: unable to kill\n", cpu);291291+}292292+293293+void arch_cpu_idle_dead(void)294294+{295295+ cpu_die();296296+}297297+/*298298+ * Called from the idle thread for the CPU which has been shutdown.299299+ *300300+ * Note that we disable IRQs here, but do not re-enable them301301+ * before returning to the caller. This is also the behaviour302302+ * of the other hotplug-cpu capable cores, so presumably coming303303+ * out of idle fixes this.304304+ */305305+void __ref cpu_die(void)306306+{307307+ idle_task_exit();308308+ local_irq_disable();309309+ __asm__ __volatile__(310310+ " movi a2, cpu_restart\n"311311+ " jx a2\n");312312+}313313+314314+#endif /* CONFIG_HOTPLUG_CPU */249315250316enum ipi_msg_type {251317 IPI_RESCHEDULE = 0,···554462 .addr2 = end,555463 };556464 on_each_cpu(ipi_flush_icache_range, &fd, 1);465465+}466466+467467+/* ------------------------------------------------------------------------- */468468+469469+static void ipi_invalidate_dcache_range(void *arg)470470+{471471+ struct flush_data *fd = arg;472472+ __invalidate_dcache_range(fd->addr1, fd->addr2);473473+}474474+475475+static void system_invalidate_dcache_range(unsigned long start,476476+ unsigned long size)477477+{478478+ struct flush_data fd = {479479+ .addr1 = start,480480+ .addr2 = size,481481+ };482482+ on_each_cpu(ipi_invalidate_dcache_range, &fd, 1);483483+}484484+485485+static void ipi_flush_invalidate_dcache_range(void *arg)486486+{487487+ struct flush_data *fd = arg;488488+ __flush_invalidate_dcache_range(fd->addr1, fd->addr2);489489+}490490+491491+static void system_flush_invalidate_dcache_range(unsigned long start,492492+ unsigned long size)493493+{494494+ struct flush_data fd = {495495+ .addr1 = start,496496+ .addr2 = size,497497+ };498498+ on_each_cpu(ipi_flush_invalidate_dcache_range, &fd, 1);557499}