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(®s->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