Ejemplo n.º 1
0
/*-------------------------------------------------------------------*/
static void* ARCH_DEP(hwl_thread)(void* arg)
{
SCCB_HWL_BK *hwl_bk = (SCCB_HWL_BK*) arg;

    if(hwl_bk->file < HWL_MAXFILETYPE && hwl_fn[hwl_bk->file])
    {
        switch(hwl_bk->type) {

        /* INFO request returns the required region size in 4K pages */
        case SCCB_HWL_TYPE_INFO:
            {
            struct stat st;

                if(!stat(hwl_fn[hwl_bk->file], &st) )
                {
                U32     size;

                    size = st.st_size;
                    size += 0x00000FFF;
                    size &= 0xFFFFF000;
                    size >>= 12;

                    STORE_FW(hwl_bk->size,size);
                }
                else
                    logmsg(_("HHCHL001I Hardware loader %s: %s\n"),
                                                hwl_fn[hwl_bk->file],strerror(errno));
            }
            break;

        /* Load request will load the image into fixed virtual storage
           the Segment Table Origin is listed in the hwl_bk */
        case SCCB_HWL_TYPE_LOAD:
#if defined(FEATURE_ESAME)
            if(!hwl_bk->asa)
                s390_hwl_loadfile(hwl_bk);
            else
#endif /*defined(FEATURE_ESAME)*/
                ARCH_DEP(hwl_loadfile)(hwl_bk);
            break;

        }
Ejemplo n.º 2
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 */
Ejemplo n.º 3
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 */
Ejemplo n.º 4
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 */
Ejemplo n.º 5
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 */
Ejemplo n.º 6
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 */