/*-------------------------------------------------------------------*/ int startall_cmd(int argc, char *argv[], char *cmdline) { int i; int rc = 0; CPU_BITMAP mask; UNREFERENCED(cmdline); if ( argc == 1 ) { OBTAIN_INTLOCK(NULL); mask = (~sysblk.started_mask) & sysblk.config_mask; for (i = 0; mask; i++) { if (mask & 1) { REGS *regs = sysblk.regs[i]; regs->opinterv = 0; regs->cpustate = CPUSTATE_STARTED; signal_condition(®s->intcond); } mask >>= 1; } RELEASE_INTLOCK(NULL); }
/*-------------------------------------------------------------------*/ static void* ARCH_DEP(scedio_thread)(void* arg) { SCCB_SCEDIOV_BK *scediov_bk; SCCB_SCEDIOR_BK *scedior_bk; SCCB_SCEDIO_BK *scedio_bk = (SCCB_SCEDIO_BK*) arg; switch(scedio_bk->flag1) { case SCCB_SCEDIO_FLG1_IOV: scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1); if( ARCH_DEP(scedio_iov)(scediov_bk) ) scedio_bk->flag3 |= SCCB_SCEDIO_FLG3_COMPLETE; else scedio_bk->flag3 &= ~SCCB_SCEDIO_FLG3_COMPLETE; break; case SCCB_SCEDIO_FLG1_IOR: scedior_bk = (SCCB_SCEDIOR_BK*)(scedio_bk + 1); if( ARCH_DEP(scedio_ior)(scedior_bk) ) scedio_bk->flag3 |= SCCB_SCEDIO_FLG3_COMPLETE; else scedio_bk->flag3 &= ~SCCB_SCEDIO_FLG3_COMPLETE; break; default: PTT(PTT_CL_ERR,"*SERVC",(U32)scedio_bk->flag0,(U32)scedio_bk->flag1,scedio_bk->flag3); } OBTAIN_INTLOCK(NULL); while(IS_IC_SERVSIG) { RELEASE_INTLOCK(NULL); sched_yield(); OBTAIN_INTLOCK(NULL); } sclp_attention(SCCB_EVD_TYPE_SCEDIO); scedio_tid = 0; RELEASE_INTLOCK(NULL); return NULL; }
/*-------------------------------------------------------------------*/ void machine_check_crwpend() { /* Signal waiting CPUs that a Channel Report is pending */ OBTAIN_INTLOCK(NULL); ON_IC_CHANRPT; WAKEUP_CPUS_MASK (sysblk.waiting_mask); RELEASE_INTLOCK(NULL); } /* end function machine_check_crwpend */
static int is_wait_sigq_pending() { int pending; OBTAIN_INTLOCK(NULL); pending = wait_sigq_pending; RELEASE_INTLOCK(NULL); return pending; }
static void wait_sigq_resp() { int pending, i; /* Wait for all CPU's to stop */ do { OBTAIN_INTLOCK(NULL); wait_sigq_pending = 0; for (i = 0; i < MAX_CPU_ENGINES; i++) if (IS_CPU_ONLINE(i) && sysblk.regs[i]->cpustate != CPUSTATE_STOPPED) wait_sigq_pending = 1; pending = wait_sigq_pending; RELEASE_INTLOCK(NULL); if(pending) SLEEP(1); } while(is_wait_sigq_pending()); }
/*---------------------------------------------------------------------------*/ static void *stop_cpus_and_ipl(int *ipltype) { int i; char iplcmd[256]; int cpustates; CPU_BITMAP mask; sysblk.diag8cmd |= DIAG8CMD_RUNNING; panel_command("stopall"); sysblk.diag8cmd &= ~DIAG8CMD_RUNNING; WRMSG(HHC01900, "I"); sprintf(iplcmd, "%s %03X", ipltype, sysblk.ipldev); do { OBTAIN_INTLOCK(NULL); cpustates = CPUSTATE_STOPPED; mask = sysblk.started_mask; for(i = 0; mask; i++) { if(mask & 1) { WRMSG(HHC01901, "I", PTYPSTR(i), i); if(IS_CPU_ONLINE(i) && sysblk.regs[i]->cpustate != CPUSTATE_STOPPED) cpustates = sysblk.regs[i]->cpustate; } mask >>= 1; } RELEASE_INTLOCK(NULL); if(cpustates != CPUSTATE_STOPPED) { WRMSG(HHC01902, "I"); SLEEP(1); } } while(cpustates != CPUSTATE_STOPPED); sysblk.diag8cmd |= DIAG8CMD_RUNNING; panel_command(iplcmd); sysblk.diag8cmd &= ~DIAG8CMD_RUNNING; return NULL; }
void subsystem_reset (void) { /* 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 */ /* Clear pending external interrupts */ OFF_IC_SERVSIG; OFF_IC_INTKEY; /* Reset the I/O subsystem */ RELEASE_INTLOCK(NULL); io_reset (); OBTAIN_INTLOCK(NULL); }
static void cancel_wait_sigq() { OBTAIN_INTLOCK(NULL); wait_sigq_pending = 0; RELEASE_INTLOCK(NULL); }
/*-------------------------------------------------------------------*/ 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]); } }
/*-------------------------------------------------------------------*/ static BOOL WINAPI console_ctrl_handler (DWORD signo) { int i; SetConsoleCtrlHandler(console_ctrl_handler, FALSE); // turn handler off while processing switch ( signo ) { case CTRL_BREAK_EVENT: WRMSG (HHC01400, "I"); OBTAIN_INTLOCK(NULL); ON_IC_INTKEY; /* Signal waiting CPUs that an interrupt is pending */ WAKEUP_CPUS_MASK (sysblk.waiting_mask); RELEASE_INTLOCK(NULL); SetConsoleCtrlHandler(console_ctrl_handler, TRUE); // reset handler return TRUE; break; case CTRL_C_EVENT: WRMSG(HHC01401, "I"); SetConsoleCtrlHandler(console_ctrl_handler, TRUE); // reset handler return TRUE; break; case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: case CTRL_LOGOFF_EVENT: if ( !sysblk.shutdown ) // (system shutdown not initiated) { WRMSG(HHC01402, "I", ( signo == CTRL_CLOSE_EVENT ? "close" : signo == CTRL_SHUTDOWN_EVENT ? "shutdown" : "logoff" ), ( signo == CTRL_CLOSE_EVENT ? "immediate " : "" ) ); if ( signo == CTRL_CLOSE_EVENT ) sysblk.shutimmed = TRUE; do_shutdown(); // logmsg("%s(%d): return from shutdown\n", __FILE__, __LINE__ ); /* debug */ for ( i = 0; i < 120; i++ ) { if ( sysblk.shutdown && sysblk.shutfini ) { // logmsg("%s(%d): %d shutdown completed\n", /* debug */ // __FILE__, __LINE__, i ); /* debug */ break; } else { // logmsg("%s(%d): %d waiting for shutdown to complete\n", /* debug */ // __FILE__, __LINE__, i ); /* debug */ sleep(1); } } if ( !sysblk.shutfini ) { sysblk.shutimmed = TRUE; do_shutdown(); } } else { sysblk.shutimmed = TRUE; do_shutdown(); WRMSG(HHC01403, "W", ( signo == CTRL_CLOSE_EVENT ? "close" : signo == CTRL_SHUTDOWN_EVENT ? "shutdown" : "logoff" ) ); } return TRUE; break; default: return FALSE; } } /* end function console_ctrl_handler */
/*-------------------------------------------------------------------*/ int ARCH_DEP(mssf_call) (int r1, int r2, REGS *regs) { U32 spccb_absolute_addr; /* Absolute addr of SPCCB */ U32 mssf_command; /* MSSF command word */ U32 spccblen; /* Length of SPCCB */ SPCCB_HEADER *spccb; /* -> SPCCB header */ SPCCB_CONFIG_INFO *spccbconfig; /* -> SPCCB CONFIG info */ SPCCB_CPU_INFO *spccbcpu; /* -> SPCCB CPU information */ SPCCB_CHP_STATUS *spccbchp; /* -> SPCCB channel path info */ U16 offset; /* Offset from start of SPCCB */ int i; /* loop counter */ DEVBLK *dev; /* Device block pointer */ /* R1 contains the real address of the SPCCB */ spccb_absolute_addr = APPLY_PREFIXING (regs->GR_L(r1), regs->PX); /* R2 contains the service-processor-command word */ mssf_command = regs->GR_L(r2); /* Program check if SPCCB is not on a doubleword boundary */ if ( spccb_absolute_addr & 0x00000007 ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Program check if SPCCB is outside main storage */ if ( spccb_absolute_addr > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); // /*debug*/logmsg("MSSF call %8.8X SPCCB=%8.8X\n", // /*debug*/ mssf_command, spccb_absolute_addr); /* Point to Service Processor Command Control Block */ spccb = (SPCCB_HEADER*)(regs->mainstor + spccb_absolute_addr); /* Load SPCCB length from header */ FETCH_HW(spccblen,spccb->length); /* Mark page referenced */ STORAGE_KEY(spccb_absolute_addr, regs) |= STORKEY_REF; /* Program check if end of SPCCB falls outside main storage */ if ( sysblk.mainsize - spccblen < spccb_absolute_addr ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Obtain the interrupt lock */ OBTAIN_INTLOCK(regs); /* If a service signal is pending then we cannot process the request */ if( IS_IC_SERVSIG && (sysblk.servparm & SERVSIG_ADDR)) { RELEASE_INTLOCK(regs); return 2; /* Service Processor Busy */ } if( spccb_absolute_addr & 0x7ffff800 ) { spccb->resp[0] = SPCCB_REAS_NOT2KALIGN; spccb->resp[1] = SPCCB_RESP_NOT2KALIGN; } else /* Test MSSF command word */ switch (mssf_command) { case MSSF_READ_CONFIG_INFO: /* Set response code X'01F0' if SPCCB length is insufficient to contain CONFIG info */ if ( spccblen < 64 ) { spccb->resp[0] = SPCCB_REAS_BADLENGTH; spccb->resp[1] = SPCCB_RESP_BADLENGTH; break; } /* Point to SPCCB data area following SPCCB header */ spccbconfig = (SPCCB_CONFIG_INFO*)(spccb+1); memset (spccbconfig, 0, sizeof(SPCCB_CONFIG_INFO)); /* Set main storage size in SPCCB */ spccbconfig->totstori = sysblk.mainsize >> 20; spccbconfig->storisiz = 1; spccbconfig->hex04 = 0x04; spccbconfig->hex01 = 0x01; /* Set CPU array count and offset in SPCCB */ STORE_HW(spccbconfig->toticpu,sysblk.maxcpu); offset = sizeof(SPCCB_HEADER) + sizeof(SPCCB_CONFIG_INFO); STORE_HW(spccbconfig->officpu,offset); /* Set HSA array count and offset in SPCCB */ STORE_HW(spccbconfig->tothsa,0); offset += (U16)(sizeof(SPCCB_CPU_INFO) * sysblk.maxcpu); STORE_HW(spccbconfig->offhsa,offset); /* Move IPL load parameter to SPCCB */ get_loadparm (spccbconfig->loadparm); /* Build the CPU information array after the SCP info */ spccbcpu = (SPCCB_CPU_INFO*)(spccbconfig+1); for (i = 0; i < sysblk.maxcpu; i++, spccbcpu++) { memset( spccbcpu, 0, sizeof(SPCCB_CPU_INFO) ); spccbcpu->cpuaddr = i; spccbcpu->todid = 0; } /* Set response code X'0010' in SPCCB header */ spccb->resp[0] = SPCCB_REAS_COMPLETE; spccb->resp[1] = SPCCB_RESP_COMPLETE; break; case MSSF_READ_CHP_STATUS: /* Set response code X'0300' if SPCCB length is insufficient to contain channel path info */ if ( spccblen < sizeof(SPCCB_HEADER) + sizeof(SPCCB_CHP_STATUS)) { spccb->resp[0] = SPCCB_REAS_BADLENGTH; spccb->resp[1] = SPCCB_RESP_BADLENGTH; break; } /* Point to SPCCB data area following SPCCB header */ spccbchp = (SPCCB_CHP_STATUS*)(spccb+1); memset( spccbchp, 0, sizeof(SPCCB_CHP_STATUS) ); /* Identify CHPIDs used */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { for (i = 0; i < 8; i++) { if( ((0x80 >> i) & dev->pmcw.pim) ) { BYTE chpid; chpid = dev->pmcw.chpid[i]; spccbchp->installed[chpid / 8] |= 0x80 >> (chpid % 8); spccbchp->assigned[chpid / 8] |= 0x80 >> (chpid % 8); spccbchp->configured[chpid / 8] |= 0x80 >> (chpid % 8); } } } /* Set response code X'0010' in SPCCB header */ spccb->resp[0] = SPCCB_REAS_COMPLETE; spccb->resp[1] = SPCCB_RESP_COMPLETE; break; default: PTT(PTT_CL_ERR,"*DIAG080",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); /* Set response code X'06F0' for invalid MSSF command */ spccb->resp[0] = SPCCB_REAS_UNASSIGNED; spccb->resp[1] = SPCCB_RESP_UNASSIGNED; break; } /* end switch(mssf_command) */ /* Mark page changed */ STORAGE_KEY(spccb_absolute_addr, regs) |= STORKEY_CHANGE; /* Set service signal external interrupt pending */ sysblk.servparm &= ~SERVSIG_ADDR; sysblk.servparm |= spccb_absolute_addr; ON_IC_SERVSIG; /* Release the interrupt lock */ RELEASE_INTLOCK(regs); /* Return condition code 0: Command initiated */ return 0; } /* end function mssf_call */
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; }
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, ®s->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, ®s->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, ®s->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, ®s->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, ®s->fpr[i], sizeof(regs->fpr[0])); break; case SR_CPU_FPC: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->fpc, sizeof(regs->fpc)); break; case SR_CPU_DXC: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->dxc, sizeof(regs->dxc)); break; case SR_CPU_MC: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->mc, sizeof(regs->mc)); break; case SR_CPU_EA: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->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, ®s->clkc, sizeof(regs->clkc)); break; case SR_CPU_CHANSET: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->chanset, sizeof(regs->chanset)); break; case SR_CPU_TODPR: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->todpr, sizeof(regs->todpr)); break; case SR_CPU_MONCLASS: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->monclass, sizeof(regs->monclass)); break; case SR_CPU_EXCARID: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->excarid, sizeof(regs->excarid)); break; case SR_CPU_BEAR: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->bear, sizeof(regs->bear)); break; case SR_CPU_OPNDRID: SR_NULL_REGS_CHECK(regs); SR_READ_VALUE(file, len, ®s->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, ®s->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, ®s->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, ®s->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, ®s->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; }
void* process_rc_file (void* dummy) { char *rcname; /* hercules.rc name pointer */ int is_default_rc = 0; /* 1 == default name used */ int numcpu = 0; /* #of ONLINE & STOPPED CPUs */ int i; /* (work) */ UNREFERENCED(dummy); /* Wait for all installed/configured CPUs to come ONLINE and enter the STOPPED state */ OBTAIN_INTLOCK(NULL); for (;;) { numcpu = 0; for (i = 0; i < MAX_CPU_ENGINES; i++) if (IS_CPU_ONLINE(i) && CPUSTATE_STOPPED == sysblk.regs[i]->cpustate) numcpu++; if (numcpu == sysblk.numcpu) break; RELEASE_INTLOCK(NULL); usleep( 10 * 1000 ); OBTAIN_INTLOCK(NULL); } RELEASE_INTLOCK(NULL); /* Wait for panel thread to engage */ while (!sysblk.panel_init) usleep( 10 * 1000 ); /* Obtain the name of the hercules.rc file or default */ if (!(rcname = getenv("HERCULES_RC"))) { rcname = "hercules.rc"; is_default_rc = 1; } #if defined(OPTION_HAO) /* Initialize the Hercules Automatic Operator */ if ( !hao_initialize() ) logmsg(_("HHCIN004S Cannot create HAO thread: %s\n"), strerror(errno)); #endif /* defined(OPTION_HAO) */ /* Run the script processor for this file */ if (process_script_file(rcname,1) != 0) if (ENOENT == errno) if (!is_default_rc) logmsg(_("HHCPN995E .RC file \"%s\" not found.\n"), rcname); // (else error message already issued) return NULL; }
/*-------------------------------------------------------------------*/ BOOL WINAPI console_ctrl_handler (DWORD signo) { int i; SetConsoleCtrlHandler(console_ctrl_handler, FALSE); // turn handler off while processing switch ( signo ) { case CTRL_BREAK_EVENT: logmsg(_("HHCIN050ICtrl-Break intercepted. Interrupt Key depressed simulated.\n")); OBTAIN_INTLOCK(NULL); ON_IC_INTKEY; /* Signal waiting CPUs that an interrupt is pending */ WAKEUP_CPUS_MASK (sysblk.waiting_mask); RELEASE_INTLOCK(NULL); SetConsoleCtrlHandler(console_ctrl_handler, TRUE); // reset handler return TRUE; break; case CTRL_C_EVENT: logmsg(_("HHCIN022I Ctrl-C intercepted\n")); SetConsoleCtrlHandler(console_ctrl_handler, TRUE); // reset handler return TRUE; break; case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: case CTRL_LOGOFF_EVENT: if ( !sysblk.shutdown ) // (system shutdown not initiated) { logmsg(_("HHCIN021ICLOSE Event received, SHUTDOWN Immediate starting...\n")); sysblk.shutimmed = TRUE; do_shutdown(); // logmsg("%s(%d): return from shutdown\n", __FILE__, __LINE__ ); /* debug */ for ( i = 0; i < 120; i++ ) { if ( sysblk.shutdown && sysblk.shutfini ) { // logmsg("%s(%d): %d shutdown completed\n", /* debug */ // __FILE__, __LINE__, i ); /* debug */ sleep(1); break; } else { // logmsg("%s(%d): %d waiting for shutdown to complete\n", /* debug */ // __FILE__, __LINE__, i ); /* debug */ sleep(1); } } socket_deinit(); } else { logmsg(_("HHCIN023W CLOSE Event received, SHUTDOWN previously requested...\n")); } usleep(10000); return FALSE; break; default: return FALSE; } } /* end function console_ctrl_handler */
/*-------------------------------------------------------------------*/ 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 */
/*-------------------------------------------------------------------*/ 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 */
/*-------------------------------------------------------------------*/ static int ARCH_DEP(scedio_request)(U32 sclp_command, SCCB_EVD_HDR *evd_hdr) { SCCB_SCEDIO_BK *scedio_bk = (SCCB_SCEDIO_BK*)(evd_hdr + 1); SCCB_SCEDIOV_BK *scediov_bk; SCCB_SCEDIOR_BK *scedior_bk; int rc; static struct { SCCB_SCEDIO_BK scedio_bk; union { SCCB_SCEDIOV_BK v; SCCB_SCEDIOR_BK r; } io; } static_scedio_bk ; static int scedio_pending; if(sclp_command == SCLP_READ_EVENT_DATA) { int pending_req = scedio_pending; U16 evd_len; /* Return no data if the scedio thread is still active */ if(scedio_tid) return 0; /* Update the scedio_bk copy in the SCCB */ if(scedio_pending) { /* Zero all fields */ memset (evd_hdr, 0, sizeof(SCCB_EVD_HDR)); /* Set type in event header */ evd_hdr->type = SCCB_EVD_TYPE_SCEDIO; /* Store scedio header */ *scedio_bk = static_scedio_bk.scedio_bk; /* Calculate event response length */ evd_len = sizeof(SCCB_EVD_HDR) + sizeof(SCCB_SCEDIO_BK); switch(scedio_bk->flag1) { case SCCB_SCEDIO_FLG1_IOR: scedior_bk = (SCCB_SCEDIOR_BK*)(scedio_bk + 1); *scedior_bk = static_scedio_bk.io.r; evd_len += sizeof(SCCB_SCEDIOR_BK); break; case SCCB_SCEDIO_FLG1_IOV: scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1); *scediov_bk = static_scedio_bk.io.v ; evd_len += sizeof(SCCB_SCEDIOV_BK); break; default: PTT(PTT_CL_ERR,"*SERVC",(U32)evd_hdr->type,(U32)scedio_bk->flag1,scedio_bk->flag3); } /* Set length in event header */ STORE_HW(evd_hdr->totlen, evd_len); } /* Reset the pending flag */ scedio_pending = 0; /* Return true if a request was pending */ return pending_req; } else { #if !defined(NO_SIGABEND_HANDLER) switch(scedio_bk->flag1) { case SCCB_SCEDIO_FLG1_IOV: scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1); switch(scediov_bk->type) { case SCCB_SCEDIOV_TYPE_INIT: /* Kill the scedio thread if it is active */ if( scedio_tid ) { OBTAIN_INTLOCK(NULL); signal_thread(scedio_tid, SIGKILL); scedio_tid = 0; scedio_pending = 0; RELEASE_INTLOCK(NULL); } break; } break; } #endif /* Take a copy of the scedio_bk in the SCCB */ static_scedio_bk.scedio_bk = *scedio_bk; switch(scedio_bk->flag1) { case SCCB_SCEDIO_FLG1_IOR: scedior_bk = (SCCB_SCEDIOR_BK*)(scedio_bk + 1); static_scedio_bk.io.r = *scedior_bk; break; case SCCB_SCEDIO_FLG1_IOV: scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1); static_scedio_bk.io.v = *scediov_bk; break; default: PTT(PTT_CL_ERR,"*SERVC",(U32)evd_hdr->type,(U32)scedio_bk->flag1,scedio_bk->flag3); } /* Create the scedio thread */ rc = create_thread(&scedio_tid, &sysblk.detattr, ARCH_DEP(scedio_thread), &static_scedio_bk, "scedio_thread"); if (rc) { WRMSG(HHC00102, "E", strerror(rc)); return -1; } scedio_pending = 1; } return 0; }
void cgibin_ipl(WEBBLK *webblk) { int i; char *value; DEVBLK *dev; U16 ipldev; int iplcpu; U32 doipl; html_header(webblk); hprintf(webblk->sock,"<h1>Perform Initial Program Load</h1>\n"); if(cgi_variable(webblk,"doipl")) doipl = 1; else doipl = 0; if((value = cgi_variable(webblk,"device"))) sscanf(value,"%hx",&ipldev); else ipldev = sysblk.ipldev; if((value = cgi_variable(webblk,"cpu"))) sscanf(value,"%x",&iplcpu); else iplcpu = sysblk.iplcpu; if((value = cgi_variable(webblk,"loadparm"))) set_loadparm(value); /* Validate CPU number */ if(iplcpu >= MAX_CPU) doipl = 0; if(!doipl) { /* Present IPL parameters */ hprintf(webblk->sock,"<form method=post>\n" "<select type=submit name=cpu>\n"); for(i = 0; i < MAX_CPU; i++) if(IS_CPU_ONLINE(i)) hprintf(webblk->sock,"<option value=%4.4X%s>CPU%4.4X</option>\n", i, ((sysblk.regs[i]->cpuad == iplcpu) ? " selected" : ""), i); hprintf(webblk->sock,"</select>\n" "<select type=submit name=device>\n"); for(dev = sysblk.firstdev; dev; dev = dev->nextdev) if(dev->pmcw.flag5 & PMCW5_V) hprintf(webblk->sock,"<option value=%4.4X%s>DEV%4.4X</option>\n", dev->devnum, ((dev->devnum == ipldev) ? " selected" : ""), dev->devnum); hprintf(webblk->sock,"</select>\n"); hprintf(webblk->sock,"Loadparm:<input type=text name=loadparm size=8 value=\"%s\">\n", str_loadparm()); hprintf(webblk->sock,"<input type=submit name=doipl value=\"IPL\">\n" "</form>\n"); } else { OBTAIN_INTLOCK(NULL); /* Perform IPL function */ if( load_ipl(0, ipldev, iplcpu,0) ) { hprintf(webblk->sock,"<h3>IPL failed, see the " "<a href=\"syslog#bottom\">system log</a> " "for details</h3>\n"); } else { hprintf(webblk->sock,"<h3>IPL completed</h3>\n"); } RELEASE_INTLOCK(NULL); } html_footer(webblk); }
/*-------------------------------------------------------------------*/ 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 */