Commit 915fea04 authored by Alexander Gordeev's avatar Alexander Gordeev Committed by Heiko Carstens
Browse files

s390/smp: enable DAT before CPU restart callback is called



The restart interrupt is triggered whenever a secondary CPU is
brought online, a remote function call dispatched from another
CPU or a manual PSW restart is initiated and causes the system
to kdump. The handling routine is always called with DAT turned
off. It then initializes the stack frame and invokes a callback.

The existing callbacks handle DAT as follows:

  * __do_restart() and __machine_kexec() turn in on upon entry;
  * __ipl_run(), __reipl_run() and __dump_run() do not turn it
    right away, but all of them call diag308() - which turns DAT
    on, but only if kasan is enabled;

In addition to the described complexity all callbacks (and the
functions they call) should avoid kasan instrumentation while
DAT is off.

This update enables DAT in the assembler restart handler and
relieves any callbacks (which are mostly C functions) from
dealing with DAT altogether.

There are four types of CPU restart that initialize control
registers in different ways:

  1. Start of secondary CPU on boot - control registers are
     inherited from the IPL CPU;
  2. Restart of online CPU - control registers of the CPU being
     restarted are kept;
  3. Hotplug of offline CPU - control registers are inherited
     from the starting CPU;
  4. Start of offline CPU triggered by manual PSW restart -
     the control registers are read from the absolute lowcore
     and contain the boot time IPL CPU values updated with all
     follow-up calls of smp_ctl_set_bit() and smp_ctl_clear_bit()
     routines;

In first three cases contents of the control registers is the
most recent. In the latter case control registers are good
enough to facilitate successful completion of kdump operation.

Suggested-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent e7dc78d3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -124,7 +124,8 @@ struct lowcore {
	/* Restart function and parameter. */
	__u64	restart_fn;			/* 0x0370 */
	__u64	restart_data;			/* 0x0378 */
	__u64	restart_source;			/* 0x0380 */
	__u32	restart_source;			/* 0x0380 */
	__u32	restart_flags;			/* 0x0384 */

	/* Address space pointer. */
	__u64	kernel_asce;			/* 0x0388 */
+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@
#define _CIF_MCCK_GUEST		BIT(CIF_MCCK_GUEST)
#define _CIF_DEDICATED_CPU	BIT(CIF_DEDICATED_CPU)

#define RESTART_FLAG_CTLREGS	_AC(1 << 0, U)

#ifndef __ASSEMBLY__

#include <linux/cpumask.h>
+1 −0
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ int main(void)
	OFFSET(__LC_RESTART_FN, lowcore, restart_fn);
	OFFSET(__LC_RESTART_DATA, lowcore, restart_data);
	OFFSET(__LC_RESTART_SOURCE, lowcore, restart_source);
	OFFSET(__LC_RESTART_FLAGS, lowcore, restart_flags);
	OFFSET(__LC_KERNEL_ASCE, lowcore, kernel_asce);
	OFFSET(__LC_USER_ASCE, lowcore, user_asce);
	OFFSET(__LC_LPP, lowcore, lpp);
+7 −4
Original line number Diff line number Diff line
@@ -624,12 +624,15 @@ ENTRY(mcck_int_handler)
4:	j	4b
ENDPROC(mcck_int_handler)

#
# PSW restart interrupt handler
#
ENTRY(restart_int_handler)
	ALTERNATIVE "", ".insn s,0xb2800000,_LPP_OFFSET", 40
	stg	%r15,__LC_SAVE_AREA_RESTART
	TSTMSK	__LC_RESTART_FLAGS,RESTART_FLAG_CTLREGS,4
	jz	0f
	la	%r15,4095
	lctlg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r15)
0:	larl	%r15,.Lstosm_tmp
	stosm	0(%r15),0x04			# turn dat on, keep irqs off
	lg	%r15,__LC_RESTART_STACK
	xc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r15),STACK_FRAME_OVERHEAD(%r15)
	stmg	%r0,%r14,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
@@ -638,7 +641,7 @@ ENTRY(restart_int_handler)
	xc	0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
	lg	%r1,__LC_RESTART_FN		# load fn, parm & source cpu
	lg	%r2,__LC_RESTART_DATA
	lg	%r3,__LC_RESTART_SOURCE
	lgf	%r3,__LC_RESTART_SOURCE
	ltgr	%r3,%r3				# test source cpu address
	jm	1f				# negative -> skip source stop
0:	sigp	%r4,%r3,SIGP_SENSE		# sigp sense to source cpu
+0 −3
Original line number Diff line number Diff line
@@ -179,8 +179,6 @@ static inline int __diag308(unsigned long subcode, void *addr)

int diag308(unsigned long subcode, void *addr)
{
	if (IS_ENABLED(CONFIG_KASAN))
		__arch_local_irq_stosm(0x04); /* enable DAT */
	diag_stat_inc(DIAG_STAT_X308);
	return __diag308(subcode, addr);
}
@@ -1843,7 +1841,6 @@ static struct kobj_attribute on_restart_attr = __ATTR_RW(on_restart);

static void __do_restart(void *ignore)
{
	__arch_local_irq_stosm(0x04); /* enable DAT */
	smp_send_stop();
#ifdef CONFIG_CRASH_DUMP
	crash_kexec(NULL);
Loading