1 /* MACHCHK.C    (c) Copyright Jan Jaeger, 2000-2009                  */
2 /*              ESA/390 Machine Check Functions                      */
3 
4 /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009      */
5 
6 /*-------------------------------------------------------------------*/
7 /* The machine check function supports dynamic I/O configuration.    */
8 /* When a subchannel is added/changed/deleted an ancillary           */
9 /* channel report is made pending.  This ancillary channel           */
10 /* report can be read by the store channel report word I/O           */
11 /* instruction.  Changes to the availability will result in          */
12 /* Messages IOS150I and IOS151I (device xxxx now/not available)      */
13 /* Added Instruction processing damage machine check function such   */
14 /* that abends/waits/loops in instructions will be reflected to the  */
15 /* system running under hercules as a machine malfunction.  This     */
16 /* includes the machine check, checkstop, and malfunction alert      */
17 /* external interrupt as defined in the architecture. - 6/8/01 *JJ   */
18 /*-------------------------------------------------------------------*/
19 
20 #include "hstdinc.h"
21 
22 #if !defined(_HENGINE_DLL_)
23 #define _HENGINE_DLL_
24 #endif
25 
26 #if !defined(_MACHCHK_C_)
27 #define _MACHCHK_C_
28 #endif
29 
30 #include "hercules.h"
31 
32 #include "opcode.h"
33 
34 #if !defined(_MACHCHK_C)
35 
36 #define _MACHCHK_C
37 
38 /*-------------------------------------------------------------------*/
39 /* Return pending channel report                                     */
40 /*                                                                   */
41 /* Returns zero if no device has CRW pending.  Otherwise returns     */
42 /* the channel report word for the first channel path or device      */
43 /* which has a CRW pending, and resets the CRW for that device.      */
44 /*-------------------------------------------------------------------*/
channel_report(REGS * regs)45 U32 channel_report(REGS *regs)
46 {
47 DEVBLK *dev;
48 U32 i,j;
49 
50     /* Scan for channel path reset CRW's */
51     for(i = 0; i < 8; i++)
52     {
53         if(sysblk.chp_reset[i])
54         {
55             OBTAIN_INTLOCK(regs);
56             for(j = 0; j < 32; j++)
57             {
58                 if(sysblk.chp_reset[i] & (0x80000000 >> j))
59                 {
60                     sysblk.chp_reset[i] &= ~(0x80000000 >> j);
61                     RELEASE_INTLOCK(regs);
62                     return CRW_SOL | CRW_CHPID | CRW_AR | CRW_INIT | ((i*32)+j);
63                 }
64             }
65             RELEASE_INTLOCK(regs);
66         }
67     }
68 
69     /* Scan for subchannel alert CRW's */
70     for(dev = sysblk.firstdev; dev!= NULL; dev = dev->nextdev)
71     {
72         if(dev->crwpending)
73         {
74             obtain_lock(&dev->lock);
75             if(dev->crwpending)
76             {
77                 dev->crwpending = 0;
78                 release_lock(&dev->lock);
79                 return CRW_SUBCH | CRW_AR | CRW_ALERT | dev->subchan;
80             }
81             release_lock(&dev->lock);
82         }
83     }
84     return 0;
85 } /* end function channel_report */
86 
87 /*-------------------------------------------------------------------*/
88 /* Indicate crw pending                                              */
89 /*-------------------------------------------------------------------*/
machine_check_crwpend()90 void machine_check_crwpend()
91 {
92     /* Signal waiting CPUs that an interrupt may be pending */
93     OBTAIN_INTLOCK(NULL);
94     ON_IC_CHANRPT;
95     WAKEUP_CPUS_MASK (sysblk.waiting_mask);
96     RELEASE_INTLOCK(NULL);
97 
98 } /* end function machine_check_crwpend */
99 
100 
101 #endif /*!defined(_MACHCHK_C)*/
102 
103 
104 /*-------------------------------------------------------------------*/
105 /* Present Machine Check Interrupt                                   */
106 /* Input:                                                            */
107 /*      regs    Pointer to the CPU register context                  */
108 /* Output:                                                           */
109 /*      mcic    Machine check interrupt code                         */
110 /*      xdmg    External damage code                                 */
111 /*      fsta    Failing storage address                              */
112 /* Return code:                                                      */
113 /*      0=No machine check, 1=Machine check presented                */
114 /*                                                                   */
115 /* Generic machine check function.  At the momement the only         */
116 /* supported machine check is the channel report.                    */
117 /*                                                                   */
118 /* This routine must be called with the sysblk.intlock held          */
119 /*-------------------------------------------------------------------*/
ARCH_DEP(present_mck_interrupt)120 int ARCH_DEP(present_mck_interrupt)(REGS *regs, U64 *mcic, U32 *xdmg, RADR *fsta)
121 {
122 int rc = 0;
123 
124     UNREFERENCED_370(regs);
125     UNREFERENCED_370(mcic);
126     UNREFERENCED_370(xdmg);
127     UNREFERENCED_370(fsta);
128 
129 #ifdef FEATURE_CHANNEL_SUBSYSTEM
130     /* If there is a crw pending and we are enabled for the channel
131        report interrupt subclass then process the interrupt */
132     if( OPEN_IC_CHANRPT(regs) )
133     {
134         *mcic =  MCIC_CP |
135                MCIC_WP |
136                MCIC_MS |
137                MCIC_PM |
138                MCIC_IA |
139 #ifdef FEATURE_HEXADECIMAL_FLOATING_POINT
140                MCIC_FP |
141 #endif /*FEATURE_HEXADECIMAL_FLOATING_POINT*/
142                MCIC_GR |
143                MCIC_CR |
144                MCIC_ST |
145 #ifdef FEATURE_ACCESS_REGISTERS
146                MCIC_AR |
147 #endif /*FEATURE_ACCESS_REGISTERS*/
148 #if defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)
149                MCIC_PR |
150 #endif /*defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)*/
151 #if defined(FEATURE_BINARY_FLOATING_POINT)
152                MCIC_XF |
153 #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
154                MCIC_AP |
155                MCIC_CT |
156                MCIC_CC ;
157         *xdmg = 0;
158         *fsta = 0;
159         OFF_IC_CHANRPT;
160         rc = 1;
161     }
162 
163     if(!IS_IC_CHANRPT)
164 #endif /*FEATURE_CHANNEL_SUBSYSTEM*/
165         OFF_IC_CHANRPT;
166 
167     return rc;
168 } /* end function present_mck_interrupt */
169 
170 
ARCH_DEP(sync_mck_interrupt)171 void ARCH_DEP(sync_mck_interrupt) (REGS *regs)
172 {
173 int     rc;                             /* Return code               */
174 PSA    *psa;                            /* -> Prefixed storage area  */
175 
176 U64     mcic = MCIC_P  |  /* Instruction processing damage */
177                MCIC_WP |
178                MCIC_MS |
179                MCIC_PM |
180                MCIC_IA |
181 #ifdef FEATURE_HEXADECIMAL_FLOATING_POINT
182                MCIC_FP |
183 #endif /*FEATURE_HEXADECIMAL_FLOATING_POINT*/
184                MCIC_GR |
185                MCIC_CR |
186                MCIC_ST |
187 #ifdef FEATURE_ACCESS_REGISTERS
188                MCIC_AR |
189 #endif /*FEATURE_ACCESS_REGISTERS*/
190 #if defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)
191                MCIC_PR |
192 #endif /*defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)*/
193 #if defined(FEATURE_BINARY_FLOATING_POINT)
194                MCIC_XF |
195 #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
196                MCIC_CT |
197                MCIC_CC ;
198 U32     xdmg = 0;
199 RADR    fsta = 0;
200 
201 
202     /* Release intlock if held */
203     if (regs->cpuad == sysblk.intowner)
204         RELEASE_INTLOCK(regs);
205 
206     /* Release mainlock if held */
207     if (regs->cpuad == sysblk.mainowner)
208         RELEASE_MAINLOCK(regs);
209 
210     /* Exit SIE when active */
211 #if defined(FEATURE_INTERPRETIVE_EXECUTION)
212     if(regs->sie_active)
213         ARCH_DEP(sie_exit) (regs, SIE_HOST_INTERRUPT);
214 #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/
215 
216 
217     /* Set the main storage reference and change bits */
218     STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE);
219 
220     /* Point to the PSA in main storage */
221     psa = (void*)(regs->mainstor + regs->PX);
222 
223     /* Store registers in machine check save area */
224     ARCH_DEP(store_status) (regs, regs->PX);
225 
226 #if !defined(FEATURE_ESAME)
227 // ZZ
228     /* Set the extended logout area to zeros */
229     memset(psa->storepsw, 0, 16);
230 #endif
231 
232     /* Store the machine check interrupt code at PSA+232 */
233     STORE_DW(psa->mckint, mcic);
234 
235     /* Trace the machine check interrupt */
236     if (CPU_STEPPING_OR_TRACING(regs, 0))
237         logmsg (_("HHCCP019I Machine Check code=%16.16" I64_FMT "u\n"),
238                   (long long)mcic);
239 
240     /* Store the external damage code at PSA+244 */
241     STORE_FW(psa->xdmgcode, xdmg);
242 
243 #if defined(FEATURE_ESAME)
244     /* Store the failing storage address at PSA+248 */
245     STORE_DW(psa->mcstorad, fsta);
246 #else /*!defined(FEATURE_ESAME)*/
247     /* Store the failing storage address at PSA+248 */
248     STORE_FW(psa->mcstorad, fsta);
249 #endif /*!defined(FEATURE_ESAME)*/
250 
251     /* Store current PSW at PSA+X'30' */
252     ARCH_DEP(store_psw) ( regs, psa->mckold );
253 
254     /* Load new PSW from PSA+X'70' */
255     rc = ARCH_DEP(load_psw) ( regs, psa->mcknew );
256 
257     if ( rc )
258         ARCH_DEP(program_interrupt) (regs, rc);
259 } /* end function sync_mck_interrupt */
260 
261 
262 #if !defined(_GEN_ARCH)
263 
264 #if defined(_ARCHMODE2)
265  #define  _GEN_ARCH _ARCHMODE2
266  #include "machchk.c"
267 #endif
268 
269 #if defined(_ARCHMODE3)
270  #undef   _GEN_ARCH
271  #define  _GEN_ARCH _ARCHMODE3
272  #include "machchk.c"
273 #endif
274 
275 #if !defined(NO_SIGABEND_HANDLER)
sigabend_handler(int signo)276 void sigabend_handler (int signo)
277 {
278 REGS *regs = NULL;
279 TID tid;
280 int i;
281 
282     tid = thread_id();
283 
284     if( signo == SIGUSR2 )
285     {
286     DEVBLK *dev;
287         if ( equal_threads( tid, sysblk.cnsltid ) ||
288              equal_threads( tid, sysblk.socktid ) ||
289              equal_threads( tid, sysblk.httptid ) )
290             return;
291         for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
292             if ( equal_threads( dev->tid, tid ) ||
293                  equal_threads( dev->shrdtid, tid ) )
294                  break;
295         if( dev == NULL)
296         {
297             if (!sysblk.shutdown)
298                 logmsg(_("HHCCP020E signal USR2 received for "
299                          "undetermined device\n"));
300         }
301         else
302             if(dev->ccwtrace)
303                 logmsg(_("HHCCP021E signal USR2 received for device "
304                          "%4.4X\n"),dev->devnum);
305         return;
306     }
307 
308     for (i = 0; i < MAX_CPU; i++)
309     {
310         if ( equal_threads( sysblk.cputid[i], tid ) )
311         {
312             regs = sysblk.regs[i];
313             break;
314         }
315     }
316 
317     if (regs == NULL)
318     {
319         signal(signo, SIG_DFL);
320         raise(signo);
321         return;
322     }
323 
324     if(MACHMASK(&regs->psw))
325     {
326 #if defined(_FEATURE_SIE)
327         logmsg(_("HHCCP017I CPU%4.4X: Machine check due to host error: %s\n"),
328           regs->sie_active ? regs->guestregs->cpuad : regs->cpuad,
329           strsignal(signo));
330 #else /*!defined(_FEATURE_SIE)*/
331         logmsg(_("HHCCP017I CPU%4.4X: Machine check due to host error: %s\n"),
332           regs->cpuad, strsignal(signo));
333 #endif /*!defined(_FEATURE_SIE)*/
334 
335         display_inst(
336 #if defined(_FEATURE_SIE)
337                      regs->sie_active ? regs->guestregs :
338 #endif /*defined(_FEATURE_SIE)*/
339                                                           regs,
340 #if defined(_FEATURE_SIE)
341           regs->sie_active ? regs->guestregs->ip :
342 #endif /*defined(_FEATURE_SIE)*/
343                                                    regs->ip);
344 
345         switch(regs->arch_mode) {
346 #if defined(_370)
347             case ARCH_370:
348                 s370_sync_mck_interrupt(regs);
349                 break;
350 #endif
351 #if defined(_390)
352             case ARCH_390:
353                 s390_sync_mck_interrupt(regs);
354                 break;
355 #endif
356 #if defined(_900)
357             case ARCH_900:
358                 z900_sync_mck_interrupt(regs);
359                 break;
360 #endif
361         }
362     }
363     else
364     {
365 #if defined(_FEATURE_SIE)
366         logmsg(_("HHCCP018I CPU%4.4X: Check-Stop due to host error: %s\n"),
367           regs->sie_active ? regs->guestregs->cpuad : regs->cpuad,
368           strsignal(signo));
369 #else /*!defined(_FEATURE_SIE)*/
370         logmsg(_("HHCCP018I CPU%4.4X: Check-Stop due to host error: %s\n"),
371           regs->cpuad, strsignal(signo));
372 #endif /*!defined(_FEATURE_SIE)*/
373         display_inst(
374 #if defined(_FEATURE_SIE)
375                      regs->sie_active ? regs->guestregs :
376 #endif /*defined(_FEATURE_SIE)*/
377                                                           regs,
378 #if defined(_FEATURE_SIE)
379           regs->sie_active ? regs->guestregs->ip :
380 #endif /*defined(_FEATURE_SIE)*/
381                                                    regs->ip);
382         regs->cpustate = CPUSTATE_STOPPING;
383         regs->checkstop = 1;
384         ON_IC_INTERRUPT(regs);
385 
386         /* Notify other CPU's by means of a malfuction alert if possible */
387         if (!try_obtain_lock(&sysblk.sigplock))
388         {
389             if(!try_obtain_lock(&sysblk.intlock))
390             {
391                 for (i = 0; i < MAX_CPU; i++)
392                     if (i != regs->cpuad && IS_CPU_ONLINE(i))
393                     {
394                         ON_IC_MALFALT(sysblk.regs[i]);
395                         sysblk.regs[i]->malfcpu[regs->cpuad] = 1;
396                     }
397                 release_lock(&sysblk.intlock);
398             }
399             release_lock(&sysblk.sigplock);
400         }
401 
402     }
403 
404     longjmp (regs->progjmp, SIE_INTERCEPT_MCK);
405 }
406 #endif /*!defined(NO_SIGABEND_HANDLER)*/
407 
408 #endif /*!defined(_GEN_ARCH)*/
409