Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c2df118 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky
Browse files

[S390] smp: always reboot on cpu 0



Always reboot on logical cpu 0. This makes sure that the IPL cpu is
always the same and usually avoids strange numbering schemes between
physical and logical cpus.

Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent abd1ecf2
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -31,6 +31,18 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);

extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1];

extern void smp_switch_to_ipl_cpu(void (*func)(void *), void *);
extern void smp_switch_to_cpu(void (*)(void *), void *, unsigned long sp,
			      int from, int to);
extern void smp_restart_cpu(void);

#else /* CONFIG_SMP */

static inline void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
{
	func(data);
}

#endif /* CONFIG_SMP */

#ifdef CONFIG_HOTPLUG_CPU
+2 −0
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ extra-y += head.o init_task.o vmlinux.lds

obj-$(CONFIG_MODULES)		+= s390_ksyms.o module.o
obj-$(CONFIG_SMP)		+= smp.o topology.o
obj-$(CONFIG_SMP)		+= $(if $(CONFIG_64BIT),switch_cpu64.o, \
							switch_cpu.o)
obj-$(CONFIG_HIBERNATION)	+= suspend.o swsusp_asm64.o
obj-$(CONFIG_AUDIT)		+= audit.o
compat-obj-$(CONFIG_AUDIT)	+= compat_audit.o
+23 −8
Original line number Diff line number Diff line
@@ -553,7 +553,7 @@ out:
	return rc;
}

static void ipl_run(struct shutdown_trigger *trigger)
static void __ipl_run(void *unused)
{
	diag308(DIAG308_IPL, NULL);
	if (MACHINE_IS_VM)
@@ -562,6 +562,11 @@ static void ipl_run(struct shutdown_trigger *trigger)
		reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
}

static void ipl_run(struct shutdown_trigger *trigger)
{
	smp_switch_to_ipl_cpu(__ipl_run, NULL);
}

static int __init ipl_init(void)
{
	int rc;
@@ -1039,7 +1044,7 @@ static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
		sprintf(dst + pos, " PARM %s", vmparm);
}

static void reipl_run(struct shutdown_trigger *trigger)
static void __reipl_run(void *unused)
{
	struct ccw_dev_id devid;
	static char buf[128];
@@ -1087,6 +1092,11 @@ static void reipl_run(struct shutdown_trigger *trigger)
	disabled_wait((unsigned long) __builtin_return_address(0));
}

static void reipl_run(struct shutdown_trigger *trigger)
{
	smp_switch_to_ipl_cpu(__reipl_run, NULL);
}

static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
{
	ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
@@ -1369,20 +1379,18 @@ static struct kobj_attribute dump_type_attr =

static struct kset *dump_kset;

static void dump_run(struct shutdown_trigger *trigger)
static void __dump_run(void *unused)
{
	struct ccw_dev_id devid;
	static char buf[100];

	switch (dump_method) {
	case DUMP_METHOD_CCW_CIO:
		smp_send_stop();
		devid.devno = dump_block_ccw->ipl_info.ccw.devno;
		devid.ssid  = 0;
		reipl_ccw_dev(&devid);
		break;
	case DUMP_METHOD_CCW_VM:
		smp_send_stop();
		sprintf(buf, "STORE STATUS");
		__cpcmd(buf, NULL, 0, NULL);
		sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
@@ -1396,10 +1404,17 @@ static void dump_run(struct shutdown_trigger *trigger)
		diag308(DIAG308_SET, dump_block_fcp);
		diag308(DIAG308_DUMP, NULL);
		break;
	case DUMP_METHOD_NONE:
		return;
	default:
		break;
	}
}
	printk(KERN_EMERG "Dump failed!\n");

static void dump_run(struct shutdown_trigger *trigger)
{
	if (dump_method == DUMP_METHOD_NONE)
		return;
	smp_send_stop();
	smp_switch_to_ipl_cpu(__dump_run, NULL);
}

static int __init dump_ccw_init(void)
+8 −2
Original line number Diff line number Diff line
@@ -54,11 +54,11 @@ void machine_shutdown(void)
{
}

void machine_kexec(struct kimage *image)
static void __machine_kexec(void *data)
{
	relocate_kernel_t data_mover;
	struct kimage *image = data;

	smp_send_stop();
	pfault_fini();
	s390_reset_system();

@@ -68,3 +68,9 @@ void machine_kexec(struct kimage *image)
	(*data_mover)(&image->head, image->start);
	for (;;);
}

void machine_kexec(struct kimage *image)
{
	smp_send_stop();
	smp_switch_to_ipl_cpu(__machine_kexec, image);
}
+35 −1
Original line number Diff line number Diff line
@@ -90,6 +90,39 @@ static int cpu_stopped(int cpu)
	return 0;
}

void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
{
	struct _lowcore *lc, *current_lc;
	struct stack_frame *sf;
	struct pt_regs *regs;
	unsigned long sp;

	if (smp_processor_id() == 0)
		func(data);
	__load_psw_mask(PSW_BASE_BITS | PSW_DEFAULT_KEY);
	/* Disable lowcore protection */
	__ctl_clear_bit(0, 28);
	current_lc = lowcore_ptr[smp_processor_id()];
	lc = lowcore_ptr[0];
	if (!lc)
		lc = current_lc;
	lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
	lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu;
	if (!cpu_online(0))
		smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]);
	while (signal_processor(0, sigp_stop_and_store_status) == sigp_busy)
		cpu_relax();
	sp = lc->panic_stack;
	sp -= sizeof(struct pt_regs);
	regs = (struct pt_regs *) sp;
	memcpy(&regs->gprs, &current_lc->gpregs_save_area, sizeof(regs->gprs));
	memcpy(&regs->psw, &current_lc->st_status_fixed_logout, sizeof(psw_t));
	sp -= STACK_FRAME_OVERHEAD;
	sf = (struct stack_frame *) sp;
	sf->back_chain = regs->gprs[15];
	smp_switch_to_cpu(func, data, sp, stap(), __cpu_logical_map[0]);
}

void smp_send_stop(void)
{
	int cpu, rc;
@@ -752,7 +785,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev,
	get_online_cpus();
	mutex_lock(&smp_cpu_state_mutex);
	rc = -EBUSY;
	if (cpu_online(cpu))
	/* disallow configuration changes of online cpus and cpu 0 */
	if (cpu_online(cpu) || cpu == 0)
		goto out;
	rc = 0;
	switch (val) {
Loading