Example #1
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 (sigp(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));
	regs->psw = lc->psw_save_area;
	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]);
}
Example #2
0
/*
 * Send an external call sigp to another cpu and return without waiting
 * for its completion.
 */
static void smp_ext_bitcall(int cpu, int sig)
{
	/*
	 * Set signaling bit in lowcore of target cpu and kick it
	 */
	set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
	while (sigp(cpu, sigp_emergency_signal) == sigp_busy)
		udelay(10);
}
Example #3
0
/*
 * Send an external call sigp to another cpu and return without waiting
 * for its completion.
 */
static void smp_ext_bitcall(int cpu, int sig)
{
	int order;

	/*
	 * Set signaling bit in lowcore of target cpu and kick it
	 */
	set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
	while (1) {
		order = smp_vcpu_scheduled(cpu) ?
			sigp_external_call : sigp_emergency_signal;
		if (sigp(cpu, order) != sigp_busy)
			break;
		udelay(10);
	}
}
Example #4
0
/*
 * Ensure that PSW restart is done on an online CPU
 */
void smp_restart_with_online_cpu(void)
{
	int cpu;

	for_each_online_cpu(cpu) {
		if (stap() == __cpu_logical_map[cpu]) {
			/* We are online: Enable DAT again and return */
			__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
			return;
		}
	}
	/* We are not online: Do PSW restart on an online CPU */
	while (sigp(cpu, sigp_restart) == sigp_busy)
		cpu_relax();
	/* And stop ourself */
	while (raw_sigp(stap(), sigp_stop) == sigp_busy)
		cpu_relax();
	for (;;);
}
Example #5
0
void smp_send_stop(void)
{
	int cpu, rc;

	/* Disable all interrupts/machine checks */
	__load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
	trace_hardirqs_off();

	/* stop all processors */
	for_each_online_cpu(cpu) {
		if (cpu == smp_processor_id())
			continue;
		do {
			rc = sigp(cpu, sigp_stop);
		} while (rc == sigp_busy);

		while (!cpu_stopped(cpu))
			cpu_relax();
	}
}