smp.c 25.7 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
M
Martin Schwidefsky 已提交
2
 *  SMP related functions
L
Linus Torvalds 已提交
3
 *
4
 *    Copyright IBM Corp. 1999, 2012
M
Martin Schwidefsky 已提交
5 6 7
 *    Author(s): Denis Joseph Barrow,
 *		 Martin Schwidefsky <schwidefsky@de.ibm.com>,
 *		 Heiko Carstens <heiko.carstens@de.ibm.com>,
L
Linus Torvalds 已提交
8
 *
9
 *  based on other smp stuff by
L
Linus Torvalds 已提交
10 11 12
 *    (c) 1995 Alan Cox, CymruNET Ltd  <alan@cymru.net>
 *    (c) 1998 Ingo Molnar
 *
M
Martin Schwidefsky 已提交
13 14 15
 * The code outside of smp.c uses logical cpu numbers, only smp.c does
 * the translation of logical to physical cpu ids. All new code that
 * operates on physical cpu numbers needs to go into smp.c.
L
Linus Torvalds 已提交
16 17
 */

18 19 20
#define KMSG_COMPONENT "cpu"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

21
#include <linux/workqueue.h>
L
Linus Torvalds 已提交
22 23 24
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
A
Alexey Dobriyan 已提交
25
#include <linux/err.h>
L
Linus Torvalds 已提交
26 27 28 29
#include <linux/spinlock.h>
#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
30
#include <linux/irqflags.h>
L
Linus Torvalds 已提交
31
#include <linux/cpu.h>
32
#include <linux/slab.h>
M
Michael Holzheu 已提交
33
#include <linux/crash_dump.h>
34
#include <asm/asm-offsets.h>
35 36
#include <asm/switch_to.h>
#include <asm/facility.h>
M
Michael Holzheu 已提交
37
#include <asm/ipl.h>
38
#include <asm/setup.h>
L
Linus Torvalds 已提交
39 40
#include <asm/irq.h>
#include <asm/tlbflush.h>
41
#include <asm/vtimer.h>
M
Michael Holzheu 已提交
42
#include <asm/lowcore.h>
43
#include <asm/sclp.h>
44
#include <asm/vdso.h>
45
#include <asm/debug.h>
46
#include <asm/os_info.h>
47
#include <asm/sigp.h>
48
#include "entry.h"
L
Linus Torvalds 已提交
49

M
Martin Schwidefsky 已提交
50 51 52 53 54 55
enum {
	ec_schedule = 0,
	ec_call_function,
	ec_call_function_single,
	ec_stop_cpu,
};
56

M
Martin Schwidefsky 已提交
57
enum {
58 59 60 61
	CPU_STATE_STANDBY,
	CPU_STATE_CONFIGURED,
};

M
Martin Schwidefsky 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
struct pcpu {
	struct cpu cpu;
	struct _lowcore *lowcore;	/* lowcore page(s) for the cpu */
	unsigned long async_stack;	/* async stack for the cpu */
	unsigned long panic_stack;	/* panic stack for the cpu */
	unsigned long ec_mask;		/* bit mask for ec_xxx functions */
	int state;			/* physical cpu state */
	u32 status;			/* last status received via sigp */
	u16 address;			/* physical cpu address */
};

static u8 boot_cpu_type;
static u16 boot_cpu_address;
static struct pcpu pcpu_devices[NR_CPUS];

77
DEFINE_MUTEX(smp_cpu_state_mutex);
78

M
Martin Schwidefsky 已提交
79 80 81 82 83 84 85
/*
 * Signal processor helper functions.
 */
static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status)
{
	register unsigned int reg1 asm ("1") = parm;
	int cc;
86

M
Martin Schwidefsky 已提交
87 88 89 90 91 92 93 94 95
	asm volatile(
		"	sigp	%1,%2,0(%3)\n"
		"	ipm	%0\n"
		"	srl	%0,28\n"
		: "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
	if (status && cc == 1)
		*status = reg1;
	return cc;
}
L
Linus Torvalds 已提交
96

M
Martin Schwidefsky 已提交
97
static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status)
98
{
M
Martin Schwidefsky 已提交
99
	int cc;
100

M
Martin Schwidefsky 已提交
101 102
	while (1) {
		cc = __pcpu_sigp(addr, order, parm, status);
103
		if (cc != SIGP_CC_BUSY)
M
Martin Schwidefsky 已提交
104 105
			return cc;
		cpu_relax();
106 107 108
	}
}

M
Martin Schwidefsky 已提交
109
static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm)
H
Heiko Carstens 已提交
110
{
M
Martin Schwidefsky 已提交
111 112 113 114
	int cc, retry;

	for (retry = 0; ; retry++) {
		cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status);
115
		if (cc != SIGP_CC_BUSY)
M
Martin Schwidefsky 已提交
116 117 118 119 120 121 122 123 124
			break;
		if (retry >= 3)
			udelay(10);
	}
	return cc;
}

static inline int pcpu_stopped(struct pcpu *pcpu)
{
125 126
	if (__pcpu_sigp(pcpu->address, SIGP_SENSE,
			0, &pcpu->status) != SIGP_CC_STATUS_STORED)
M
Martin Schwidefsky 已提交
127
		return 0;
128
	return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED));
M
Martin Schwidefsky 已提交
129 130 131
}

static inline int pcpu_running(struct pcpu *pcpu)
H
Heiko Carstens 已提交
132
{
133 134
	if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING,
			0, &pcpu->status) != SIGP_CC_STATUS_STORED)
M
Martin Schwidefsky 已提交
135
		return 1;
136 137
	/* Status stored condition code is equivalent to cpu not running. */
	return 0;
H
Heiko Carstens 已提交
138 139
}

140
/*
M
Martin Schwidefsky 已提交
141
 * Find struct pcpu by cpu address.
142
 */
M
Martin Schwidefsky 已提交
143
static struct pcpu *pcpu_find_address(const struct cpumask *mask, int address)
144 145 146
{
	int cpu;

M
Martin Schwidefsky 已提交
147 148 149 150 151 152 153 154 155 156 157 158
	for_each_cpu(cpu, mask)
		if (pcpu_devices[cpu].address == address)
			return pcpu_devices + cpu;
	return NULL;
}

static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit)
{
	int order;

	set_bit(ec_bit, &pcpu->ec_mask);
	order = pcpu_running(pcpu) ?
159
		SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL;
M
Martin Schwidefsky 已提交
160 161 162 163 164 165 166 167 168 169 170 171 172 173
	pcpu_sigp_retry(pcpu, order, 0);
}

static int __cpuinit pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
{
	struct _lowcore *lc;

	if (pcpu != &pcpu_devices[0]) {
		pcpu->lowcore =	(struct _lowcore *)
			__get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER);
		pcpu->async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
		pcpu->panic_stack = __get_free_page(GFP_KERNEL);
		if (!pcpu->lowcore || !pcpu->panic_stack || !pcpu->async_stack)
			goto out;
174
	}
M
Martin Schwidefsky 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
	lc = pcpu->lowcore;
	memcpy(lc, &S390_lowcore, 512);
	memset((char *) lc + 512, 0, sizeof(*lc) - 512);
	lc->async_stack = pcpu->async_stack + ASYNC_SIZE;
	lc->panic_stack = pcpu->panic_stack + PAGE_SIZE;
	lc->cpu_nr = cpu;
#ifndef CONFIG_64BIT
	if (MACHINE_HAS_IEEE) {
		lc->extended_save_area_addr = get_zeroed_page(GFP_KERNEL);
		if (!lc->extended_save_area_addr)
			goto out;
	}
#else
	if (vdso_alloc_per_cpu(lc))
		goto out;
#endif
	lowcore_ptr[cpu] = lc;
192
	pcpu_sigp_retry(pcpu, SIGP_SET_PREFIX, (u32)(unsigned long) lc);
M
Martin Schwidefsky 已提交
193 194 195 196 197 198 199 200
	return 0;
out:
	if (pcpu != &pcpu_devices[0]) {
		free_page(pcpu->panic_stack);
		free_pages(pcpu->async_stack, ASYNC_ORDER);
		free_pages((unsigned long) pcpu->lowcore, LC_ORDER);
	}
	return -ENOMEM;
201 202
}

203 204
#ifdef CONFIG_HOTPLUG_CPU

M
Martin Schwidefsky 已提交
205
static void pcpu_free_lowcore(struct pcpu *pcpu)
206
{
207
	pcpu_sigp_retry(pcpu, SIGP_SET_PREFIX, 0);
M
Martin Schwidefsky 已提交
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
	lowcore_ptr[pcpu - pcpu_devices] = NULL;
#ifndef CONFIG_64BIT
	if (MACHINE_HAS_IEEE) {
		struct _lowcore *lc = pcpu->lowcore;

		free_page((unsigned long) lc->extended_save_area_addr);
		lc->extended_save_area_addr = 0;
	}
#else
	vdso_free_per_cpu(pcpu->lowcore);
#endif
	if (pcpu != &pcpu_devices[0]) {
		free_page(pcpu->panic_stack);
		free_pages(pcpu->async_stack, ASYNC_ORDER);
		free_pages((unsigned long) pcpu->lowcore, LC_ORDER);
	}
}

226 227
#endif /* CONFIG_HOTPLUG_CPU */

M
Martin Schwidefsky 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)
{
	struct _lowcore *lc = pcpu->lowcore;

	atomic_inc(&init_mm.context.attach_count);
	lc->cpu_nr = cpu;
	lc->percpu_offset = __per_cpu_offset[cpu];
	lc->kernel_asce = S390_lowcore.kernel_asce;
	lc->machine_flags = S390_lowcore.machine_flags;
	lc->ftrace_func = S390_lowcore.ftrace_func;
	lc->user_timer = lc->system_timer = lc->steal_timer = 0;
	__ctl_store(lc->cregs_save_area, 0, 15);
	save_access_regs((unsigned int *) lc->access_regs_save_area);
	memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
	       MAX_FACILITY_BIT/8);
}

static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk)
{
	struct _lowcore *lc = pcpu->lowcore;
	struct thread_info *ti = task_thread_info(tsk);

	lc->kernel_stack = (unsigned long) task_stack_page(tsk) + THREAD_SIZE;
	lc->thread_info = (unsigned long) task_thread_info(tsk);
	lc->current_task = (unsigned long) tsk;
	lc->user_timer = ti->user_timer;
	lc->system_timer = ti->system_timer;
	lc->steal_timer = 0;
}

static void pcpu_start_fn(struct pcpu *pcpu, void (*func)(void *), void *data)
{
	struct _lowcore *lc = pcpu->lowcore;

	lc->restart_stack = lc->kernel_stack;
	lc->restart_fn = (unsigned long) func;
	lc->restart_data = (unsigned long) data;
	lc->restart_source = -1UL;
266
	pcpu_sigp_retry(pcpu, SIGP_RESTART, 0);
M
Martin Schwidefsky 已提交
267 268 269 270 271 272 273 274
}

/*
 * Call function via PSW restart on pcpu and stop the current cpu.
 */
static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *),
			  void *data, unsigned long stack)
{
275
	struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices];
276
	unsigned long source_cpu = stap();
M
Martin Schwidefsky 已提交
277 278

	__load_psw_mask(psw_kernel_bits);
279
	if (pcpu->address == source_cpu)
M
Martin Schwidefsky 已提交
280 281
		func(data);	/* should not return */
	/* Stop target cpu (if func returns this stops the current cpu). */
282
	pcpu_sigp_retry(pcpu, SIGP_STOP, 0);
M
Martin Schwidefsky 已提交
283
	/* Restart func on the target cpu and stop the current cpu. */
284 285 286 287
	mem_assign_absolute(lc->restart_stack, stack);
	mem_assign_absolute(lc->restart_fn, (unsigned long) func);
	mem_assign_absolute(lc->restart_data, (unsigned long) data);
	mem_assign_absolute(lc->restart_source, source_cpu);
M
Martin Schwidefsky 已提交
288
	asm volatile(
289
		"0:	sigp	0,%0,%2	# sigp restart to target cpu\n"
M
Martin Schwidefsky 已提交
290
		"	brc	2,0b	# busy, try again\n"
291
		"1:	sigp	0,%1,%3	# sigp stop to current cpu\n"
M
Martin Schwidefsky 已提交
292
		"	brc	2,1b	# busy, try again\n"
293
		: : "d" (pcpu->address), "d" (source_cpu),
294 295
		    "K" (SIGP_RESTART), "K" (SIGP_STOP)
		: "0", "1", "cc");
M
Martin Schwidefsky 已提交
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
	for (;;) ;
}

/*
 * Call function on an online CPU.
 */
void smp_call_online_cpu(void (*func)(void *), void *data)
{
	struct pcpu *pcpu;

	/* Use the current cpu if it is online. */
	pcpu = pcpu_find_address(cpu_online_mask, stap());
	if (!pcpu)
		/* Use the first online cpu. */
		pcpu = pcpu_devices + cpumask_first(cpu_online_mask);
	pcpu_delegate(pcpu, func, data, (unsigned long) restart_stack);
}

/*
 * Call function on the ipl CPU.
 */
void smp_call_ipl_cpu(void (*func)(void *), void *data)
{
319 320
	pcpu_delegate(&pcpu_devices[0], func, data,
		      pcpu_devices->panic_stack + PAGE_SIZE);
M
Martin Schwidefsky 已提交
321 322 323 324 325 326 327 328 329 330
}

int smp_find_processor_id(u16 address)
{
	int cpu;

	for_each_present_cpu(cpu)
		if (pcpu_devices[cpu].address == address)
			return cpu;
	return -1;
331 332
}

M
Martin Schwidefsky 已提交
333
int smp_vcpu_scheduled(int cpu)
334
{
M
Martin Schwidefsky 已提交
335 336 337 338 339 340 341
	return pcpu_running(pcpu_devices + cpu);
}

void smp_yield(void)
{
	if (MACHINE_HAS_DIAG44)
		asm volatile("diag 0,0,0x44");
342 343
}

M
Martin Schwidefsky 已提交
344
void smp_yield_cpu(int cpu)
345
{
M
Martin Schwidefsky 已提交
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
	if (MACHINE_HAS_DIAG9C)
		asm volatile("diag %0,0,0x9c"
			     : : "d" (pcpu_devices[cpu].address));
	else if (MACHINE_HAS_DIAG44)
		asm volatile("diag 0,0,0x44");
}

/*
 * Send cpus emergency shutdown signal. This gives the cpus the
 * opportunity to complete outstanding interrupts.
 */
void smp_emergency_stop(cpumask_t *cpumask)
{
	u64 end;
	int cpu;

	end = get_clock() + (1000000UL << 12);
	for_each_cpu(cpu, cpumask) {
		struct pcpu *pcpu = pcpu_devices + cpu;
		set_bit(ec_stop_cpu, &pcpu->ec_mask);
366 367
		while (__pcpu_sigp(pcpu->address, SIGP_EMERGENCY_SIGNAL,
				   0, NULL) == SIGP_CC_BUSY &&
M
Martin Schwidefsky 已提交
368 369 370 371 372 373 374 375 376
		       get_clock() < end)
			cpu_relax();
	}
	while (get_clock() < end) {
		for_each_cpu(cpu, cpumask)
			if (pcpu_stopped(pcpu_devices + cpu))
				cpumask_clear_cpu(cpu, cpumask);
		if (cpumask_empty(cpumask))
			break;
377
		cpu_relax();
M
Martin Schwidefsky 已提交
378
	}
379 380
}

M
Martin Schwidefsky 已提交
381 382 383
/*
 * Stop all cpus but the current one.
 */
384
void smp_send_stop(void)
L
Linus Torvalds 已提交
385
{
386 387
	cpumask_t cpumask;
	int cpu;
L
Linus Torvalds 已提交
388

389
	/* Disable all interrupts/machine checks */
390
	__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
391
	trace_hardirqs_off();
L
Linus Torvalds 已提交
392

393
	debug_set_critical();
394 395 396
	cpumask_copy(&cpumask, cpu_online_mask);
	cpumask_clear_cpu(smp_processor_id(), &cpumask);

M
Martin Schwidefsky 已提交
397 398
	if (oops_in_progress)
		smp_emergency_stop(&cpumask);
L
Linus Torvalds 已提交
399

400 401
	/* stop all processors */
	for_each_cpu(cpu, &cpumask) {
M
Martin Schwidefsky 已提交
402
		struct pcpu *pcpu = pcpu_devices + cpu;
403
		pcpu_sigp_retry(pcpu, SIGP_STOP, 0);
M
Martin Schwidefsky 已提交
404
		while (!pcpu_stopped(pcpu))
H
Heiko Carstens 已提交
405 406 407 408
			cpu_relax();
	}
}

M
Martin Schwidefsky 已提交
409 410 411 412 413
/*
 * Stop the current cpu.
 */
void smp_stop_cpu(void)
{
414
	pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0);
M
Martin Schwidefsky 已提交
415 416 417
	for (;;) ;
}

L
Linus Torvalds 已提交
418 419 420 421
/*
 * This is the main routine where commands issued by other
 * cpus are handled.
 */
422
static void do_ext_call_interrupt(struct ext_code ext_code,
423
				  unsigned int param32, unsigned long param64)
L
Linus Torvalds 已提交
424
{
425
	unsigned long bits;
M
Martin Schwidefsky 已提交
426
	int cpu;
L
Linus Torvalds 已提交
427

M
Martin Schwidefsky 已提交
428
	cpu = smp_processor_id();
429
	if (ext_code.code == 0x1202)
M
Martin Schwidefsky 已提交
430
		kstat_cpu(cpu).irqs[EXTINT_EXC]++;
431
	else
M
Martin Schwidefsky 已提交
432
		kstat_cpu(cpu).irqs[EXTINT_EMS]++;
433 434 435
	/*
	 * handle bit signal external calls
	 */
M
Martin Schwidefsky 已提交
436
	bits = xchg(&pcpu_devices[cpu].ec_mask, 0);
L
Linus Torvalds 已提交
437

438 439 440
	if (test_bit(ec_stop_cpu, &bits))
		smp_stop_cpu();

441 442 443
	if (test_bit(ec_schedule, &bits))
		scheduler_ipi();

444
	if (test_bit(ec_call_function, &bits))
445 446 447 448
		generic_smp_call_function_interrupt();

	if (test_bit(ec_call_function_single, &bits))
		generic_smp_call_function_single_interrupt();
449

L
Linus Torvalds 已提交
450 451
}

452
void arch_send_call_function_ipi_mask(const struct cpumask *mask)
453 454 455
{
	int cpu;

456
	for_each_cpu(cpu, mask)
M
Martin Schwidefsky 已提交
457
		pcpu_ec_call(pcpu_devices + cpu, ec_call_function);
458 459 460 461
}

void arch_send_call_function_single_ipi(int cpu)
{
M
Martin Schwidefsky 已提交
462
	pcpu_ec_call(pcpu_devices + cpu, ec_call_function_single);
463 464
}

465
#ifndef CONFIG_64BIT
L
Linus Torvalds 已提交
466 467 468
/*
 * this function sends a 'purge tlb' signal to another CPU.
 */
469
static void smp_ptlb_callback(void *info)
L
Linus Torvalds 已提交
470
{
M
Martin Schwidefsky 已提交
471
	__tlb_flush_local();
L
Linus Torvalds 已提交
472 473 474 475
}

void smp_ptlb_all(void)
{
476
	on_each_cpu(smp_ptlb_callback, NULL, 1);
L
Linus Torvalds 已提交
477 478
}
EXPORT_SYMBOL(smp_ptlb_all);
479
#endif /* ! CONFIG_64BIT */
L
Linus Torvalds 已提交
480 481 482 483 484 485 486 487

/*
 * this function sends a 'reschedule' IPI to another CPU.
 * it goes straight through and wastes no time serializing
 * anything. Worst case is that we lose a reschedule ...
 */
void smp_send_reschedule(int cpu)
{
M
Martin Schwidefsky 已提交
488
	pcpu_ec_call(pcpu_devices + cpu, ec_schedule);
L
Linus Torvalds 已提交
489 490 491 492 493
}

/*
 * parameter area for the set/clear control bit callbacks
 */
494
struct ec_creg_mask_parms {
M
Martin Schwidefsky 已提交
495 496 497
	unsigned long orval;
	unsigned long andval;
	int cr;
498
};
L
Linus Torvalds 已提交
499 500 501 502

/*
 * callback for setting/clearing control bits
 */
503 504
static void smp_ctl_bit_callback(void *info)
{
505
	struct ec_creg_mask_parms *pp = info;
L
Linus Torvalds 已提交
506
	unsigned long cregs[16];
507

508
	__ctl_store(cregs, 0, 15);
M
Martin Schwidefsky 已提交
509
	cregs[pp->cr] = (cregs[pp->cr] & pp->andval) | pp->orval;
510
	__ctl_load(cregs, 0, 15);
L
Linus Torvalds 已提交
511 512 513 514 515
}

/*
 * Set a bit in a control register of all cpus
 */
516 517
void smp_ctl_set_bit(int cr, int bit)
{
M
Martin Schwidefsky 已提交
518
	struct ec_creg_mask_parms parms = { 1UL << bit, -1UL, cr };
L
Linus Torvalds 已提交
519

520
	on_each_cpu(smp_ctl_bit_callback, &parms, 1);
L
Linus Torvalds 已提交
521
}
522
EXPORT_SYMBOL(smp_ctl_set_bit);
L
Linus Torvalds 已提交
523 524 525 526

/*
 * Clear a bit in a control register of all cpus
 */
527 528
void smp_ctl_clear_bit(int cr, int bit)
{
M
Martin Schwidefsky 已提交
529
	struct ec_creg_mask_parms parms = { 0, ~(1UL << bit), cr };
L
Linus Torvalds 已提交
530

531
	on_each_cpu(smp_ctl_bit_callback, &parms, 1);
L
Linus Torvalds 已提交
532
}
533
EXPORT_SYMBOL(smp_ctl_clear_bit);
L
Linus Torvalds 已提交
534

M
Michael Holzheu 已提交
535
#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP)
M
Michael Holzheu 已提交
536

M
Martin Schwidefsky 已提交
537 538 539 540
struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
EXPORT_SYMBOL_GPL(zfcpdump_save_areas);

static void __init smp_get_save_area(int cpu, u16 address)
M
Michael Holzheu 已提交
541
{
M
Martin Schwidefsky 已提交
542 543 544
	void *lc = pcpu_devices[0].lowcore;
	struct save_area *save_area;

M
Michael Holzheu 已提交
545
	if (is_kdump_kernel())
M
Michael Holzheu 已提交
546
		return;
M
Martin Schwidefsky 已提交
547 548 549
	if (!OLDMEM_BASE && (address == boot_cpu_address ||
			     ipl_info.type != IPL_TYPE_FCP_DUMP))
		return;
550
	if (cpu >= NR_CPUS) {
M
Martin Schwidefsky 已提交
551 552
		pr_warning("CPU %i exceeds the maximum %i and is excluded "
			   "from the dump\n", cpu, NR_CPUS - 1);
553
		return;
M
Michael Holzheu 已提交
554
	}
M
Martin Schwidefsky 已提交
555 556 557 558 559 560 561 562 563 564 565 566 567
	save_area = kmalloc(sizeof(struct save_area), GFP_KERNEL);
	if (!save_area)
		panic("could not allocate memory for save area\n");
	zfcpdump_save_areas[cpu] = save_area;
#ifdef CONFIG_CRASH_DUMP
	if (address == boot_cpu_address) {
		/* Copy the registers of the boot cpu. */
		copy_oldmem_page(1, (void *) save_area, sizeof(*save_area),
				 SAVE_AREA_BASE - PAGE_SIZE, 0);
		return;
	}
#endif
	/* Get the registers of a non-boot cpu. */
568
	__pcpu_sigp_relax(address, SIGP_STOP_AND_STORE_STATUS, 0, NULL);
M
Martin Schwidefsky 已提交
569
	memcpy_real(save_area, lc + SAVE_AREA_BASE, sizeof(*save_area));
M
Michael Holzheu 已提交
570 571
}

M
Martin Schwidefsky 已提交
572
int smp_store_status(int cpu)
573
{
M
Martin Schwidefsky 已提交
574
	struct pcpu *pcpu;
575

M
Martin Schwidefsky 已提交
576
	pcpu = pcpu_devices + cpu;
577 578
	if (__pcpu_sigp_relax(pcpu->address, SIGP_STOP_AND_STORE_STATUS,
			      0, NULL) != SIGP_CC_ORDER_CODE_ACCEPTED)
M
Martin Schwidefsky 已提交
579
		return -EIO;
580 581 582
	return 0;
}

M
Martin Schwidefsky 已提交
583
#else /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */
584

M
Martin Schwidefsky 已提交
585
static inline void smp_get_save_area(int cpu, u16 address) { }
586

M
Martin Schwidefsky 已提交
587
#endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */
588

M
Martin Schwidefsky 已提交
589
static struct sclp_cpu_info *smp_get_cpu_info(void)
590
{
M
Martin Schwidefsky 已提交
591
	static int use_sigp_detection;
592
	struct sclp_cpu_info *info;
M
Martin Schwidefsky 已提交
593 594 595 596 597 598
	int address;

	info = kzalloc(sizeof(*info), GFP_KERNEL);
	if (info && (use_sigp_detection || sclp_get_cpu_info(info))) {
		use_sigp_detection = 1;
		for (address = 0; address <= MAX_CPU_ADDRESS; address++) {
599 600
			if (__pcpu_sigp_relax(address, SIGP_SENSE, 0, NULL) ==
			    SIGP_CC_NOT_OPERATIONAL)
M
Martin Schwidefsky 已提交
601 602 603 604 605
				continue;
			info->cpu[info->configured].address = address;
			info->configured++;
		}
		info->combined = info->configured;
606
	}
M
Martin Schwidefsky 已提交
607
	return info;
608 609
}

M
Martin Schwidefsky 已提交
610 611 612 613
static int __devinit smp_add_present_cpu(int cpu);

static int __devinit __smp_rescan_cpus(struct sclp_cpu_info *info,
				       int sysfs_add)
614
{
M
Martin Schwidefsky 已提交
615
	struct pcpu *pcpu;
616
	cpumask_t avail;
M
Martin Schwidefsky 已提交
617
	int cpu, nr, i;
618

M
Martin Schwidefsky 已提交
619
	nr = 0;
620
	cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask);
M
Martin Schwidefsky 已提交
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
	cpu = cpumask_first(&avail);
	for (i = 0; (i < info->combined) && (cpu < nr_cpu_ids); i++) {
		if (info->has_cpu_type && info->cpu[i].type != boot_cpu_type)
			continue;
		if (pcpu_find_address(cpu_present_mask, info->cpu[i].address))
			continue;
		pcpu = pcpu_devices + cpu;
		pcpu->address = info->cpu[i].address;
		pcpu->state = (cpu >= info->configured) ?
			CPU_STATE_STANDBY : CPU_STATE_CONFIGURED;
		cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
		set_cpu_present(cpu, true);
		if (sysfs_add && smp_add_present_cpu(cpu) != 0)
			set_cpu_present(cpu, false);
		else
			nr++;
		cpu = cpumask_next(cpu, &avail);
	}
	return nr;
L
Linus Torvalds 已提交
640 641
}

642 643 644 645 646
static void __init smp_detect_cpus(void)
{
	unsigned int cpu, c_cpus, s_cpus;
	struct sclp_cpu_info *info;

M
Martin Schwidefsky 已提交
647
	info = smp_get_cpu_info();
648 649 650 651
	if (!info)
		panic("smp_detect_cpus failed to allocate memory\n");
	if (info->has_cpu_type) {
		for (cpu = 0; cpu < info->combined; cpu++) {
M
Martin Schwidefsky 已提交
652 653 654 655 656
			if (info->cpu[cpu].address != boot_cpu_address)
				continue;
			/* The boot cpu dictates the cpu type. */
			boot_cpu_type = info->cpu[cpu].type;
			break;
657 658
		}
	}
M
Martin Schwidefsky 已提交
659
	c_cpus = s_cpus = 0;
660
	for (cpu = 0; cpu < info->combined; cpu++) {
M
Martin Schwidefsky 已提交
661
		if (info->has_cpu_type && info->cpu[cpu].type != boot_cpu_type)
662
			continue;
M
Martin Schwidefsky 已提交
663 664 665 666
		if (cpu < info->configured) {
			smp_get_save_area(c_cpus, info->cpu[cpu].address);
			c_cpus++;
		} else
667 668
			s_cpus++;
	}
669
	pr_info("%d configured CPUs, %d standby CPUs\n", c_cpus, s_cpus);
670
	get_online_cpus();
M
Martin Schwidefsky 已提交
671
	__smp_rescan_cpus(info, 0);
672
	put_online_cpus();
M
Martin Schwidefsky 已提交
673
	kfree(info);
674 675
}

L
Linus Torvalds 已提交
676
/*
677
 *	Activate a secondary processor.
L
Linus Torvalds 已提交
678
 */
M
Martin Schwidefsky 已提交
679
static void __cpuinit smp_start_secondary(void *cpuvoid)
L
Linus Torvalds 已提交
680
{
M
Martin Schwidefsky 已提交
681 682 683 684 685 686 687 688
	S390_lowcore.last_update_clock = get_clock();
	S390_lowcore.restart_stack = (unsigned long) restart_stack;
	S390_lowcore.restart_fn = (unsigned long) do_restart;
	S390_lowcore.restart_data = 0;
	S390_lowcore.restart_source = -1UL;
	restore_access_regs(S390_lowcore.access_regs_save_area);
	__ctl_load(S390_lowcore.cregs_save_area, 0, 15);
	__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
689
	cpu_init();
690
	preempt_disable();
691 692
	init_cpu_timer();
	init_cpu_vtimer();
H
Heiko Carstens 已提交
693
	pfault_init();
694
	notify_cpu_starting(smp_processor_id());
695
	set_cpu_online(smp_processor_id(), true);
L
Linus Torvalds 已提交
696
	local_irq_enable();
697 698
	/* cpu_idle will call schedule for us */
	cpu_idle();
L
Linus Torvalds 已提交
699 700 701
}

/* Upping and downing of CPUs */
702
int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
L
Linus Torvalds 已提交
703
{
M
Martin Schwidefsky 已提交
704 705
	struct pcpu *pcpu;
	int rc;
L
Linus Torvalds 已提交
706

M
Martin Schwidefsky 已提交
707 708
	pcpu = pcpu_devices + cpu;
	if (pcpu->state != CPU_STATE_CONFIGURED)
709
		return -EIO;
710 711
	if (pcpu_sigp_retry(pcpu, SIGP_INITIAL_CPU_RESET, 0) !=
	    SIGP_CC_ORDER_CODE_ACCEPTED)
712
		return -EIO;
713

M
Martin Schwidefsky 已提交
714 715 716 717
	rc = pcpu_alloc_lowcore(pcpu, cpu);
	if (rc)
		return rc;
	pcpu_prepare_secondary(pcpu, cpu);
718
	pcpu_attach_task(pcpu, tidle);
M
Martin Schwidefsky 已提交
719
	pcpu_start_fn(pcpu, smp_start_secondary, NULL);
L
Linus Torvalds 已提交
720 721 722 723 724
	while (!cpu_online(cpu))
		cpu_relax();
	return 0;
}

725
static int __init setup_possible_cpus(char *s)
726
{
M
Martin Schwidefsky 已提交
727
	int max, cpu;
728

M
Martin Schwidefsky 已提交
729 730
	if (kstrtoint(s, 0, &max) < 0)
		return 0;
731
	init_cpu_possible(cpumask_of(0));
M
Martin Schwidefsky 已提交
732
	for (cpu = 1; cpu < max && cpu < nr_cpu_ids; cpu++)
733
		set_cpu_possible(cpu, true);
734 735 736 737
	return 0;
}
early_param("possible_cpus", setup_possible_cpus);

738 739
#ifdef CONFIG_HOTPLUG_CPU

740
int __cpu_disable(void)
L
Linus Torvalds 已提交
741
{
M
Martin Schwidefsky 已提交
742
	unsigned long cregs[16];
L
Linus Torvalds 已提交
743

M
Martin Schwidefsky 已提交
744 745
	set_cpu_online(smp_processor_id(), false);
	/* Disable pseudo page faults on this cpu. */
H
Heiko Carstens 已提交
746
	pfault_fini();
M
Martin Schwidefsky 已提交
747 748 749 750 751 752
	/* Disable interrupt sources via control register. */
	__ctl_store(cregs, 0, 15);
	cregs[0]  &= ~0x0000ee70UL;	/* disable all external interrupts */
	cregs[6]  &= ~0xff000000UL;	/* disable all I/O interrupts */
	cregs[14] &= ~0x1f000000UL;	/* disable most machine checks */
	__ctl_load(cregs, 0, 15);
L
Linus Torvalds 已提交
753 754 755
	return 0;
}

756
void __cpu_die(unsigned int cpu)
L
Linus Torvalds 已提交
757
{
M
Martin Schwidefsky 已提交
758 759
	struct pcpu *pcpu;

L
Linus Torvalds 已提交
760
	/* Wait until target cpu is down */
M
Martin Schwidefsky 已提交
761 762
	pcpu = pcpu_devices + cpu;
	while (!pcpu_stopped(pcpu))
L
Linus Torvalds 已提交
763
		cpu_relax();
M
Martin Schwidefsky 已提交
764
	pcpu_free_lowcore(pcpu);
765
	atomic_dec(&init_mm.context.attach_count);
L
Linus Torvalds 已提交
766 767
}

768
void __noreturn cpu_die(void)
L
Linus Torvalds 已提交
769 770
{
	idle_task_exit();
771
	pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0);
M
Martin Schwidefsky 已提交
772
	for (;;) ;
L
Linus Torvalds 已提交
773 774
}

775 776
#endif /* CONFIG_HOTPLUG_CPU */

L
Linus Torvalds 已提交
777 778
void __init smp_prepare_cpus(unsigned int max_cpus)
{
779 780 781
	/* request the 0x1201 emergency signal external interrupt */
	if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
		panic("Couldn't request external interrupt 0x1201");
782 783 784
	/* request the 0x1202 external call external interrupt */
	if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
		panic("Couldn't request external interrupt 0x1202");
M
Martin Schwidefsky 已提交
785
	smp_detect_cpus();
L
Linus Torvalds 已提交
786 787
}

H
Heiko Carstens 已提交
788
void __init smp_prepare_boot_cpu(void)
L
Linus Torvalds 已提交
789
{
M
Martin Schwidefsky 已提交
790 791 792 793 794 795 796 797
	struct pcpu *pcpu = pcpu_devices;

	boot_cpu_address = stap();
	pcpu->state = CPU_STATE_CONFIGURED;
	pcpu->address = boot_cpu_address;
	pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix();
	pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE;
	pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE;
L
Linus Torvalds 已提交
798
	S390_lowcore.percpu_offset = __per_cpu_offset[0];
799
	cpu_set_polarization(0, POLARIZATION_UNKNOWN);
M
Martin Schwidefsky 已提交
800 801
	set_cpu_present(0, true);
	set_cpu_online(0, true);
L
Linus Torvalds 已提交
802 803
}

H
Heiko Carstens 已提交
804
void __init smp_cpus_done(unsigned int max_cpus)
L
Linus Torvalds 已提交
805 806 807
{
}

808 809 810 811 812
void __init smp_setup_processor_id(void)
{
	S390_lowcore.cpu_nr = 0;
}

L
Linus Torvalds 已提交
813 814 815 816 817 818 819 820
/*
 * the frequency of the profiling timer can be changed
 * by writing a multiplier value into /proc/profile.
 *
 * usually you want to run this on all CPUs ;)
 */
int setup_profiling_timer(unsigned int multiplier)
{
821
	return 0;
L
Linus Torvalds 已提交
822 823
}

824
#ifdef CONFIG_HOTPLUG_CPU
825
static ssize_t cpu_configure_show(struct device *dev,
M
Martin Schwidefsky 已提交
826
				  struct device_attribute *attr, char *buf)
827 828 829 830
{
	ssize_t count;

	mutex_lock(&smp_cpu_state_mutex);
M
Martin Schwidefsky 已提交
831
	count = sprintf(buf, "%d\n", pcpu_devices[dev->id].state);
832 833 834 835
	mutex_unlock(&smp_cpu_state_mutex);
	return count;
}

836
static ssize_t cpu_configure_store(struct device *dev,
M
Martin Schwidefsky 已提交
837 838
				   struct device_attribute *attr,
				   const char *buf, size_t count)
839
{
M
Martin Schwidefsky 已提交
840 841
	struct pcpu *pcpu;
	int cpu, val, rc;
842 843 844 845 846 847
	char delim;

	if (sscanf(buf, "%d %c", &val, &delim) != 1)
		return -EINVAL;
	if (val != 0 && val != 1)
		return -EINVAL;
848
	get_online_cpus();
H
Heiko Carstens 已提交
849
	mutex_lock(&smp_cpu_state_mutex);
850
	rc = -EBUSY;
851
	/* disallow configuration changes of online cpus and cpu 0 */
M
Martin Schwidefsky 已提交
852
	cpu = dev->id;
853
	if (cpu_online(cpu) || cpu == 0)
854
		goto out;
M
Martin Schwidefsky 已提交
855
	pcpu = pcpu_devices + cpu;
856 857 858
	rc = 0;
	switch (val) {
	case 0:
M
Martin Schwidefsky 已提交
859 860 861 862 863 864 865 866
		if (pcpu->state != CPU_STATE_CONFIGURED)
			break;
		rc = sclp_cpu_deconfigure(pcpu->address);
		if (rc)
			break;
		pcpu->state = CPU_STATE_STANDBY;
		cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
		topology_expect_change();
867 868
		break;
	case 1:
M
Martin Schwidefsky 已提交
869 870 871 872 873 874 875 876
		if (pcpu->state != CPU_STATE_STANDBY)
			break;
		rc = sclp_cpu_configure(pcpu->address);
		if (rc)
			break;
		pcpu->state = CPU_STATE_CONFIGURED;
		cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
		topology_expect_change();
877 878 879 880 881 882
		break;
	default:
		break;
	}
out:
	mutex_unlock(&smp_cpu_state_mutex);
H
Heiko Carstens 已提交
883
	put_online_cpus();
884 885
	return rc ? rc : count;
}
886
static DEVICE_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
887 888
#endif /* CONFIG_HOTPLUG_CPU */

889 890
static ssize_t show_cpu_address(struct device *dev,
				struct device_attribute *attr, char *buf)
891
{
M
Martin Schwidefsky 已提交
892
	return sprintf(buf, "%d\n", pcpu_devices[dev->id].address);
893
}
894
static DEVICE_ATTR(address, 0444, show_cpu_address, NULL);
895 896 897

static struct attribute *cpu_common_attrs[] = {
#ifdef CONFIG_HOTPLUG_CPU
898
	&dev_attr_configure.attr,
899
#endif
900
	&dev_attr_address.attr,
901 902 903 904 905 906
	NULL,
};

static struct attribute_group cpu_common_attr_group = {
	.attrs = cpu_common_attrs,
};
L
Linus Torvalds 已提交
907

908 909
static ssize_t show_idle_count(struct device *dev,
				struct device_attribute *attr, char *buf)
910
{
M
Martin Schwidefsky 已提交
911
	struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
912
	unsigned long long idle_count;
913
	unsigned int sequence;
914

M
Martin Schwidefsky 已提交
915 916 917
	do {
		sequence = ACCESS_ONCE(idle->sequence);
		idle_count = ACCESS_ONCE(idle->idle_count);
918
		if (ACCESS_ONCE(idle->clock_idle_enter))
M
Martin Schwidefsky 已提交
919 920
			idle_count++;
	} while ((sequence & 1) || (idle->sequence != sequence));
921 922
	return sprintf(buf, "%llu\n", idle_count);
}
923
static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
924

925 926
static ssize_t show_idle_time(struct device *dev,
				struct device_attribute *attr, char *buf)
927
{
M
Martin Schwidefsky 已提交
928 929
	struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
	unsigned long long now, idle_time, idle_enter, idle_exit;
930
	unsigned int sequence;
931

M
Martin Schwidefsky 已提交
932 933 934 935
	do {
		now = get_clock();
		sequence = ACCESS_ONCE(idle->sequence);
		idle_time = ACCESS_ONCE(idle->idle_time);
936 937
		idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
		idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
M
Martin Schwidefsky 已提交
938 939
	} while ((sequence & 1) || (idle->sequence != sequence));
	idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
940
	return sprintf(buf, "%llu\n", idle_time >> 12);
941
}
942
static DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
943

944
static struct attribute *cpu_online_attrs[] = {
945 946
	&dev_attr_idle_count.attr,
	&dev_attr_idle_time_us.attr,
947 948 949
	NULL,
};

950 951
static struct attribute_group cpu_online_attr_group = {
	.attrs = cpu_online_attrs,
952 953
};

954 955 956 957
static int __cpuinit smp_cpu_notify(struct notifier_block *self,
				    unsigned long action, void *hcpu)
{
	unsigned int cpu = (unsigned int)(long)hcpu;
M
Martin Schwidefsky 已提交
958
	struct cpu *c = &pcpu_devices[cpu].cpu;
959
	struct device *s = &c->dev;
960
	int err = 0;
961 962 963

	switch (action) {
	case CPU_ONLINE:
964
	case CPU_ONLINE_FROZEN:
965
		err = sysfs_create_group(&s->kobj, &cpu_online_attr_group);
966 967
		break;
	case CPU_DEAD:
968
	case CPU_DEAD_FROZEN:
969
		sysfs_remove_group(&s->kobj, &cpu_online_attr_group);
970 971
		break;
	}
972
	return notifier_from_errno(err);
973 974
}

975
static int __devinit smp_add_present_cpu(int cpu)
976
{
M
Martin Schwidefsky 已提交
977
	struct cpu *c = &pcpu_devices[cpu].cpu;
978
	struct device *s = &c->dev;
979 980 981 982 983 984 985 986 987
	int rc;

	c->hotpluggable = 1;
	rc = register_cpu(c, cpu);
	if (rc)
		goto out;
	rc = sysfs_create_group(&s->kobj, &cpu_common_attr_group);
	if (rc)
		goto out_cpu;
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
	if (cpu_online(cpu)) {
		rc = sysfs_create_group(&s->kobj, &cpu_online_attr_group);
		if (rc)
			goto out_online;
	}
	rc = topology_cpu_init(c);
	if (rc)
		goto out_topology;
	return 0;

out_topology:
	if (cpu_online(cpu))
		sysfs_remove_group(&s->kobj, &cpu_online_attr_group);
out_online:
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
	sysfs_remove_group(&s->kobj, &cpu_common_attr_group);
out_cpu:
#ifdef CONFIG_HOTPLUG_CPU
	unregister_cpu(c);
#endif
out:
	return rc;
}

#ifdef CONFIG_HOTPLUG_CPU
1012

1013
int __ref smp_rescan_cpus(void)
1014
{
M
Martin Schwidefsky 已提交
1015 1016
	struct sclp_cpu_info *info;
	int nr;
1017

M
Martin Schwidefsky 已提交
1018 1019 1020
	info = smp_get_cpu_info();
	if (!info)
		return -ENOMEM;
1021
	get_online_cpus();
H
Heiko Carstens 已提交
1022
	mutex_lock(&smp_cpu_state_mutex);
M
Martin Schwidefsky 已提交
1023
	nr = __smp_rescan_cpus(info, 1);
1024
	mutex_unlock(&smp_cpu_state_mutex);
H
Heiko Carstens 已提交
1025
	put_online_cpus();
M
Martin Schwidefsky 已提交
1026 1027
	kfree(info);
	if (nr)
H
Heiko Carstens 已提交
1028
		topology_schedule_update();
M
Martin Schwidefsky 已提交
1029
	return 0;
1030 1031
}

1032 1033
static ssize_t __ref rescan_store(struct device *dev,
				  struct device_attribute *attr,
1034
				  const char *buf,
1035 1036 1037 1038 1039
				  size_t count)
{
	int rc;

	rc = smp_rescan_cpus();
1040 1041
	return rc ? rc : count;
}
1042
static DEVICE_ATTR(rescan, 0200, NULL, rescan_store);
1043 1044
#endif /* CONFIG_HOTPLUG_CPU */

1045
static int __init s390_smp_init(void)
L
Linus Torvalds 已提交
1046
{
1047
	int cpu, rc;
1048

1049
	hotcpu_notifier(smp_cpu_notify, 0);
1050
#ifdef CONFIG_HOTPLUG_CPU
1051
	rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan);
1052 1053 1054 1055 1056
	if (rc)
		return rc;
#endif
	for_each_present_cpu(cpu) {
		rc = smp_add_present_cpu(cpu);
1057 1058
		if (rc)
			return rc;
L
Linus Torvalds 已提交
1059 1060 1061
	}
	return 0;
}
1062
subsys_initcall(s390_smp_init);