aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/kernel/ipl.c10
-rw-r--r--arch/s390/kernel/reset.S42
-rw-r--r--drivers/s390/cio/cio.c25
-rw-r--r--include/asm-s390/reset.h1
4 files changed, 75 insertions, 3 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index a36bea1188d9..d2e6a0a56ade 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -1037,13 +1037,15 @@ static void do_reset_calls(void)
1037} 1037}
1038 1038
1039extern void reset_mcck_handler(void); 1039extern void reset_mcck_handler(void);
1040extern void reset_pgm_handler(void);
1040 1041
1041void s390_reset_system(void) 1042void s390_reset_system(void)
1042{ 1043{
1043 struct _lowcore *lc; 1044 struct _lowcore *lc;
1044 1045
1045 /* Stack for interrupt/machine check handler */
1046 lc = (struct _lowcore *)(unsigned long) store_prefix(); 1046 lc = (struct _lowcore *)(unsigned long) store_prefix();
1047
1048 /* Stack for interrupt/machine check handler */
1047 lc->panic_stack = S390_lowcore.panic_stack; 1049 lc->panic_stack = S390_lowcore.panic_stack;
1048 1050
1049 /* Disable prefixing */ 1051 /* Disable prefixing */
@@ -1056,5 +1058,11 @@ void s390_reset_system(void)
1056 S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK; 1058 S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
1057 S390_lowcore.mcck_new_psw.addr = 1059 S390_lowcore.mcck_new_psw.addr =
1058 PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler; 1060 PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler;
1061
1062 /* Set new program check handler */
1063 S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
1064 S390_lowcore.program_new_psw.addr =
1065 PSW_ADDR_AMODE | (unsigned long) &reset_pgm_handler;
1066
1059 do_reset_calls(); 1067 do_reset_calls();
1060} 1068}
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S
index be8688c0665c..8a87355161fa 100644
--- a/arch/s390/kernel/reset.S
+++ b/arch/s390/kernel/reset.S
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) IBM Corp. 2006 4 * Copyright (C) IBM Corp. 2006
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> 5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6 * Michael Holzheu <holzheu@de.ibm.com>
6 */ 7 */
7 8
8#include <asm/ptrace.h> 9#include <asm/ptrace.h>
@@ -27,6 +28,26 @@ reset_mcck_handler:
27s390_reset_mcck_handler: 28s390_reset_mcck_handler:
28 .quad 0 29 .quad 0
29 30
31 .globl reset_pgm_handler
32reset_pgm_handler:
33 stmg %r0,%r15,__LC_SAVE_AREA
34 basr %r13,0
350: lg %r15,__LC_PANIC_STACK # load panic stack
36 aghi %r15,-STACK_FRAME_OVERHEAD
37 lg %r1,s390_reset_pgm_handler-0b(%r13)
38 ltgr %r1,%r1
39 jz 1f
40 basr %r14,%r1
41 lmg %r0,%r15,__LC_SAVE_AREA
42 lpswe __LC_PGM_OLD_PSW
431: lpswe disabled_wait_psw-0b(%r13)
44 .globl s390_reset_pgm_handler
45s390_reset_pgm_handler:
46 .quad 0
47 .align 8
48disabled_wait_psw:
49 .quad 0x0002000180000000,0x0000000000000000 + reset_pgm_handler
50
30#else /* CONFIG_64BIT */ 51#else /* CONFIG_64BIT */
31 52
32 .globl reset_mcck_handler 53 .globl reset_mcck_handler
@@ -45,4 +66,25 @@ reset_mcck_handler:
45s390_reset_mcck_handler: 66s390_reset_mcck_handler:
46 .long 0 67 .long 0
47 68
69 .globl reset_pgm_handler
70reset_pgm_handler:
71 stm %r0,%r15,__LC_SAVE_AREA
72 basr %r13,0
730: l %r15,__LC_PANIC_STACK # load panic stack
74 ahi %r15,-STACK_FRAME_OVERHEAD
75 l %r1,s390_reset_pgm_handler-0b(%r13)
76 ltr %r1,%r1
77 jz 1f
78 basr %r14,%r1
79 lm %r0,%r15,__LC_SAVE_AREA
80 lpsw __LC_PGM_OLD_PSW
81
821: lpsw disabled_wait_psw-0b(%r13)
83 .globl s390_reset_pgm_handler
84s390_reset_pgm_handler:
85 .long 0
86disabled_wait_psw:
87 .align 8
88 .long 0x000a0000,0x00000000 + reset_pgm_handler
89
48#endif /* CONFIG_64BIT */ 90#endif /* CONFIG_64BIT */
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 7835a714a405..3a403f195cf8 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -871,11 +871,32 @@ __clear_subchannel_easy(struct subchannel_id schid)
871 return -EBUSY; 871 return -EBUSY;
872} 872}
873 873
874static int pgm_check_occured;
875
876static void cio_reset_pgm_check_handler(void)
877{
878 pgm_check_occured = 1;
879}
880
881static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
882{
883 int rc;
884
885 pgm_check_occured = 0;
886 s390_reset_pgm_handler = cio_reset_pgm_check_handler;
887 rc = stsch(schid, addr);
888 s390_reset_pgm_handler = NULL;
889 if (pgm_check_occured)
890 return -EIO;
891 else
892 return rc;
893}
894
874static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) 895static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
875{ 896{
876 struct schib schib; 897 struct schib schib;
877 898
878 if (stsch_err(schid, &schib)) 899 if (stsch_reset(schid, &schib))
879 return -ENXIO; 900 return -ENXIO;
880 if (!schib.pmcw.ena) 901 if (!schib.pmcw.ena)
881 return 0; 902 return 0;
@@ -972,7 +993,7 @@ static int __reipl_subchannel_match(struct subchannel_id schid, void *data)
972 struct schib schib; 993 struct schib schib;
973 struct sch_match_id *match_id = data; 994 struct sch_match_id *match_id = data;
974 995
975 if (stsch_err(schid, &schib)) 996 if (stsch_reset(schid, &schib))
976 return -ENXIO; 997 return -ENXIO;
977 if (schib.pmcw.dnv && 998 if (schib.pmcw.dnv &&
978 (schib.pmcw.dev == match_id->devid.devno) && 999 (schib.pmcw.dev == match_id->devid.devno) &&
diff --git a/include/asm-s390/reset.h b/include/asm-s390/reset.h
index 9b439cf67800..532e65a2aafc 100644
--- a/include/asm-s390/reset.h
+++ b/include/asm-s390/reset.h
@@ -19,5 +19,6 @@ extern void register_reset_call(struct reset_call *reset);
19extern void unregister_reset_call(struct reset_call *reset); 19extern void unregister_reset_call(struct reset_call *reset);
20extern void s390_reset_system(void); 20extern void s390_reset_system(void);
21extern void (*s390_reset_mcck_handler)(void); 21extern void (*s390_reset_mcck_handler)(void);
22extern void (*s390_reset_pgm_handler)(void);
22 23
23#endif /* _ASM_S390_RESET_H */ 24#endif /* _ASM_S390_RESET_H */