From 9dc7356ee1266d6a69fc80f28d006f71c20bf172 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Wed, 3 Aug 2011 16:44:22 +0200 Subject: [PATCH] [S390] Use diagnose 308 for system reset The diagnose 308 call is the prefered method for clearing all ongoing I/O. Therefore if it is available we use it instead of doing a manual reset. Signed-off-by: Michael Holzheu Signed-off-by: Heiko Carstens --- arch/s390/include/asm/ipl.h | 1 + arch/s390/kernel/base.S | 36 ++++++++++++++++++++++++++++++++++++ arch/s390/kernel/ipl.c | 6 ++++++ 3 files changed, 43 insertions(+) diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h index 5e95d95450b3..97cc4403fabf 100644 --- a/arch/s390/include/asm/ipl.h +++ b/arch/s390/include/asm/ipl.h @@ -167,5 +167,6 @@ enum diag308_rc { }; extern int diag308(unsigned long subcode, void *addr); +extern void diag308_reset(void); #endif /* _ASM_S390_IPL_H */ diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S index 209938c1dfc8..255435663bf8 100644 --- a/arch/s390/kernel/base.S +++ b/arch/s390/kernel/base.S @@ -76,6 +76,42 @@ s390_base_pgm_handler_fn: .quad 0 .previous +# +# Calls diag 308 subcode 1 and continues execution +# +# The following conditions must be ensured before calling this function: +# * Prefix register = 0 +# * Lowcore protection is disabled +# +ENTRY(diag308_reset) + larl %r4,.Lctlregs # Save control registers + stctg %c0,%c15,0(%r4) + larl %r4,.Lrestart_psw # Setup restart PSW at absolute 0 + lghi %r3,0 + lg %r4,0(%r4) # Save PSW + sturg %r4,%r3 # Use sturg, because of large pages + lghi %r1,1 + diag %r1,%r1,0x308 +.Lrestart_part2: + lhi %r0,0 # Load r0 with zero + lhi %r1,2 # Use mode 2 = ESAME (dump) + sigp %r1,%r0,0x12 # Switch to ESAME mode + sam64 # Switch to 64 bit addressing mode + larl %r4,.Lctlregs # Restore control registers + lctlg %c0,%c15,0(%r4) + br %r14 +.align 16 +.Lrestart_psw: + .long 0x00080000,0x80000000 + .Lrestart_part2 + + .section .bss +.align 8 +.Lctlregs: + .rept 16 + .quad 0 + .endr + .previous + #else /* CONFIG_64BIT */ ENTRY(s390_base_mcck_handler) diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 059c59027ac0..04361d5a4279 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1996,6 +1996,12 @@ static void do_reset_calls(void) { struct reset_call *reset; +#ifdef CONFIG_64BIT + if (diag308_set_works) { + diag308_reset(); + return; + } +#endif list_for_each_entry(reset, &rcall, list) reset->fn(); }