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