smp.c 14.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9
/*
 *  linux/arch/arm/kernel/smp.c
 *
 *  Copyright (C) 2002 ARM Limited, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
R
Russell King 已提交
10
#include <linux/module.h>
L
Linus Torvalds 已提交
11 12 13 14 15 16 17 18 19
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/cache.h>
#include <linux/profile.h>
#include <linux/errno.h>
#include <linux/mm.h>
A
Alexey Dobriyan 已提交
20
#include <linux/err.h>
L
Linus Torvalds 已提交
21 22 23
#include <linux/cpu.h>
#include <linux/smp.h>
#include <linux/seq_file.h>
R
Russell King 已提交
24
#include <linux/irq.h>
25 26
#include <linux/percpu.h>
#include <linux/clockchips.h>
27
#include <linux/completion.h>
28
#include <linux/cpufreq.h>
L
Linus Torvalds 已提交
29

A
Arun Sharma 已提交
30
#include <linux/atomic.h>
L
Linus Torvalds 已提交
31 32
#include <asm/cacheflush.h>
#include <asm/cpu.h>
33
#include <asm/cputype.h>
34
#include <asm/exception.h>
35
#include <asm/idmap.h>
36
#include <asm/topology.h>
37 38 39
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
L
Linus Torvalds 已提交
40
#include <asm/processor.h>
41
#include <asm/sections.h>
L
Linus Torvalds 已提交
42 43
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
44
#include <asm/localtimer.h>
45
#include <asm/smp_plat.h>
L
Linus Torvalds 已提交
46

47 48 49 50 51 52 53
/*
 * as from 2.5, kernels no longer have an init_tasks structure
 * so we need some other way of telling a new secondary core
 * where to place its SVC stack
 */
struct secondary_data secondary_data;

L
Linus Torvalds 已提交
54
enum ipi_msg_type {
55
	IPI_TIMER = 2,
L
Linus Torvalds 已提交
56 57
	IPI_RESCHEDULE,
	IPI_CALL_FUNC,
58
	IPI_CALL_FUNC_SINGLE,
L
Linus Torvalds 已提交
59 60 61
	IPI_CPU_STOP,
};

62 63
static DECLARE_COMPLETION(cpu_running);

64
int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
L
Linus Torvalds 已提交
65 66 67
{
	int ret;

68 69 70 71
	/*
	 * We need to tell the secondary core where to find
	 * its stack and the page tables.
	 */
A
Al Viro 已提交
72
	secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
73
	secondary_data.pgdir = virt_to_phys(idmap_pgd);
74
	secondary_data.swapper_pg_dir = virt_to_phys(swapper_pg_dir);
75 76
	__cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data));
	outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1));
77

L
Linus Torvalds 已提交
78 79 80 81
	/*
	 * Now bring the CPU into our world.
	 */
	ret = boot_secondary(cpu, idle);
82 83 84 85 86
	if (ret == 0) {
		/*
		 * CPU was successfully started, wait for it
		 * to come online or time out.
		 */
87 88
		wait_for_completion_timeout(&cpu_running,
						 msecs_to_jiffies(1000));
89

90 91
		if (!cpu_online(cpu)) {
			pr_crit("CPU%u: failed to come online\n", cpu);
92
			ret = -EIO;
93 94 95
		}
	} else {
		pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
96 97
	}

98
	secondary_data.stack = NULL;
99 100
	secondary_data.pgdir = 0;

L
Linus Torvalds 已提交
101 102 103
	return ret;
}

104
#ifdef CONFIG_HOTPLUG_CPU
105 106
static void percpu_timer_stop(void);

107 108 109
/*
 * __cpu_disable runs on the processor to be shutdown.
 */
110
int __cpu_disable(void)
111 112 113 114
{
	unsigned int cpu = smp_processor_id();
	int ret;

115
	ret = platform_cpu_disable(cpu);
116 117 118 119 120 121 122
	if (ret)
		return ret;

	/*
	 * Take this CPU offline.  Once we clear this, we can't return,
	 * and we must not schedule until we're ready to give up the cpu.
	 */
123
	set_cpu_online(cpu, false);
124 125 126 127 128 129

	/*
	 * OK - migrate IRQs away from this CPU
	 */
	migrate_irqs();

130 131 132
	/*
	 * Stop the local timer for this CPU.
	 */
133
	percpu_timer_stop();
134

135 136 137 138 139 140 141
	/*
	 * Flush user cache and TLB mappings, and then remove this CPU
	 * from the vm mask set of all processes.
	 */
	flush_cache_all();
	local_flush_tlb_all();

142
	clear_tasks_mm_cpumask(cpu);
143 144 145 146

	return 0;
}

147 148
static DECLARE_COMPLETION(cpu_died);

149 150 151 152
/*
 * called on the thread which is asking for a CPU to be shutdown -
 * waits until shutdown has completed, or it is timed out.
 */
153
void __cpu_die(unsigned int cpu)
154
{
155 156 157 158 159 160
	if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
		pr_err("CPU%u: cpu didn't die\n", cpu);
		return;
	}
	printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);

161 162 163 164 165 166 167 168 169 170 171 172
	if (!platform_cpu_kill(cpu))
		printk("CPU%u: unable to kill\n", cpu);
}

/*
 * Called from the idle thread for the CPU which has been shutdown.
 *
 * Note that we disable IRQs here, but do not re-enable them
 * before returning to the caller. This is also the behaviour
 * of the other hotplug-cpu capable cores, so presumably coming
 * out of idle fixes this.
 */
173
void __ref cpu_die(void)
174 175 176 177 178
{
	unsigned int cpu = smp_processor_id();

	idle_task_exit();

179 180 181
	local_irq_disable();
	mb();

182
	/* Tell __cpu_die() that this CPU is now safe to dispose of */
183
	RCU_NONIDLE(complete(&cpu_died));
184

185 186
	/*
	 * actual CPU shutdown procedure is at least platform (if not
187
	 * CPU) specific.
188 189 190 191 192 193 194 195 196
	 */
	platform_cpu_die(cpu);

	/*
	 * Do not return to the idle loop - jump back to the secondary
	 * cpu initialisation.  There's some initialisation which needs
	 * to be repeated to undo the effects of taking the CPU offline.
	 */
	__asm__("mov	sp, %0\n"
197
	"	mov	fp, #0\n"
198 199
	"	b	secondary_start_kernel"
		:
A
Al Viro 已提交
200
		: "r" (task_stack_page(current) + THREAD_SIZE - 8));
201 202 203
}
#endif /* CONFIG_HOTPLUG_CPU */

204 205 206 207 208 209 210 211 212
/*
 * Called by both boot and secondaries to move global data into
 * per-processor storage.
 */
static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
{
	struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);

	cpu_info->loops_per_jiffy = loops_per_jiffy;
213 214

	store_cpu_topology(cpuid);
215 216
}

217 218
static void percpu_timer_setup(void);

219 220 221 222
/*
 * This is the secondary CPU boot entry.  We're using this CPUs
 * idle thread stack, but a set of temporary page tables.
 */
223
asmlinkage void __cpuinit secondary_start_kernel(void)
224 225
{
	struct mm_struct *mm = &init_mm;
226
	unsigned int cpu = smp_processor_id();
227 228 229 230 231 232 233

	/*
	 * All kernel threads share the same mm context; grab a
	 * reference and switch to it.
	 */
	atomic_inc(&mm->mm_count);
	current->active_mm = mm;
234
	cpumask_set_cpu(cpu, mm_cpumask(mm));
235 236
	cpu_switch_mm(mm->pgd, mm);
	enter_lazy_tlb(mm, current);
237
	local_flush_tlb_all();
238

239 240
	printk("CPU%u: Booted secondary processor\n", cpu);

241
	cpu_init();
242
	preempt_disable();
243
	trace_hardirqs_off();
244 245 246 247 248 249

	/*
	 * Give the platform a chance to do its own initialisation.
	 */
	platform_secondary_init(cpu);

250
	notify_cpu_starting(cpu);
251

252 253 254 255 256
	calibrate_delay();

	smp_store_cpu_info(cpu);

	/*
257 258
	 * OK, now it's safe to let the boot CPU continue.  Wait for
	 * the CPU migration code to notice that the CPU is online
259
	 * before we continue - which happens after __cpu_up returns.
260
	 */
261
	set_cpu_online(cpu, true);
262
	complete(&cpu_running);
263 264 265 266 267 268 269 270 271

	/*
	 * Setup the percpu timer for this CPU.
	 */
	percpu_timer_setup();

	local_irq_enable();
	local_fiq_enable();

272 273 274 275 276 277
	/*
	 * OK, it's off to the idle thread for us
	 */
	cpu_idle();
}

L
Linus Torvalds 已提交
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
void __init smp_cpus_done(unsigned int max_cpus)
{
	int cpu;
	unsigned long bogosum = 0;

	for_each_online_cpu(cpu)
		bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy;

	printk(KERN_INFO "SMP: Total of %d processors activated "
	       "(%lu.%02lu BogoMIPS).\n",
	       num_online_cpus(),
	       bogosum / (500000/HZ),
	       (bogosum / (5000/HZ)) % 100);
}

void __init smp_prepare_boot_cpu(void)
{
}

297
void __init smp_prepare_cpus(unsigned int max_cpus)
L
Linus Torvalds 已提交
298
{
299
	unsigned int ncores = num_possible_cpus();
L
Linus Torvalds 已提交
300

301 302
	init_cpu_topology();

303
	smp_store_cpu_info(smp_processor_id());
L
Linus Torvalds 已提交
304 305

	/*
306
	 * are we trying to boot more cores than exist?
L
Linus Torvalds 已提交
307
	 */
308 309
	if (max_cpus > ncores)
		max_cpus = ncores;
310
	if (ncores > 1 && max_cpus) {
311 312 313 314 315
		/*
		 * Enable the local timer or broadcast device for the
		 * boot CPU, but only if we have more than one CPU.
		 */
		percpu_timer_setup();
L
Linus Torvalds 已提交
316

317 318 319 320 321 322
		/*
		 * Initialise the present map, which describes the set of CPUs
		 * actually populated at the present time. A platform should
		 * re-initialize the map in platform_smp_prepare_cpus() if
		 * present != possible (e.g. physical hotplug).
		 */
323
		init_cpu_present(cpu_possible_mask);
324

325 326 327 328 329 330
		/*
		 * Initialise the SCU if there are more than one CPU
		 * and let them know where to start.
		 */
		platform_smp_prepare_cpus(max_cpus);
	}
L
Linus Torvalds 已提交
331 332
}

333 334 335 336 337 338 339
static void (*smp_cross_call)(const struct cpumask *, unsigned int);

void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
{
	smp_cross_call = fn;
}

340
void arch_send_call_function_ipi_mask(const struct cpumask *mask)
L
Linus Torvalds 已提交
341
{
R
Russell King 已提交
342
	smp_cross_call(mask, IPI_CALL_FUNC);
L
Linus Torvalds 已提交
343 344
}

345
void arch_send_call_function_single_ipi(int cpu)
346
{
R
Russell King 已提交
347
	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
348 349
}

350 351 352 353 354 355 356 357 358
static const char *ipi_types[NR_IPI] = {
#define S(x,s)	[x - IPI_TIMER] = s
	S(IPI_TIMER, "Timer broadcast interrupts"),
	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
	S(IPI_CALL_FUNC, "Function call interrupts"),
	S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
	S(IPI_CPU_STOP, "CPU stop interrupts"),
};

359
void show_ipi_list(struct seq_file *p, int prec)
L
Linus Torvalds 已提交
360
{
361
	unsigned int cpu, i;
L
Linus Torvalds 已提交
362

363 364
	for (i = 0; i < NR_IPI; i++) {
		seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
L
Linus Torvalds 已提交
365

366 367 368
		for_each_present_cpu(cpu)
			seq_printf(p, "%10u ",
				   __get_irq_stat(cpu, ipi_irqs[i]));
L
Linus Torvalds 已提交
369

370 371
		seq_printf(p, " %s\n", ipi_types[i]);
	}
L
Linus Torvalds 已提交
372 373
}

374
u64 smp_irq_stat_cpu(unsigned int cpu)
375
{
376 377
	u64 sum = 0;
	int i;
378

379 380
	for (i = 0; i < NR_IPI; i++)
		sum += __get_irq_stat(cpu, ipi_irqs[i]);
381

382
	return sum;
383 384
}

385 386 387 388 389
/*
 * Timer (local or broadcast) support
 */
static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);

R
Russell King 已提交
390
static void ipi_timer(void)
L
Linus Torvalds 已提交
391
{
392 393
	struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
	evt->event_handler(evt);
L
Linus Torvalds 已提交
394 395
}

396 397 398
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
static void smp_timer_broadcast(const struct cpumask *mask)
{
R
Russell King 已提交
399
	smp_cross_call(mask, IPI_TIMER);
400
}
401 402 403
#else
#define smp_timer_broadcast	NULL
#endif
404 405 406 407 408 409

static void broadcast_timer_set_mode(enum clock_event_mode mode,
	struct clock_event_device *evt)
{
}

410
static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)
411 412 413 414 415 416 417 418 419 420 421 422
{
	evt->name	= "dummy_timer";
	evt->features	= CLOCK_EVT_FEAT_ONESHOT |
			  CLOCK_EVT_FEAT_PERIODIC |
			  CLOCK_EVT_FEAT_DUMMY;
	evt->rating	= 400;
	evt->mult	= 1;
	evt->set_mode	= broadcast_timer_set_mode;

	clockevents_register_device(evt);
}

423 424 425 426 427
static struct local_timer_ops *lt_ops;

#ifdef CONFIG_LOCAL_TIMERS
int local_timer_register(struct local_timer_ops *ops)
{
428 429 430
	if (!is_smp() || !setup_max_cpus)
		return -ENXIO;

431 432 433 434 435 436 437 438
	if (lt_ops)
		return -EBUSY;

	lt_ops = ops;
	return 0;
}
#endif

439
static void __cpuinit percpu_timer_setup(void)
440 441 442 443 444
{
	unsigned int cpu = smp_processor_id();
	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);

	evt->cpumask = cpumask_of(cpu);
445
	evt->broadcast = smp_timer_broadcast;
446

447
	if (!lt_ops || lt_ops->setup(evt))
448
		broadcast_timer_setup(evt);
449 450
}

451 452 453 454 455 456 457 458 459 460 461
#ifdef CONFIG_HOTPLUG_CPU
/*
 * The generic clock events code purposely does not stop the local timer
 * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
 * manually here.
 */
static void percpu_timer_stop(void)
{
	unsigned int cpu = smp_processor_id();
	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);

462 463
	if (lt_ops)
		lt_ops->stop(evt);
464 465 466
}
#endif

467
static DEFINE_RAW_SPINLOCK(stop_lock);
L
Linus Torvalds 已提交
468 469 470 471 472 473

/*
 * ipi_cpu_stop - handle IPI from smp_send_stop()
 */
static void ipi_cpu_stop(unsigned int cpu)
{
474 475
	if (system_state == SYSTEM_BOOTING ||
	    system_state == SYSTEM_RUNNING) {
476
		raw_spin_lock(&stop_lock);
477 478
		printk(KERN_CRIT "CPU%u: stopping\n", cpu);
		dump_stack();
479
		raw_spin_unlock(&stop_lock);
480
	}
L
Linus Torvalds 已提交
481

482
	set_cpu_online(cpu, false);
L
Linus Torvalds 已提交
483 484 485 486 487 488 489 490 491 492 493

	local_fiq_disable();
	local_irq_disable();

	while (1)
		cpu_relax();
}

/*
 * Main handler for inter-processor interrupts
 */
R
Russell King 已提交
494
asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
495 496 497 498 499
{
	handle_IPI(ipinr, regs);
}

void handle_IPI(int ipinr, struct pt_regs *regs)
L
Linus Torvalds 已提交
500 501
{
	unsigned int cpu = smp_processor_id();
R
Russell King 已提交
502
	struct pt_regs *old_regs = set_irq_regs(regs);
L
Linus Torvalds 已提交
503

504 505
	if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
		__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
L
Linus Torvalds 已提交
506

507 508
	switch (ipinr) {
	case IPI_TIMER:
509
		irq_enter();
510
		ipi_timer();
511
		irq_exit();
512
		break;
L
Linus Torvalds 已提交
513

514
	case IPI_RESCHEDULE:
515
		scheduler_ipi();
516
		break;
L
Linus Torvalds 已提交
517

518
	case IPI_CALL_FUNC:
519
		irq_enter();
520
		generic_smp_call_function_interrupt();
521
		irq_exit();
522
		break;
523

524
	case IPI_CALL_FUNC_SINGLE:
525
		irq_enter();
526
		generic_smp_call_function_single_interrupt();
527
		irq_exit();
528
		break;
L
Linus Torvalds 已提交
529

530
	case IPI_CPU_STOP:
531
		irq_enter();
532
		ipi_cpu_stop(cpu);
533
		irq_exit();
534
		break;
L
Linus Torvalds 已提交
535

536 537 538 539
	default:
		printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
		       cpu, ipinr);
		break;
L
Linus Torvalds 已提交
540
	}
R
Russell King 已提交
541
	set_irq_regs(old_regs);
L
Linus Torvalds 已提交
542 543 544 545
}

void smp_send_reschedule(int cpu)
{
R
Russell King 已提交
546
	smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
L
Linus Torvalds 已提交
547 548
}

549 550 551 552 553 554 555 556 557 558 559
#ifdef CONFIG_HOTPLUG_CPU
static void smp_kill_cpus(cpumask_t *mask)
{
	unsigned int cpu;
	for_each_cpu(cpu, mask)
		platform_cpu_kill(cpu);
}
#else
static void smp_kill_cpus(cpumask_t *mask) { }
#endif

L
Linus Torvalds 已提交
560 561
void smp_send_stop(void)
{
562
	unsigned long timeout;
563
	struct cpumask mask;
L
Linus Torvalds 已提交
564

565 566
	cpumask_copy(&mask, cpu_online_mask);
	cpumask_clear_cpu(smp_processor_id(), &mask);
567 568
	if (!cpumask_empty(&mask))
		smp_cross_call(&mask, IPI_CPU_STOP);
569

570 571 572 573
	/* Wait up to one second for other CPUs to stop */
	timeout = USEC_PER_SEC;
	while (num_online_cpus() > 1 && timeout--)
		udelay(1);
574

575 576
	if (num_online_cpus() > 1)
		pr_warning("SMP: failed to stop secondary CPUs\n");
577 578

	smp_kill_cpus(&mask);
579 580 581
}

/*
L
Linus Torvalds 已提交
582
 * not supported here
583
 */
584
int setup_profiling_timer(unsigned int multiplier)
585
{
L
Linus Torvalds 已提交
586
	return -EINVAL;
587
}
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640

#ifdef CONFIG_CPU_FREQ

static DEFINE_PER_CPU(unsigned long, l_p_j_ref);
static DEFINE_PER_CPU(unsigned long, l_p_j_ref_freq);
static unsigned long global_l_p_j_ref;
static unsigned long global_l_p_j_ref_freq;

static int cpufreq_callback(struct notifier_block *nb,
					unsigned long val, void *data)
{
	struct cpufreq_freqs *freq = data;
	int cpu = freq->cpu;

	if (freq->flags & CPUFREQ_CONST_LOOPS)
		return NOTIFY_OK;

	if (!per_cpu(l_p_j_ref, cpu)) {
		per_cpu(l_p_j_ref, cpu) =
			per_cpu(cpu_data, cpu).loops_per_jiffy;
		per_cpu(l_p_j_ref_freq, cpu) = freq->old;
		if (!global_l_p_j_ref) {
			global_l_p_j_ref = loops_per_jiffy;
			global_l_p_j_ref_freq = freq->old;
		}
	}

	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
		loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
						global_l_p_j_ref_freq,
						freq->new);
		per_cpu(cpu_data, cpu).loops_per_jiffy =
			cpufreq_scale(per_cpu(l_p_j_ref, cpu),
					per_cpu(l_p_j_ref_freq, cpu),
					freq->new);
	}
	return NOTIFY_OK;
}

static struct notifier_block cpufreq_notifier = {
	.notifier_call  = cpufreq_callback,
};

static int __init register_cpufreq_notifier(void)
{
	return cpufreq_register_notifier(&cpufreq_notifier,
						CPUFREQ_TRANSITION_NOTIFIER);
}
core_initcall(register_cpufreq_notifier);

#endif