Example #1
0
/*-------------------------------------------------------------------*/
static int ARCH_DEP(display_real) (REGS *regs, RADR raddr, char *buf,
                                    int draflag)
{
RADR    aaddr;                          /* Absolute storage address  */
int     i, j;                           /* Loop counters             */
int     n = 0;                          /* Number of bytes in buffer */
char    hbuf[40];                       /* Hexadecimal buffer        */
BYTE    cbuf[17];                       /* Character buffer          */
BYTE    c;                              /* Character work area       */

#if defined(FEATURE_INTERVAL_TIMER)
    if(ITIMER_ACCESS(raddr,16))
        ARCH_DEP(store_int_timer)(regs);
#endif

    if (draflag)
    {
        n = sprintf (buf, "R:"F_RADR":", raddr);
    }

    aaddr = APPLY_PREFIXING (raddr, regs->PX);
    if (aaddr > regs->mainlim)
    {
        n += sprintf (buf+n, " Real address is not valid");
        return n;
    }

    n += sprintf (buf+n, "K:%2.2X=", STORAGE_KEY(aaddr, regs));

    memset (hbuf, SPACE, sizeof(hbuf));
    memset (cbuf, SPACE, sizeof(cbuf));

    for (i = 0, j = 0; i < 16; i++)
    {
        c = regs->mainstor[aaddr++];
        j += sprintf (hbuf+j, "%2.2X", c);
        if ((aaddr & 0x3) == 0x0) hbuf[j++] = SPACE;
        c = guest_to_host(c);
        if (!isprint(c)) c = '.';
        cbuf[i] = c;
        if ((aaddr & PAGEFRAME_BYTEMASK) == 0x000) break;
    } /* end for(i) */

    n += sprintf (buf+n, "%36.36s %16.16s", hbuf, cbuf);
    return n;

} /* end function display_real */
Example #2
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(load_main) (char *fname, RADR startloc)
{
int fd;
int len;
int rc = 0;
RADR pageaddr;
U32  pagesize;

    fd = HOPEN (fname, O_RDONLY|O_BINARY);
    if (fd < 0)
    {
        if(errno != ENOENT)
            WRMSG(HHC00600,"E",fname,"open()",strerror(errno));
        return fd;
    }

    pagesize = PAGEFRAME_PAGESIZE - (startloc & PAGEFRAME_BYTEMASK);
    pageaddr = startloc;

    for( ; ; ) {
        if (pageaddr >= sysblk.mainsize)
        {
            WRMSG(HHC00603, "W", fname);
            close(fd);
            return rc;
        }

        len = read(fd, sysblk.mainstor + pageaddr, pagesize);
        if (len > 0)
        {
            STORAGE_KEY(pageaddr, &sysblk) |= STORKEY_REF|STORKEY_CHANGE;
            rc += len;
        }

        if (len < (int)pagesize)
        {
            close(fd);
            return rc;
        }

        pageaddr += PAGEFRAME_PAGESIZE;
        pageaddr &= PAGEFRAME_PAGEMASK;
        pagesize  = PAGEFRAME_PAGESIZE;
    }

} /* end function load_main */
Example #3
0
/*-------------------------------------------------------------------*/
static void ARCH_DEP(alter_display_real) (char *opnd, REGS *regs)
{
U64     saddr, eaddr;                   /* Range start/end addresses */
U64     maxadr;                         /* Highest real storage addr */
RADR    raddr;                          /* Real storage address      */
RADR    aaddr;                          /* Absolute storage address  */
int     len;                            /* Number of bytes to alter  */
int     i;                              /* Loop counter              */
BYTE    newval[32];                     /* Storage alteration value  */
char    buf[100];                       /* Message buffer            */

    /* Set limit for address range */
  #if defined(FEATURE_ESAME)
    maxadr = 0xFFFFFFFFFFFFFFFFULL;
  #else /*!defined(FEATURE_ESAME)*/
    maxadr = 0x7FFFFFFF;
  #endif /*!defined(FEATURE_ESAME)*/

    /* Parse the range or alteration operand */
    len = parse_range (opnd, maxadr, &saddr, &eaddr, newval);
    if (len < 0) return;
    raddr = saddr;

    /* Alter real storage */
    if (len > 0)
    {
        for (i = 0; i < len && raddr+i <= regs->mainlim; i++)
        {
            aaddr = raddr + i;
            aaddr = APPLY_PREFIXING (aaddr, regs->PX);
            regs->mainstor[aaddr] = newval[i];
            STORAGE_KEY(aaddr, regs) |= (STORKEY_REF | STORKEY_CHANGE);
        } /* end for(i) */

    }

    /* Display real storage */
    for (i = 0; i < 999 && raddr <= eaddr; i++)
    {
        ARCH_DEP(display_real) (regs, raddr, buf, 1);
        logmsg ("%s\n", buf);
        raddr += 16;
    } /* end for(i) */

} /* end function alter_display_real */
Example #4
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(diag224_call) (int r1, int r2, REGS *regs)
{
RADR              abs;                 /* abs addr of data area      */
BYTE             *p;                   /* pointer to the data area   */
unsigned int      i;                   /* loop index                 */

//FIXME : this is probably incomplete.
//        see linux/arch/s390/hypfs/hypfs_diag.c
    UNREFERENCED(r1);

    abs = APPLY_PREFIXING (regs->GR_L(r2), regs->PX);

    /* Program check if data area is not on a page boundary */
    if ( (abs & PAGEFRAME_BYTEMASK) != 0x000)
        ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

    /* Program check if data area is outside main storage */
    if ( abs > regs->mainlim )
        ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);

    /* Point to DIAG 224 data area */
    p = regs->mainstor + abs;

    /* Mark page referenced */
    STORAGE_KEY(abs, regs) |= STORKEY_REF | STORKEY_CHANGE;

    /* First byte contains the number of entries - 1 */
    *p = 5;

    /* Clear the next 15 bytes */
    memset (p + 1, 0, 15);

    /* Set the 6 possible entries */
    p += 16;
    memcpy(p,diag224_cputable,sizeof(diag224_cputable)-1);

    /* Convert to EBCDIC */
    for (i = 0; i < sizeof(diag224_cputable); i++)
        p[i] = host_to_guest(p[i]);

} /* end function diag224_call */
Example #5
0
/*-------------------------------------------------------------------*/
static S64 ARCH_DEP(read_file)(char *fname, CREG sto, S64 seek, S64 size)
{
int fd, nread;
U64 totread = 0;

    fd = HOPEN (fname, O_RDONLY|O_BINARY);
    if (fd < 0)
    {
        if(errno != ENOENT)
            WRMSG (HHC00600, "E", fname, "open()", strerror(errno));
        return -1;
    }

    if(lseek(fd, (off_t)seek, SEEK_SET) == (off_t)seek)
    {
#if defined(FEATURE_ESAME)
        sto &= ASCE_TO;
#else /*!defined(FEATURE_ESAME)*/
        sto &= STD_STO;
#endif /*!defined(FEATURE_ESAME)*/

        for( ; size > 0 ; sto += sizeof(sto))
        {
#if defined(FEATURE_ESAME)
        DBLWRD *ste;
#else /*!defined(FEATURE_ESAME)*/
        FWORD *ste;
#endif /*!defined(FEATURE_ESAME)*/
        CREG pto, pti;

            /* Fetch segment table entry and calc Page Table Origin */
            if( sto >= sysblk.mainsize)
                goto eof;
#if defined(FEATURE_ESAME)
            ste = (DBLWRD*)(sysblk.mainstor + sto);
#else /*!defined(FEATURE_ESAME)*/
            ste = (FWORD*)(sysblk.mainstor + sto);
#endif /*!defined(FEATURE_ESAME)*/
            FETCH_W(pto, ste);
            STORAGE_KEY(sto, &sysblk) |= (STORKEY_REF);
            if( pto & SEGTAB_INVALID )
                goto eof;
#if defined(FEATURE_ESAME)
            pto &= ZSEGTAB_PTO;
#else /*!defined(FEATURE_ESAME)*/
            pto &= SEGTAB_PTO;
#endif /*!defined(FEATURE_ESAME)*/

            for(pti = 0; pti < 256 && size > 0; pti++, pto += sizeof(pto))
            {
#if defined(FEATURE_ESAME)
            DBLWRD *pte;
#else /*!defined(FEATURE_ESAME)*/
            FWORD *pte;
#endif /*!defined(FEATURE_ESAME)*/
            CREG pgo;
            BYTE *page;

                /* Fetch Page Table Entry to get page origin */
                if( pto >= sysblk.mainsize)
                    goto eof;
#if defined(FEATURE_ESAME)
                pte = (DBLWRD*)(sysblk.mainstor + pto);
#else /*!defined(FEATURE_ESAME)*/
                pte = (FWORD*)(sysblk.mainstor + pto);
#endif /*!defined(FEATURE_ESAME)*/
                FETCH_W(pgo, pte);
                STORAGE_KEY(pto, &sysblk) |= (STORKEY_REF);
                if( pgo & PAGETAB_INVALID )
                    goto eof;
#if defined(FEATURE_ESAME)
                pgo &= ZPGETAB_PFRA;
#else /*!defined(FEATURE_ESAME)*/
                pgo &= PAGETAB_PFRA;
#endif /*!defined(FEATURE_ESAME)*/

                /* Read page into main storage */
                if( pgo >= sysblk.mainsize)
                    goto eof;
                page = sysblk.mainstor + pgo;
                nread = read(fd, page, STORAGE_KEY_PAGESIZE);
                totread += nread;
                size -= nread;
                if( nread != STORAGE_KEY_PAGESIZE )
                    goto eof;
                STORAGE_KEY(pgo, &sysblk) |= (STORKEY_REF|STORKEY_CHANGE);
            }
        }
    }
eof:
    close(fd);
    return totread;
}
Example #6
0
/*-------------------------------------------------------------------*/
static S64 ARCH_DEP(write_file)(char *fname, int mode, CREG sto, S64 size)
{
int fd, nwrite;
U64 totwrite = 0;

    fd = HOPEN (fname, mode |O_WRONLY|O_BINARY,
            S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    if (fd < 0)
    {
        WRMSG (HHC00600, "E", fname, "open()", strerror(errno));
        return -1;
    }

#if defined(FEATURE_ESAME)
    sto &= ASCE_TO;
#else /*!defined(FEATURE_ESAME)*/
    sto &= STD_STO;
#endif /*!defined(FEATURE_ESAME)*/

    for( ; size > 0 ; sto += sizeof(sto))
    {
#if defined(FEATURE_ESAME)
    DBLWRD *ste;
#else /*!defined(FEATURE_ESAME)*/
    FWORD *ste;
#endif /*!defined(FEATURE_ESAME)*/
    CREG pto, pti;

        /* Fetch segment table entry and calc Page Table Origin */
        if( sto >= sysblk.mainsize)
            goto eof;
#if defined(FEATURE_ESAME)
        ste = (DBLWRD*)(sysblk.mainstor + sto);
#else /*!defined(FEATURE_ESAME)*/
        ste = (FWORD*)(sysblk.mainstor + sto);
#endif /*!defined(FEATURE_ESAME)*/
        FETCH_W(pto, ste);
        STORAGE_KEY(sto, &sysblk) |= (STORKEY_REF);
        if( pto & SEGTAB_INVALID )
            goto eof;
#if defined(FEATURE_ESAME)
        pto &= ZSEGTAB_PTO;
#else /*!defined(FEATURE_ESAME)*/
        pto &= SEGTAB_PTO;
#endif /*!defined(FEATURE_ESAME)*/

        for(pti = 0; pti < 256 && size > 0; pti++, pto += sizeof(pto))
        {
#if defined(FEATURE_ESAME)
        DBLWRD *pte;
#else /*!defined(FEATURE_ESAME)*/
        FWORD *pte;
#endif /*!defined(FEATURE_ESAME)*/
        CREG pgo;
        BYTE *page;

            /* Fetch Page Table Entry to get page origin */
            if( pto >= sysblk.mainsize)
                goto eof;

#if defined(FEATURE_ESAME)
            pte = (DBLWRD*)(sysblk.mainstor + pto);
#else /*!defined(FEATURE_ESAME)*/
            pte = (FWORD*)(sysblk.mainstor + pto);
#endif /*!defined(FEATURE_ESAME)*/
            FETCH_W(pgo, pte);
            STORAGE_KEY(pto, &sysblk) |= (STORKEY_REF);
            if( !(pgo & PAGETAB_INVALID) )
            {
#if defined(FEATURE_ESAME)
                pgo &= ZPGETAB_PFRA;
#else /*!defined(FEATURE_ESAME)*/
                pgo &= PAGETAB_PFRA;
#endif /*!defined(FEATURE_ESAME)*/

                /* Write page to SCE disk */
                if( pgo >= sysblk.mainsize)
                    goto eof;

                page = sysblk.mainstor + pgo;
                nwrite = write(fd, page, STORAGE_KEY_PAGESIZE);
                totwrite += nwrite;
                if( nwrite != STORAGE_KEY_PAGESIZE )
                    goto eof;

                STORAGE_KEY(pgo, &sysblk) |= (STORKEY_REF);
            }
            size -= STORAGE_KEY_PAGESIZE;
        }
    }
eof:
    close(fd);
    return totwrite;
}
Example #7
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(load_main) (char *fname, RADR startloc, int noisy)
{
U64 loaded;
RADR aaddr;
RADR pageaddr;
int fd;
size_t chunk;
int bytes;
time_t begtime, curtime;
char fmt_mem[8];

    fd = HOPEN (fname, O_RDONLY|O_BINARY);
    if (fd < 0)
    {
        if(errno != ENOENT)
            WRMSG(HHC00600,"E",fname,"open()",strerror(errno));
        return fd;
    }

    /* Calculate size of first chunk to reach page boundary */
    chunk = PAGEFRAME_PAGESIZE - (startloc & PAGEFRAME_BYTEMASK);
    aaddr = startloc;

    if (noisy)
    {
        loaded = 0;
        time( &begtime );
    }

    /* Read file into storage until end of file or end of storage */
    for( ; ; ) {

        bytes = read(fd, sysblk.mainstor + aaddr, chunk);

        /* Check for I/O error */
        if (bytes < 0)
        {
            // "SCE file %s: error in function %s: %s"
            WRMSG(HHC00600, "E", fname, "read()",strerror(errno));
            close(fd);
            return -1;
        }

        /* Check for end-of-file */
        if (bytes == 0)
        {
            close(fd);
            return 0;
        }

        /* Update the storage keys for all of the pages we just read */
        chunk = bytes;
        pageaddr = aaddr;

        for ( ; chunk > 0; chunk -= PAGEFRAME_PAGESIZE)
        {
            STORAGE_KEY(pageaddr, &sysblk) |= STORKEY_REF|STORKEY_CHANGE;
            pageaddr += PAGEFRAME_PAGESIZE;
        }

        aaddr += bytes;
        aaddr &= PAGEFRAME_PAGEMASK;

        /* Check if end of storge reached */
        if (aaddr >= sysblk.mainsize)
        {
            int rc;
            if (read(fd, &rc, 1) > 0)
            {
                rc = +1;
                if (noisy)
                {
                    // "SCE file %s: load main terminated at end of mainstor"
                    WRMSG(HHC00603, "W", fname);
                }
            }
            else /* ignore any error; we're at end of storage anyway */
                rc = 0;
            close(fd);
            return rc;
        }

        /* Issue periodic progress messages */
        if (noisy)
        {
            loaded += bytes;
            time( &curtime );

            if (difftime( curtime, begtime ) > 2.0)
            {
                begtime = curtime;
                // "%s bytes %s so far..."
                WRMSG( HHC02317, "I",
                    fmt_memsize_rounded( loaded, fmt_mem, sizeof( fmt_mem )),
                        "loaded" );
            }
        }

        chunk = (64 * 1024 * 1024);

        if (chunk > (sysblk.mainsize - aaddr))
            chunk = (sysblk.mainsize - aaddr);

    } /* end for( ; ; ) */

} /* end function load_main */
Example #8
0
/*-------------------------------------------------------------------*/
static void ARCH_DEP(external_interrupt) (int code, REGS *regs)
{
RADR    pfx;
PSA     *psa;
int     rc;

    PTT(PTT_CL_SIG,"*EXTINT",code,regs->cpuad,regs->psw.IA_L);

#if defined(_FEATURE_SIE)
    /* Set the main storage reference and change bits */
    if(SIE_MODE(regs)
#if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
                       && !SIE_FEATB(regs, S, EXP_TIMER)
#endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
#if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST)
                       && !SIE_FEATB(regs, EC0, EXTA)
#endif
                                                            )
    {
        /* Point to SIE copy of PSA in state descriptor */
        psa = (void*)(regs->hostregs->mainstor + SIE_STATE(regs) + SIE_IP_PSA_OFFSET);
        STORAGE_KEY(SIE_STATE(regs), regs->hostregs) |= (STORKEY_REF | STORKEY_CHANGE);
    }
    else
#endif /*defined(_FEATURE_SIE)*/
    {
        /* Point to PSA in main storage */
        pfx = regs->PX;
#if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
        SIE_TRANSLATE(&pfx, ACCTYPE_SIE, regs);
#endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
        psa = (void*)(regs->mainstor + pfx);
        STORAGE_KEY(pfx, regs) |= (STORKEY_REF | STORKEY_CHANGE);
    }

    /* Store the interrupt code in the PSW */
    regs->psw.intcode = code;


    /* Zero extcpuad field unless extcall or ems signal or blockio */
    if(code != EXT_EXTERNAL_CALL_INTERRUPT
#if defined(FEATURE_VM_BLOCKIO)
    && code != EXT_BLOCKIO_INTERRUPT
#endif /* defined(FEATURE_VM_BLOCKIO) */
    && code != EXT_EMERGENCY_SIGNAL_INTERRUPT)
        STORE_HW(psa->extcpad,0);

#if defined(FEATURE_BCMODE)
    /* For ECMODE, store external interrupt code at PSA+X'86' */
    if ( ECMODE(&regs->psw) )
#endif /*defined(FEATURE_BCMODE)*/
        STORE_HW(psa->extint,code);

    if ( !SIE_MODE(regs)
#if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
                       || SIE_FEATB(regs, S, EXP_TIMER)
#endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
#if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST)
                       || SIE_FEATB(regs, EC0, EXTA)
#endif
       )
    {
        /* Store current PSW at PSA+X'18' */
        ARCH_DEP(store_psw) (regs, psa->extold);

        /* Load new PSW from PSA+X'58' */
        rc = ARCH_DEP(load_psw) (regs, psa->extnew);

        if ( rc )
        {
            RELEASE_INTLOCK(regs);
            ARCH_DEP(program_interrupt)(regs, rc);
        }
    }

#if defined(FEATURE_INTERVAL_TIMER)
    /* Ensure the interval timer is uptodate */
    ARCH_DEP(store_int_timer_nolock) (regs);
#endif
    RELEASE_INTLOCK(regs);


    if ( SIE_MODE(regs)
#if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
                       && !SIE_FEATB(regs, S, EXP_TIMER)
#endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
#if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST)
                       && !SIE_FEATB(regs, EC0, EXTA)
#endif
       )
        longjmp (regs->progjmp, SIE_INTERCEPT_EXT);
    else
        longjmp (regs->progjmp, SIE_NO_INTERCEPT);

} /* end function external_interrupt */
Example #9
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(diagnose_call) (VADR effective_addr2, int b2,
                              int r1, int r2, REGS *regs)
{
#ifdef FEATURE_HERCULES_DIAGCALLS
U32   n;                                /* 32-bit operand value      */
#endif /*FEATURE_HERCULES_DIAGCALLS*/
U32   code;

    code = effective_addr2;

    switch(code) {


#if defined(FEATURE_IO_ASSIST)
    case 0x002:
    /*---------------------------------------------------------------*/
    /* Diagnose 002: Update Interrupt Interlock Control Bit in PMCW  */
    /*---------------------------------------------------------------*/

        ARCH_DEP(diagnose_002) (regs, r1, r2);

        break;
#endif


    case 0x01F:
    /*---------------------------------------------------------------*/
    /* Diagnose 01F: Power Off                                       */
    /*---------------------------------------------------------------*/

        /* If diag8cmd is not enabled then we are not allowed
         * to manipulate the real machine i.e. hercules itself
         */
        if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
            ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);

        /* The poweroff diagnose is only valid on the 9221 */
        if (sysblk.cpumodel != 0x9221
          /* and r1/r2 must contain C'POWEROFF' in EBCDIC */
          || regs->GR_L(r1) != 0xD7D6E6C5
          || regs->GR_L(r2) != 0xD9D6C6C6)
            ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

        regs->cpustate = CPUSTATE_STOPPING;
        ON_IC_INTERRUPT(regs);

        /* Release the configuration */
        do_shutdown();

        /* Power Off: exit hercules */
        exit(0);

#if defined(FEATURE_HYPERVISOR) || defined(FEATURE_EMULATE_VM)
    case 0x044:
    /*---------------------------------------------------------------*/
    /* Diagnose 044: Voluntary Time Slice End                        */
    /*---------------------------------------------------------------*/
        ARCH_DEP(scpend_call) ();
        break;
#endif


#ifdef FEATURE_MSSF_CALL
    case 0x080:
    /*---------------------------------------------------------------*/
    /* Diagnose 080: MSSF Call                                       */
    /*---------------------------------------------------------------*/
        regs->psw.cc = ARCH_DEP(mssf_call) (r1, r2, regs);
        break;
#endif /*FEATURE_MSSF_CALL*/


#if defined(FEATURE_HYPERVISOR) || defined(FEATURE_EMULATE_VM)
    case 0x09C:
    /*---------------------------------------------------------------*/
    /* Diagnose 09C: Voluntary Time Slice End With Target CPU        */
    /*---------------------------------------------------------------*/
        ARCH_DEP(scpend_call) ();   // (treat same as DIAG X'44')
        break;
#endif


#if defined(FEATURE_HYPERVISOR)
    case 0x204:
    /*---------------------------------------------------------------*/
    /* Diagnose 204: LPAR RMF Interface                              */
    /*---------------------------------------------------------------*/
        ARCH_DEP(diag204_call) (r1, r2, regs);
        regs->psw.cc = 0;
        break;

    case 0x224:
    /*---------------------------------------------------------------*/
    /* Diagnose 224: CPU Names                                       */
    /*---------------------------------------------------------------*/
        ARCH_DEP(diag224_call) (r1, r2, regs);
        regs->psw.cc = 0;
        break;
#endif /*defined(FEATURE_HYPERVISOR)*/

#if 0
    case 0x21C:
    /*---------------------------------------------------------------*/
    /* Diagnose 21C: ????                                            */
    /*---------------------------------------------------------------*/
        /*INCOMPLETE*/
        regs->psw.cc = 0;
        break;
#endif

#if 0
    case 0x288;:
    /*---------------------------------------------------------------*/
    /* Diagnose 288: Control Virtual Machine Time Bomb               */
    /*---------------------------------------------------------------*/
        regs->psw.cc = ARCH_DEP(vm_timebomb) (r1, r2, regs);
        break;
#endif

#ifdef FEATURE_EMULATE_VM
    case 0x000:
    /*---------------------------------------------------------------*/
    /* Diagnose 000: Store Extended Identification Code              */
    /*---------------------------------------------------------------*/
        ARCH_DEP(extid_call) (r1, r2, regs);
        break;

    case 0x008:
    /*---------------------------------------------------------------*/
    /* Diagnose 008: Virtual Console Function                        */
    /*---------------------------------------------------------------*/
        /* If diag8cmd is not enabled then we are not allowed
         * to manipulate the real machine i.e. hercules itself
         */
        if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
            ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);

        /* Process CP command and set condition code */
        regs->psw.cc = ARCH_DEP(cpcmd_call) (r1, r2, regs);
        break;

    case 0x00C:
    /*---------------------------------------------------------------*/
    /* Diagnose 00C: Pseudo Timer                                    */
    /*---------------------------------------------------------------*/
        ARCH_DEP(pseudo_timer) (code, r1, r2, regs);
        break;

    case 0x024:
    /*---------------------------------------------------------------*/
    /* Diagnose 024: Device Type and Features                        */
    /*---------------------------------------------------------------*/
        regs->psw.cc = ARCH_DEP(diag_devtype) (r1, r2, regs);
        break;

    case 0x05C:
    /*---------------------------------------------------------------*/
    /* Diagnose 05C: Error Message Editing                           */
    /*---------------------------------------------------------------*/
        /* This function is implemented as a no-operation */
        regs->psw.cc = 0;
        break;

    case 0x060:
    /*---------------------------------------------------------------*/
    /* Diagnose 060: Virtual Machine Storage Size                    */
    /*---------------------------------------------------------------*/
        /* Load main storage size in bytes into R1 register */
        regs->GR_L(r1) = regs->mainlim + 1;
        break;

    case 0x064:
    /*---------------------------------------------------------------*/
    /* Diagnose 064: Named Saved Segment Manipulation                */
    /*---------------------------------------------------------------*/
        /* Return code 44 cond code 2 means segment does not exist */
        regs->GR_L(r2) = 44;
        regs->psw.cc = 2;
        break;

    case 0x0A4:
    /*---------------------------------------------------------------*/
    /* Diagnose 0A4: Synchronous I/O (Standard CMS Blocksize)        */
    /*---------------------------------------------------------------*/
        regs->psw.cc = ARCH_DEP(syncblk_io) (r1, r2, regs);
//      logmsg ("Diagnose X\'0A4\': CC=%d, R15=%8.8X\n",      /*debug*/
//              regs->psw.cc, regs->GR_L(15));                 /*debug*/
        break;

    case 0x0A8:
    /*---------------------------------------------------------------*/
    /* Diagnose 0A8: Synchronous General I/O                         */
    /*---------------------------------------------------------------*/
        regs->psw.cc = ARCH_DEP(syncgen_io) (r1, r2, regs);
//      logmsg ("Diagnose X\'0A8\': CC=%d, R15=%8.8X\n",      /*debug*/
//              regs->psw.cc, regs->GR_L(15));                 /*debug*/
        break;

    case 0x0B0:
    /*---------------------------------------------------------------*/
    /* Diagnose 0B0: Access Re-IPL Data                              */
    /*---------------------------------------------------------------*/
        ARCH_DEP(access_reipl_data) (r1, r2, regs);
        break;

    case 0x0DC:
    /*---------------------------------------------------------------*/
    /* Diagnose 0DC: Control Application Monitor Record Collection   */
    /*---------------------------------------------------------------*/
        /* This function is implemented as a no-operation */
        regs->GR_L(r2) = 0;
        regs->psw.cc = 0;
        break;

    case 0x210:
    /*---------------------------------------------------------------*/
    /* Diagnose 210: Retrieve Device Information                     */
    /*---------------------------------------------------------------*/
        regs->psw.cc = ARCH_DEP(device_info) (r1, r2, regs);
        break;

    case 0x214:
    /*---------------------------------------------------------------*/
    /* Diagnose 214: Pending Page Release                            */
    /*---------------------------------------------------------------*/
        regs->psw.cc = ARCH_DEP(diag_ppagerel) (r1, r2, regs);
        break;


    case 0x220:
    /*---------------------------------------------------------------*/
    /* Diagnose 220: TOD Epoch                                       */
    /*---------------------------------------------------------------*/
        ODD_CHECK(r2, regs);

        switch(regs->GR_L(r1))
        {
            case 0:
                /* Obtain TOD features */
                regs->GR_L(r2)  =0xc0000000;
                regs->GR_L(r2+1)=0x00000000;
                break;
            case 1:
                /* Obtain TOD offset to real TOD in R2, R2+1 */
                regs->GR_L(r2)  = (regs->tod_epoch >> 24) & 0xFFFFFFFF;
                regs->GR_L(r2+1)= (regs->tod_epoch << 8) & 0xFFFFFFFF;
                break;
            default:
                ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
        }
        break;


    case 0x23C:
    /*---------------------------------------------------------------*/
    /* Diagnose 23C: Address Space Services                          */
    /*---------------------------------------------------------------*/
        /* This function is implemented as a no-operation */
        regs->GR_L(r2) = 0;
        break;


#if defined(FEATURE_VM_BLOCKIO)
    case 0x250:
    /*---------------------------------------------------------------*/
    /* Diagnose 250: Standardized Block I/O                          */
    /*---------------------------------------------------------------*/
        regs->psw.cc = ARCH_DEP(vm_blockio) (r1, r2, regs);
        break;
#endif /*defined(FEATURE_VM_BLOCKIO)*/


    case 0x260:
    /*---------------------------------------------------------------*/
    /* Diagnose 260: Access Certain Virtual Machine Information      */
    /*---------------------------------------------------------------*/
        ARCH_DEP(vm_info) (r1, r2, regs);
        break;

    case 0x264:
    /*---------------------------------------------------------------*/
    /* Diagnose 264: CP Communication                                */
    /*---------------------------------------------------------------*/
        /* This function is implemented as a no-operation */
        PTT_ERR("*DIAG264",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
        regs->psw.cc = 0;
        break;

    case 0x270:
    /*---------------------------------------------------------------*/
    /* Diagnose 270: Pseudo Timer Extended                           */
    /*---------------------------------------------------------------*/
        ARCH_DEP(pseudo_timer) (code, r1, r2, regs);
        break;

    case 0x274:
    /*---------------------------------------------------------------*/
    /* Diagnose 274: Set Timezone Interrupt Flag                     */
    /*---------------------------------------------------------------*/
        /* This function is implemented as a no-operation */
        PTT_ERR("*DIAG274",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
        regs->psw.cc = 0;
        break;
#endif /*FEATURE_EMULATE_VM*/


#ifdef FEATURE_PROGRAM_DIRECTED_REIPL
    case 0x308:
    /*---------------------------------------------------------------*/
    /* Diagnose 308: IPL functions                                   */
    /*---------------------------------------------------------------*/
        switch(r2)
        {
            TID   tid;                              /* Thread identifier         */
            char *ipltype;                          /* "ipl" or "iplc"           */
            int   rc;

        case DIAG308_IPL_CLEAR:
            ipltype = "iplc";
            goto diag308_cthread;
        case DIAG308_IPL_NORMAL:
            ipltype = "ipl";
        diag308_cthread:
            rc = create_thread(&tid, DETACHED, stop_cpus_and_ipl, ipltype, "Stop cpus and ipl");
            if(rc)
                WRMSG(HHC00102, "E", strerror(rc));
            regs->cpustate = CPUSTATE_STOPPING;
            ON_IC_INTERRUPT(regs);
            break;
        case DIAG308_SET_PARAM:
            /* INCOMPLETE */
            regs->GR(1) = DIAG308_RC_OK;
            break;
        case DIAG308_STORE_PARAM:
            /* INCOMPLETE */
            regs->GR(1) = DIAG308_RC_OK;
            break;
        default:
            ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
        } /* end switch(r2) */
        break;
#endif /*FEATURE_PROGRAM_DIRECTED_REIPL*/


#ifdef FEATURE_HERCULES_DIAGCALLS
    case 0xF00:
    /*---------------------------------------------------------------*/
    /* Diagnose F00: Hercules normal mode                            */
    /*---------------------------------------------------------------*/
        /* If diag8cmd is not enabled then we are not allowed
         * to manipulate the real machine i.e. hercules itself
         */
        if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
            ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);

        sysblk.inststep = 0;
        SET_IC_TRACE;
        break;

    case 0xF04:
    /*---------------------------------------------------------------*/
    /* Diagnose F04: Hercules single step mode                       */
    /*---------------------------------------------------------------*/
        /* If diag8cmd is not enabled then we are not allowed
         * to manipulate the real machine i.e. hercules itself
         */
        if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
            ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);

        sysblk.inststep = 1;
        SET_IC_TRACE;
        break;

    case 0xF08:
    /*---------------------------------------------------------------*/
    /* Diagnose F08: Hercules get instruction counter                */
    /*---------------------------------------------------------------*/
        regs->GR_L(r1) = (U32)INSTCOUNT(regs);
        break;

    case 0xF0C:
    /*---------------------------------------------------------------*/
    /* Diagnose F0C: Set/reset bad frame indicator                   */
    /*---------------------------------------------------------------*/
        /* If diag8cmd is not enabled then we are not allowed
         * to manipulate the real machine i.e. hercules itself
         */
        if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
            ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);

        /* Load 4K block address from R2 register */
        n = regs->GR_L(r2) & ADDRESS_MAXWRAP(regs);

        /* Convert real address to absolute address */
        n = APPLY_PREFIXING (n, regs->PX);

        /* Addressing exception if block is outside main storage */
        if ( n > regs->mainlim )
        {
            ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);
            break;
        }

        /* Update the storage key from R1 register bit 31 */
        STORAGE_KEY(n, regs) &= ~(STORKEY_BADFRM);
        STORAGE_KEY(n, regs) |= regs->GR_L(r1) & STORKEY_BADFRM;

        break;

    case 0xF10:
    /*---------------------------------------------------------------*/
    /* Diagnose F10: Hercules CPU stop                               */
    /*---------------------------------------------------------------*/
        /* If diag8cmd is not enabled then we are not allowed
         * to manipulate the real machine i.e. hercules itself
         */
        if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
            ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);

        regs->cpustate = CPUSTATE_STOPPING;
        ON_IC_INTERRUPT(regs);
        break;

#if defined(OPTION_DYNAMIC_LOAD)
    case 0xF14:
    /*---------------------------------------------------------------*/
    /* Diagnose F14: Hercules DLL interface                          */
    /*---------------------------------------------------------------*/
        ARCH_DEP(diagf14_call) (r1, r2, regs);
        break;
#endif /*defined(OPTION_DYNAMIC_LOAD)*/

#if defined(_FEATURE_HOST_RESOURCE_ACCESS_FACILITY)
    case 0xF18:
    /*---------------------------------------------------------------*/
    /* Diagnose F18: Hercules Access Host Resource                   */
    /*---------------------------------------------------------------*/
        ARCH_DEP(diagf18_call) (r1, r2, regs);
        break;
#endif /* defined(_FEATURE_HOST_RESOURCE_ACCESS_FACILITY) */

#if !defined(NO_SIGABEND_HANDLER)
    /* The following diagnose calls cause a exigent (non-repressible)
       machine check, and are used for test purposes only *JJ */
    case 0xFE8:
    /*---------------------------------------------------------------*/
    /* Diagnose FE8: Simulate Illegal Instruction                    */
    /*---------------------------------------------------------------*/
        raise(SIGILL);
        break;

    case 0xFEC:
    /*---------------------------------------------------------------*/
    /* Diagnose FEC: Simulate Floating Point Exception               */
    /*---------------------------------------------------------------*/
        raise(SIGFPE);
        break;

    case 0xFF0:
    /*---------------------------------------------------------------*/
    /* Diagnose FF0: Simulate Segment Violation                      */
    /*---------------------------------------------------------------*/
        CRASH();
        break;

    case 0xFF4:
    /*---------------------------------------------------------------*/
    /* Diagnose FF4: Simulate BUS Error                              */
    /*---------------------------------------------------------------*/
        raise(SIGBUS);
        break;

    case 0xFF8:
    /*---------------------------------------------------------------*/
    /* Diagnose FF8: Simulate Loop                                   */
    /*---------------------------------------------------------------*/
        while(1);
        /* (never reached) */

    case 0xFFC:
    /*---------------------------------------------------------------*/
    /* Diagnose FFC: Simulate Wait                                   */
    /*---------------------------------------------------------------*/
        SLEEP(300);
        break;
#endif /*!defined(NO_SIGABEND_HANDLER)*/

#endif /*FEATURE_HERCULES_DIAGCALLS*/


    default:
    /*---------------------------------------------------------------*/
    /* Diagnose xxx: Invalid function code                           */
    /*---------------------------------------------------------------*/

        if( HDC4(debug_diagnose, code, r1, r2, regs) )
            return;

        /* Power Off diagnose on 4361, 9371, 9373, 9375, 9377, 9221: */
        /*                                                           */
        /*          DS 0H                                            */
        /*          DC X'8302',S(SHUTDATA)     MUST BE R0 AND R2     */
        /*          ...                                              */
        /*          DS 0H                                            */
        /* SHUTDATA DC X'0000FFFF'             MUST BE X'0000FFFF'   */

        if (0 == r1 && 2 == r2
             && sysblk.cpuversion != 0xFF
             && (sysblk.cpumodel == 0x4361
              || (sysblk.cpumodel & 0xFFF9) == 0x9371   /* (937X) */
              || sysblk.cpumodel == 0x9221)
           )
        {
            if (0x0000FFFF == ARCH_DEP(vfetch4)(effective_addr2, b2, regs))
            {
                /* If diag8cmd is not enabled then we are not allowed
                 * to manipulate the real machine i.e. hercules itself
                 */
                if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE))
                    ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);

                regs->cpustate = CPUSTATE_STOPPING;
                ON_IC_INTERRUPT(regs);

                /* Release the configuration */
                do_shutdown();

                /* Power Off: exit hercules */
                exit(0);
            }
        }

#if defined(FEATURE_S370_CHANNEL) && defined(OPTION_NOP_MODEL158_DIAGNOSE)
        if (regs->cpumodel != 0x0158)
#endif
        ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
        return;

    } /* end switch(code) */

    return;

} /* end function diagnose_call */
Example #10
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(mssf_call) (int r1, int r2, REGS *regs)
{
U32     spccb_absolute_addr;            /* Absolute addr of SPCCB    */
U32     mssf_command;                   /* MSSF command word         */
U32               spccblen;            /* Length of SPCCB            */
SPCCB_HEADER      *spccb;              /* -> SPCCB header            */
SPCCB_CONFIG_INFO *spccbconfig;        /* -> SPCCB CONFIG info       */
SPCCB_CPU_INFO    *spccbcpu;           /* -> SPCCB CPU information   */
SPCCB_CHP_STATUS  *spccbchp;           /* -> SPCCB channel path info */
U16               offset;              /* Offset from start of SPCCB */
int               i;                   /* loop counter               */
DEVBLK            *dev;                /* Device block pointer       */

    /* R1 contains the real address of the SPCCB */
    spccb_absolute_addr = APPLY_PREFIXING (regs->GR_L(r1), regs->PX);

    /* R2 contains the service-processor-command word */
    mssf_command = regs->GR_L(r2);

    /* Program check if SPCCB is not on a doubleword boundary */
    if ( spccb_absolute_addr & 0x00000007 )
        ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

    /* Program check if SPCCB is outside main storage */
    if ( spccb_absolute_addr > regs->mainlim )
        ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);

//  /*debug*/logmsg("MSSF call %8.8X SPCCB=%8.8X\n",
//  /*debug*/       mssf_command, spccb_absolute_addr);

    /* Point to Service Processor Command Control Block */
    spccb = (SPCCB_HEADER*)(regs->mainstor + spccb_absolute_addr);

    /* Load SPCCB length from header */
    FETCH_HW(spccblen,spccb->length);

    /* Mark page referenced */
    STORAGE_KEY(spccb_absolute_addr, regs) |= STORKEY_REF;

    /* Program check if end of SPCCB falls outside main storage */
    if ( sysblk.mainsize - spccblen < spccb_absolute_addr )
        ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);

    /* Obtain the interrupt lock */
    OBTAIN_INTLOCK(regs);

    /* If a service signal is pending then we cannot process the request */
    if( IS_IC_SERVSIG && (sysblk.servparm & SERVSIG_ADDR)) {
        RELEASE_INTLOCK(regs);
        return 2;   /* Service Processor Busy */
    }

    if( spccb_absolute_addr & 0x7ffff800 ) {
        spccb->resp[0] = SPCCB_REAS_NOT2KALIGN;
        spccb->resp[1] = SPCCB_RESP_NOT2KALIGN;
    } else
        /* Test MSSF command word */
        switch (mssf_command) {

        case MSSF_READ_CONFIG_INFO:

            /* Set response code X'01F0' if SPCCB length
               is insufficient to contain CONFIG info */
            if ( spccblen < 64 )
            {
                spccb->resp[0] = SPCCB_REAS_BADLENGTH;
                spccb->resp[1] = SPCCB_RESP_BADLENGTH;
            break;
            }

            /* Point to SPCCB data area following SPCCB header */
            spccbconfig = (SPCCB_CONFIG_INFO*)(spccb+1);
            memset (spccbconfig, 0, sizeof(SPCCB_CONFIG_INFO));

            /* Set main storage size in SPCCB */
            spccbconfig->totstori = sysblk.mainsize >> 20;
            spccbconfig->storisiz = 1;
            spccbconfig->hex04 = 0x04;
            spccbconfig->hex01 = 0x01;

            /* Set CPU array count and offset in SPCCB */
            STORE_HW(spccbconfig->toticpu,sysblk.maxcpu);
            offset = sizeof(SPCCB_HEADER) + sizeof(SPCCB_CONFIG_INFO);
            STORE_HW(spccbconfig->officpu,offset);

            /* Set HSA array count and offset in SPCCB */
            STORE_HW(spccbconfig->tothsa,0);
            offset += (U16)(sizeof(SPCCB_CPU_INFO) * sysblk.maxcpu);
            STORE_HW(spccbconfig->offhsa,offset);

            /* Move IPL load parameter to SPCCB */
            get_loadparm (spccbconfig->loadparm);

            /* Build the CPU information array after the SCP info */
            spccbcpu = (SPCCB_CPU_INFO*)(spccbconfig+1);
            for (i = 0; i < sysblk.maxcpu; i++, spccbcpu++)
            {
                memset( spccbcpu, 0, sizeof(SPCCB_CPU_INFO) );
                spccbcpu->cpuaddr = i;
                spccbcpu->todid = 0;
            }

            /* Set response code X'0010' in SPCCB header */
            spccb->resp[0] = SPCCB_REAS_COMPLETE;
            spccb->resp[1] = SPCCB_RESP_COMPLETE;

            break;

        case MSSF_READ_CHP_STATUS:

            /* Set response code X'0300' if SPCCB length
               is insufficient to contain channel path info */
            if ( spccblen < sizeof(SPCCB_HEADER) + sizeof(SPCCB_CHP_STATUS))
            {
                spccb->resp[0] = SPCCB_REAS_BADLENGTH;
                spccb->resp[1] = SPCCB_RESP_BADLENGTH;
                break;
            }

            /* Point to SPCCB data area following SPCCB header */
            spccbchp = (SPCCB_CHP_STATUS*)(spccb+1);
            memset( spccbchp, 0, sizeof(SPCCB_CHP_STATUS) );

            /* Identify CHPIDs used */
            for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
            {
                for (i = 0; i < 8; i++)
                {
                    if( ((0x80 >> i) & dev->pmcw.pim) )
                    {
                    BYTE chpid;
                        chpid = dev->pmcw.chpid[i];
                        spccbchp->installed[chpid / 8] |= 0x80 >> (chpid % 8);
                        spccbchp->assigned[chpid / 8] |= 0x80 >> (chpid % 8);
                        spccbchp->configured[chpid / 8] |= 0x80 >> (chpid % 8);
                    }
               }
            }

            /* Set response code X'0010' in SPCCB header */
            spccb->resp[0] = SPCCB_REAS_COMPLETE;
            spccb->resp[1] = SPCCB_RESP_COMPLETE;

            break;

        default:
            PTT(PTT_CL_ERR,"*DIAG080",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
            /* Set response code X'06F0' for invalid MSSF command */
            spccb->resp[0] = SPCCB_REAS_UNASSIGNED;
            spccb->resp[1] = SPCCB_RESP_UNASSIGNED;

            break;

        } /* end switch(mssf_command) */

    /* Mark page changed */
    STORAGE_KEY(spccb_absolute_addr, regs) |= STORKEY_CHANGE;

    /* Set service signal external interrupt pending */
    sysblk.servparm &= ~SERVSIG_ADDR;
    sysblk.servparm |= spccb_absolute_addr;
    ON_IC_SERVSIG; 

    /* Release the interrupt lock */
    RELEASE_INTLOCK(regs);

    /* Return condition code 0: Command initiated */
    return 0;

} /* end function mssf_call */
Example #11
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(diag204_call) (int r1, int r2, REGS *regs)
{
DIAG204_HDR       *hdrinfo;            /* Header                     */
DIAG204_PART      *partinfo;           /* Partition info             */
DIAG204_PART_CPU  *cpuinfo;            /* CPU info                   */
#if defined(FEATURE_EXTENDED_DIAG204)
DIAG204_X_HDR      *hdrxinfo;          /* Header                     */
DIAG204_X_PART     *partxinfo;         /* Partition info             */
DIAG204_X_PART_CPU *cpuxinfo;          /* CPU info                   */
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/
RADR              abs;                 /* abs addr of data area      */
int               i;                   /* loop counter               */
struct rusage     usage;               /* RMF type data              */
ETOD              ETOD;                /* Extended TOD clock         */
U64               uCPU[MAX_CPU_ENGINES];    /* User CPU time    (us) */
U64               tCPU[MAX_CPU_ENGINES];    /* Total CPU time   (us) */

#if defined(FEATURE_PHYSICAL_DIAG204)
static BYTE       physical[8] =
              {0xD7,0xC8,0xE8,0xE2,0xC9,0xC3,0xC1,0xD3}; /* PHYSICAL */
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

#if defined(FEATURE_EXTENDED_DIAG204)
U64               oCPU[MAX_CPU_ENGINES];    /* Online CPU time  (us) */
U64               wCPU[MAX_CPU_ENGINES];    /* Wait CPU time    (us) */
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/

    /* Test DIAG204 command word */
    switch (regs->GR_L(r2)) {

    case 0x04:

        abs = APPLY_PREFIXING (GR_A(r1,regs), regs->PX);

        /* Program check if RMF data is not on a page boundary */
        if ( (abs & PAGEFRAME_BYTEMASK) != 0x000)
            ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

        /* Program check if RMF data area is outside main storage */
        if ( abs > regs->mainlim )
            ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);

        /* Point to DIAG 204 data area */
        hdrinfo = (DIAG204_HDR*)(regs->mainstor + abs);

        /* Mark page referenced */
        STORAGE_KEY(abs, regs) |= STORKEY_REF | STORKEY_CHANGE;

        /* Retrieve the TOD clock value */
        etod_clock(regs, &ETOD, ETOD_extended);

        /* Get processor time(s) and leave out non-CPU processes and
         * threads
         */
        for(i = 0; i < sysblk.maxcpu; ++i)
        {
            if (IS_CPU_ONLINE(i))
            {
                /* Get CPU times in microseconds */
                getrusage((int)sysblk.cputid[i], &usage);
                uCPU[i] = timeval2us(&usage.ru_utime);
                tCPU[i] = uCPU[i] + timeval2us(&usage.ru_stime);
            }
        }

        memset(hdrinfo, 0, sizeof(DIAG204_HDR));
        hdrinfo->numpart = 1;
#if defined(FEATURE_PHYSICAL_DIAG204)
        hdrinfo->flags = DIAG204_PHYSICAL_PRESENT;
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/
        STORE_HW(hdrinfo->physcpu,sysblk.cpus);
        STORE_HW(hdrinfo->offown,sizeof(DIAG204_HDR));
        STORE_DW(hdrinfo->diagstck,ETOD2tod(ETOD));

        /* hercules partition */
        partinfo = (DIAG204_PART*)(hdrinfo + 1);
        memset(partinfo, 0, sizeof(DIAG204_PART));
        partinfo->partnum = sysblk.lparnum;     /* Hercules partition */
        partinfo->virtcpu = sysblk.cpus;
        get_lparname(partinfo->partname);

        /* hercules cpu's */
        cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU));
              STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuinfo->index=sysblk.ptyp[i];
              STORE_HW(cpuinfo->weight,100);
              STORE_DW(cpuinfo->totdispatch,tCPU[i]);
              STORE_DW(cpuinfo->effdispatch, uCPU[i]);
              cpuinfo += 1;
          }

#if defined(FEATURE_PHYSICAL_DIAG204)
        /* LPAR management */
        /* FIXME: This section should report on the real CPUs, appearing
         *        and transformed for reporting purposes. This should
         *        also be properly reflected in STSI information.
         */
        partinfo = (DIAG204_PART*)cpuinfo;
        memset(partinfo, 0, sizeof(DIAG204_PART));
        partinfo->partnum = 0; /* Physical machine */
        partinfo->virtcpu = sysblk.cpus;
        memcpy(partinfo->partname,physical,sizeof(physical));

        /* report all emulated physical cpu's */
        cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU));
              STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuinfo->weight,100);
              STORE_DW(cpuinfo->totdispatch, tCPU[i]);
              STORE_DW(cpuinfo->effdispatch, uCPU[i]);
              cpuinfo += 1;
          }
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

        regs->GR_L(r2) = 0;

        break;

#if defined(FEATURE_EXTENDED_DIAG204)
    /* Extended subcode 5 returns the size of the data areas provided by extended subcodes 6 and 7 */
    case 0x00010005:
        i = sizeof(DIAG204_X_HDR) + ((sizeof(DIAG204_X_PART) + (sysblk.maxcpu * sizeof(DIAG204_X_PART_CPU))) * 2);
        regs->GR_L(r2+1) = (i + PAGEFRAME_BYTEMASK) / PAGEFRAME_PAGESIZE;
        regs->GR_L(r2) = 0;

        break;

    /* Provide extended information */
    case 0x00010006:
        /* We fall through as we do not have any secondary cpus (that we know of) */

    /* Provide extended information, including information about secondary CPUs */
    case 0x00010007:
        /* Program check if RMF data is not on a page boundary */
        if ( (regs->GR_L(r1) & PAGEFRAME_BYTEMASK) != 0x000)
            ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

        /* Obtain absolute address of main storage block,
           check protection, and set reference and change bits */
        hdrxinfo = (DIAG204_X_HDR*)MADDR (GR_A(r1,regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey);

        /* Retrieve the TOD clock value */
        etod_clock(regs, &ETOD, ETOD_extended);

        /* Get processor time(s) and leave out non-CPU processes and
         * threads
         */
        for(i = 0; i < sysblk.maxcpu; ++i)
        {
            if (IS_CPU_ONLINE(i))
            {
                /* Get CPU times in microseconds */
                getrusage((int)sysblk.cputid[i], &usage);
                oCPU[i] = etod2us(ETOD.high - regs->tod_epoch - sysblk.cpucreateTOD[i]);
                uCPU[i] = timeval2us(&usage.ru_utime);
                tCPU[i] = uCPU[i] + timeval2us(&usage.ru_stime);
                wCPU[i] = tCPU[i] - uCPU[i];
            }
        }

        memset(hdrxinfo, 0, sizeof(DIAG204_X_HDR));
        hdrxinfo->numpart = 1;
#if defined(FEATURE_PHYSICAL_DIAG204)
        hdrxinfo->flags = DIAG204_X_PHYSICAL_PRESENT;
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/
        STORE_HW(hdrxinfo->physcpu,sysblk.cpus);
        STORE_HW(hdrxinfo->offown,sizeof(DIAG204_X_HDR));
        STORE_DW(hdrxinfo->diagstck1,ETOD.high);
        STORE_DW(hdrxinfo->diagstck2,ETOD.low);

        /* hercules partition */
        partxinfo = (DIAG204_X_PART*)(hdrxinfo + 1);
        memset(partxinfo, 0, sizeof(DIAG204_PART));
        partxinfo->partnum = sysblk.lparnum;    /* Hercules partition */
        partxinfo->virtcpu = sysblk.cpus;
        get_lparname(partxinfo->partname);
        get_sysname(partxinfo->cpcname);
        get_systype(partxinfo->osname);
        STORE_DW(partxinfo->cssize,sysblk.mainsize);
        STORE_DW(partxinfo->essize,sysblk.xpndsize);
        get_sysplex(partxinfo->gr_name);

        /* hercules cpu's */
        cpuxinfo = (DIAG204_X_PART_CPU*)(partxinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU));
              STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuxinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuxinfo->weight,100);

              STORE_DW(cpuxinfo->totdispatch, tCPU[i]);
              STORE_DW(cpuxinfo->effdispatch, uCPU[i]);

              STORE_HW(cpuxinfo->minweight,1000);
              STORE_HW(cpuxinfo->curweight,1000);
              STORE_HW(cpuxinfo->maxweight,1000);

              STORE_DW(cpuxinfo->onlinetime, oCPU[i]);
              STORE_DW(cpuxinfo->waittime,   wCPU[i]);

              STORE_HW(cpuxinfo->pmaweight,1000);
              STORE_HW(cpuxinfo->polarweight,1000);

              cpuxinfo += 1;
          }


#if defined(FEATURE_PHYSICAL_DIAG204)
        /* LPAR management */
        /* FIXME: This section should report on the real CPUs, appearing
         *        and transformed for reporting purposes. This should
         *        also be properly reflected in STSI information.
         */
        partxinfo = (DIAG204_X_PART*)cpuxinfo;
        memset(partxinfo, 0, sizeof(DIAG204_X_PART));
        partxinfo->partnum = 0; /* Physical machine */
        partxinfo->virtcpu = sysblk.cpus;
        memcpy(partxinfo->partname,physical,sizeof(physical));

        /* report all emulated physical cpu's */
        cpuxinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU));
              STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuxinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuxinfo->weight,100);

              STORE_DW(cpuxinfo->totdispatch, tCPU[i]);
              STORE_DW(cpuxinfo->effdispatch, uCPU[i]);

              STORE_HW(cpuxinfo->minweight,1000);
              STORE_HW(cpuxinfo->curweight,1000);
              STORE_HW(cpuxinfo->maxweight,1000);

              STORE_DW(cpuxinfo->onlinetime, oCPU[i]);
              STORE_DW(cpuxinfo->waittime,   wCPU[i]);

              STORE_HW(cpuxinfo->pmaweight,1000);
              STORE_HW(cpuxinfo->polarweight,1000);

              cpuxinfo += 1;
          }
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

        regs->GR_L(r2) = 0;

        break;
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/

    default:
        PTT_ERR("*DIAG204",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
        regs->GR_L(r2) = 4;

    } /*switch(regs->GR_L(r2))*/

} /* end function diag204_call */
Example #12
0
void ARCH_DEP(sync_mck_interrupt) (REGS *regs)
{
int     rc;                             /* Return code               */
PSA    *psa;                            /* -> Prefixed storage area  */

U64     mcic = MCIC_P  |  /* Instruction processing damage */
               MCIC_WP |
               MCIC_MS |
               MCIC_PM |
               MCIC_IA |
#ifdef FEATURE_HEXADECIMAL_FLOATING_POINT
               MCIC_FP |
#endif /*FEATURE_HEXADECIMAL_FLOATING_POINT*/
               MCIC_GR |
               MCIC_CR |
               MCIC_ST |
#ifdef FEATURE_ACCESS_REGISTERS
               MCIC_AR |
#endif /*FEATURE_ACCESS_REGISTERS*/
#if defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)
               MCIC_PR |
#endif /*defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)*/
#if defined(FEATURE_BINARY_FLOATING_POINT)
               MCIC_XF |
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
               MCIC_CT |
               MCIC_CC ;
U32     xdmg = 0;
RADR    fsta = 0;


    /* Release intlock if held */
    if (regs->cpuad == sysblk.intowner)
        RELEASE_INTLOCK(regs);

    /* Release mainlock if held */
    if (regs->cpuad == sysblk.mainowner)
        RELEASE_MAINLOCK(regs);

    /* Exit SIE when active */
#if defined(FEATURE_INTERPRETIVE_EXECUTION)
    if(regs->sie_active)
        ARCH_DEP(sie_exit) (regs, SIE_HOST_INTERRUPT);
#endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/


    /* Set the main storage reference and change bits */
    STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE);

    /* Point to the PSA in main storage */
    psa = (void*)(regs->mainstor + regs->PX);

    /* Store registers in machine check save area */
    ARCH_DEP(store_status) (regs, regs->PX);

#if !defined(FEATURE_ESAME)
// ZZ
    /* Set the extended logout area to zeros */
    memset(psa->storepsw, 0, 16);
#endif

    /* Store the machine check interrupt code at PSA+232 */
    STORE_DW(psa->mckint, mcic);

    /* Trace the machine check interrupt */
    if (CPU_STEPPING_OR_TRACING(regs, 0))
#if defined(_FEATURE_SIE)
        WRMSG (HHC00824, "I", regs->sie_active ? "IE" : PTYPSTR(regs->cpuad),
            regs->sie_active ? regs->guestregs->cpuad : regs->cpuad, mcic);
#else
        WRMSG (HHC00824, "I", PTYPSTR(regs->cpuad), regs->cpuad, mcic);
#endif

    /* Store the external damage code at PSA+244 */
    STORE_FW(psa->xdmgcode, xdmg);

#if defined(FEATURE_ESAME)
    /* Store the failing storage address at PSA+248 */
    STORE_DW(psa->mcstorad, fsta);
#else /*!defined(FEATURE_ESAME)*/
    /* Store the failing storage address at PSA+248 */
    STORE_FW(psa->mcstorad, fsta);
#endif /*!defined(FEATURE_ESAME)*/

    /* Store current PSW at PSA+X'30' */
    ARCH_DEP(store_psw) ( regs, psa->mckold );

    /* Load new PSW from PSA+X'70' */
    rc = ARCH_DEP(load_psw) ( regs, psa->mcknew );

    if ( rc )
        ARCH_DEP(program_interrupt) (regs, rc);
} /* end function sync_mck_interrupt */
Example #13
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(load_ipl) (U16 lcss, U16 devnum, int cpu, int clear)
{
REGS   *regs;                           /* -> Regs                   */
DEVBLK *dev;                            /* -> Device control block   */
int     i;                              /* Array subscript           */
BYTE    unitstat;                       /* IPL device unit status    */
BYTE    chanstat;                       /* IPL device channel status */

    /* Get started */
    if (ARCH_DEP(common_load_begin) (cpu, clear) != 0)
        return -1;

    /* The actual IPL proper starts here... */

    regs = sysblk.regs[cpu];    /* Point to IPL CPU's registers */

    /* Point to the device block for the IPL device */
    dev = find_device_by_devnum (lcss,devnum);
    if (dev == NULL)
    {
        logmsg (_("HHCCP027E Device %4.4X not in configuration%s\n"),
                devnum,
                (sysblk.arch_mode == ARCH_370 ?
                  " or not conneceted to channelset" : ""));
        HDC1(debug_cpu_state, regs);
        return -1;
    }
#if defined(OPTION_IPLPARM)
    if(sysblk.haveiplparm)
    {
        for(i=0;i<16;i++)
        {
            regs->GR_L(i)=fetch_fw(&sysblk.iplparmstring[i*4]);
        }
        sysblk.haveiplparm=0;
    }
#endif

    /* Set Main Storage Reference and Update bits */
    STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE);
    sysblk.main_clear = sysblk.xpnd_clear = 0;

    /* Build the IPL CCW at location 0 */
    regs->psa->iplpsw[0] = 0x02;              /* CCW command = Read */
    regs->psa->iplpsw[1] = 0;                 /* Data address = zero */
    regs->psa->iplpsw[2] = 0;
    regs->psa->iplpsw[3] = 0;
    regs->psa->iplpsw[4] = CCW_FLAGS_CC | CCW_FLAGS_SLI;
                                        /* CCW flags */
    regs->psa->iplpsw[5] = 0;                 /* Reserved byte */
    regs->psa->iplpsw[6] = 0;                 /* Byte count = 24 */
    regs->psa->iplpsw[7] = 24;

    /* Enable the subchannel for the IPL device */
    dev->pmcw.flag5 |= PMCW5_E;

    /* Build the operation request block */                    /*@IWZ*/
    memset (&dev->orb, 0, sizeof(ORB));                        /*@IWZ*/
    dev->busy = 1;

    RELEASE_INTLOCK(NULL);

    /* Execute the IPL channel program */
    ARCH_DEP(execute_ccw_chain) (dev);

    OBTAIN_INTLOCK(NULL);

    /* Clear the interrupt pending and device busy conditions */
    obtain_lock (&sysblk.iointqlk);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->ioint);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->pciioint);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->attnioint);
    release_lock(&sysblk.iointqlk);
    dev->busy = 0;
    dev->scsw.flag2 = 0;
    dev->scsw.flag3 = 0;

    /* Check that load completed normally */
#ifdef FEATURE_S370_CHANNEL
    unitstat = dev->csw[4];
    chanstat = dev->csw[5];
#endif /*FEATURE_S370_CHANNEL*/

#ifdef FEATURE_CHANNEL_SUBSYSTEM
    unitstat = dev->scsw.unitstat;
    chanstat = dev->scsw.chanstat;
#endif /*FEATURE_CHANNEL_SUBSYSTEM*/

    if (unitstat != (CSW_CE | CSW_DE) || chanstat != 0) {
        logmsg (_("HHCCP029E %s mode IPL failed: CSW status=%2.2X%2.2X\n"
                  "           Sense="),
                get_arch_mode_string(regs), unitstat, chanstat);
        for (i=0; i < (int)dev->numsense; i++)
        {
            logmsg ("%2.2X", dev->sense[i]);
            if ((i & 3) == 3) logmsg(" ");
        }
        logmsg ("\n");
        HDC1(debug_cpu_state, regs);
        return -1;
    }

#ifdef FEATURE_S370_CHANNEL
    /* Test the EC mode bit in the IPL PSW */
    if (regs->psa->iplpsw[1] & 0x08) {
        /* In EC mode, store device address at locations 184-187 */
        STORE_FW(regs->psa->ioid, dev->devnum);
    } else {
        /* In BC mode, store device address at locations 2-3 */
        STORE_HW(regs->psa->iplpsw + 2, dev->devnum);
    }
#endif /*FEATURE_S370_CHANNEL*/

#ifdef FEATURE_CHANNEL_SUBSYSTEM
    /* Set LPUM */
    dev->pmcw.lpum = 0x80;
    STORE_FW(regs->psa->ioid, (dev->ssid<<16)|dev->subchan);

    /* Store zeroes at locations 188-191 */
    memset (regs->psa->ioparm, 0, 4);
#endif /*FEATURE_CHANNEL_SUBSYSTEM*/

    /* Save IPL device number, cpu number and lcss */
    sysblk.ipldev = devnum;
    sysblk.iplcpu = regs->cpuad;
    sysblk.ipllcss = lcss;

    /* Finish up... */
    return ARCH_DEP(common_load_finish) (regs);
} /* end function load_ipl */
Example #14
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(store_status) (REGS *ssreg, RADR aaddr)
{
int     i;                              /* Array subscript           */
PSA     *sspsa;                         /* -> Store status area      */

    /* Set reference and change bits */
    STORAGE_KEY(aaddr, ssreg) |= (STORKEY_REF | STORKEY_CHANGE);
#if defined(FEATURE_ESAME)
    /* The ESAME PSA is two pages in size */
    if(!aaddr)
        STORAGE_KEY(aaddr + 4096, ssreg) |= (STORKEY_REF | STORKEY_CHANGE);
#endif /*defined(FEATURE_ESAME)*/

#if defined(FEATURE_ESAME)
    /* For store status at address, we must adjust the PSA offset */
    /* ZZ THIS TEST IS NOT CONCLUSIVE */
    if(aaddr != 0 && aaddr != ssreg->PX)
        aaddr -= 512 + 4096 ;
#endif

    aaddr &= 0x7FFFFE00;

    /* Point to the PSA into which status is to be stored */
    sspsa = (void*)(ssreg->mainstor + aaddr);

    /* Store CPU timer in bytes 216-223 */
    STORE_DW(sspsa->storeptmr, cpu_timer(ssreg));

    /* Store clock comparator in bytes 224-231 */
#if defined(FEATURE_ESAME)
    STORE_DW(sspsa->storeclkc, ssreg->clkc);
#else /*defined(FEATURE_ESAME)*/
    STORE_DW(sspsa->storeclkc, ssreg->clkc << 8);
#endif /*defined(FEATURE_ESAME)*/

    /* Store PSW in bytes 256-263 */
    ARCH_DEP(store_psw) (ssreg, sspsa->storepsw);

    /* Store prefix register in bytes 264-267 */
    STORE_FW(sspsa->storepfx,ssreg->PX);

#if defined(FEATURE_ESAME)
    /* Store Floating Point Control Register */
    STORE_FW(sspsa->storefpc,ssreg->fpc);

    /* Store TOD Programable register */
    STORE_FW(sspsa->storetpr,ssreg->todpr);
#endif /*defined(FEATURE_ESAME)*/

#if defined(_900)
    /* Only store the arch mode indicator for a PSA type store status */
    if(!aaddr)
#if defined(FEATURE_ESAME)
        sspsa->arch = 1;
#else /*defined(FEATURE_ESAME)*/
        sspsa->arch = 0;
#endif /*defined(FEATURE_ESAME)*/
#endif /*defined(_900)*/

    /* Store access registers in bytes 288-351 */
    for (i = 0; i < 16; i++)
        STORE_FW(sspsa->storear[i],ssreg->AR(i));

    /* Store floating-point registers in bytes 352-383 */
#if defined(FEATURE_ESAME)
    for (i = 0; i < 32; i++)
#else /*!defined(FEATURE_ESAME)*/
    for (i = 0; i < 8; i++)
#endif /*!defined(FEATURE_ESAME)*/
        STORE_FW(sspsa->storefpr[i],ssreg->fpr[i]);

    /* Store general-purpose registers in bytes 384-447 */
    for (i = 0; i < 16; i++)
        STORE_W(sspsa->storegpr[i],ssreg->GR(i));

    /* Store control registers in bytes 448-511 */
    for (i = 0; i < 16; i++)
        STORE_W(sspsa->storecr[i],ssreg->CR(i));

} /* end function store_status */
Example #15
0
/*-------------------------------------------------------------------*/
static void ARCH_DEP(alter_display_virt) (char *opnd, REGS *regs)
{
U64     saddr, eaddr;                   /* Range start/end addresses */
U64     maxadr;                         /* Highest virt storage addr */
VADR    vaddr;                          /* Virtual storage address   */
RADR    raddr;                          /* Real storage address      */
RADR    aaddr;                          /* Absolute storage address  */
int     stid;                           /* Segment table indication  */
int     len;                            /* Number of bytes to alter  */
int     i;                              /* Loop counter              */
int     n;                              /* Number of bytes in buffer */
int     arn = 0;                        /* Access register number    */
U16     xcode;                          /* Exception code            */
BYTE    newval[32];                     /* Storage alteration value  */
char    buf[100];                       /* Message buffer            */

    /* Set limit for address range */
  #if defined(FEATURE_ESAME)
    maxadr = 0xFFFFFFFFFFFFFFFFULL;
  #else /*!defined(FEATURE_ESAME)*/
    maxadr = 0x7FFFFFFF;
  #endif /*!defined(FEATURE_ESAME)*/

    while((opnd && *opnd != '\0') &&
      (*opnd == ' ' || *opnd == '\t'))
        opnd++;

    switch(toupper(*opnd))
    {
        case 'P': /* primary */
          arn = USE_PRIMARY_SPACE;
          opnd++;
          break;
        case 'S': /* secondary */
          arn = USE_SECONDARY_SPACE;
          opnd++;
          break;
        case 'H': /* home */
          arn = USE_HOME_SPACE;
          opnd++;
          break;
    }

    /* Parse the range or alteration operand */
    len = parse_range (opnd, maxadr, &saddr, &eaddr, newval);
    if (len < 0) return;
    vaddr = saddr;

    /* Alter virtual storage */
    if (len > 0
        && ARCH_DEP(virt_to_abs) (&raddr, &stid, vaddr, arn,
                                   regs, ACCTYPE_LRA) == 0
        && ARCH_DEP(virt_to_abs) (&raddr, &stid, eaddr, arn,
                                   regs, ACCTYPE_LRA) == 0)
    {
        for (i = 0; i < len && raddr+i <= regs->mainlim; i++)
        {
            ARCH_DEP(virt_to_abs) (&raddr, &stid, vaddr+i, arn,
                                    regs, ACCTYPE_LRA);
            aaddr = APPLY_PREFIXING (raddr, regs->PX);
            regs->mainstor[aaddr] = newval[i];
            STORAGE_KEY(aaddr, regs) |= (STORKEY_REF | STORKEY_CHANGE);
        } /* end for(i) */
    }

    /* Display virtual storage */
    for (i = 0; i < 999 && vaddr <= eaddr; i++)
    {
        if (i == 0 || (vaddr & PAGEFRAME_BYTEMASK) < 16)
        {
            xcode = ARCH_DEP(virt_to_abs) (&raddr, &stid, vaddr, arn,
                                            regs, ACCTYPE_LRA);
            n = sprintf (buf, "V:"F_VADR" ", vaddr);
            if (REAL_MODE(&regs->psw))
                n += sprintf (buf+n, "(dat off)");
            else if (stid == TEA_ST_PRIMARY)
                n += sprintf (buf+n, "(primary)");
            else if (stid == TEA_ST_SECNDRY)
                n += sprintf (buf+n, "(secondary)");
            else if (stid == TEA_ST_HOME)
                n += sprintf (buf+n, "(home)");
            else
                n += sprintf (buf+n, "(AR%2.2d)", arn);
            if (xcode == 0)
                n += sprintf (buf+n, " R:"F_RADR, raddr);
            logmsg ("%s\n", buf);
        }
        ARCH_DEP(display_virt) (regs, vaddr, buf, arn, ACCTYPE_LRA);
        logmsg ("%s\n", buf);
        vaddr += 16;
    } /* end for(i) */

} /* end function alter_display_virt */
Example #16
0
/*-------------------------------------------------------------------*/
static void ARCH_DEP(hwl_loadfile)(SCCB_HWL_BK *hwl_bk)
{
CREG sto;
U32  size;
int fd;

    fd = open (hwl_fn[hwl_bk->file], O_RDONLY|O_BINARY);
    if (fd < 0)
    {
        logmsg (_("HHCHL002I %s open error: %s\n"),
            hwl_fn[hwl_bk->file], strerror(errno));
        return;
    }
//  else
//      logmsg(_("HHCHL004I Loading %s\n"),hwl_fn[hwl_bk->file]);

    FETCH_FW(size,hwl_bk->size);

    /* Segment Table Origin */
    FETCH_DW(sto,hwl_bk->sto);
#if defined(FEATURE_ESAME)
    sto &= ASCE_TO;
#else /*!defined(FEATURE_ESAME)*/
    sto &= STD_STO;
#endif /*!defined(FEATURE_ESAME)*/

    for( ; ; sto += sizeof(sto))
    {
#if defined(FEATURE_ESAME)
    DBLWRD *ste;
#else /*!defined(FEATURE_ESAME)*/
    FWORD *ste;
#endif /*!defined(FEATURE_ESAME)*/
    CREG pto, pti;

        /* Fetch segment table entry and calculate Page Table Origin */
        if( sto >= sysblk.mainsize)
            goto eof;
#if defined(FEATURE_ESAME)
        ste = (DBLWRD*)(sysblk.mainstor + sto);
#else /*!defined(FEATURE_ESAME)*/
        ste = (FWORD*)(sysblk.mainstor + sto);
#endif /*!defined(FEATURE_ESAME)*/
        FETCH_W(pto, ste);
        if( pto & SEGTAB_INVALID )
            goto eof;
#if defined(FEATURE_ESAME)
        pto &= ZSEGTAB_PTO;
#else /*!defined(FEATURE_ESAME)*/
        pto &= SEGTAB_PTO;
#endif /*!defined(FEATURE_ESAME)*/

        for(pti = 0; pti < 256 ; pti++, pto += sizeof(pto))
        {
#if defined(FEATURE_ESAME)
        DBLWRD *pte;
#else /*!defined(FEATURE_ESAME)*/
        FWORD *pte;
#endif /*!defined(FEATURE_ESAME)*/
        CREG pgo;
        BYTE *page;

            /* Fetch Page Table Entry to get page origin */
            if( pto >= sysblk.mainsize)
                goto eof;
#if defined(FEATURE_ESAME)
            pte = (DBLWRD*)(sysblk.mainstor + pto);
#else /*!defined(FEATURE_ESAME)*/
            pte = (FWORD*)(sysblk.mainstor + pto);
#endif /*!defined(FEATURE_ESAME)*/
            FETCH_W(pgo, pte);
            if( pgo & PAGETAB_INVALID )
                goto eof;
#if defined(FEATURE_ESAME)
            pgo &= ZPGETAB_PFRA;
#else /*!defined(FEATURE_ESAME)*/
            pgo &= PAGETAB_PFRA;
#endif /*!defined(FEATURE_ESAME)*/

            /* Read page into main storage */
            if( pgo >= sysblk.mainsize)
                goto eof;
            page = sysblk.mainstor + pgo;
            if( !(size--) || !read(fd, page, STORAGE_KEY_PAGESIZE) ) 
                goto eof;
            STORAGE_KEY(pgo, &sysblk) |= (STORKEY_REF|STORKEY_CHANGE);
        }
    }
    eof:
    close(fd);
}
Example #17
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(diag204_call) (int r1, int r2, REGS *regs)
{
DIAG204_HDR       *hdrinfo;            /* Header                     */
DIAG204_PART      *partinfo;           /* Partition info             */
DIAG204_PART_CPU  *cpuinfo;            /* CPU info                   */
#if defined(FEATURE_EXTENDED_DIAG204)
DIAG204_X_HDR      *hdrxinfo;          /* Header                     */
DIAG204_X_PART     *partxinfo;         /* Partition info             */
DIAG204_X_PART_CPU *cpuxinfo;          /* CPU info                   */
U64               tdis;       
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/
RADR              abs;                 /* abs addr of data area      */
U64               dreg;                /* work doubleword            */
int               i;                   /* loop counter               */
struct rusage     usage;               /* RMF type data              */
static U64        diag204tod;          /* last diag204 tod           */
#if defined(FEATURE_PHYSICAL_DIAG204)
static BYTE       physical[8] =
              {0xD7,0xC8,0xE8,0xE2,0xC9,0xC3,0xC1,0xD3}; /* PHYSICAL */
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

    /* Test DIAG204 command word */
    switch (regs->GR_L(r2)) {

    case 0x04:

        abs = APPLY_PREFIXING (GR_A(r1,regs), regs->PX);

        /* Program check if RMF data is not on a page boundary */
        if ( (abs & PAGEFRAME_BYTEMASK) != 0x000)
            ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

        /* Program check if RMF data area is outside main storage */
        if ( abs > regs->mainlim )
            ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);

        /* Point to DIAG 204 data area */
        hdrinfo = (DIAG204_HDR*)(regs->mainstor + abs);

        /* Mark page referenced */
        STORAGE_KEY(abs, regs) |= STORKEY_REF | STORKEY_CHANGE;

        /* save last diag204 tod */
        dreg = diag204tod;

        /* Retrieve the TOD clock value and shift out the epoch */
        diag204tod = tod_clock(regs) << 8;

        memset(hdrinfo, 0, sizeof(DIAG204_HDR));
        hdrinfo->numpart = 1;
#if defined(FEATURE_PHYSICAL_DIAG204)
        hdrinfo->flags = DIAG204_PHYSICAL_PRESENT;
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/
        STORE_HW(hdrinfo->physcpu,sysblk.cpus);
        STORE_HW(hdrinfo->offown,sizeof(DIAG204_HDR));
        STORE_DW(hdrinfo->diagstck,dreg);

        /* hercules partition */
        partinfo = (DIAG204_PART*)(hdrinfo + 1);
        memset(partinfo, 0, sizeof(DIAG204_PART));
        partinfo->partnum = 1; /* Hercules partition */
        partinfo->virtcpu = sysblk.cpus;
        get_lparname(partinfo->partname);

        /* hercules cpu's */
        getrusage(RUSAGE_SELF,&usage);
        cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU));
              STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuinfo->index=sysblk.ptyp[i];
              STORE_HW(cpuinfo->weight,100);
              dreg = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuinfo->totdispatch,dreg);

              dreg = (U64)(usage.ru_utime.tv_sec)* 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuinfo->effdispatch,dreg);

              cpuinfo += 1;
          }

#if defined(FEATURE_PHYSICAL_DIAG204)
        /* lpar management */
        getrusage(RUSAGE_CHILDREN,&usage);
        partinfo = (DIAG204_PART*)cpuinfo;
        memset(partinfo, 0, sizeof(DIAG204_PART));
        partinfo->partnum = 0; /* Physical machine */
        partinfo->virtcpu = sysblk.cpus;
        memcpy(partinfo->partname,physical,sizeof(physical));

        /* report all emulated physical cpu's */
        getrusage(RUSAGE_SELF,&usage);
        cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU));
              STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuinfo->weight,100);

              dreg = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuinfo->totdispatch,dreg);

              dreg = (U64)(usage.ru_utime.tv_sec) * 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuinfo->effdispatch,dreg);

              cpuinfo += 1;
          }
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

        regs->GR_L(r2) = 0;

        break;

#if defined(FEATURE_EXTENDED_DIAG204)
    /* Extended subcode 5 returns the size of the data areas provided by extended subcodes 6 and 7 */
    case 0x00010005:
        i = sizeof(DIAG204_X_HDR) + ((sizeof(DIAG204_X_PART) + (sysblk.maxcpu * sizeof(DIAG204_X_PART_CPU))) * 2);
        regs->GR_L(r2+1) = (i + PAGEFRAME_BYTEMASK) / PAGEFRAME_PAGESIZE;
        regs->GR_L(r2) = 0;

        break;

    /* Provide extended information */
    case 0x00010006:
        /* We fall through as we do not have any secondary cpus (that we know of) */

    /* Provide extended information, including information about secondary CPUs */
    case 0x00010007:
        /* Program check if RMF data is not on a page boundary */
        if ( (regs->GR_L(r1) & PAGEFRAME_BYTEMASK) != 0x000)
            ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

        /* Obtain absolute address of main storage block,
           check protection, and set reference and change bits */
        hdrxinfo = (DIAG204_X_HDR*)MADDR (GR_A(r1,regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey);

        /* save last diag204 tod */
        dreg = diag204tod;

        /* Retrieve the TOD clock value and shift out the epoch */
        diag204tod = tod_clock(regs) << 8;

        memset(hdrxinfo, 0, sizeof(DIAG204_X_HDR));
        hdrxinfo->numpart = 1;
#if defined(FEATURE_PHYSICAL_DIAG204)
        hdrxinfo->flags = DIAG204_X_PHYSICAL_PRESENT;
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/
        STORE_HW(hdrxinfo->physcpu,sysblk.cpus);
        STORE_HW(hdrxinfo->offown,sizeof(DIAG204_X_HDR));
        STORE_DW(hdrxinfo->diagstck1,(dreg >> 8));
        STORE_DW(hdrxinfo->diagstck2,( 0x0000000001000000ULL | (regs->cpuad << 16) | regs->todpr));

        /* hercules partition */
        partxinfo = (DIAG204_X_PART*)(hdrxinfo + 1);
        memset(partxinfo, 0, sizeof(DIAG204_PART));
        partxinfo->partnum = 1; /* Hercules partition */
        partxinfo->virtcpu = sysblk.cpus;
        get_lparname(partxinfo->partname);
        get_sysname(partxinfo->cpcname);
        get_systype(partxinfo->osname);
        STORE_DW(partxinfo->cssize,sysblk.mainsize);
        STORE_DW(partxinfo->essize,sysblk.xpndsize);
        get_sysplex(partxinfo->gr_name);

        /* hercules cpu's */
        getrusage(RUSAGE_SELF,&usage);
        cpuxinfo = (DIAG204_X_PART_CPU*)(partxinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU));
              STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuxinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuxinfo->weight,100);
              
              tdis = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000;
              tdis = (tdis + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus;
              tdis <<= 12;
              STORE_DW(cpuxinfo->totdispatch,tdis);

              dreg = (U64)(usage.ru_utime.tv_sec)* 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuxinfo->effdispatch,dreg);

              STORE_HW(cpuxinfo->minweight,1000);
              STORE_HW(cpuxinfo->curweight,1000);
              STORE_HW(cpuxinfo->maxweight,1000);

              STORE_DW(cpuxinfo->onlinetime, diag204tod - sysblk.todstart);
              STORE_DW(cpuxinfo->waittime, (diag204tod - sysblk.todstart) - tdis);

              STORE_HW(cpuxinfo->pmaweight,1000);
              STORE_HW(cpuxinfo->polarweight,1000);

              cpuxinfo += 1;
          }


#if defined(FEATURE_PHYSICAL_DIAG204)
        /* lpar management */
        partxinfo = (DIAG204_X_PART*)cpuxinfo;
        memset(partxinfo, 0, sizeof(DIAG204_X_PART));
        partxinfo->partnum = 0; /* Physical machine */
        partxinfo->virtcpu = sysblk.cpus;
        memcpy(partxinfo->partname,physical,sizeof(physical));

        /* report all emulated physical cpu's */
        getrusage(RUSAGE_CHILDREN,&usage);
        cpuxinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU));
              STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuxinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuxinfo->weight,100);
              
              tdis = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000;
              tdis = (tdis + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus;
              tdis <<= 12;
              STORE_DW(cpuxinfo->totdispatch,tdis);

              dreg = (U64)(usage.ru_utime.tv_sec)* 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuxinfo->effdispatch,dreg);

              STORE_HW(cpuxinfo->minweight,1000);
              STORE_HW(cpuxinfo->curweight,1000);
              STORE_HW(cpuxinfo->maxweight,1000);

              STORE_DW(cpuxinfo->onlinetime, diag204tod - sysblk.todstart);
              STORE_DW(cpuxinfo->waittime, (diag204tod - sysblk.todstart) - tdis);

              STORE_HW(cpuxinfo->pmaweight,1000);
              STORE_HW(cpuxinfo->polarweight,1000);

              cpuxinfo += 1;
          }
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

        regs->GR_L(r2) = 0;

        break;
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/

    default:
        PTT(PTT_CL_ERR,"*DIAG204",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
        regs->GR_L(r2) = 4;

    } /*switch(regs->GR_L(r2))*/

} /* end function diag204_call */
Example #18
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(load_ipl) (U16 lcss, U16 devnum, int cpu, int clear)
{
REGS   *regs;                           /* -> Regs                   */
DEVBLK *dev;                            /* -> Device control block   */
int     i;                              /* Array subscript           */
BYTE    unitstat;                       /* IPL device unit status    */
BYTE    chanstat;                       /* IPL device channel status */
int rc;

    /* Get started */
    if ((rc = ARCH_DEP(common_load_begin) (cpu, clear)) )
        return rc;

    /* Ensure CPU is online */
    if (!IS_CPU_ONLINE(cpu))
    {
        char buf[80];
        MSGBUF(buf, "CP%02.2X Offline", devnum);
        WRMSG (HHC00810, "E", PTYPSTR(sysblk.pcpu), sysblk.pcpu, buf);
        return -1;
    }

    /* The actual IPL proper starts here... */

    regs = sysblk.regs[cpu];    /* Point to IPL CPU's registers */
    /* Point to the device block for the IPL device */
    dev = find_device_by_devnum (lcss,devnum);
    if (dev == NULL)
    {
        char buf[80];
        MSGBUF(buf, "device %4.4X not found", devnum);
        WRMSG (HHC00810, "E", PTYPSTR(sysblk.pcpu), sysblk.pcpu, buf);
        HDC1(debug_cpu_state, regs);
        return -1;
    }

    if(sysblk.haveiplparm)
    {
        for(i=0;i<16;i++)
        {
            regs->GR_L(i)=fetch_fw(&sysblk.iplparmstring[i*4]);
        }
        sysblk.haveiplparm=0;
    }

    /* Set Main Storage Reference and Update bits */
    STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE);
    sysblk.main_clear = sysblk.xpnd_clear = 0;

    /* Build the IPL CCW at location 0 */
    regs->psa->iplpsw[0] = 0x02;              /* CCW command = Read */
    regs->psa->iplpsw[1] = 0;                 /* Data address = zero */
    regs->psa->iplpsw[2] = 0;
    regs->psa->iplpsw[3] = 0;
    regs->psa->iplpsw[4] = CCW_FLAGS_CC | CCW_FLAGS_SLI;
                                        /* CCW flags */
    regs->psa->iplpsw[5] = 0;                 /* Reserved byte */
    regs->psa->iplpsw[6] = 0;                 /* Byte count = 24 */
    regs->psa->iplpsw[7] = 24;

    /* Enable the subchannel for the IPL device */
    dev->pmcw.flag5 |= PMCW5_E;

    /* Build the operation request block */                    /*@IWZ*/
    memset (&dev->orb, 0, sizeof(ORB));                        /*@IWZ*/
    dev->busy = 1;

    RELEASE_INTLOCK(NULL);

    /* Execute the IPL channel program */
    ARCH_DEP(execute_ccw_chain) (dev);

    OBTAIN_INTLOCK(NULL);

    /* Clear the interrupt pending and device busy conditions */
    obtain_lock (&sysblk.iointqlk);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->ioint);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->pciioint);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->attnioint);
    release_lock(&sysblk.iointqlk);
    dev->busy = 0;
    dev->scsw.flag2 = 0;
    dev->scsw.flag3 = 0;

    /* Check that load completed normally */
    unitstat = dev->scsw.unitstat;
    chanstat = dev->scsw.chanstat;

    if (unitstat != (CSW_CE | CSW_DE) || chanstat != 0)
    {
        char buf[80];
        char buf2[16];

        memset(buf,0,sizeof(buf));
        for (i=0; i < (int)dev->numsense; i++)
        {
            MSGBUF(buf2, "%2.2X", dev->sense[i]);
            strlcat(buf, buf2, sizeof(buf) );
            if ((i & 3) == 3) strlcat(buf, " ", sizeof(buf));
        }
        {
            char buffer[256];
            MSGBUF(buffer, "architecture mode %s, csw status %2.2X%2.2X, sense %s",
                get_arch_mode_string((REGS *)0),
                unitstat, chanstat, buf);
            WRMSG (HHC00828, "E", PTYPSTR(sysblk.pcpu), sysblk.pcpu, buffer);
        }
        HDC1(debug_cpu_state, regs);
        return -1;
    }

#ifdef FEATURE_S370_CHANNEL
    /* Test the EC mode bit in the IPL PSW */
    if (regs->psa->iplpsw[1] & 0x08) {
        /* In EC mode, store device address at locations 184-187 */
        STORE_FW(regs->psa->ioid, dev->devnum);
    } else {
        /* In BC mode, store device address at locations 2-3 */
        STORE_HW(regs->psa->iplpsw + 2, dev->devnum);
    }
#endif /*FEATURE_S370_CHANNEL*/

#ifdef FEATURE_CHANNEL_SUBSYSTEM
    /* Set LPUM */
    dev->pmcw.lpum = 0x80;
    STORE_FW(regs->psa->ioid, (dev->ssid<<16)|dev->subchan);

    /* Store zeroes at locations 188-191 */
    memset (regs->psa->ioparm, 0, 4);
#endif /*FEATURE_CHANNEL_SUBSYSTEM*/

    /* Save IPL device number, cpu number and lcss */
    sysblk.ipldev = devnum;
    sysblk.iplcpu = regs->cpuad;
    sysblk.ipllcss = lcss;
    sysblk.ipled = TRUE;

    /* Finish up... */
    return ARCH_DEP(common_load_finish) (regs);
} /* end function load_ipl */
Example #19
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(perform_external_interrupt) (REGS *regs)
{
PSA    *psa;                            /* -> Prefixed storage area  */
U16     cpuad;                          /* Originating CPU address   */
#if defined(FEATURE_VM_BLOCKIO)
#if defined(FEATURE_ESAME)
RADR    servpadr;      /* Address of 64-bit block I/O interrupt */
#endif
U16     servcode;      /* Service Signal or Block I/O Interrupt code */
#endif /* defined(FEATURE_VM_BLOCKIO) */

    /* External interrupt if console interrupt key was depressed */
    if ( OPEN_IC_INTKEY(regs) && !SIE_MODE(regs) )
    {
        WRMSG (HHC00840, "I");

        /* Reset interrupt key pending */
        OFF_IC_INTKEY;

        /* Generate interrupt key interrupt */
        ARCH_DEP(external_interrupt) (EXT_INTERRUPT_KEY_INTERRUPT, regs);
    }

    /* External interrupt if malfunction alert is pending */
    if (OPEN_IC_MALFALT(regs))
    {
        /* Find first CPU which generated a malfunction alert */
        for (cpuad = 0; regs->malfcpu[cpuad] == 0; cpuad++)
        {
            if (cpuad >= sysblk.maxcpu)
            {
                OFF_IC_MALFALT(regs);
                return;
            }
        } /* end for(cpuad) */

// /*debug*/ logmsg (_("External interrupt: Malfuction Alert from CPU %d\n"),
// /*debug*/    cpuad);

        /* Reset the indicator for the CPU which was found */
        regs->malfcpu[cpuad] = 0;

        /* Store originating CPU address at PSA+X'84' */
        psa = (void*)(regs->mainstor + regs->PX);
        STORE_HW(psa->extcpad,cpuad);

        /* Reset emergency signal pending flag if there are
           no other CPUs which generated emergency signal */
        OFF_IC_MALFALT(regs);
        while (++cpuad < sysblk.maxcpu)
        {
            if (regs->malfcpu[cpuad])
            {
                ON_IC_MALFALT(regs);
                break;
            }
        } /* end while */

        /* Generate emergency signal interrupt */
        ARCH_DEP(external_interrupt) (EXT_MALFUNCTION_ALERT_INTERRUPT, regs);
    }


    /* External interrupt if emergency signal is pending */
    if (OPEN_IC_EMERSIG(regs))
    {
        /* Find first CPU which generated an emergency signal */
        for (cpuad = 0; regs->emercpu[cpuad] == 0; cpuad++)
        {
            if (cpuad >= sysblk.maxcpu)
            {
                OFF_IC_EMERSIG(regs);
                return;
            }
        } /* end for(cpuad) */

// /*debug*/ logmsg (_("External interrupt: Emergency Signal from CPU %d\n"),
// /*debug*/    cpuad);

        /* Reset the indicator for the CPU which was found */
        regs->emercpu[cpuad] = 0;

        /* Store originating CPU address at PSA+X'84' */
        psa = (void*)(regs->mainstor + regs->PX);
        STORE_HW(psa->extcpad,cpuad);

        /* Reset emergency signal pending flag if there are
           no other CPUs which generated emergency signal */
        OFF_IC_EMERSIG(regs);
        while (++cpuad < sysblk.maxcpu)
        {
            if (regs->emercpu[cpuad])
            {
                ON_IC_EMERSIG(regs);
                break;
            }
        } /* end while */

        /* Generate emergency signal interrupt */
        ARCH_DEP(external_interrupt) (EXT_EMERGENCY_SIGNAL_INTERRUPT, regs);
    }

    /* External interrupt if external call is pending */
    if (OPEN_IC_EXTCALL(regs))
    {
//  /*debug*/logmsg (_("External interrupt: External Call from CPU %d\n"),
//  /*debug*/       regs->extccpu);

        /* Reset external call pending */
        OFF_IC_EXTCALL(regs);

        /* Store originating CPU address at PSA+X'84' */
        psa = (void*)(regs->mainstor + regs->PX);
        STORE_HW(psa->extcpad,regs->extccpu);

        /* Generate external call interrupt */
        ARCH_DEP(external_interrupt) (EXT_EXTERNAL_CALL_INTERRUPT, regs);
    }

    /* External interrupt if TOD clock exceeds clock comparator */
    if ( tod_clock(regs) > regs->clkc
        && OPEN_IC_CLKC(regs) )
    {
        if (CPU_STEPPING_OR_TRACING_ALL)
        {
            WRMSG (HHC00841, "I");
        }
        ARCH_DEP(external_interrupt) (EXT_CLOCK_COMPARATOR_INTERRUPT, regs);
    }

    /* External interrupt if CPU timer is negative */
    if ( CPU_TIMER(regs) < 0
        && OPEN_IC_PTIMER(regs) )
    {
        if (CPU_STEPPING_OR_TRACING_ALL)
        {
            WRMSG (HHC00842, "I", CPU_TIMER(regs) << 8);
        }
        ARCH_DEP(external_interrupt) (EXT_CPU_TIMER_INTERRUPT, regs);
    }

    /* External interrupt if interval timer interrupt is pending */
#if defined(FEATURE_INTERVAL_TIMER)
    if (OPEN_IC_ITIMER(regs)
#if defined(_FEATURE_SIE)
        && !(SIE_STATB(regs, M, ITMOF))
#endif /*defined(_FEATURE_SIE)*/
        )
    {
        if (CPU_STEPPING_OR_TRACING_ALL)
        {
            WRMSG (HHC00843, "I");
        }
        OFF_IC_ITIMER(regs);
        ARCH_DEP(external_interrupt) (EXT_INTERVAL_TIMER_INTERRUPT, regs);
    }

#if defined(FEATURE_ECPSVM)
    if ( OPEN_IC_ECPSVTIMER(regs) )
    {
        OFF_IC_ECPSVTIMER(regs);
        ARCH_DEP(external_interrupt) (EXT_VINTERVAL_TIMER_INTERRUPT,regs);
    }
#endif /*FEATURE_ECPSVM*/
#endif /*FEATURE_INTERVAL_TIMER*/

    /* External interrupt if service signal is pending */
    if ( OPEN_IC_SERVSIG(regs) && !SIE_MODE(regs) )
    {

#if defined(FEATURE_VM_BLOCKIO)
        
        /* Note: Both Block I/O and Service Signal are enabled by the */
        /* the same CR0 bit.  Hence they are handled in the same code */
        switch(sysblk.servcode)
        {
        case EXT_BLOCKIO_INTERRUPT:  /* VM Block I/O Interrupt */

           if (sysblk.biodev->ccwtrace)
           {
           WRMSG (HHC00844, "I",
                SSID_TO_LCSS(sysblk.biodev->ssid),
                sysblk.biodev->devnum,
                sysblk.servcode,
                sysblk.bioparm,
                sysblk.biostat,
                sysblk.biosubcd
                );
           }

           servcode = EXT_BLOCKIO_INTERRUPT;

#if defined(FEATURE_ESAME)
/* Real address used to store the 64-bit interrupt parameter */
#define VM_BLOCKIO_INT_PARM 0x11B8
           if (sysblk.biosubcd == 0x07)
           {
           /* 8-byte interrupt parm */
           
               if (CPU_STEPPING_OR_TRACING_ALL)
               {
                  char buf[40];
                  MSGBUF(buf, "%16.16X", (unsigned) sysblk.bioparm);
                  WRMSG (HHC00845,"I", buf);
               }

               /* Set the main storage reference and change bits   */
               /* for 64-bit interruption parameter.               */
               /* Note: This is handled for the first 4K page in   */
               /* ARCH_DEP(external_interrupt), but not for the    */
               /* the second 4K page used for the 64-bit interrupt */
               /* parameter.                                       */

               /* Point to 2nd page of PSA in main storage */
               servpadr=APPLY_PREFIXING(VM_BLOCKIO_INT_PARM,regs->PX);

               STORAGE_KEY(servpadr, regs) 
                     |= (STORKEY_REF | STORKEY_CHANGE);

#if 0
               /* Store the 64-bit interrupt parameter */
               logmsg (_("Saving 64-bit Block I/O interrupt parm at "
                         "%16.16X: %16.16X\n"),
                         servpadr,
                         sysblk.bioparm
                      );
#endif

               STORE_DW(regs->mainstor + servpadr,sysblk.bioparm);
               psa = (void*)(regs->mainstor + regs->PX);
           }
           else
           {
#endif  /* defined(FEATURE_ESAME) */

           /* 4-byte interrupt parm */

              if (CPU_STEPPING_OR_TRACING_ALL)
              {
                 char buf[40];
                 MSGBUF(buf, "%8.8X", (U32) sysblk.bioparm);
                 WRMSG (HHC00845,"I", buf);
              }

              /* Store Block I/O parameter at PSA+X'80' */
              psa = (void*)(regs->mainstor + regs->PX);
              STORE_FW(psa->extparm,(U32)sysblk.bioparm);

#if defined(FEATURE_ESAME)
           }
#endif

           /* Store sub-interruption code and status at PSA+X'84' */
           STORE_HW(psa->extcpad,(sysblk.biosubcd<<8)|sysblk.biostat);
           
           /* Reset interruption data */
           sysblk.bioparm  = 0;
           sysblk.biosubcd = 0;
           sysblk.biostat  = 0;
           
           break;

        case EXT_SERVICE_SIGNAL_INTERRUPT: /* Service Signal */
        default:
             servcode = EXT_SERVICE_SIGNAL_INTERRUPT;
             
            /* Apply prefixing if the parameter is a storage address */
            if ( (sysblk.servparm & SERVSIG_ADDR) )
                sysblk.servparm =
                     APPLY_PREFIXING (sysblk.servparm, regs->PX);

             if (CPU_STEPPING_OR_TRACING_ALL)
             {
                 WRMSG (HHC00846,"I", sysblk.servparm);
             }

             /* Store service signal parameter at PSA+X'80' */
             psa = (void*)(regs->mainstor + regs->PX);
             STORE_FW(psa->extparm,sysblk.servparm);

        }  /* end switch(sysblk.servcode) */
        /* Reset service parameter */
        sysblk.servparm = 0;

        /* Reset service code */
        sysblk.servcode = 0;

        /* Reset service signal pending */
        OFF_IC_SERVSIG;

        /* Generate service signal interrupt */
        ARCH_DEP(external_interrupt) (servcode, regs);
             
#else /* defined(FEATURE_VM_BLOCKIO) */

        /* Apply prefixing if the parameter is a storage address */
        if ( (sysblk.servparm & SERVSIG_ADDR) )
            sysblk.servparm =
                APPLY_PREFIXING (sysblk.servparm, regs->PX);

        if (CPU_STEPPING_OR_TRACING_ALL)
        {
            WRMSG (HHC00846,"I", sysblk.servparm);
        }

        /* Store service signal parameter at PSA+X'80' */
        psa = (void*)(regs->mainstor + regs->PX);
        STORE_FW(psa->extparm,sysblk.servparm);

        /* Reset service parameter */
        sysblk.servparm = 0;

        /* Reset service signal pending */
        OFF_IC_SERVSIG;
        
        /* Generate service signal interrupt */
        ARCH_DEP(external_interrupt) (EXT_SERVICE_SIGNAL_INTERRUPT, regs);

#endif /* defined(FEATURE_VM_BLOCKIO) */

    }  /* end OPEN_IC_SERVSIG(regs) */

} /* end function perform_external_interrupt */