1 /* DIAGNOSE.C (c) Copyright Roger Bowler, 2000-2009 */
2 /* ESA/390 Diagnose Functions */
3
4 /*-------------------------------------------------------------------*/
5 /* This module implements miscellaneous diagnose functions */
6 /*-------------------------------------------------------------------*/
7
8 /*-------------------------------------------------------------------*/
9 /* Additional credits: */
10 /* Hercules-specific diagnose calls by Jay Maynard. */
11 /* Set/reset bad frame indicator call by Jan Jaeger. */
12 /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */
13 /*-------------------------------------------------------------------*/
14
15 #include "hstdinc.h"
16
17 #if !defined(_HENGINE_DLL_)
18 #define _HENGINE_DLL_
19 #endif
20
21 #if !defined(_DIAGNOSE_C_)
22 #define _DIAGNOSE_C_
23 #endif
24
25 #include "hercules.h"
26
27 #include "opcode.h"
28
29 #include "inline.h"
30
31 #if !defined(_DIAGNOSE_H)
32
33 #define _DIAGNOSE_H
34
35 /*-------------------------------------------------------------------*/
36 /* Internal macro definitions */
37 /*-------------------------------------------------------------------*/
38
39 /* Diagnose 308 function subcodes */
40 #define DIAG308_IPL_CLEAR 3 /* IPL clear */
41 #define DIAG308_IPL_NORMAL 4 /* IPL normal/dump */
42 #define DIAG308_SET_PARAM 5 /* Set IPL parameters */
43 #define DIAG308_STORE_PARAM 6 /* Store IPL parameters */
44
45 /* Diagnose 308 return codes */
46 #define DIAG308_RC_OK 1
47
48 #endif /*!defined(_DIAGNOSE_H)*/
49
50 #if defined(OPTION_DYNAMIC_LOAD) && defined(FEATURE_HERCULES_DIAGCALLS)
51
ARCH_DEP(diagf14_call)52 void ARCH_DEP(diagf14_call)(int r1, int r3, REGS *regs)
53 {
54 char name[32+1];
55 char entry[64];
56 unsigned int i;
57 void (*dllcall)(int, int, REGS *);
58
59 static char *prefix[] = {
60 #if defined(_370)
61 "s370_diagf14_",
62 #endif
63 #if defined(_390)
64 "s390_diagf14_",
65 #endif
66 #if defined(_900)
67 "z900_diagf14_"
68 #endif
69 };
70
71 ARCH_DEP(vfetchc) (name,sizeof(name)-2, regs->GR(r1), USE_REAL_ADDR, regs);
72
73 for(i = 0; i < sizeof(name)-1; i++)
74 {
75 name[i] = guest_to_host(name[i]);
76 if(!isprint(name[i]) || isspace(name[i]))
77 {
78 name[i] = '\0';
79 break;
80 }
81 }
82 /* Ensure string terminator */
83 name[i] = '\0';
84 strcpy(entry,prefix[regs->arch_mode]);
85 strcat(entry,name);
86
87 if( (dllcall = HDL_FINDSYM(entry)) )
88 dllcall(r1, r3, regs);
89 else
90 ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
91
92 }
93 #endif /*defined(OPTION_DYNAMIC_LOAD)*/
94
95 #if defined(FEATURE_PROGRAM_DIRECTED_REIPL) && !defined(STOP_CPUS_AND_IPL)
96 #define STOP_CPUS_AND_IPL
97 /*---------------------------------------------------------------------------*/
98 /* Within diagnose 0x308 (re-ipl) a thread is started with the next code. */
99 /*---------------------------------------------------------------------------*/
stop_cpus_and_ipl(int * ipltype)100 void *stop_cpus_and_ipl(int *ipltype)
101 {
102 int i;
103 char iplcmd[256];
104 int cpustates;
105 CPU_BITMAP mask;
106
107 panel_command("stopall");
108 logmsg("HHCDN001I Diagnose 0x308 called: System is re-ipled\n");
109 sprintf(iplcmd, "%s %03X", ipltype, sysblk.ipldev);
110 do
111 {
112 OBTAIN_INTLOCK(NULL);
113 cpustates = CPUSTATE_STOPPED;
114 mask = sysblk.started_mask;
115 for(i = 0; mask; i++)
116 {
117 if(mask & 1)
118 {
119 logmsg("HHCDN002I Checking cpu %d\n", i);
120 if(IS_CPU_ONLINE(i) && sysblk.regs[i]->cpustate != CPUSTATE_STOPPED)
121 cpustates = sysblk.regs[i]->cpustate;
122 }
123 mask >>= 1;
124 }
125 RELEASE_INTLOCK(NULL);
126 if(cpustates != CPUSTATE_STOPPED)
127 {
128 logmsg("HHCDN003I Waiting 1 second for cpu's to stop...\n");
129 SLEEP(1);
130 }
131 }
132 while(cpustates != CPUSTATE_STOPPED);
133 panel_command(iplcmd);
134 return NULL;
135 }
136 #endif /*defined(FEATURE_PROGRAM_DIRECTED_REIPL) && !defined(STOP_CPUS_AND_IPL)*/
137
138 /*-------------------------------------------------------------------*/
139 /* Diagnose instruction */
140 /*-------------------------------------------------------------------*/
ARCH_DEP(diagnose_call)141 void ARCH_DEP(diagnose_call) (VADR effective_addr2, int b2,
142 int r1, int r2, REGS *regs)
143 {
144 #ifdef FEATURE_HERCULES_DIAGCALLS
145 U32 n; /* 32-bit operand value */
146 #endif /*FEATURE_HERCULES_DIAGCALLS*/
147 U32 code;
148
149 code = effective_addr2;
150
151 switch(code) {
152
153
154 #if defined(FEATURE_IO_ASSIST)
155 case 0x002:
156 /*---------------------------------------------------------------*/
157 /* Diagnose 002: Update Interrupt Interlock Control Bit in PMCW */
158 /*---------------------------------------------------------------*/
159
160 ARCH_DEP(diagnose_002) (regs, r1, r2);
161
162 break;
163 #endif
164
165
166 case 0x01F:
167 /*---------------------------------------------------------------*/
168 /* Diagnose 01F: Power Off */
169 /*---------------------------------------------------------------*/
170
171 /* If diag8cmd is not enabled then we are not allowed
172 * to manipulate the real machine i.e. hercules itself
173 */
174 if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
175 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
176
177 /* The poweroff diagnose is only valid on the 9221 */
178 if(((sysblk.cpuid >> 16 & 0xFFFF) != 0x9221 )
179 /* and r1/r2 must contain C'POWEROFF' in EBCDIC */
180 || regs->GR_L(r1) != 0xD7D6E6C5
181 || regs->GR_L(r2) != 0xD9D6C6C6)
182 ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
183
184 regs->cpustate = CPUSTATE_STOPPING;
185 ON_IC_INTERRUPT(regs);
186
187 /* Release the configuration */
188 do_shutdown();
189
190 /* Power Off: exit hercules */
191 exit(0);
192
193 break;
194
195
196 #if defined(FEATURE_HYPERVISOR) || defined(FEATURE_EMULATE_VM)
197 case 0x044:
198 /*---------------------------------------------------------------*/
199 /* Diagnose 044: Voluntary Time Slice End */
200 /*---------------------------------------------------------------*/
201 ARCH_DEP(scpend_call) ();
202 break;
203 #endif
204
205
206 #ifdef FEATURE_MSSF_CALL
207 case 0x080:
208 /*---------------------------------------------------------------*/
209 /* Diagnose 080: MSSF Call */
210 /*---------------------------------------------------------------*/
211 regs->psw.cc = ARCH_DEP(mssf_call) (r1, r2, regs);
212 break;
213 #endif /*FEATURE_MSSF_CALL*/
214
215
216 #if defined(FEATURE_HYPERVISOR) || defined(FEATURE_EMULATE_VM)
217 case 0x09C:
218 /*---------------------------------------------------------------*/
219 /* Diagnose 09C: Voluntary Time Slice End With Target CPU */
220 /*---------------------------------------------------------------*/
221 ARCH_DEP(scpend_call) (); // (treat same as DIAG X'44')
222 break;
223 #endif
224
225
226 #if defined(FEATURE_HYPERVISOR)
227 case 0x204:
228 /*---------------------------------------------------------------*/
229 /* Diagnose 204: LPAR RMF Interface */
230 /*---------------------------------------------------------------*/
231 ARCH_DEP(diag204_call) (r1, r2, regs);
232 regs->psw.cc = 0;
233 break;
234
235 case 0x224:
236 /*---------------------------------------------------------------*/
237 /* Diagnose 224: CPU Names */
238 /*---------------------------------------------------------------*/
239 ARCH_DEP(diag224_call) (r1, r2, regs);
240 regs->psw.cc = 0;
241 break;
242 #endif /*defined(FEATURE_HYPERVISOR)*/
243
244 #if 0
245 case 0x21C:
246 /*---------------------------------------------------------------*/
247 /* Diagnose 21C: ???? */
248 /*---------------------------------------------------------------*/
249 /*INCOMPLETE*/
250 regs->psw.cc = 0;
251 break;
252 #endif
253
254 #ifdef FEATURE_EMULATE_VM
255 case 0x000:
256 /*---------------------------------------------------------------*/
257 /* Diagnose 000: Store Extended Identification Code */
258 /*---------------------------------------------------------------*/
259 ARCH_DEP(extid_call) (r1, r2, regs);
260 break;
261
262 case 0x008:
263 /*---------------------------------------------------------------*/
264 /* Diagnose 008: Virtual Console Function */
265 /*---------------------------------------------------------------*/
266 /* If diag8cmd is not enabled then we are not allowed
267 * to manipulate the real machine i.e. hercules itself
268 */
269 if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
270 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
271
272 /* Process CP command and set condition code */
273 regs->psw.cc = ARCH_DEP(cpcmd_call) (r1, r2, regs);
274 break;
275
276 case 0x00C:
277 /*---------------------------------------------------------------*/
278 /* Diagnose 00C: Pseudo Timer */
279 /*---------------------------------------------------------------*/
280 ARCH_DEP(pseudo_timer) (code, r1, r2, regs);
281 break;
282
283 case 0x024:
284 /*---------------------------------------------------------------*/
285 /* Diagnose 024: Device Type and Features */
286 /*---------------------------------------------------------------*/
287 regs->psw.cc = ARCH_DEP(diag_devtype) (r1, r2, regs);
288 break;
289
290 case 0x05C:
291 /*---------------------------------------------------------------*/
292 /* Diagnose 05C: Error Message Editing */
293 /*---------------------------------------------------------------*/
294 /* This function is implemented as a no-operation */
295 regs->psw.cc = 0;
296 break;
297
298 case 0x060:
299 /*---------------------------------------------------------------*/
300 /* Diagnose 060: Virtual Machine Storage Size */
301 /*---------------------------------------------------------------*/
302 /* Load main storage size in bytes into R1 register */
303 regs->GR_L(r1) = sysblk.mainsize;
304 break;
305
306 case 0x064:
307 /*---------------------------------------------------------------*/
308 /* Diagnose 064: Named Saved Segment Manipulation */
309 /*---------------------------------------------------------------*/
310 /* Return code 44 cond code 2 means segment does not exist */
311 regs->GR_L(r2) = 44;
312 regs->psw.cc = 2;
313 break;
314
315 case 0x0A4:
316 /*---------------------------------------------------------------*/
317 /* Diagnose 0A4: Synchronous I/O (Standard CMS Blocksize) */
318 /*---------------------------------------------------------------*/
319 regs->psw.cc = ARCH_DEP(syncblk_io) (r1, r2, regs);
320 // logmsg ("Diagnose X\'0A4\': CC=%d, R15=%8.8X\n", /*debug*/
321 // regs->psw.cc, regs->GR_L(15)); /*debug*/
322 break;
323
324 case 0x0A8:
325 /*---------------------------------------------------------------*/
326 /* Diagnose 0A8: Synchronous General I/O */
327 /*---------------------------------------------------------------*/
328 regs->psw.cc = ARCH_DEP(syncgen_io) (r1, r2, regs);
329 // logmsg ("Diagnose X\'0A8\': CC=%d, R15=%8.8X\n", /*debug*/
330 // regs->psw.cc, regs->GR_L(15)); /*debug*/
331 break;
332
333 case 0x0B0:
334 /*---------------------------------------------------------------*/
335 /* Diagnose 0B0: Access Re-IPL Data */
336 /*---------------------------------------------------------------*/
337 ARCH_DEP(access_reipl_data) (r1, r2, regs);
338 break;
339
340 case 0x0DC:
341 /*---------------------------------------------------------------*/
342 /* Diagnose 0DC: Control Application Monitor Record Collection */
343 /*---------------------------------------------------------------*/
344 /* This function is implemented as a no-operation */
345 regs->GR_L(r2) = 0;
346 regs->psw.cc = 0;
347 break;
348
349 case 0x210:
350 /*---------------------------------------------------------------*/
351 /* Diagnose 210: Retrieve Device Information */
352 /*---------------------------------------------------------------*/
353 regs->psw.cc = ARCH_DEP(device_info) (r1, r2, regs);
354 break;
355
356 case 0x214:
357 /*---------------------------------------------------------------*/
358 /* Diagnose 214: Pending Page Release */
359 /*---------------------------------------------------------------*/
360 regs->psw.cc = ARCH_DEP(diag_ppagerel) (r1, r2, regs);
361 break;
362
363
364 case 0x220:
365 /*---------------------------------------------------------------*/
366 /* Diagnose 220: TOD Epoch */
367 /*---------------------------------------------------------------*/
368 ODD_CHECK(r2, regs);
369
370 switch(regs->GR_L(r1))
371 {
372 case 0:
373 /* Obtain TOD features */
374 regs->GR_L(r2) =0xc0000000;
375 regs->GR_L(r2+1)=0x00000000;
376 break;
377 case 1:
378 /* Obtain TOD offset to real TOD in R2, R2+1 */
379 regs->GR_L(r2) = (regs->tod_epoch >> 24) & 0xFFFFFFFF;
380 regs->GR_L(r2+1)= (regs->tod_epoch << 8) & 0xFFFFFFFF;
381 break;
382 default:
383 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
384 }
385 break;
386
387
388 case 0x23C:
389 /*---------------------------------------------------------------*/
390 /* Diagnose 23C: Address Space Services */
391 /*---------------------------------------------------------------*/
392 /* This function is implemented as a no-operation */
393 regs->GR_L(r2) = 0;
394 break;
395
396
397 #if defined(FEATURE_VM_BLOCKIO)
398 case 0x250:
399 /*---------------------------------------------------------------*/
400 /* Diagnose 250: Standardized Block I/O */
401 /*---------------------------------------------------------------*/
402 regs->psw.cc = ARCH_DEP(vm_blockio) (r1, r2, regs);
403 break;
404 #endif /*defined(FEATURE_VM_BLOCKIO)*/
405
406
407 case 0x260:
408 /*---------------------------------------------------------------*/
409 /* Diagnose 260: Access Certain Virtual Machine Information */
410 /*---------------------------------------------------------------*/
411 ARCH_DEP(vm_info) (r1, r2, regs);
412 break;
413
414 case 0x264:
415 /*---------------------------------------------------------------*/
416 /* Diagnose 264: CP Communication */
417 /*---------------------------------------------------------------*/
418 /* This function is implemented as a no-operation */
419 PTT(PTT_CL_ERR,"*DIAG264",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
420 regs->psw.cc = 0;
421 break;
422
423 case 0x270:
424 /*---------------------------------------------------------------*/
425 /* Diagnose 270: Pseudo Timer Extended */
426 /*---------------------------------------------------------------*/
427 ARCH_DEP(pseudo_timer) (code, r1, r2, regs);
428 break;
429
430 case 0x274:
431 /*---------------------------------------------------------------*/
432 /* Diagnose 274: Set Timezone Interrupt Flag */
433 /*---------------------------------------------------------------*/
434 /* This function is implemented as a no-operation */
435 PTT(PTT_CL_ERR,"*DIAG274",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
436 regs->psw.cc = 0;
437 break;
438 #endif /*FEATURE_EMULATE_VM*/
439
440 #ifdef FEATURE_HERCULES_DIAGCALLS
441 case 0xF00:
442 /*---------------------------------------------------------------*/
443 /* Diagnose F00: Hercules normal mode */
444 /*---------------------------------------------------------------*/
445 /* If diag8cmd is not enabled then we are not allowed
446 * to manipulate the real machine i.e. hercules itself
447 */
448 if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
449 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
450
451 sysblk.inststep = 0;
452 SET_IC_TRACE;
453 break;
454
455 case 0xF04:
456 /*---------------------------------------------------------------*/
457 /* Diagnose F04: Hercules single step mode */
458 /*---------------------------------------------------------------*/
459 /* If diag8cmd is not enabled then we are not allowed
460 * to manipulate the real machine i.e. hercules itself
461 */
462 if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
463 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
464
465 sysblk.inststep = 1;
466 SET_IC_TRACE;
467 break;
468
469 case 0xF08:
470 /*---------------------------------------------------------------*/
471 /* Diagnose F08: Hercules get instruction counter */
472 /*---------------------------------------------------------------*/
473 regs->GR_L(r1) = (U32)INSTCOUNT(regs);
474 break;
475
476 case 0xF0C:
477 /*---------------------------------------------------------------*/
478 /* Diagnose F0C: Set/reset bad frame indicator */
479 /*---------------------------------------------------------------*/
480 /* If diag8cmd is not enabled then we are not allowed
481 * to manipulate the real machine i.e. hercules itself
482 */
483 if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
484 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
485
486 /* Load 4K block address from R2 register */
487 n = regs->GR_L(r2) & ADDRESS_MAXWRAP(regs);
488
489 /* Convert real address to absolute address */
490 n = APPLY_PREFIXING (n, regs->PX);
491
492 /* Addressing exception if block is outside main storage */
493 if ( n > regs->mainlim )
494 {
495 ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);
496 break;
497 }
498
499 /* Update the storage key from R1 register bit 31 */
500 STORAGE_KEY(n, regs) &= ~(STORKEY_BADFRM);
501 STORAGE_KEY(n, regs) |= regs->GR_L(r1) & STORKEY_BADFRM;
502
503 break;
504
505 case 0xF10:
506 /*---------------------------------------------------------------*/
507 /* Diagnose F10: Hercules CPU stop */
508 /*---------------------------------------------------------------*/
509 /* If diag8cmd is not enabled then we are not allowed
510 * to manipulate the real machine i.e. hercules itself
511 */
512 if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
513 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
514
515 regs->cpustate = CPUSTATE_STOPPING;
516 ON_IC_INTERRUPT(regs);
517 break;
518
519 #if defined(OPTION_DYNAMIC_LOAD)
520 case 0xF14:
521 /*---------------------------------------------------------------*/
522 /* Diagnose F14: Hercules DLL interface */
523 /*---------------------------------------------------------------*/
524 ARCH_DEP(diagf14_call) (r1, r2, regs);
525 break;
526 #endif /*defined(OPTION_DYNAMIC_LOAD)*/
527
528 #if !defined(NO_SIGABEND_HANDLER)
529 /* The following diagnose calls cause a exigent (non-repressible)
530 machine check, and are used for test purposes only *JJ */
531 case 0xFE8:
532 /*---------------------------------------------------------------*/
533 /* Diagnose FE8: Simulate Illegal Instruction */
534 /*---------------------------------------------------------------*/
535 raise(SIGILL);
536 break;
537
538 case 0xFEC:
539 /*---------------------------------------------------------------*/
540 /* Diagnose FEC: Simulate Floating Point Exception */
541 /*---------------------------------------------------------------*/
542 raise(SIGFPE);
543 break;
544
545 case 0xFF0:
546 /*---------------------------------------------------------------*/
547 /* Diagnose FF0: Simulate Segment Violation */
548 /*---------------------------------------------------------------*/
549 raise(SIGSEGV);
550 break;
551
552 case 0xFF4:
553 /*---------------------------------------------------------------*/
554 /* Diagnose FF4: Simulate BUS Error */
555 /*---------------------------------------------------------------*/
556 raise(SIGBUS);
557 break;
558
559 case 0xFF8:
560 /*---------------------------------------------------------------*/
561 /* Diagnose FF8: Simulate Loop */
562 /*---------------------------------------------------------------*/
563 while(1);
564 break;
565
566 case 0xFFC:
567 /*---------------------------------------------------------------*/
568 /* Diagnose FFC: Simulate Wait */
569 /*---------------------------------------------------------------*/
570 SLEEP(300);
571 break;
572 #endif /*!defined(NO_SIGABEND_HANDLER)*/
573
574 #endif /*FEATURE_HERCULES_DIAGCALLS*/
575
576
577 case 0x308:
578 /*---------------------------------------------------------------*/
579 /* Diagnose 308: IPL functions */
580 /*---------------------------------------------------------------*/
581 switch(r2) {
582 #ifdef FEATURE_PROGRAM_DIRECTED_REIPL
583 TID tid; /* Thread identifier */
584 char *ipltype; /* "ipl" or "iplc" */
585 case DIAG308_IPL_CLEAR:
586 ipltype = "iplc";
587 goto diag308_cthread;
588 case DIAG308_IPL_NORMAL:
589 ipltype = "ipl";
590 diag308_cthread:
591 if(create_thread(&tid, DETACHED, stop_cpus_and_ipl, ipltype, "Stop cpus and ipl"))
592 logmsg("HHCDN004E Error starting thread in diagnose 0x308: %s\n",
593 strerror(errno));
594 regs->cpustate = CPUSTATE_STOPPING;
595 ON_IC_INTERRUPT(regs);
596 break;
597 case DIAG308_SET_PARAM:
598 /* INCOMPLETE */
599 regs->GR(1) = DIAG308_RC_OK;
600 break;
601 case DIAG308_STORE_PARAM:
602 /* INCOMPLETE */
603 regs->GR(1) = DIAG308_RC_OK;
604 break;
605 #endif /*FEATURE_PROGRAM_DIRECTED_REIPL*/
606 default:
607 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
608 } /* end switch(r2) */
609 break;
610
611 default:
612 /*---------------------------------------------------------------*/
613 /* Diagnose xxx: Invalid function code */
614 /*---------------------------------------------------------------*/
615
616 if( HDC4(debug_diagnose, code, r1, r2, regs) )
617 return;
618
619 /* Power Off diagnose on 4361, 9371, 9373, 9375, 9377, 9221: */
620 /* */
621 /* DS 0H */
622 /* DC X'8302',S(SHUTDATA) MUST BE R0 AND R2 */
623 /* ... */
624 /* DS 0H */
625 /* SHUTDATA DC X'0000FFFF' MUST BE X'0000FFFF' */
626
627 if (0 == r1 && 2 == r2
628 && (sysblk.cpuid >> 56 & 0xFF) != 0xFF
629 && ((sysblk.cpuid >> 16 & 0xFFFF) == 0x4361
630 || (sysblk.cpuid >> 16 & 0xFFF9) == 0x9371 /* (937X) */
631 || (sysblk.cpuid >> 16 & 0xFFFF) == 0x9221)
632 )
633 {
634 if (0x0000FFFF == ARCH_DEP(vfetch4)(effective_addr2, b2, regs))
635 {
636 /* If diag8cmd is not enabled then we are not allowed
637 * to manipulate the real machine i.e. hercules itself
638 */
639 if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
640 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
641
642 regs->cpustate = CPUSTATE_STOPPING;
643 ON_IC_INTERRUPT(regs);
644
645 /* Release the configuration */
646 do_shutdown();
647
648 /* Power Off: exit hercules */
649 exit(0);
650 }
651 }
652
653 #if defined(FEATURE_S370_CHANNEL) && defined(OPTION_NOP_MODEL158_DIAGNOSE)
654 if((sysblk.cpuid >> 16 & 0xFFFF) != 0x0158)
655 #endif
656 ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
657 return;
658
659 } /* end switch(code) */
660
661 return;
662
663 } /* end function diagnose_call */
664
665
666 #if !defined(_GEN_ARCH)
667
668 #if defined(_ARCHMODE2)
669 #define _GEN_ARCH _ARCHMODE2
670 #include "diagnose.c"
671 #endif
672
673 #if defined(_ARCHMODE3)
674 #undef _GEN_ARCH
675 #define _GEN_ARCH _ARCHMODE3
676 #include "diagnose.c"
677 #endif
678
679 #endif /*!defined(_GEN_ARCH)*/
680