From a438bdc1590195e7446427602bc7e4844969f773 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Wed, 3 Aug 2011 16:44:22 +0200 Subject: [PATCH] --- yaml --- r: 262393 b: refs/heads/master c: 9dc7356ee1266d6a69fc80f28d006f71c20bf172 h: refs/heads/master i: 262391: 6d05d452221dde3d372667baf382bd3bfe1d554f v: v3 --- [refs] | 2 +- trunk/arch/s390/include/asm/ipl.h | 1 + trunk/arch/s390/kernel/base.S | 36 +++++++++++++++++++++++++++++++ trunk/arch/s390/kernel/ipl.c | 6 ++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 4ec364dbf6c4..613e0b0f130f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ef1daec8da2c04b0c6e91a34b9cac1aad33c6692 +refs/heads/master: 9dc7356ee1266d6a69fc80f28d006f71c20bf172 diff --git a/trunk/arch/s390/include/asm/ipl.h b/trunk/arch/s390/include/asm/ipl.h index 5e95d95450b3..97cc4403fabf 100644 --- a/trunk/arch/s390/include/asm/ipl.h +++ b/trunk/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/trunk/arch/s390/kernel/base.S b/trunk/arch/s390/kernel/base.S index 209938c1dfc8..255435663bf8 100644 --- a/trunk/arch/s390/kernel/base.S +++ b/trunk/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/trunk/arch/s390/kernel/ipl.c b/trunk/arch/s390/kernel/ipl.c index 059c59027ac0..04361d5a4279 100644 --- a/trunk/arch/s390/kernel/ipl.c +++ b/trunk/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(); }