Example #1
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(cpu_reset) (REGS *regs)
{
int i, rc = 0;                          /* Array subscript           */

    regs->ip = regs->inst;

    /* Clear indicators */
    regs->loadstate = 0;
    regs->checkstop = 0;
    regs->sigpreset = 0;
    regs->extccpu = 0;
    for (i = 0; i < sysblk.maxcpu; i++)
        regs->emercpu[i] = 0;
    regs->instinvalid = 1;
    regs->instcount = regs->prevcount = 0;

    /* Clear interrupts */
    SET_IC_INITIAL_MASK(regs);
    SET_IC_INITIAL_STATE(regs);

    /* Clear the translation exception identification */
    regs->EA_G = 0;
    regs->excarid = 0;

    /* Clear monitor code */
    regs->MC_G = 0;

    /* Purge the lookaside buffers */
    ARCH_DEP(purge_tlb) (regs);

#if defined(FEATURE_ACCESS_REGISTERS)
    ARCH_DEP(purge_alb) (regs);
#endif /*defined(FEATURE_ACCESS_REGISTERS)*/

    if(regs->host)
    {
        /* Put the CPU into the stopped state */
        regs->opinterv = 0;
        regs->cpustate = CPUSTATE_STOPPED;
        ON_IC_INTERRUPT(regs);
    }

#ifdef FEATURE_INTERVAL_TIMER
    ARCH_DEP(store_int_timer_nolock) (regs);
#endif

   if(regs->host && regs->guestregs)
   {
        rc = ARCH_DEP(cpu_reset)(regs->guestregs);
        /* CPU state of SIE copy cannot be controlled */
        regs->guestregs->opinterv = 0;
        regs->guestregs->cpustate = CPUSTATE_STARTED;
   }

    /* Initialize Architecture Level Set */
    init_als(regs);

   return rc;
} /* end function cpu_reset */
Example #2
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(system_reset) (const int cpu, const int clear, const int target_mode)
{
    int         rc;
    int         n;
    int         regs_mode;
    int         architecture_switch;
    REGS*       regs;
    CPU_BITMAP  mask;

    /* Configure the cpu if it is not online (configure implies initial
     * reset)
     */
    if (!IS_CPU_ONLINE(cpu))
    {
        sysblk.arch_mode = target_mode;
        if ( (rc = configure_cpu(cpu)) )
            return rc;
    }

    HDC1(debug_cpu_state, sysblk.regs[cpu]);

    /* Define the target mode for reset */
    if (target_mode > ARCH_390 &&
        (clear || sysblk.arch_mode != target_mode))
        regs_mode = ARCH_390;
    else
        regs_mode = target_mode;

    architecture_switch = (target_mode != sysblk.arch_mode);

    /* Signal all CPUs in configuration to stop and reset */
    {
        /* Switch lock context to hold both sigplock and intlock */
        RELEASE_INTLOCK(NULL);
        obtain_lock(&sysblk.sigplock);
        OBTAIN_INTLOCK(NULL);

        /* Ensure no external updates pending */
        OFF_IC_SERVSIG;
        OFF_IC_INTKEY;

        /* Loop through CPUs and issue appropriate CPU reset function
         */
        {
            mask = sysblk.config_mask;

            for (n = 0; mask; mask >>= 1, ++n)
            {
                if (mask & 1)
                {
                    regs = sysblk.regs[n];

                    /* Signal CPU reset function; if requesting CPU with
                     * CLEAR or architecture change, signal initial CPU
                     * reset. Otherwise, signal a normal CPU reset.
                     */
                    regs->arch_mode = regs_mode;

                    if (n == cpu &&
                        (clear || architecture_switch))
                        regs->sigpireset = 1;
                    else
                        regs->sigpreset = 1;

                    regs->opinterv = 1;
                    regs->cpustate = CPUSTATE_STOPPING;
                    ON_IC_INTERRUPT(regs);
                    wakeup_cpu(regs);
                }
            }
        }

        /* Return to hold of just intlock */
        RELEASE_INTLOCK(NULL);
        release_lock(&sysblk.sigplock);
        OBTAIN_INTLOCK(NULL);
    }

    /* Wait for CPUs to complete reset */
    {
        int i;
        int wait;

        for (n = 0; ; ++n)
        {
            mask = sysblk.config_mask;

            for (i = wait = 0; mask; mask >>= 1, ++i)
            {
                regs = sysblk.regs[i];

                if (regs->cpustate != CPUSTATE_STOPPED)
                {
                    /* Release intlock, take a nap, and re-acquire */
                    RELEASE_INTLOCK(NULL);
                    wait = 1;
                    usleep(10000);
                    OBTAIN_INTLOCK(NULL);
                }
            }

            if (!wait)
                break;

            if (n < 300)
                continue;

            /* FIXME: Recovery code needed to handle case where CPUs
             *        are misbehaving. Outstanding locks should be
             *        reported, then take-over CPUs and perform an
             *        initial reset of each CPU.
             */
            WRMSG(HHC90000, "E", "Could not perform reset within three seconds");
            break;
        }
    }

    /* Perform subsystem reset */
    subsystem_reset();

    /* Switch modes to requested mode */
    sysblk.arch_mode = regs_mode;

    /* Perform system-reset-clear additional functions */
    if (clear)
    {
        /* Finish reset-clear of all CPUs in the configuration */
        for (n = 0; n < sysblk.maxcpu; ++n)
        {
            if (IS_CPU_ONLINE(n))
            {
                regs = sysblk.regs[n];

                /* Clear all the registers (AR, GPR, FPR, VR) as part
                 * of the CPU CLEAR RESET operation
                 */
                memset (regs->ar, 0, sizeof(regs->ar));
                memset (regs->gr, 0, sizeof(regs->gr));
                memset (regs->fpr, 0, sizeof(regs->fpr));
                #if defined(_FEATURE_VECTOR_FACILITY)
                    memset (regs->vf->vr, 0, sizeof(regs->vf->vr));
                #endif /*defined(_FEATURE_VECTOR_FACILITY)*/
            }
        }

        sysblk.ipled = FALSE;
        sysblk.program_parameter = 0;

        /* Clear storage */
        sysblk.main_clear = sysblk.xpnd_clear = 0;
        storage_clear();
        xstorage_clear();
    }

#if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)
    /* Clear topology-change-report-pending condition */
    sysblk.topchnge = 0;
#endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/

    /* set default system state to reset */
    sysblk.sys_reset = TRUE;

    return (0);
} /* end function system_reset */
Example #3
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 #4
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(system_reset)
(
    const int cpu,              /* CPU address                       */
    const int flags,            /* Flags:
                                 * 0x00 0000 0000 System reset normal
                                 * 0x01 .... ...1 System reset clear
                                 * 0x02 .... ..1. System reset normal
                                 *                with initial CPU
                                 *                reset on requesting
                                 *                processor (used by
                                 *                IPL)
                                 */
    const int target_mode       /* Target architecture mode          */
)
{
    int         rc;
    int         n;
    int         regs_mode;
    int         architecture_switch;
    REGS*       regs;
    CPU_BITMAP  mask;

    /* Configure the cpu if it is not online (configure implies initial
     * reset)
     */
    if (!IS_CPU_ONLINE(cpu))
    {
        sysblk.arch_mode = target_mode;
        if ( (rc = configure_cpu(cpu)) )
            return rc;
    }

    HDC1(debug_cpu_state, sysblk.regs[cpu]);

    /* Define the target mode for reset */
    if (flags &&
        target_mode > ARCH_390)
        regs_mode = ARCH_390;
    else
        regs_mode = target_mode;

    architecture_switch = (regs_mode != sysblk.arch_mode);

    /* Signal all CPUs in configuration to stop and reset */
    {
        /* Switch lock context to hold both sigplock and intlock */
        RELEASE_INTLOCK(NULL);
        obtain_lock(&sysblk.sigplock);
        OBTAIN_INTLOCK(NULL);

        /* Ensure no external updates pending */
        OFF_IC_SERVSIG;
        OFF_IC_INTKEY;

        /* Loop through CPUs and issue appropriate CPU reset function
         */
        {
            mask = sysblk.config_mask;

            for (n = 0; mask; mask >>= 1, ++n)
            {
                if (mask & 1)
                {
                    regs = sysblk.regs[n];

                    /* Signal CPU reset function; if requesting CPU with
                     * CLEAR or architecture change, signal initial CPU
                     * reset. Otherwise, signal a normal CPU reset.
                     */
                    if ((n == cpu && (flags & 0x03))    ||
                        architecture_switch)
                        regs->sigpireset = 1;
                    else
                        regs->sigpreset = 1;

                    regs->opinterv = 1;
                    regs->cpustate = CPUSTATE_STOPPING;
                    ON_IC_INTERRUPT(regs);
                    wakeup_cpu(regs);
                }
            }
        }

        /* Return to hold of just intlock */
        RELEASE_INTLOCK(NULL);
        release_lock(&sysblk.sigplock);
        OBTAIN_INTLOCK(NULL);
    }

    /* Wait for CPUs to complete reset */
    {
        int i;
        int wait;

        for (n = 0; ; ++n)
        {
            mask = sysblk.config_mask;

            for (i = wait = 0; mask; mask >>= 1, ++i)
            {
                if (!(mask & 1))
                    continue;

                regs = sysblk.regs[i];

                if (regs->cpustate != CPUSTATE_STOPPED)
                {
                    /* Release intlock, take a nap, and re-acquire */
                    RELEASE_INTLOCK(NULL);
                    wait = 1;
                    usleep(10000);
                    OBTAIN_INTLOCK(NULL);
                }
            }

            if (!wait)
                break;

            if (n < 300)
                continue;

            /* FIXME: Recovery code needed to handle case where CPUs
             *        are misbehaving. Outstanding locks should be
             *        reported, then take-over CPUs and perform an
             *        initial reset of each CPU.
             */
            WRMSG(HHC90000, "E", "Could not perform reset within three seconds");
            break;
        }
    }

    /* If architecture switch, complete reset in requested mode */
    if (architecture_switch)
    {
        sysblk.arch_mode = regs_mode;
        return ARCH_DEP(system_reset)(cpu, flags, target_mode);
    }

    /* Perform subsystem reset
     *
     * GA22-7000-10 IBM System/370 Principles of Operation, Chapter 4.
     *              Control, Subsystem Reset, p. 4-34
     * SA22-7085-00 IBM System/370 Extended Architecture Principles of
     *              Operation, Chapter 4. Control, Subsystem Reset,
     *              p. 4-28
     * SA22-7832-09 z/Architecture Principles of Operation, Chapter 4.
     *              Control, Subsystem Reset, p. 4-57
     */
    subsystem_reset();

    /* Perform system-reset-clear additional functions */
    if (flags & 0x01)
    {
        /* Finish reset-clear of all CPUs in the configuration */
        for (n = 0; n < sysblk.maxcpu; ++n)
        {
            if (IS_CPU_ONLINE(n))
            {
                regs = sysblk.regs[n];

                /* Clear all the registers (AR, GPR, FPR, VR) as part
                 * of the CPU CLEAR RESET operation
                 */
                memset (regs->ar, 0, sizeof(regs->ar));
                memset (regs->gr, 0, sizeof(regs->gr));
                memset (regs->fpr, 0, sizeof(regs->fpr));
                #if defined(_FEATURE_VECTOR_FACILITY)
                    memset (regs->vf->vr, 0, sizeof(regs->vf->vr));
                #endif /*defined(_FEATURE_VECTOR_FACILITY)*/

                /* Clear the instruction counter and CPU time used */
                cpu_reset_instcount_and_cputime(regs);
            }
        }

        /* Clear storage */
        sysblk.main_clear = sysblk.xpnd_clear = 0;
        storage_clear();
        xstorage_clear();

        /* Clear IPL program parameter */
        sysblk.program_parameter = 0;
    }

    /* If IPL call, reset CPU instruction counts and times */
    else if (flags & 0x02)
    {
        CPU_BITMAP  mask = sysblk.config_mask;
        int         i;

        for (i = 0; mask; mask >>= 1, ++i)
        {
            if (mask & 1)
                cpu_reset_instcount_and_cputime(sysblk.regs[i]);
        }
    }
Example #5
0
int suspend_cmd(int argc, char *argv[],char *cmdline)
{
char    *fn = SR_DEFAULT_FILENAME;
SR_FILE *file;
CPU_BITMAP started_mask;
struct   timeval tv;
time_t   tt;
int      i, j, rc;
REGS    *regs;
DEVBLK  *dev;
IOINT   *ioq;
BYTE     psw[16];

    UNREFERENCED(cmdline);

    if (argc > 2)
    {
        // "SR: too many arguments"
        WRMSG(HHC02000, "E");
        return -1;
    }

    if (argc == 2)
        fn = argv[1];

    file = SR_OPEN (fn, "wb");
    if (file == NULL)
    {
        // "SR: error in function '%s': '%s'"
        WRMSG(HHC02001, "E","open()",strerror(errno));
        return -1;
    }

    TRACE("SR: Begin Suspend Processing...\n");

    /* Save CPU state and stop all CPU's */
    TRACE("SR: Stopping All CPUs...\n");
    OBTAIN_INTLOCK(NULL);
    started_mask = sysblk.started_mask;
    while (sysblk.started_mask)
    {
        for (i = 0; i < sysblk.maxcpu; i++)
        {
            if (IS_CPU_ONLINE(i))
            {
                sysblk.regs[i]->cpustate = CPUSTATE_STOPPING;
                ON_IC_INTERRUPT(sysblk.regs[i]);
                signal_condition(&sysblk.regs[i]->intcond);
            }
        }
        RELEASE_INTLOCK(NULL);
        usleep (1000);
        OBTAIN_INTLOCK(NULL);
    }
    RELEASE_INTLOCK(NULL);

    /* Wait for I/O queue to clear out */
    TRACE("SR: Waiting for I/O Queue to clear...\n");
#ifdef OPTION_FISHIO
    SLEEP (2);
#else
    obtain_lock (&sysblk.ioqlock);
    while (sysblk.ioq)
    {
        release_lock (&sysblk.ioqlock);
        usleep (1000);
        obtain_lock (&sysblk.ioqlock);
    }
    release_lock (&sysblk.ioqlock);
#endif

    /* Wait for active I/Os to complete */
    TRACE("SR: Waiting for Active I/Os to Complete...\n");
    for (i = 1; i < 5000; i++)
    {
        dev = sr_active_devices();
        if (dev == NULL) break;
        if (i % 500 == 0)
        {
            // "SR: waiting for device %04X"
            WRMSG(HHC02002, "W", dev->devnum);
        }
        usleep (10000);
    }
    if (dev != NULL)
    {
        // "SR: device %04X still busy, proceeding anyway"
        WRMSG(HHC02003, "W",dev->devnum);
    }

    /* Write header */
    TRACE("SR: Writing File Header...\n");
    SR_WRITE_STRING(file, SR_HDR_ID, SR_ID);
    SR_WRITE_STRING(file, SR_HDR_VERSION, VERSION);
    gettimeofday(&tv, NULL); tt = tv.tv_sec;
    SR_WRITE_STRING(file, SR_HDR_DATE, ctime(&tt));

    /* Write system data */
    TRACE("SR: Saving System Data...\n");
    SR_WRITE_STRING(file,SR_SYS_ARCH_NAME,arch_name[sysblk.arch_mode]);
    SR_WRITE_VALUE (file,SR_SYS_STARTED_MASK,started_mask,sizeof(started_mask));
    SR_WRITE_VALUE (file,SR_SYS_MAINSIZE,sysblk.mainsize,sizeof(sysblk.mainsize));
    TRACE("SR: Saving MAINSTOR...\n");
    SR_WRITE_BUF   (file,SR_SYS_MAINSTOR,sysblk.mainstor,sysblk.mainsize);
    SR_WRITE_VALUE (file,SR_SYS_SKEYSIZE,(sysblk.mainsize/STORAGE_KEY_UNITSIZE),sizeof(U32));
    TRACE("SR: Saving Storage Keys...\n");
    SR_WRITE_BUF   (file,SR_SYS_STORKEYS,sysblk.storkeys,sysblk.mainsize/STORAGE_KEY_UNITSIZE);
    SR_WRITE_VALUE (file,SR_SYS_XPNDSIZE,sysblk.xpndsize,sizeof(sysblk.xpndsize));
    TRACE("SR: Saving Expanded Storage...\n");
    SR_WRITE_BUF   (file,SR_SYS_XPNDSTOR,sysblk.xpndstor,4096*sysblk.xpndsize);
    SR_WRITE_VALUE (file,SR_SYS_CPUID,sysblk.cpuid,sizeof(sysblk.cpuid));
    SR_WRITE_VALUE (file,SR_SYS_IPLDEV,sysblk.ipldev,sizeof(sysblk.ipldev));
    SR_WRITE_VALUE (file,SR_SYS_IPLCPU,sysblk.iplcpu,sizeof(sysblk.iplcpu));
    SR_WRITE_VALUE (file,SR_SYS_MBO,sysblk.mbo,sizeof(sysblk.mbo));
    SR_WRITE_VALUE (file,SR_SYS_MBK,sysblk.mbk,sizeof(sysblk.mbk));
    SR_WRITE_VALUE (file,SR_SYS_MBM,sysblk.mbm,sizeof(sysblk.mbm));
    SR_WRITE_VALUE (file,SR_SYS_MBD,sysblk.mbd,sizeof(sysblk.mbd));

    for (ioq = sysblk.iointq; ioq; ioq = ioq->next)
        if (ioq->pcipending)
        {
            SR_WRITE_VALUE(file,SR_SYS_PCIPENDING_LCSS, SSID_TO_LCSS(ioq->dev->ssid),sizeof(U16));
            SR_WRITE_VALUE(file,SR_SYS_PCIPENDING, ioq->dev->devnum,sizeof(ioq->dev->devnum));
        }
        else if (ioq->attnpending)
        {
            SR_WRITE_VALUE(file,SR_SYS_ATTNPENDING_LCSS, SSID_TO_LCSS(ioq->dev->ssid),sizeof(U16));
            SR_WRITE_VALUE(file,SR_SYS_ATTNPENDING, ioq->dev->devnum,sizeof(ioq->dev->devnum));
        }
        else
        {
            SR_WRITE_VALUE(file,SR_SYS_IOPENDING_LCSS, SSID_TO_LCSS(ioq->dev->ssid),sizeof(U16));
            SR_WRITE_VALUE(file,SR_SYS_IOPENDING, ioq->dev->devnum,sizeof(ioq->dev->devnum));
        }

    for (i = 0; i < 8; i++)
        SR_WRITE_VALUE(file,SR_SYS_CHP_RESET+i,sysblk.chp_reset[i],sizeof(sysblk.chp_reset[0]));

    SR_WRITE_VALUE (file,SR_SYS_SERVPARM,sysblk.servparm,sizeof(sysblk.servparm));
    SR_WRITE_VALUE (file,SR_SYS_SIGINTREQ,sysblk.sigintreq,1);
    SR_WRITE_STRING(file,SR_SYS_LOADPARM,str_loadparm());
    SR_WRITE_VALUE (file,SR_SYS_INTS_STATE,sysblk.ints_state,sizeof(sysblk.ints_state));
    SR_WRITE_HDR(file, SR_DELIMITER, 0);

    /* Save service console state */
    TRACE("SR: Saving Service Console State...\n");
    SR_WRITE_HDR(file, SR_SYS_SERVC, 0);
    servc_hsuspend(file);
    SR_WRITE_HDR(file, SR_DELIMITER, 0);

    /* Save clock state */
    TRACE("SR: Saving Clock State...\n");
    SR_WRITE_HDR(file, SR_SYS_CLOCK, 0);
    clock_hsuspend(file);
    SR_WRITE_HDR(file, SR_DELIMITER, 0);

    /* Write CPU data */
    for (i = 0; i < sysblk.maxcpu; i++)
    {
        if (!IS_CPU_ONLINE(i)) continue;

        TRACE("SR: Saving CPU %d Data...\n", i);

        regs = sysblk.regs[i];
        SR_WRITE_VALUE(file, SR_CPU, i, sizeof(i));
        SR_WRITE_VALUE(file, SR_CPU_ARCHMODE, regs->arch_mode,sizeof(regs->arch_mode));
        SR_WRITE_VALUE(file, SR_CPU_PX, regs->PX_G,sizeof(regs->PX_G));
        copy_psw (regs, psw);
        SR_WRITE_BUF(file, SR_CPU_PSW, psw, 16);
        for (j = 0; j < 16; j++)
            SR_WRITE_VALUE(file, SR_CPU_GR+j, regs->GR_G(j),sizeof(regs->GR_G(0)));
        for (j = 0; j < 16; j++)
            SR_WRITE_VALUE(file, SR_CPU_CR+j, regs->CR_G(j),sizeof(regs->CR_G(0)));
        for (j = 0; j < 16; j++)
            SR_WRITE_VALUE(file, SR_CPU_AR+j, regs->ar[j],sizeof(regs->ar[0]));
        for (j = 0; j < 32; j++)
            SR_WRITE_VALUE(file, SR_CPU_FPR+j, regs->fpr[j],sizeof(regs->fpr[0]));
        SR_WRITE_VALUE(file, SR_CPU_FPC, regs->fpc, sizeof(regs->fpc));
        SR_WRITE_VALUE(file, SR_CPU_DXC, regs->dxc, sizeof(regs->dxc));
        SR_WRITE_VALUE(file, SR_CPU_MC, regs->MC_G, sizeof(regs->MC_G));
        SR_WRITE_VALUE(file, SR_CPU_EA, regs->EA_G, sizeof(regs->EA_G));
        SR_WRITE_VALUE(file, SR_CPU_PTIMER, cpu_timer(regs), sizeof(S64));
        SR_WRITE_VALUE(file, SR_CPU_CLKC, regs->clkc, sizeof(regs->clkc));
        SR_WRITE_VALUE(file, SR_CPU_CHANSET, regs->chanset, sizeof(regs->chanset));
        SR_WRITE_VALUE(file, SR_CPU_TODPR, regs->todpr, sizeof(regs->todpr));
        SR_WRITE_VALUE(file, SR_CPU_MONCLASS, regs->monclass, sizeof(regs->monclass));
        SR_WRITE_VALUE(file, SR_CPU_EXCARID, regs->excarid, sizeof(regs->excarid));
        SR_WRITE_VALUE(file, SR_CPU_BEAR, regs->bear, sizeof(regs->bear));
        SR_WRITE_VALUE(file, SR_CPU_OPNDRID, regs->opndrid, sizeof(regs->opndrid));
        SR_WRITE_VALUE(file, SR_CPU_CHECKSTOP, regs->checkstop, 1);
        SR_WRITE_VALUE(file, SR_CPU_HOSTINT, regs->hostint, 1);
        SR_WRITE_VALUE(file, SR_CPU_EXECFLAG, regs->execflag, 1);
//      SR_WRITE_VALUE(file, SR_CPU_INSTVALID, regs->instvalid, 1);
        SR_WRITE_VALUE(file, SR_CPU_PERMODE, regs->permode, 1);
        SR_WRITE_VALUE(file, SR_CPU_LOADSTATE, regs->loadstate, 1);
        SR_WRITE_VALUE(file, SR_CPU_INVALIDATE, regs->invalidate, 1);
        SR_WRITE_VALUE(file, SR_CPU_SIGPRESET, regs->sigpreset, 1);
        SR_WRITE_VALUE(file, SR_CPU_SIGPIRESET, regs->sigpireset, 1);
        SR_WRITE_VALUE(file, SR_CPU_INTS_STATE, regs->ints_state, sizeof(regs->ints_state));
        SR_WRITE_VALUE(file, SR_CPU_INTS_MASK, regs->ints_mask, sizeof(regs->ints_mask));
        for (j = 0; j < sysblk.maxcpu; j++)
            SR_WRITE_VALUE(file, SR_CPU_MALFCPU+j, regs->malfcpu[j], sizeof(regs->malfcpu[0]));
        for (j = 0; j < sysblk.maxcpu; j++)
            SR_WRITE_VALUE(file, SR_CPU_EMERCPU+j, regs->emercpu[j], sizeof(regs->emercpu[0]));
        SR_WRITE_VALUE(file, SR_CPU_EXTCCPU, regs->extccpu, sizeof(regs->extccpu));
        SR_WRITE_HDR(file, SR_DELIMITER, 0);
    }

    /* Write Device data */
    for (dev = sysblk.firstdev; dev; dev = dev->nextdev)
    {
        if (!(dev->pmcw.flag5 & PMCW5_V)) continue;

        TRACE("SR: Saving Device %4.4X...\n", dev->devnum);

        /* These fields must come first so the device could be attached */
        SR_WRITE_VALUE(file, SR_DEV, dev->devnum, sizeof(dev->devnum));
        SR_WRITE_VALUE(file, SR_DEV_LCSS, SSID_TO_LCSS(dev->ssid), sizeof(U16));
        SR_WRITE_VALUE(file, SR_DEV_ARGC, dev->argc, sizeof(dev->argc));
        for (i = 0; i < dev->argc; i++)
            if (dev->argv[i])
            {
                SR_WRITE_STRING(file, SR_DEV_ARGV, dev->argv[i]);
            }
            else
            {
                SR_WRITE_STRING(file, SR_DEV_ARGV, "");
            }
        SR_WRITE_STRING(file, SR_DEV_TYPNAME, dev->typname);

        /* Common device fields */
        SR_WRITE_BUF  (file, SR_DEV_ORB, &dev->orb, sizeof(ORB));
        SR_WRITE_BUF  (file, SR_DEV_PMCW, &dev->pmcw, sizeof(PMCW));
        SR_WRITE_BUF  (file, SR_DEV_SCSW, &dev->scsw, sizeof(SCSW));
        SR_WRITE_BUF  (file, SR_DEV_PCISCSW, &dev->pciscsw, sizeof(SCSW));
        SR_WRITE_BUF  (file, SR_DEV_ATTNSCSW, &dev->attnscsw, sizeof(SCSW));
        SR_WRITE_BUF  (file, SR_DEV_CSW, dev->csw, 8);
        SR_WRITE_BUF  (file, SR_DEV_PCICSW, dev->pcicsw, 8);
        SR_WRITE_BUF  (file, SR_DEV_ATTNCSW, dev->attncsw, 8);
        SR_WRITE_BUF  (file, SR_DEV_ESW, &dev->esw, sizeof(ESW));
        SR_WRITE_BUF  (file, SR_DEV_ECW, dev->ecw, 32);
        SR_WRITE_BUF  (file, SR_DEV_SENSE, dev->sense, 32);
        SR_WRITE_VALUE(file, SR_DEV_PGSTAT, dev->pgstat, sizeof(dev->pgstat));
        SR_WRITE_BUF  (file, SR_DEV_PGID, dev->pgid, 11);
        /* By Adrian - SR_DEV_DRVPWD */
        SR_WRITE_BUF  (file, SR_DEV_DRVPWD, dev->drvpwd, 11);
        SR_WRITE_VALUE(file, SR_DEV_BUSY, dev->busy, 1);
        SR_WRITE_VALUE(file, SR_DEV_RESERVED, dev->reserved, 1);
        SR_WRITE_VALUE(file, SR_DEV_SUSPENDED, dev->suspended, 1);
        SR_WRITE_VALUE(file, SR_DEV_PCIPENDING, dev->pcipending, 1);
        SR_WRITE_VALUE(file, SR_DEV_ATTNPENDING, dev->attnpending, 1);
        SR_WRITE_VALUE(file, SR_DEV_PENDING, dev->pending, 1);
        SR_WRITE_VALUE(file, SR_DEV_STARTPENDING, dev->startpending, 1);
        SR_WRITE_VALUE(file, SR_DEV_CRWPENDING, dev->crwpending, 1);
        SR_WRITE_VALUE(file, SR_DEV_CCWADDR, dev->ccwaddr, sizeof(dev->ccwaddr));
        SR_WRITE_VALUE(file, SR_DEV_IDAPMASK, dev->idapmask, sizeof(dev->idapmask));
        SR_WRITE_VALUE(file, SR_DEV_IDAWFMT, dev->idawfmt, sizeof(dev->idawfmt));
        SR_WRITE_VALUE(file, SR_DEV_CCWFMT, dev->ccwfmt, sizeof(dev->ccwfmt));
        SR_WRITE_VALUE(file, SR_DEV_CCWKEY, dev->ccwkey, sizeof(dev->ccwkey));

        /* Device type specific data */
        SR_WRITE_VALUE(file, SR_DEV_DEVTYPE, dev->devtype, sizeof(dev->devtype));
        if (dev->hnd->hsuspend)
        {
            rc = (dev->hnd->hsuspend) (dev, file);
            if (rc < 0) goto sr_error_exit;
        }
        SR_WRITE_HDR(file, SR_DELIMITER, 0);
    }

    TRACE("SR: Writing EOF\n");

    SR_WRITE_HDR(file, SR_EOF, 0);
    SR_CLOSE (file);

    TRACE("SR: Suspend Complete; shutting down...\n");

    /* Shutdown */
    do_shutdown();

    return 0;

sr_error_exit:
    // "SR: error processing file '%s'"
    WRMSG(HHC02004, "E", fn);
    SR_CLOSE (file);
    return -1;
}
Example #6
0
int resume_cmd(int argc, char *argv[],char *cmdline)
{
char    *fn = SR_DEFAULT_FILENAME;
SR_FILE *file;
U32      key = 0, len = 0;
U64      mainsize = 0;
U64      xpndsize = 0;
CPU_BITMAP started_mask = 0;
int      i, rc = -1;
REGS    *regs = NULL;
U16      devnum=0;
U16      lcss=0;
U16      hw;
int      devargc=0;
char    *devargv[16];
int      devargx=0;
DEVBLK  *dev = NULL;
IOINT   *ioq = NULL;
char     buf[SR_MAX_STRING_LENGTH+1];
char     zeros[16];
S64      dreg;

    UNREFERENCED(cmdline);

    if (argc > 2)
    {
        // "SR: too many arguments"
        WRMSG(HHC02000, "E");
        return -1;
    }

    if (argc == 2)
        fn = argv[1];

    memset (zeros, 0, sizeof(zeros));

    TRACE("SR: Begin Resume Processing...\n");

    /* Make sure all CPUs are deconfigured or stopped */
    TRACE("SR: Waiting for CPUs to stop...\n");
    OBTAIN_INTLOCK(NULL);
    for (i = 0; i < sysblk.maxcpu; i++)
        if (IS_CPU_ONLINE(i)
         && CPUSTATE_STOPPED != sysblk.regs[i]->cpustate)
        {
            RELEASE_INTLOCK(NULL);
            // "SR: all processors must be stopped to resume"
            WRMSG(HHC02005, "E");
            return -1;
        }
    RELEASE_INTLOCK(NULL);

    file = SR_OPEN (fn, "rb");
    if (file == NULL)
    {
        // "SR: error in function '%s': '%s'"
        WRMSG(HHC02001, "E", "open()",strerror(errno));
        return -1;
    }

    /* First key must be SR_HDR_ID and string must match SR_ID */
    TRACE("SR: Reading File Header...\n");
    SR_READ_HDR(file, key, len);
    if (key == SR_HDR_ID) SR_READ_STRING(file, buf, len);
    if (key != SR_HDR_ID || strcmp(buf, SR_ID))
    {
        // "SR: file identifier error"
        WRMSG(HHC02006, "E");
        goto sr_error_exit;
    }

    /* Deconfigure all CPUs */
    TRACE("SR: Deconfiguring all CPUs...\n");
    OBTAIN_INTLOCK(NULL);
    for (i = 0; i < sysblk.maxcpu; i++)
        if (IS_CPU_ONLINE(i))
            deconfigure_cpu(i);
    RELEASE_INTLOCK(NULL);

    TRACE("SR: Processing Resume File...\n");

    while (key != SR_EOF)
    {
        SR_READ_HDR(file, key, len);
        switch (key) {

        case SR_HDR_DATE:
            SR_READ_STRING(file, buf, len);
            if (len >= 2)
            {
                len -= 2;
                while (len > 0 && isspace(buf[len]))
                    --len;
                buf[len+1]=0;
            }
            // "SR: resuming suspended file created on '%s'"
            WRMSG(HHC02007, "I", buf);
            break;

        case SR_SYS_STARTED_MASK:
            SR_READ_VALUE(file, len, &started_mask, sizeof(started_mask));
            break;

        case SR_SYS_ARCH_NAME:
            SR_READ_STRING(file, buf, len);
            i = -1;
#if defined (_370)
            if (strcasecmp (buf, arch_name[ARCH_370]) == 0)
            {
                i = ARCH_370;
            }
#endif
#if defined (_390)
            if (strcasecmp (buf, arch_name[ARCH_390]) == 0)
            {
                i = ARCH_390;
            }
#endif
#if defined (_900)
            if (0
                || strcasecmp (buf, arch_name[ARCH_900]) == 0
                || strcasecmp (buf, "ESAME") == 0
            )
            {
                i = ARCH_900;
            }
#endif
            if (i < 0)
            {
                // "SR: archmode '%s' not supported"
                WRMSG(HHC02008, "E", buf);
                goto sr_error_exit;
            }
            sysblk.arch_mode = i;
            sysblk.pcpu = 0;
            sysblk.dummyregs.arch_mode = sysblk.arch_mode;
#if defined(OPTION_FISHIO)
            ios_arch_mode = sysblk.arch_mode;
#endif
            break;

        case SR_SYS_MAINSIZE:
            SR_READ_VALUE(file, len, &mainsize, sizeof(mainsize));
            if (mainsize > sysblk.mainsize)
            {
                char buf1[20];
                char buf2[20];
                MSGBUF(buf1, "%dM", (U32)(mainsize / (1024*1024)));
                MSGBUF(buf2, "%dM", (U32)(sysblk.mainsize / (1024*1024)));
                // "SR: mismatch in '%s': '%s' found, '%s' expected"
                WRMSG(HHC02009, "E", "mainsize", buf1, buf2);
                goto sr_error_exit;
            }
            break;

        case SR_SYS_MAINSTOR:
            TRACE("SR: Restoring MAINSTOR...\n");
            SR_READ_BUF(file, sysblk.mainstor, mainsize);
            break;

        case SR_SYS_SKEYSIZE:
            SR_READ_VALUE(file, len, &len, sizeof(len));
            if (len > (U32)(sysblk.mainsize/STORAGE_KEY_UNITSIZE))
            {
                char buf1[20];
                char buf2[20];
                MSGBUF(buf1, "%d", len);
                MSGBUF(buf2, "%d", (U32)(sysblk.mainsize/STORAGE_KEY_UNITSIZE));
                // "SR: mismatch in '%s': '%s' found, '%s' expected"
                WRMSG(HHC02009, "E", "storkey size", buf1, buf2);
                goto sr_error_exit;
            }
            break;

        case SR_SYS_STORKEYS:
            TRACE("SR: Restoring Storage Keys...\n");
            SR_READ_BUF(file, sysblk.storkeys, len);
            break;

        case SR_SYS_XPNDSIZE:
            SR_READ_VALUE(file, len, &xpndsize, sizeof(xpndsize));
            if (xpndsize > sysblk.xpndsize)
            {
                char buf1[20];
                char buf2[20];
                MSGBUF(buf1, "%dM", (U32)(xpndsize / (256)));
                MSGBUF(buf2, "%dM", sysblk.xpndsize / (256));
                // "SR: mismatch in '%s': '%s' found, '%s' expected"
                WRMSG(HHC02009, "E", "expand size", buf1, buf2);
                goto sr_error_exit;
            }
            break;

        case SR_SYS_XPNDSTOR:
            TRACE("SR: Restoring Expanded Storage...\n");
            SR_READ_BUF(file, sysblk.xpndstor, xpndsize * 4096);
            break;

        case SR_SYS_IPLDEV:
            SR_READ_VALUE(file, len, &sysblk.ipldev, sizeof(sysblk.ipldev));
            break;

        case SR_SYS_IPLCPU:
            SR_READ_VALUE(file, len, &sysblk.iplcpu, sizeof(sysblk.iplcpu));
            break;

        case SR_SYS_MBO:
            SR_READ_VALUE(file, len, &sysblk.mbo, sizeof(sysblk.mbo));
            break;

        case SR_SYS_MBK:
            SR_READ_VALUE(file, len, &sysblk.mbk, sizeof(sysblk.mbk));
            break;

        case SR_SYS_MBM:
            SR_READ_VALUE(file, len, &sysblk.mbm, sizeof(sysblk.mbm));
            break;

        case SR_SYS_MBD:
            SR_READ_VALUE(file, len, &sysblk.mbd, sizeof(sysblk.mbd));
            break;

        case SR_SYS_IOPENDING_LCSS:
            SR_READ_VALUE(file,len,&lcss,sizeof(lcss));
            break;

        case SR_SYS_IOPENDING:
            SR_READ_VALUE(file, len, &hw, sizeof(hw));
            dev = find_device_by_devnum(lcss,hw);
            if (dev == NULL) break;
            if (ioq == NULL)
                sysblk.iointq = &dev->ioint;
            else
                ioq->next = &dev->ioint;
            ioq = &dev->ioint;
            dev = NULL;
            lcss = 0;
            break;

        case SR_SYS_PCIPENDING_LCSS:
            SR_READ_VALUE(file,len,&lcss,sizeof(lcss));
            break;

        case SR_SYS_PCIPENDING:
            SR_READ_VALUE(file, len, &hw, sizeof(hw));
            dev = find_device_by_devnum(lcss,hw);
            if (dev == NULL) break;
            if (ioq == NULL)
                sysblk.iointq = &dev->pciioint;
            else
                ioq->next = &dev->pciioint;
            ioq = &dev->pciioint;
            dev = NULL;
            lcss = 0;
            break;

        case SR_SYS_ATTNPENDING_LCSS:
            SR_READ_VALUE(file,len,&lcss,sizeof(lcss));
            break;

        case SR_SYS_ATTNPENDING:
            SR_READ_VALUE(file, len, &hw, sizeof(hw));
            dev = find_device_by_devnum(lcss,hw);
            if (dev == NULL) break;
            if (ioq == NULL)
                sysblk.iointq = &dev->attnioint;
            else
                ioq->next = &dev->attnioint;
            ioq = &dev->attnioint;
            dev = NULL;
            lcss = 0;
            break;

        case SR_SYS_CHP_RESET_0:
        case SR_SYS_CHP_RESET_1:
        case SR_SYS_CHP_RESET_2:
        case SR_SYS_CHP_RESET_3:
        case SR_SYS_CHP_RESET_4:
        case SR_SYS_CHP_RESET_5:
        case SR_SYS_CHP_RESET_6:
        case SR_SYS_CHP_RESET_7:
            i = key - SR_SYS_CHP_RESET;
            SR_READ_VALUE(file, len, &sysblk.chp_reset[i], sizeof(sysblk.chp_reset[0]));
            break;

        case SR_SYS_SERVPARM:
            SR_READ_VALUE(file, len, &sysblk.servparm, sizeof(sysblk.servparm));
            break;

        case SR_SYS_SIGINTREQ:
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            sysblk.sigintreq = rc;
            break;

        case SR_SYS_LOADPARM:
            SR_READ_STRING(file, buf, len);
            set_loadparm ((char *)buf);
            break;

        case SR_SYS_SERVC:
            TRACE("SR: Restoring Service Console State...\n");
            rc = servc_hresume(file);
            if (rc < 0) goto sr_error_exit;
            break;

        case SR_SYS_CLOCK:
            TRACE("SR: Restoring Clock State...\n");
            rc = clock_hresume(file);
            if (rc < 0) goto sr_error_exit;
            break;

        case SR_CPU:
            SR_READ_VALUE(file, len, &i, sizeof(i));
            TRACE("SR: Restoring CPU %d Data...\n", i);
            if (i >= sysblk.maxcpu)
            {
                // "SR: processor CP%02X exceeds max allowed CP%02X"
                WRMSG(HHC02010, "E", i, sysblk.maxcpu-1);
                goto sr_error_exit;
            }
            OBTAIN_INTLOCK(NULL);
            if (IS_CPU_ONLINE(i))
            {
                RELEASE_INTLOCK(NULL);
                // "SR: processor %s%02X already configured"
                WRMSG(HHC02011, "E", PTYPSTR(i), i);
                goto sr_error_exit;
            }
            rc = configure_cpu(i);
            RELEASE_INTLOCK(NULL);
            if (rc < 0)
            {
                // "SR: processor %s%02X unable to configure online"
                WRMSG(HHC02012, "E", PTYPSTR(i), i);
                goto sr_error_exit;
            }
            regs = sysblk.regs[i];
            break;

        case SR_CPU_PX:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->px, sizeof(regs->px));
            break;

        case SR_CPU_PSW:
            SR_NULL_REGS_CHECK(regs);
            if (len != 8 && len != 16)
            {
                // "SR: processor %s%02X invalid psw length %d"
                WRMSG(HHC02013, "E", PTYPSTR(regs->cpuad), regs->cpuad, len);
                goto sr_error_exit;
            }
            memset(buf, 0, 16);
            SR_READ_BUF(file, buf, len);
            switch (regs->arch_mode) {
#if defined (_370)
            case ARCH_370:
                len = 8;
                rc = s370_load_psw(regs, (BYTE *)&buf);
                break;
#endif
#if defined (_390)
            case ARCH_390:
                len = 8;
                rc = s390_load_psw(regs, (BYTE *)&buf);
                break;
#endif
#if defined (_900)
            case ARCH_900:
                len = 16;
                rc = z900_load_psw(regs, (BYTE *)&buf);
                break;
#endif
            } /* switch (regs->arch_mode) */
            if (rc != 0 && memcmp(buf, zeros, len))
            {
                // "SR: processor %s%02X error loading psw, rc %d"
                WRMSG(HHC02014, "E", PTYPSTR(regs->cpuad), regs->cpuad, rc);
                goto sr_error_exit;
            }
            break;

        case SR_CPU_GR_0:
        case SR_CPU_GR_1:
        case SR_CPU_GR_2:
        case SR_CPU_GR_3:
        case SR_CPU_GR_4:
        case SR_CPU_GR_5:
        case SR_CPU_GR_6:
        case SR_CPU_GR_7:
        case SR_CPU_GR_8:
        case SR_CPU_GR_9:
        case SR_CPU_GR_10:
        case SR_CPU_GR_11:
        case SR_CPU_GR_12:
        case SR_CPU_GR_13:
        case SR_CPU_GR_14:
        case SR_CPU_GR_15:
            SR_NULL_REGS_CHECK(regs);
            i = key - SR_CPU_GR;
            SR_READ_VALUE(file, len, &regs->gr[i], sizeof(regs->gr[0]));
            break;

        case SR_CPU_CR_0:
        case SR_CPU_CR_1:
        case SR_CPU_CR_2:
        case SR_CPU_CR_3:
        case SR_CPU_CR_4:
        case SR_CPU_CR_5:
        case SR_CPU_CR_6:
        case SR_CPU_CR_7:
        case SR_CPU_CR_8:
        case SR_CPU_CR_9:
        case SR_CPU_CR_10:
        case SR_CPU_CR_11:
        case SR_CPU_CR_12:
        case SR_CPU_CR_13:
        case SR_CPU_CR_14:
        case SR_CPU_CR_15:
            SR_NULL_REGS_CHECK(regs);
            i = key - SR_CPU_CR;
            SR_READ_VALUE(file, len, &regs->CR(i), sizeof(regs->CR(0)));
            break;

        case SR_CPU_AR_0:
        case SR_CPU_AR_1:
        case SR_CPU_AR_2:
        case SR_CPU_AR_3:
        case SR_CPU_AR_4:
        case SR_CPU_AR_5:
        case SR_CPU_AR_6:
        case SR_CPU_AR_7:
        case SR_CPU_AR_8:
        case SR_CPU_AR_9:
        case SR_CPU_AR_10:
        case SR_CPU_AR_11:
        case SR_CPU_AR_12:
        case SR_CPU_AR_13:
        case SR_CPU_AR_14:
        case SR_CPU_AR_15:
            SR_NULL_REGS_CHECK(regs);
            i = key - SR_CPU_AR;
            SR_READ_VALUE(file, len, &regs->ar[i], sizeof(regs->ar[0]));
            break;

        case SR_CPU_FPR_0:
        case SR_CPU_FPR_1:
        case SR_CPU_FPR_2:
        case SR_CPU_FPR_3:
        case SR_CPU_FPR_4:
        case SR_CPU_FPR_5:
        case SR_CPU_FPR_6:
        case SR_CPU_FPR_7:
        case SR_CPU_FPR_8:
        case SR_CPU_FPR_9:
        case SR_CPU_FPR_10:
        case SR_CPU_FPR_11:
        case SR_CPU_FPR_12:
        case SR_CPU_FPR_13:
        case SR_CPU_FPR_14:
        case SR_CPU_FPR_15:
        case SR_CPU_FPR_16:
        case SR_CPU_FPR_17:
        case SR_CPU_FPR_18:
        case SR_CPU_FPR_19:
        case SR_CPU_FPR_20:
        case SR_CPU_FPR_21:
        case SR_CPU_FPR_22:
        case SR_CPU_FPR_23:
        case SR_CPU_FPR_24:
        case SR_CPU_FPR_25:
        case SR_CPU_FPR_26:
        case SR_CPU_FPR_27:
        case SR_CPU_FPR_28:
        case SR_CPU_FPR_29:
        case SR_CPU_FPR_30:
        case SR_CPU_FPR_31:
            SR_NULL_REGS_CHECK(regs);
            i = key - SR_CPU_FPR;
            SR_READ_VALUE(file, len, &regs->fpr[i], sizeof(regs->fpr[0]));
            break;

        case SR_CPU_FPC:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->fpc, sizeof(regs->fpc));
            break;

        case SR_CPU_DXC:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->dxc, sizeof(regs->dxc));
            break;

        case SR_CPU_MC:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->mc, sizeof(regs->mc));
            break;

        case SR_CPU_EA:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->ea, sizeof(regs->ea));
            break;

        case SR_CPU_PTIMER:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &dreg, sizeof(S64));
            set_cpu_timer(regs, dreg);
            break;

        case SR_CPU_CLKC:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->clkc, sizeof(regs->clkc));
            break;

        case SR_CPU_CHANSET:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->chanset, sizeof(regs->chanset));
            break;

        case SR_CPU_TODPR:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->todpr, sizeof(regs->todpr));
            break;

        case SR_CPU_MONCLASS:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->monclass, sizeof(regs->monclass));
            break;

        case SR_CPU_EXCARID:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->excarid, sizeof(regs->excarid));
            break;

        case SR_CPU_BEAR:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->bear, sizeof(regs->bear));
            break;

        case SR_CPU_OPNDRID:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->opndrid, sizeof(regs->opndrid));
            break;

        case SR_CPU_CHECKSTOP:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            regs->checkstop = rc;
            break;

        case SR_CPU_HOSTINT:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            regs->hostint = rc;
            break;

        case SR_CPU_LOADSTATE:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            regs->loadstate = rc;
            break;

        case SR_CPU_INVALIDATE:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            regs->invalidate = rc;
            break;

        case SR_CPU_SIGPRESET:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            regs->sigpreset = rc;
            break;

        case SR_CPU_SIGPIRESET:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            regs->sigpireset = rc;
            break;

        case SR_CPU_INTS_STATE:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->ints_state, sizeof(regs->ints_state));
            /* Force CPU to examine the interrupt state */
            ON_IC_INTERRUPT(regs);
            break;

        case SR_CPU_INTS_MASK:
            SR_NULL_REGS_CHECK(regs);
            SR_READ_VALUE(file, len, &regs->ints_mask, sizeof(regs->ints_mask));
            break;

        case SR_CPU_MALFCPU_0:
        case SR_CPU_MALFCPU_1:
        case SR_CPU_MALFCPU_2:
        case SR_CPU_MALFCPU_3:
        case SR_CPU_MALFCPU_4:
        case SR_CPU_MALFCPU_5:
        case SR_CPU_MALFCPU_6:
        case SR_CPU_MALFCPU_7:
        case SR_CPU_MALFCPU_8:
        case SR_CPU_MALFCPU_9:
        case SR_CPU_MALFCPU_10:
        case SR_CPU_MALFCPU_11:
        case SR_CPU_MALFCPU_12:
        case SR_CPU_MALFCPU_13:
        case SR_CPU_MALFCPU_14:
        case SR_CPU_MALFCPU_15:
        case SR_CPU_MALFCPU_16:
        case SR_CPU_MALFCPU_17:
        case SR_CPU_MALFCPU_18:
        case SR_CPU_MALFCPU_19:
        case SR_CPU_MALFCPU_20:
        case SR_CPU_MALFCPU_21:
        case SR_CPU_MALFCPU_22:
        case SR_CPU_MALFCPU_23:
        case SR_CPU_MALFCPU_24:
        case SR_CPU_MALFCPU_25:
        case SR_CPU_MALFCPU_26:
        case SR_CPU_MALFCPU_27:
        case SR_CPU_MALFCPU_28:
        case SR_CPU_MALFCPU_29:
        case SR_CPU_MALFCPU_30:
        case SR_CPU_MALFCPU_31:
            SR_NULL_REGS_CHECK(regs);
            i = key - SR_CPU_MALFCPU;
            if (i < sysblk.maxcpu)
                SR_READ_VALUE(file, len, &regs->malfcpu[i], sizeof(regs->malfcpu[0]));
            break;

        case SR_CPU_EMERCPU_0:
        case SR_CPU_EMERCPU_1:
        case SR_CPU_EMERCPU_2:
        case SR_CPU_EMERCPU_3:
        case SR_CPU_EMERCPU_4:
        case SR_CPU_EMERCPU_5:
        case SR_CPU_EMERCPU_6:
        case SR_CPU_EMERCPU_7:
        case SR_CPU_EMERCPU_8:
        case SR_CPU_EMERCPU_9:
        case SR_CPU_EMERCPU_10:
        case SR_CPU_EMERCPU_11:
        case SR_CPU_EMERCPU_12:
        case SR_CPU_EMERCPU_13:
        case SR_CPU_EMERCPU_14:
        case SR_CPU_EMERCPU_15:
        case SR_CPU_EMERCPU_16:
        case SR_CPU_EMERCPU_17:
        case SR_CPU_EMERCPU_18:
        case SR_CPU_EMERCPU_19:
        case SR_CPU_EMERCPU_20:
        case SR_CPU_EMERCPU_21:
        case SR_CPU_EMERCPU_22:
        case SR_CPU_EMERCPU_23:
        case SR_CPU_EMERCPU_24:
        case SR_CPU_EMERCPU_25:
        case SR_CPU_EMERCPU_26:
        case SR_CPU_EMERCPU_27:
        case SR_CPU_EMERCPU_28:
        case SR_CPU_EMERCPU_29:
        case SR_CPU_EMERCPU_30:
        case SR_CPU_EMERCPU_31:
            SR_NULL_REGS_CHECK(regs);
            i = key - SR_CPU_EMERCPU;
            if (i < sysblk.maxcpu)
                SR_READ_VALUE(file, len, &regs->emercpu[i], sizeof(regs->emercpu[0]));
            break;

        case SR_DEV:
            SR_READ_VALUE(file, len, &devnum, sizeof(devnum));
            TRACE("SR: Restoring Device %4.4X...\n", devnum);
            lcss=0;
            break;

        case SR_DEV_LCSS:
            SR_READ_VALUE(file, len, &lcss, sizeof(U16));
            break;

        case SR_DEV_ARGC:
            SR_READ_VALUE(file, len, &devargc, sizeof(devargc));
            if (devargc > 16) devargc = 16;
            for (i = 0; i < devargc; i++) devargv[i] = NULL;
            devargx = 0;
            break;

        case SR_DEV_ARGV:
            SR_READ_STRING(file, buf, len);
            if (devargx < devargc) devargv[devargx++] = strdup(buf);
            break;

        case SR_DEV_TYPNAME:
            SR_READ_STRING(file, buf, len);
            dev = find_device_by_devnum(lcss,devnum);
            if (dev == NULL)
            {
                if (attach_device (lcss, devnum, buf, devargc, devargv))
                {
                    // "SR: %04X: device initialization failed"
                    WRMSG(HHC02015, "E", devnum);
                }
            }
            else if (strcmp(dev->typname, buf))
            {
                // "SR: %04X: device type mismatch; '%s' found, '%s' expected"
                WRMSG(HHC02016, "W", devnum, buf, dev->typname);
                dev = NULL;
            }
            for (i = 0; i < devargx; i++)
            {
                if (devargv[i]) free(devargv[i]);
                devargv[i] = NULL;
            }
            devnum = devargc = devargx = 0;
            break;

        case SR_DEV_ORB:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != sizeof(ORB))
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "ORB", len, (int)sizeof(ORB));
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->orb, len);
            break;

        case SR_DEV_PMCW:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != sizeof(PMCW))
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "PMCW", len, (int)sizeof(PMCW));
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->pmcw, len);
            break;

        case SR_DEV_SCSW:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != sizeof(SCSW))
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "SCSW", len, (int)sizeof(SCSW));
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->scsw, len);
            break;

        case SR_DEV_PCISCSW:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != sizeof(SCSW))
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "PCI SCSW", len, (int)sizeof(SCSW));
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->pciscsw, len);
            break;

        case SR_DEV_ATTNSCSW:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != sizeof(SCSW))
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "ATTN SCSW", len, (int)sizeof(SCSW));
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->attnscsw, len);
            break;

        case SR_DEV_CSW:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != 8)
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "CSW", len, 8);
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->csw, len);
            break;

        case SR_DEV_PCICSW:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != 8)
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "PCI CSW", len, 8);
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->pcicsw, len);
            break;

        case SR_DEV_ATTNCSW:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != 8)
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "ATTN CSW", len, 8);
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->attncsw, len);
            break;

        case SR_DEV_ESW:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != sizeof(ESW))
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "ESW", len, (int)sizeof(ESW));
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->esw, len);
            break;

        case SR_DEV_ECW:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != 32)
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "ECW", len, 32);
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->ecw, len);
            break;

        case SR_DEV_SENSE:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != 32)
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "Sense", len, 32);
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->ecw, len);
            break;

        case SR_DEV_PGSTAT:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &dev->pgstat, sizeof(dev->pgstat));
            break;

        case SR_DEV_PGID:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != 11)
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "PGID", len, 11);
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->pgid, len);
            break;
   
        /* By Adrian - SR_DEV_DRVPWD */
        case SR_DEV_DRVPWD:
            SR_SKIP_NULL_DEV(dev, file, len);
            if (len != 11)
            {
                // "SR: %04X: '%s' size mismatch: %d found, %d expected"
                WRMSG(HHC02017, "E", dev->devnum, "DRVPWD", len, 11);
                goto sr_error_exit;
            }
            SR_READ_BUF(file, &dev->drvpwd, len);
            break;   
   
   

        case SR_DEV_BUSY:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            dev->busy = rc;
            break;

        case SR_DEV_RESERVED:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            dev->reserved = rc;
            break;

        case SR_DEV_SUSPENDED:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            dev->suspended = rc;
            break;

        case SR_DEV_PENDING:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            dev->pending = rc;
            QUEUE_IO_INTERRUPT(&dev->ioint);
            break;

        case SR_DEV_PCIPENDING:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            dev->pcipending = rc;
            QUEUE_IO_INTERRUPT(&dev->pciioint);
            break;

        case SR_DEV_ATTNPENDING:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            dev->attnpending = rc;
            QUEUE_IO_INTERRUPT(&dev->attnioint);
            break;

        case SR_DEV_STARTPENDING:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            dev->startpending = rc;
            break;

        case SR_DEV_CRWPENDING:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &rc, sizeof(rc));
            dev->crwpending = rc;
            break;

        case SR_DEV_CCWADDR:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &dev->ccwaddr, sizeof(dev->ccwaddr));
            break;

        case SR_DEV_IDAPMASK:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &dev->idapmask, sizeof(dev->idapmask));
            break;

        case SR_DEV_IDAWFMT:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &dev->idawfmt, sizeof(dev->idawfmt));
            break;

        case SR_DEV_CCWFMT:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &dev->ccwfmt, sizeof(dev->ccwfmt));
            break;

        case SR_DEV_CCWKEY:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &dev->ccwkey, sizeof(dev->ccwkey));
            break;

        /* This is the trigger to call the device dependent resume routine */
        case SR_DEV_DEVTYPE:
            SR_SKIP_NULL_DEV(dev, file, len);
            SR_READ_VALUE(file, len, &hw, sizeof(hw));
            if (hw != dev->devtype)
            {
                char buf1[20];
                char buf2[20];
                MSGBUF(buf1, "%04X", hw);
                MSGBUF(buf2, "%04X", dev->devtype);
                // "SR: %04X: device type mismatch; '%s' found, '%s' expected"
                WRMSG(HHC02016, "E", dev->devnum, buf1, buf2);
                goto sr_error_exit;
            }
            if (dev->hnd->hresume)
            {
                rc = (dev->hnd->hresume) (dev, file);
                if (rc < 0) goto sr_error_exit;
            }
            break;

        default:
            if ((key & SR_KEY_ID_MASK) != SR_KEY_ID)
            {
                // "SR: invalid key %8.8X"
                WRMSG(HHC02018, "E", key);
                goto sr_error_exit;
            }
            SR_READ_SKIP(file, len);
            break;

        } /* switch (key) */

    } /* while (key != SR_EOF) */

    TRACE("SR: Resume File Processing Complete...\n");
    TRACE("SR: Resuming Devices...\n");

    /* For all suspended devices, resume the `suspended' state */
    for (dev = sysblk.firstdev; dev; dev = dev->nextdev)
    {
        if (dev->suspended && (dev->pmcw.flag5 & PMCW5_V))
        {
            dev->resumesuspended=1;
            switch (sysblk.arch_mode) {
#if defined(_370)
            case ARCH_370:
                rc = create_thread (&dev->tid, DETACHED,
                                    s370_execute_ccw_chain, dev, "device thread");
                break;
#endif
#if defined(_390)
            case ARCH_390:
                rc = create_thread (&dev->tid, DETACHED,
                                    s390_execute_ccw_chain, dev, "device thread");
                break;
#endif
#if defined(_900)
            case ARCH_900:
                rc = create_thread (&dev->tid, DETACHED,
                                    z900_execute_ccw_chain, dev, "device thread");
                break;
#endif
            } /* switch (sysblk.arch_mode) */
            if (rc != 0)
            {
                // "Error in function create_thread(): %s"
                WRMSG(HHC00102, "E", strerror(rc));
                goto sr_error_exit;
            }
        } /* If suspended device */
    } /* For each device */

    /* Indicate crw pending for any new devices */
#if defined(_370)
    if (sysblk.arch_mode != ARCH_370)
#endif
    machine_check_crwpend();

    /* Start the CPUs */
    TRACE("SR: Resuming CPUs...\n");
    OBTAIN_INTLOCK(NULL);
    ON_IC_IOPENDING;
    for (i = 0; i < sysblk.maxcpu; i++)
        if (IS_CPU_ONLINE(i) && (started_mask & CPU_BIT(i)))
        {
            sysblk.regs[i]->opinterv = 0;
            sysblk.regs[i]->cpustate = CPUSTATE_STARTED;
            sysblk.regs[i]->checkstop = 0;
            WAKEUP_CPU(sysblk.regs[i]);
        }
    RELEASE_INTLOCK(NULL);

    TRACE("SR: Resume Complete; System Resumed.\n");
    return 0;

sr_null_regs_exit:
    // "SR: CPU key %8.8X found but no active CPU"
    WRMSG(HHC02019, "E", key);
    goto sr_error_exit;
sr_error_exit:
    // "SR: error processing file '%s'"
    WRMSG(HHC02004, "E", fn);
    SR_CLOSE (file);
    return -1;
}
Example #7
0
void sigabend_handler (int signo)
{
REGS *regs = NULL;
TID tid;
int i;

    tid = thread_id();

    if( signo == SIGUSR2 )
    {
    DEVBLK *dev;
        if (0
            || equal_threads( tid, sysblk.cnsltid )
            || equal_threads( tid, sysblk.socktid )
#if defined(OPTION_SHARED_DEVICES)
            || equal_threads( tid, sysblk.shrdtid )
#endif // defined(OPTION_SHARED_DEVICES)
            || equal_threads( tid, sysblk.httptid )
        )
            return;
        for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
            if (0
                || equal_threads( dev->tid, tid )
#if defined(OPTION_SHARED_DEVICES)
                || equal_threads( dev->shrdtid, tid )
#endif // defined(OPTION_SHARED_DEVICES)
            )
                 break;
        if( dev == NULL)
        {
            if (!sysblk.shutdown)
                WRMSG(HHC00825, "E");
        }
        else
            if(dev->ccwtrace)
                WRMSG(HHC00826, "E", SSID_TO_LCSS(dev->ssid), dev->devnum);
        return;
    }

    for (i = 0; i < sysblk.maxcpu; i++)
    {
        if ( equal_threads( sysblk.cputid[i], tid ) )
        {
            regs = sysblk.regs[i];
            break;
        }
    }

    if (regs == NULL)
    {
        signal(signo, SIG_DFL);
        raise(signo);
        return;
    }

    if(MACHMASK(&regs->psw))
    {
#if defined(_FEATURE_SIE)
        WRMSG(HHC00822, "I", regs->sie_active ? "IE" : PTYPSTR(regs->cpuad),
            regs->sie_active ? regs->guestregs->cpuad : regs->cpuad,
            strsignal(signo) );
#else /*!defined(_FEATURE_SIE)*/
        WRMSG(HHC00822, "I", PTYPSTR(regs->cpuad), regs->cpuad, strsignal(signo));
#endif /*!defined(_FEATURE_SIE)*/

        display_inst(
#if defined(_FEATURE_SIE)
                     regs->sie_active ? regs->guestregs :
#endif /*defined(_FEATURE_SIE)*/
                                                          regs,
#if defined(_FEATURE_SIE)
          regs->sie_active ? regs->guestregs->ip :
#endif /*defined(_FEATURE_SIE)*/
                                                   regs->ip);

        switch(regs->arch_mode) {
#if defined(_370)
            case ARCH_370:
                s370_sync_mck_interrupt(regs);
                break;
#endif
#if defined(_390)
            case ARCH_390:
                s390_sync_mck_interrupt(regs);
                break;
#endif
#if defined(_900)
            case ARCH_900:
                z900_sync_mck_interrupt(regs);
                break;
#endif
        }
    }
    else
    {
#if defined(_FEATURE_SIE)
        WRMSG(HHC00823, "I", regs->sie_active ? "IE" : PTYPSTR(regs->cpuad),
            regs->sie_active ? regs->guestregs->cpuad : regs->cpuad,
            strsignal(signo));
#else /*!defined(_FEATURE_SIE)*/
        WRMSG(HHC00823, "I", PTYPSTR(regs->cpuad), regs->cpuad, strsignal(signo));
#endif /*!defined(_FEATURE_SIE)*/
        display_inst(
#if defined(_FEATURE_SIE)
                     regs->sie_active ? regs->guestregs :
#endif /*defined(_FEATURE_SIE)*/
                                                          regs,
#if defined(_FEATURE_SIE)
          regs->sie_active ? regs->guestregs->ip :
#endif /*defined(_FEATURE_SIE)*/
                                                   regs->ip);
        regs->cpustate = CPUSTATE_STOPPING;
        regs->checkstop = 1;
        ON_IC_INTERRUPT(regs);

        /* Notify other CPU's by means of a malfuction alert if possible */
        if (!try_obtain_lock(&sysblk.sigplock))
        {
            if(!try_obtain_lock(&sysblk.intlock))
            {
                for (i = 0; i < sysblk.maxcpu; i++)
                    if (i != regs->cpuad && IS_CPU_ONLINE(i))
                    {
                        ON_IC_MALFALT(sysblk.regs[i]);
                        sysblk.regs[i]->malfcpu[regs->cpuad] = 1;
                    }
                release_lock(&sysblk.intlock);
            }
            release_lock(&sysblk.sigplock);
        }

    }

    longjmp (regs->progjmp, SIE_INTERCEPT_MCK);
}