Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[S390] split/move machine check handler code

Split machine check handler code and move it to cio and kernel code
where it belongs to. No functional change.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Heiko Carstens and committed by
Martin Schwidefsky
f5daba1d 70193af9

+340 -339
+68
arch/s390/include/asm/crw.h
··· 1 + /* 2 + * Data definitions for channel report processing 3 + * Copyright IBM Corp. 2000,2009 4 + * Author(s): Ingo Adlung <adlung@de.ibm.com>, 5 + * Martin Schwidefsky <schwidefsky@de.ibm.com>, 6 + * Cornelia Huck <cornelia.huck@de.ibm.com>, 7 + * Heiko Carstens <heiko.carstens@de.ibm.com>, 8 + */ 9 + 10 + #ifndef _ASM_S390_CRW_H 11 + #define _ASM_S390_CRW_H 12 + 13 + #include <linux/types.h> 14 + 15 + /* 16 + * Channel Report Word 17 + */ 18 + struct crw { 19 + __u32 res1 : 1; /* reserved zero */ 20 + __u32 slct : 1; /* solicited */ 21 + __u32 oflw : 1; /* overflow */ 22 + __u32 chn : 1; /* chained */ 23 + __u32 rsc : 4; /* reporting source code */ 24 + __u32 anc : 1; /* ancillary report */ 25 + __u32 res2 : 1; /* reserved zero */ 26 + __u32 erc : 6; /* error-recovery code */ 27 + __u32 rsid : 16; /* reporting-source ID */ 28 + } __attribute__ ((packed)); 29 + 30 + typedef void (*crw_handler_t)(struct crw *, struct crw *, int); 31 + 32 + extern int crw_register_handler(int rsc, crw_handler_t handler); 33 + extern void crw_unregister_handler(int rsc); 34 + extern void crw_handle_channel_report(void); 35 + 36 + #define NR_RSCS 16 37 + 38 + #define CRW_RSC_MONITOR 0x2 /* monitoring facility */ 39 + #define CRW_RSC_SCH 0x3 /* subchannel */ 40 + #define CRW_RSC_CPATH 0x4 /* channel path */ 41 + #define CRW_RSC_CONFIG 0x9 /* configuration-alert facility */ 42 + #define CRW_RSC_CSS 0xB /* channel subsystem */ 43 + 44 + #define CRW_ERC_EVENT 0x00 /* event information pending */ 45 + #define CRW_ERC_AVAIL 0x01 /* available */ 46 + #define CRW_ERC_INIT 0x02 /* initialized */ 47 + #define CRW_ERC_TERROR 0x03 /* temporary error */ 48 + #define CRW_ERC_IPARM 0x04 /* installed parm initialized */ 49 + #define CRW_ERC_TERM 0x05 /* terminal */ 50 + #define CRW_ERC_PERRN 0x06 /* perm. error, fac. not init */ 51 + #define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ 52 + #define CRW_ERC_PMOD 0x08 /* installed parameters modified */ 53 + 54 + static inline int stcrw(struct crw *pcrw) 55 + { 56 + int ccode; 57 + 58 + asm volatile( 59 + " stcrw 0(%2)\n" 60 + " ipm %0\n" 61 + " srl %0,28\n" 62 + : "=d" (ccode), "=m" (*pcrw) 63 + : "a" (pcrw) 64 + : "cc" ); 65 + return ccode; 66 + } 67 + 68 + #endif /* _ASM_S390_CRW_H */
+66
arch/s390/include/asm/nmi.h
··· 1 + /* 2 + * Machine check handler definitions 3 + * 4 + * Copyright IBM Corp. 2000,2009 5 + * Author(s): Ingo Adlung <adlung@de.ibm.com>, 6 + * Martin Schwidefsky <schwidefsky@de.ibm.com>, 7 + * Cornelia Huck <cornelia.huck@de.ibm.com>, 8 + * Heiko Carstens <heiko.carstens@de.ibm.com>, 9 + */ 10 + 11 + #ifndef _ASM_S390_NMI_H 12 + #define _ASM_S390_NMI_H 13 + 14 + #include <linux/types.h> 15 + 16 + struct mci { 17 + __u32 sd : 1; /* 00 system damage */ 18 + __u32 pd : 1; /* 01 instruction-processing damage */ 19 + __u32 sr : 1; /* 02 system recovery */ 20 + __u32 : 1; /* 03 */ 21 + __u32 cd : 1; /* 04 timing-facility damage */ 22 + __u32 ed : 1; /* 05 external damage */ 23 + __u32 : 1; /* 06 */ 24 + __u32 dg : 1; /* 07 degradation */ 25 + __u32 w : 1; /* 08 warning pending */ 26 + __u32 cp : 1; /* 09 channel-report pending */ 27 + __u32 sp : 1; /* 10 service-processor damage */ 28 + __u32 ck : 1; /* 11 channel-subsystem damage */ 29 + __u32 : 2; /* 12-13 */ 30 + __u32 b : 1; /* 14 backed up */ 31 + __u32 : 1; /* 15 */ 32 + __u32 se : 1; /* 16 storage error uncorrected */ 33 + __u32 sc : 1; /* 17 storage error corrected */ 34 + __u32 ke : 1; /* 18 storage-key error uncorrected */ 35 + __u32 ds : 1; /* 19 storage degradation */ 36 + __u32 wp : 1; /* 20 psw mwp validity */ 37 + __u32 ms : 1; /* 21 psw mask and key validity */ 38 + __u32 pm : 1; /* 22 psw program mask and cc validity */ 39 + __u32 ia : 1; /* 23 psw instruction address validity */ 40 + __u32 fa : 1; /* 24 failing storage address validity */ 41 + __u32 : 1; /* 25 */ 42 + __u32 ec : 1; /* 26 external damage code validity */ 43 + __u32 fp : 1; /* 27 floating point register validity */ 44 + __u32 gr : 1; /* 28 general register validity */ 45 + __u32 cr : 1; /* 29 control register validity */ 46 + __u32 : 1; /* 30 */ 47 + __u32 st : 1; /* 31 storage logical validity */ 48 + __u32 ie : 1; /* 32 indirect storage error */ 49 + __u32 ar : 1; /* 33 access register validity */ 50 + __u32 da : 1; /* 34 delayed access exception */ 51 + __u32 : 7; /* 35-41 */ 52 + __u32 pr : 1; /* 42 tod programmable register validity */ 53 + __u32 fc : 1; /* 43 fp control register validity */ 54 + __u32 ap : 1; /* 44 ancillary report */ 55 + __u32 : 1; /* 45 */ 56 + __u32 ct : 1; /* 46 cpu timer validity */ 57 + __u32 cc : 1; /* 47 clock comparator validity */ 58 + __u32 : 16; /* 47-63 */ 59 + }; 60 + 61 + struct pt_regs; 62 + 63 + extern void s390_handle_mcck(void); 64 + extern void s390_do_machine_check(struct pt_regs *regs); 65 + 66 + #endif /* _ASM_S390_NMI_H */
+1 -1
arch/s390/kernel/Makefile
··· 22 22 obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ 23 23 processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ 24 24 s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ 25 - vdso.o vtime.o sysinfo.o 25 + vdso.o vtime.o sysinfo.o nmi.o 26 26 27 27 obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) 28 28 obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
+1 -1
arch/s390/kernel/process.c
··· 39 39 #include <asm/processor.h> 40 40 #include <asm/irq.h> 41 41 #include <asm/timer.h> 42 + #include <asm/nmi.h> 42 43 #include "entry.h" 43 44 44 45 asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); ··· 69 68 return sf->gprs[8]; 70 69 } 71 70 72 - extern void s390_handle_mcck(void); 73 71 /* 74 72 * The idle loop on a S390... 75 73 */
+1 -3
arch/s390/kvm/kvm-s390.c
··· 23 23 #include <linux/timer.h> 24 24 #include <asm/lowcore.h> 25 25 #include <asm/pgtable.h> 26 - 26 + #include <asm/nmi.h> 27 27 #include "kvm-s390.h" 28 28 #include "gaccess.h" 29 29 ··· 439 439 { 440 440 return -EINVAL; /* not implemented yet */ 441 441 } 442 - 443 - extern void s390_handle_mcck(void); 444 442 445 443 static void __vcpu_run(struct kvm_vcpu *vcpu) 446 444 {
-1
drivers/s390/Makefile
··· 2 2 # Makefile for the S/390 specific device drivers 3 3 # 4 4 5 - obj-y += s390mach.o 6 5 obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/ 7 6 8 7 drivers-y += drivers/s390/built-in.o
+1 -1
drivers/s390/cio/Makefile
··· 3 3 # 4 4 5 5 obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \ 6 - fcx.o itcw.o 6 + fcx.o itcw.o crw.o 7 7 ccw_device-objs += device.o device_fsm.o device_ops.o 8 8 ccw_device-objs += device_id.o device_pgid.o device_status.o 9 9 obj-y += ccw_device.o cmf.o
+3 -3
drivers/s390/cio/chp.c
··· 17 17 #include <linux/errno.h> 18 18 #include <asm/chpid.h> 19 19 #include <asm/sclp.h> 20 + #include <asm/crw.h> 20 21 21 - #include "../s390mach.h" 22 22 #include "cio.h" 23 23 #include "css.h" 24 24 #include "ioasm.h" ··· 706 706 struct chp_id chpid; 707 707 int ret; 708 708 709 - ret = s390_register_crw_handler(CRW_RSC_CPATH, chp_process_crw); 709 + ret = crw_register_handler(CRW_RSC_CPATH, chp_process_crw); 710 710 if (ret) 711 711 return ret; 712 712 chp_wq = create_singlethread_workqueue("cio_chp"); 713 713 if (!chp_wq) { 714 - s390_unregister_crw_handler(CRW_RSC_CPATH); 714 + crw_unregister_handler(CRW_RSC_CPATH); 715 715 return -ENOMEM; 716 716 } 717 717 INIT_WORK(&cfg_work, cfg_func);
+3 -3
drivers/s390/cio/chsc.c
··· 19 19 #include <asm/cio.h> 20 20 #include <asm/chpid.h> 21 21 #include <asm/chsc.h> 22 + #include <asm/crw.h> 22 23 23 - #include "../s390mach.h" 24 24 #include "css.h" 25 25 #include "cio.h" 26 26 #include "cio_debug.h" ··· 820 820 "chsc machine checks!\n"); 821 821 return -ENOMEM; 822 822 } 823 - ret = s390_register_crw_handler(CRW_RSC_CSS, chsc_process_crw); 823 + ret = crw_register_handler(CRW_RSC_CSS, chsc_process_crw); 824 824 if (ret) 825 825 kfree(sei_page); 826 826 return ret; ··· 828 828 829 829 void __init chsc_free_sei_area(void) 830 830 { 831 - s390_unregister_crw_handler(CRW_RSC_CSS); 831 + crw_unregister_handler(CRW_RSC_CSS); 832 832 kfree(sei_page); 833 833 } 834 834
+2 -1
drivers/s390/cio/cio.c
··· 30 30 #include <asm/isc.h> 31 31 #include <asm/cpu.h> 32 32 #include <asm/fcx.h> 33 + #include <asm/nmi.h> 34 + #include <asm/crw.h> 33 35 #include "cio.h" 34 36 #include "css.h" 35 37 #include "chsc.h" ··· 40 38 #include "blacklist.h" 41 39 #include "cio_debug.h" 42 40 #include "chp.h" 43 - #include "../s390mach.h" 44 41 45 42 debug_info_t *cio_debug_msg_id; 46 43 debug_info_t *cio_debug_trace_id;
+145
drivers/s390/cio/crw.c
··· 1 + /* 2 + * Channel report handling code 3 + * 4 + * Copyright IBM Corp. 2000,2009 5 + * Author(s): Ingo Adlung <adlung@de.ibm.com>, 6 + * Martin Schwidefsky <schwidefsky@de.ibm.com>, 7 + * Cornelia Huck <cornelia.huck@de.ibm.com>, 8 + * Heiko Carstens <heiko.carstens@de.ibm.com>, 9 + */ 10 + 11 + #include <linux/semaphore.h> 12 + #include <linux/kthread.h> 13 + #include <linux/init.h> 14 + #include <asm/crw.h> 15 + 16 + static struct semaphore crw_semaphore; 17 + static crw_handler_t crw_handlers[NR_RSCS]; 18 + 19 + /** 20 + * crw_register_handler() - register a channel report word handler 21 + * @rsc: reporting source code to handle 22 + * @handler: handler to be registered 23 + * 24 + * Returns %0 on success and a negative error value otherwise. 25 + */ 26 + int crw_register_handler(int rsc, crw_handler_t handler) 27 + { 28 + if ((rsc < 0) || (rsc >= NR_RSCS)) 29 + return -EINVAL; 30 + if (!cmpxchg(&crw_handlers[rsc], NULL, handler)) 31 + return 0; 32 + return -EBUSY; 33 + } 34 + 35 + /** 36 + * crw_unregister_handler() - unregister a channel report word handler 37 + * @rsc: reporting source code to handle 38 + */ 39 + void crw_unregister_handler(int rsc) 40 + { 41 + if ((rsc < 0) || (rsc >= NR_RSCS)) 42 + return; 43 + xchg(&crw_handlers[rsc], NULL); 44 + synchronize_sched(); 45 + } 46 + 47 + /* 48 + * Retrieve CRWs and call function to handle event. 49 + */ 50 + static int crw_collect_info(void *unused) 51 + { 52 + struct crw crw[2]; 53 + int ccode; 54 + unsigned int chain; 55 + int ignore; 56 + 57 + repeat: 58 + ignore = down_interruptible(&crw_semaphore); 59 + chain = 0; 60 + while (1) { 61 + if (unlikely(chain > 1)) { 62 + struct crw tmp_crw; 63 + 64 + printk(KERN_WARNING"%s: Code does not support more " 65 + "than two chained crws; please report to " 66 + "linux390@de.ibm.com!\n", __func__); 67 + ccode = stcrw(&tmp_crw); 68 + printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " 69 + "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", 70 + __func__, tmp_crw.slct, tmp_crw.oflw, 71 + tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc, 72 + tmp_crw.erc, tmp_crw.rsid); 73 + printk(KERN_WARNING"%s: This was crw number %x in the " 74 + "chain\n", __func__, chain); 75 + if (ccode != 0) 76 + break; 77 + chain = tmp_crw.chn ? chain + 1 : 0; 78 + continue; 79 + } 80 + ccode = stcrw(&crw[chain]); 81 + if (ccode != 0) 82 + break; 83 + printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " 84 + "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", 85 + crw[chain].slct, crw[chain].oflw, crw[chain].chn, 86 + crw[chain].rsc, crw[chain].anc, crw[chain].erc, 87 + crw[chain].rsid); 88 + /* Check for overflows. */ 89 + if (crw[chain].oflw) { 90 + int i; 91 + 92 + pr_debug("%s: crw overflow detected!\n", __func__); 93 + for (i = 0; i < NR_RSCS; i++) { 94 + if (crw_handlers[i]) 95 + crw_handlers[i](NULL, NULL, 1); 96 + } 97 + chain = 0; 98 + continue; 99 + } 100 + if (crw[0].chn && !chain) { 101 + chain++; 102 + continue; 103 + } 104 + if (crw_handlers[crw[chain].rsc]) 105 + crw_handlers[crw[chain].rsc](&crw[0], 106 + chain ? &crw[1] : NULL, 107 + 0); 108 + /* chain is always 0 or 1 here. */ 109 + chain = crw[chain].chn ? chain + 1 : 0; 110 + } 111 + goto repeat; 112 + return 0; 113 + } 114 + 115 + void crw_handle_channel_report(void) 116 + { 117 + up(&crw_semaphore); 118 + } 119 + 120 + /* 121 + * Separate initcall needed for semaphore initialization since 122 + * crw_handle_channel_report might be called before crw_machine_check_init. 123 + */ 124 + static int __init crw_init_semaphore(void) 125 + { 126 + init_MUTEX_LOCKED(&crw_semaphore); 127 + return 0; 128 + } 129 + pure_initcall(crw_init_semaphore); 130 + 131 + /* 132 + * Machine checks for the channel subsystem must be enabled 133 + * after the channel subsystem is initialized 134 + */ 135 + static int __init crw_machine_check_init(void) 136 + { 137 + struct task_struct *task; 138 + 139 + task = kthread_run(crw_collect_info, NULL, "kmcheck"); 140 + if (IS_ERR(task)) 141 + return PTR_ERR(task); 142 + ctl_set_bit(14, 28); /* enable channel report MCH */ 143 + return 0; 144 + } 145 + device_initcall(crw_machine_check_init);
+3 -3
drivers/s390/cio/css.c
··· 18 18 #include <linux/list.h> 19 19 #include <linux/reboot.h> 20 20 #include <asm/isc.h> 21 + #include <asm/crw.h> 21 22 22 - #include "../s390mach.h" 23 23 #include "css.h" 24 24 #include "cio.h" 25 25 #include "cio_debug.h" ··· 765 765 if (ret) 766 766 goto out; 767 767 768 - ret = s390_register_crw_handler(CRW_RSC_SCH, css_process_crw); 768 + ret = crw_register_handler(CRW_RSC_SCH, css_process_crw); 769 769 if (ret) 770 770 goto out; 771 771 ··· 845 845 out_bus: 846 846 bus_unregister(&css_bus_type); 847 847 out: 848 - s390_unregister_crw_handler(CRW_RSC_CSS); 848 + crw_unregister_handler(CRW_RSC_CSS); 849 849 chsc_free_sei_area(); 850 850 kfree(slow_subchannel_set); 851 851 pr_alert("The CSS device driver initialization failed with "
+46 -200
drivers/s390/s390mach.c arch/s390/kernel/nmi.c
··· 1 1 /* 2 - * drivers/s390/s390mach.c 3 - * S/390 machine check handler 2 + * Machine check handler 4 3 * 5 - * Copyright IBM Corp. 2000,2008 6 - * Author(s): Ingo Adlung (adlung@de.ibm.com) 7 - * Martin Schwidefsky (schwidefsky@de.ibm.com) 8 - * Cornelia Huck <cornelia.huck@de.ibm.com> 4 + * Copyright IBM Corp. 2000,2009 5 + * Author(s): Ingo Adlung <adlung@de.ibm.com>, 6 + * Martin Schwidefsky <schwidefsky@de.ibm.com>, 7 + * Cornelia Huck <cornelia.huck@de.ibm.com>, 8 + * Heiko Carstens <heiko.carstens@de.ibm.com>, 9 9 */ 10 10 11 11 #include <linux/init.h> 12 - #include <linux/sched.h> 13 12 #include <linux/errno.h> 14 - #include <linux/workqueue.h> 15 13 #include <linux/time.h> 16 - #include <linux/device.h> 17 - #include <linux/kthread.h> 18 - #include <asm/etr.h> 14 + #include <linux/module.h> 19 15 #include <asm/lowcore.h> 20 - #include <asm/cio.h> 16 + #include <asm/smp.h> 17 + #include <asm/etr.h> 21 18 #include <asm/cpu.h> 22 - #include "s390mach.h" 23 - 24 - static struct semaphore m_sem; 25 - 26 - static NORET_TYPE void 27 - s390_handle_damage(char *msg) 28 - { 29 - #ifdef CONFIG_SMP 30 - smp_send_stop(); 31 - #endif 32 - disabled_wait((unsigned long) __builtin_return_address(0)); 33 - for(;;); 34 - } 35 - 36 - static crw_handler_t crw_handlers[NR_RSCS]; 37 - 38 - /** 39 - * s390_register_crw_handler() - register a channel report word handler 40 - * @rsc: reporting source code to handle 41 - * @handler: handler to be registered 42 - * 43 - * Returns %0 on success and a negative error value otherwise. 44 - */ 45 - int s390_register_crw_handler(int rsc, crw_handler_t handler) 46 - { 47 - if ((rsc < 0) || (rsc >= NR_RSCS)) 48 - return -EINVAL; 49 - if (!cmpxchg(&crw_handlers[rsc], NULL, handler)) 50 - return 0; 51 - return -EBUSY; 52 - } 53 - 54 - /** 55 - * s390_unregister_crw_handler() - unregister a channel report word handler 56 - * @rsc: reporting source code to handle 57 - */ 58 - void s390_unregister_crw_handler(int rsc) 59 - { 60 - if ((rsc < 0) || (rsc >= NR_RSCS)) 61 - return; 62 - xchg(&crw_handlers[rsc], NULL); 63 - synchronize_sched(); 64 - } 65 - 66 - /* 67 - * Retrieve CRWs and call function to handle event. 68 - */ 69 - static int s390_collect_crw_info(void *param) 70 - { 71 - struct crw crw[2]; 72 - int ccode; 73 - struct semaphore *sem; 74 - unsigned int chain; 75 - int ignore; 76 - 77 - sem = (struct semaphore *)param; 78 - repeat: 79 - ignore = down_interruptible(sem); 80 - chain = 0; 81 - while (1) { 82 - if (unlikely(chain > 1)) { 83 - struct crw tmp_crw; 84 - 85 - printk(KERN_WARNING"%s: Code does not support more " 86 - "than two chained crws; please report to " 87 - "linux390@de.ibm.com!\n", __func__); 88 - ccode = stcrw(&tmp_crw); 89 - printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " 90 - "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", 91 - __func__, tmp_crw.slct, tmp_crw.oflw, 92 - tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc, 93 - tmp_crw.erc, tmp_crw.rsid); 94 - printk(KERN_WARNING"%s: This was crw number %x in the " 95 - "chain\n", __func__, chain); 96 - if (ccode != 0) 97 - break; 98 - chain = tmp_crw.chn ? chain + 1 : 0; 99 - continue; 100 - } 101 - ccode = stcrw(&crw[chain]); 102 - if (ccode != 0) 103 - break; 104 - printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " 105 - "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", 106 - crw[chain].slct, crw[chain].oflw, crw[chain].chn, 107 - crw[chain].rsc, crw[chain].anc, crw[chain].erc, 108 - crw[chain].rsid); 109 - /* Check for overflows. */ 110 - if (crw[chain].oflw) { 111 - int i; 112 - 113 - pr_debug("%s: crw overflow detected!\n", __func__); 114 - for (i = 0; i < NR_RSCS; i++) { 115 - if (crw_handlers[i]) 116 - crw_handlers[i](NULL, NULL, 1); 117 - } 118 - chain = 0; 119 - continue; 120 - } 121 - if (crw[0].chn && !chain) { 122 - chain++; 123 - continue; 124 - } 125 - if (crw_handlers[crw[chain].rsc]) 126 - crw_handlers[crw[chain].rsc](&crw[0], 127 - chain ? &crw[1] : NULL, 128 - 0); 129 - /* chain is always 0 or 1 here. */ 130 - chain = crw[chain].chn ? chain + 1 : 0; 131 - } 132 - goto repeat; 133 - return 0; 134 - } 19 + #include <asm/nmi.h> 20 + #include <asm/crw.h> 135 21 136 22 struct mcck_struct { 137 23 int kill_task; ··· 28 142 29 143 static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck); 30 144 145 + static NORET_TYPE void s390_handle_damage(char *msg) 146 + { 147 + smp_send_stop(); 148 + disabled_wait((unsigned long) __builtin_return_address(0)); 149 + while (1); 150 + } 151 + 31 152 /* 32 153 * Main machine check handler function. Will be called with interrupts enabled 33 154 * or disabled and machine checks enabled or disabled. 34 155 */ 35 - void 36 - s390_handle_mcck(void) 156 + void s390_handle_mcck(void) 37 157 { 38 158 unsigned long flags; 39 159 struct mcck_struct mcck; ··· 58 166 local_irq_restore(flags); 59 167 60 168 if (mcck.channel_report) 61 - up(&m_sem); 169 + crw_handle_channel_report(); 62 170 63 171 #ifdef CONFIG_MACHCHK_WARNING 64 172 /* ··· 96 204 * returns 0 if all registers could be validated 97 205 * returns 1 otherwise 98 206 */ 99 - static int 100 - s390_revalidate_registers(struct mci *mci) 207 + static int notrace s390_revalidate_registers(struct mci *mci) 101 208 { 102 209 int kill_task; 103 210 u64 tmpclock; ··· 105 214 106 215 kill_task = 0; 107 216 zero = 0; 108 - /* General purpose registers */ 109 - if (!mci->gr) 217 + 218 + if (!mci->gr) { 110 219 /* 111 220 * General purpose registers couldn't be restored and have 112 221 * unknown contents. Process needs to be terminated. 113 222 */ 114 223 kill_task = 1; 115 - 116 - /* Revalidate floating point registers */ 117 - if (!mci->fp) 224 + } 225 + if (!mci->fp) { 118 226 /* 119 227 * Floating point registers can't be restored and 120 228 * therefore the process needs to be terminated. 121 229 */ 122 230 kill_task = 1; 123 - 231 + } 124 232 #ifndef CONFIG_64BIT 125 233 asm volatile( 126 234 " ld 0,0(%0)\n" ··· 135 245 fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area; 136 246 #else 137 247 fpt_save_area = (void *) S390_lowcore.extended_save_area_addr; 138 - fpt_creg_save_area = fpt_save_area+128; 248 + fpt_creg_save_area = fpt_save_area + 128; 139 249 #endif 140 - /* Floating point control register */ 141 250 if (!mci->fc) { 142 251 /* 143 252 * Floating point control register can't be restored. ··· 167 278 " ld 15,120(%0)\n" 168 279 : : "a" (fpt_save_area)); 169 280 } 170 - 171 281 /* Revalidate access registers */ 172 282 asm volatile( 173 283 " lam 0,15,0(%0)" 174 284 : : "a" (&S390_lowcore.access_regs_save_area)); 175 - if (!mci->ar) 285 + if (!mci->ar) { 176 286 /* 177 287 * Access registers have unknown contents. 178 288 * Terminating task. 179 289 */ 180 290 kill_task = 1; 181 - 291 + } 182 292 /* Revalidate control registers */ 183 - if (!mci->cr) 293 + if (!mci->cr) { 184 294 /* 185 295 * Control registers have unknown contents. 186 296 * Can't recover and therefore stopping machine. 187 297 */ 188 298 s390_handle_damage("invalid control registers."); 189 - else 299 + } else { 190 300 #ifdef CONFIG_64BIT 191 301 asm volatile( 192 302 " lctlg 0,15,0(%0)" ··· 195 307 " lctl 0,15,0(%0)" 196 308 : : "a" (&S390_lowcore.cregs_save_area)); 197 309 #endif 198 - 310 + } 199 311 /* 200 312 * We don't even try to revalidate the TOD register, since we simply 201 313 * can't write something sensible into that register. 202 314 */ 203 - 204 315 #ifdef CONFIG_64BIT 205 316 /* 206 317 * See if we can revalidate the TOD programmable register with its ··· 217 330 : : "a" (&S390_lowcore.tod_progreg_save_area) 218 331 : "0", "cc"); 219 332 #endif 220 - 221 333 /* Revalidate clock comparator register */ 222 334 asm volatile( 223 335 " stck 0(%1)\n" ··· 240 354 #define MAX_IPD_COUNT 29 241 355 #define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */ 242 356 357 + #define ED_STP_ISLAND 6 /* External damage STP island check */ 358 + #define ED_STP_SYNC 7 /* External damage STP sync check */ 359 + #define ED_ETR_SYNC 12 /* External damage ETR sync check */ 360 + #define ED_ETR_SWITCH 13 /* External damage ETR switch to local */ 361 + 243 362 /* 244 363 * machine check handler. 245 364 */ 246 365 void notrace s390_do_machine_check(struct pt_regs *regs) 247 366 { 367 + static int ipd_count; 248 368 static DEFINE_SPINLOCK(ipd_lock); 249 369 static unsigned long long last_ipd; 250 - static int ipd_count; 370 + struct mcck_struct *mcck; 251 371 unsigned long long tmp; 252 372 struct mci *mci; 253 - struct mcck_struct *mcck; 254 373 int umode; 255 374 256 375 lockdep_off(); 257 - 258 376 s390_idle_check(); 259 377 260 378 mci = (struct mci *) &S390_lowcore.mcck_interruption_code; 261 379 mcck = &__get_cpu_var(cpu_mcck); 262 380 umode = user_mode(regs); 263 381 264 - if (mci->sd) 382 + if (mci->sd) { 265 383 /* System damage -> stopping machine */ 266 384 s390_handle_damage("received system damage machine check."); 267 - 385 + } 268 386 if (mci->pd) { 269 387 if (mci->b) { 270 388 /* Processing backup -> verify if we can survive this */ ··· 298 408 * Nullifying exigent condition, therefore we might 299 409 * retry this instruction. 300 410 */ 301 - 302 411 spin_lock(&ipd_lock); 303 - 304 412 tmp = get_clock(); 305 - 306 413 if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME) 307 414 ipd_count++; 308 415 else 309 416 ipd_count = 1; 310 - 311 417 last_ipd = tmp; 312 - 313 418 if (ipd_count == MAX_IPD_COUNT) 314 419 s390_handle_damage("too many ipd retries."); 315 - 316 420 spin_unlock(&ipd_lock); 317 - } 318 - else { 421 + } else { 319 422 /* Processing damage -> stopping machine */ 320 423 s390_handle_damage("received instruction processing " 321 424 "damage machine check."); ··· 323 440 mcck->kill_task = 1; 324 441 mcck->mcck_code = *(unsigned long long *) mci; 325 442 set_thread_flag(TIF_MCCK_PENDING); 326 - } 327 - else 443 + } else { 328 444 /* 329 445 * Couldn't restore all register contents while in 330 446 * kernel mode -> stopping machine. 331 447 */ 332 448 s390_handle_damage("unable to revalidate registers."); 449 + } 333 450 } 334 - 335 451 if (mci->cd) { 336 452 /* Timing facility damage */ 337 453 s390_handle_damage("TOD clock damaged"); 338 454 } 339 - 340 455 if (mci->ed && mci->ec) { 341 456 /* External damage */ 342 457 if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC)) ··· 346 465 if (S390_lowcore.external_damage_code & (1U << ED_STP_ISLAND)) 347 466 stp_island_check(); 348 467 } 349 - 350 468 if (mci->se) 351 469 /* Storage error uncorrected */ 352 470 s390_handle_damage("received storage error uncorrected " 353 471 "machine check."); 354 - 355 472 if (mci->ke) 356 473 /* Storage key-error uncorrected */ 357 474 s390_handle_damage("received storage key-error uncorrected " 358 475 "machine check."); 359 - 360 476 if (mci->ds && mci->fa) 361 477 /* Storage degradation */ 362 478 s390_handle_damage("received storage degradation machine " 363 479 "check."); 364 - 365 480 if (mci->cp) { 366 481 /* Channel report word pending */ 367 482 mcck->channel_report = 1; 368 483 set_thread_flag(TIF_MCCK_PENDING); 369 484 } 370 - 371 485 if (mci->w) { 372 486 /* Warning pending */ 373 487 mcck->warning = 1; ··· 371 495 lockdep_on(); 372 496 } 373 497 374 - /* 375 - * s390_init_machine_check 376 - * 377 - * initialize machine check handling 378 - */ 379 - static int 380 - machine_check_init(void) 498 + static int __init machine_check_init(void) 381 499 { 382 - init_MUTEX_LOCKED(&m_sem); 383 500 ctl_set_bit(14, 25); /* enable external damage MCH */ 384 - ctl_set_bit(14, 27); /* enable system recovery MCH */ 501 + ctl_set_bit(14, 27); /* enable system recovery MCH */ 385 502 #ifdef CONFIG_MACHCHK_WARNING 386 503 ctl_set_bit(14, 24); /* enable warning MCH */ 387 504 #endif 388 505 return 0; 389 506 } 390 - 391 - /* 392 - * Initialize the machine check handler really early to be able to 393 - * catch all machine checks that happen during boot 394 - */ 395 507 arch_initcall(machine_check_init); 396 - 397 - /* 398 - * Machine checks for the channel subsystem must be enabled 399 - * after the channel subsystem is initialized 400 - */ 401 - static int __init 402 - machine_check_crw_init (void) 403 - { 404 - struct task_struct *task; 405 - 406 - task = kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); 407 - if (IS_ERR(task)) 408 - return PTR_ERR(task); 409 - ctl_set_bit(14, 28); /* enable channel report MCH */ 410 - return 0; 411 - } 412 - 413 - device_initcall (machine_check_crw_init);
-122
drivers/s390/s390mach.h
··· 1 - /* 2 - * drivers/s390/s390mach.h 3 - * S/390 data definitions for machine check processing 4 - * 5 - * S390 version 6 - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation 7 - * Author(s): Ingo Adlung (adlung@de.ibm.com) 8 - */ 9 - 10 - #ifndef __s390mach_h 11 - #define __s390mach_h 12 - 13 - #include <asm/types.h> 14 - 15 - struct mci { 16 - __u32 sd : 1; /* 00 system damage */ 17 - __u32 pd : 1; /* 01 instruction-processing damage */ 18 - __u32 sr : 1; /* 02 system recovery */ 19 - __u32 to_be_defined_1 : 1; /* 03 */ 20 - __u32 cd : 1; /* 04 timing-facility damage */ 21 - __u32 ed : 1; /* 05 external damage */ 22 - __u32 to_be_defined_2 : 1; /* 06 */ 23 - __u32 dg : 1; /* 07 degradation */ 24 - __u32 w : 1; /* 08 warning pending */ 25 - __u32 cp : 1; /* 09 channel-report pending */ 26 - __u32 sp : 1; /* 10 service-processor damage */ 27 - __u32 ck : 1; /* 11 channel-subsystem damage */ 28 - __u32 to_be_defined_3 : 2; /* 12-13 */ 29 - __u32 b : 1; /* 14 backed up */ 30 - __u32 to_be_defined_4 : 1; /* 15 */ 31 - __u32 se : 1; /* 16 storage error uncorrected */ 32 - __u32 sc : 1; /* 17 storage error corrected */ 33 - __u32 ke : 1; /* 18 storage-key error uncorrected */ 34 - __u32 ds : 1; /* 19 storage degradation */ 35 - __u32 wp : 1; /* 20 psw mwp validity */ 36 - __u32 ms : 1; /* 21 psw mask and key validity */ 37 - __u32 pm : 1; /* 22 psw program mask and cc validity */ 38 - __u32 ia : 1; /* 23 psw instruction address validity */ 39 - __u32 fa : 1; /* 24 failing storage address validity */ 40 - __u32 to_be_defined_5 : 1; /* 25 */ 41 - __u32 ec : 1; /* 26 external damage code validity */ 42 - __u32 fp : 1; /* 27 floating point register validity */ 43 - __u32 gr : 1; /* 28 general register validity */ 44 - __u32 cr : 1; /* 29 control register validity */ 45 - __u32 to_be_defined_6 : 1; /* 30 */ 46 - __u32 st : 1; /* 31 storage logical validity */ 47 - __u32 ie : 1; /* 32 indirect storage error */ 48 - __u32 ar : 1; /* 33 access register validity */ 49 - __u32 da : 1; /* 34 delayed access exception */ 50 - __u32 to_be_defined_7 : 7; /* 35-41 */ 51 - __u32 pr : 1; /* 42 tod programmable register validity */ 52 - __u32 fc : 1; /* 43 fp control register validity */ 53 - __u32 ap : 1; /* 44 ancillary report */ 54 - __u32 to_be_defined_8 : 1; /* 45 */ 55 - __u32 ct : 1; /* 46 cpu timer validity */ 56 - __u32 cc : 1; /* 47 clock comparator validity */ 57 - __u32 to_be_defined_9 : 16; /* 47-63 */ 58 - }; 59 - 60 - /* 61 - * Channel Report Word 62 - */ 63 - struct crw { 64 - __u32 res1 : 1; /* reserved zero */ 65 - __u32 slct : 1; /* solicited */ 66 - __u32 oflw : 1; /* overflow */ 67 - __u32 chn : 1; /* chained */ 68 - __u32 rsc : 4; /* reporting source code */ 69 - __u32 anc : 1; /* ancillary report */ 70 - __u32 res2 : 1; /* reserved zero */ 71 - __u32 erc : 6; /* error-recovery code */ 72 - __u32 rsid : 16; /* reporting-source ID */ 73 - } __attribute__ ((packed)); 74 - 75 - typedef void (*crw_handler_t)(struct crw *, struct crw *, int); 76 - 77 - extern int s390_register_crw_handler(int rsc, crw_handler_t handler); 78 - extern void s390_unregister_crw_handler(int rsc); 79 - 80 - #define NR_RSCS 16 81 - 82 - #define CRW_RSC_MONITOR 0x2 /* monitoring facility */ 83 - #define CRW_RSC_SCH 0x3 /* subchannel */ 84 - #define CRW_RSC_CPATH 0x4 /* channel path */ 85 - #define CRW_RSC_CONFIG 0x9 /* configuration-alert facility */ 86 - #define CRW_RSC_CSS 0xB /* channel subsystem */ 87 - 88 - #define CRW_ERC_EVENT 0x00 /* event information pending */ 89 - #define CRW_ERC_AVAIL 0x01 /* available */ 90 - #define CRW_ERC_INIT 0x02 /* initialized */ 91 - #define CRW_ERC_TERROR 0x03 /* temporary error */ 92 - #define CRW_ERC_IPARM 0x04 /* installed parm initialized */ 93 - #define CRW_ERC_TERM 0x05 /* terminal */ 94 - #define CRW_ERC_PERRN 0x06 /* perm. error, fac. not init */ 95 - #define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ 96 - #define CRW_ERC_PMOD 0x08 /* installed parameters modified */ 97 - 98 - static inline int stcrw(struct crw *pcrw ) 99 - { 100 - int ccode; 101 - 102 - __asm__ __volatile__( 103 - "stcrw 0(%2)\n\t" 104 - "ipm %0\n\t" 105 - "srl %0,28\n\t" 106 - : "=d" (ccode), "=m" (*pcrw) 107 - : "a" (pcrw) 108 - : "cc" ); 109 - return ccode; 110 - } 111 - 112 - #define ED_ETR_SYNC 12 /* External damage ETR sync check */ 113 - #define ED_ETR_SWITCH 13 /* External damage ETR switch to local */ 114 - 115 - #define ED_STP_SYNC 7 /* External damage STP sync check */ 116 - #define ED_STP_ISLAND 6 /* External damage STP island check */ 117 - 118 - struct pt_regs; 119 - 120 - void s390_handle_mcck(void); 121 - void s390_do_machine_check(struct pt_regs *regs); 122 - #endif /* __s390mach */