/*-------------------------------------------------------------------*/ int ARCH_DEP(common_load_finish) (REGS *regs) { /* Zeroize the interrupt code in the PSW */ regs->psw.intcode = 0; /* Load IPL PSW from PSA+X'0' */ if (ARCH_DEP(load_psw) (regs, regs->psa->iplpsw) != 0) { logmsg (_("HHCCP030E %s mode IPL failed: Invalid IPL PSW: " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n"), get_arch_mode_string(regs), regs->psa->iplpsw[0], regs->psa->iplpsw[1], regs->psa->iplpsw[2], regs->psa->iplpsw[3], regs->psa->iplpsw[4], regs->psa->iplpsw[5], regs->psa->iplpsw[6], regs->psa->iplpsw[7]); HDC1(debug_cpu_state, regs); return -1; } /* Set the CPU into the started state */ regs->opinterv = 0; regs->cpustate = CPUSTATE_STARTED; /* The actual IPL (load) is now completed... */ regs->loadstate = 0; /* Signal the CPU to retest stopped indicator */ WAKEUP_CPU (regs); HDC1(debug_cpu_state, regs); return 0; } /* end function common_load_finish */
static void *watchdog_thread(void *arg) { S64 savecount[MAX_CPU_ENGINES]; int i; UNREFERENCED(arg); /* Set watchdog priority just below cpu priority such that it will not invalidly detect an inoperable cpu */ if(sysblk.cpuprio >= 0) set_thread_priority(0, sysblk.cpuprio+1); for (i = 0; i < sysblk.maxcpu; i ++) savecount[i] = -1; while(!sysblk.shutdown) { for (i = 0; i < sysblk.maxcpu; i++) { // obtain_lock (&sysblk.cpulock[i]); if (IS_CPU_ONLINE(i) && sysblk.regs[i]->cpustate == CPUSTATE_STARTED && (!WAITSTATE(&sysblk.regs[i]->psw) #if defined(_FEATURE_WAITSTATE_ASSIST) && !(sysblk.regs[i]->sie_active && WAITSTATE(&sysblk.regs[i]->guestregs->psw)) #endif )) { /* If the cpu is running but not executing instructions then it must be malfunctioning */ if((INSTCOUNT(sysblk.regs[i]) == (U64)savecount[i]) && !HDC1(debug_watchdog_signal, sysblk.regs[i]) ) { /* Send signal to looping CPU */ signal_thread(sysblk.cputid[i], SIGUSR1); savecount[i] = -1; } else /* Save current instcount */ savecount[i] = INSTCOUNT(sysblk.regs[i]); } else /* mark savecount invalid as CPU not in running state */ savecount[i] = -1; // release_lock (&sysblk.cpulock[i]); } /* Sleep for 20 seconds */ SLEEP(20); } return NULL; }
/*-------------------------------------------------------------------*/ int ARCH_DEP(common_load_finish) (REGS *regs) { int rc; /* Zeroize the interrupt code in the PSW */ regs->psw.intcode = 0; /* Load IPL PSW from PSA+X'0' */ if ((rc = ARCH_DEP(load_psw) (regs, regs->psa->iplpsw)) ) { char buf[80]; MSGBUF(buf, "architecture mode %s, invalid ipl psw %2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", get_arch_mode_string((REGS *)0), regs->psa->iplpsw[0], regs->psa->iplpsw[1], regs->psa->iplpsw[2], regs->psa->iplpsw[3], regs->psa->iplpsw[4], regs->psa->iplpsw[5], regs->psa->iplpsw[6], regs->psa->iplpsw[7]); WRMSG (HHC00839, "E", PTYPSTR(sysblk.pcpu), sysblk.pcpu, buf); HDC1(debug_cpu_state, regs); return rc; } /* Set the CPU into the started state */ regs->opinterv = 0; regs->cpustate = CPUSTATE_STARTED; /* The actual IPL (load) is now completed... */ regs->loadstate = 0; /* reset sys_reset flag to indicate a active machine */ sysblk.sys_reset = FALSE; /* Signal the CPU to retest stopped indicator */ WAKEUP_CPU (regs); HDC1(debug_cpu_state, regs); return 0; } /* end function common_load_finish */
/*-------------------------------------------------------------------*/ 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 */
/*-------------------------------------------------------------------*/ 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) (int cpu, int clear) { int rc1 = 0, rc; int n; REGS *regs; /* Configure the cpu if it is not online (configure implies init reset) */ if (!IS_CPU_ONLINE(cpu)) if ( (rc = configure_cpu(cpu)) ) return rc; HDC1(debug_cpu_state, sysblk.regs[cpu]); /* Reset external interrupts */ OFF_IC_SERVSIG; OFF_IC_INTKEY; /* Perform system-reset-normal or system-reset-clear function */ if (clear) { /* Reset all CPUs in the configuration */ for (n = 0; n < sysblk.maxcpu; n++) if (IS_CPU_ONLINE(n)) { regs=sysblk.regs[n]; if ((rc = ARCH_DEP(initial_cpu_reset) (regs)) ) rc1 = rc; else { /* 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.program_parameter = 0; /* Clear storage */ sysblk.main_clear = sysblk.xpnd_clear = 0; storage_clear(); xstorage_clear(); } else { /* Reset all CPUs in the configuration */ for (n = 0; n < sysblk.maxcpu; n++) if (IS_CPU_ONLINE(n)) { regs=sysblk.regs[n]; if(n == cpu) { /* Perform initial reset on the IPL CPU */ if ( (rc = ARCH_DEP(initial_cpu_reset) (regs)) ) rc1 = rc; } else { /* Perform reset on the other CPUs */ if ( (rc = ARCH_DEP(cpu_reset) (regs)) ) rc1 = rc; } } } /* Perform I/O subsystem reset */ io_reset (); #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 rc1; } /* end function system_reset */
/*-------------------------------------------------------------------*/ 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]); } }
/*-------------------------------------------------------------------*/ int ARCH_DEP(load_hmc) (char *fname, int cpu, int clear) { REGS *regs; /* -> Regs */ FILE *fp; char inputbuff[MAX_PATH]; char *inputline; char filename[MAX_PATH]; /* filename of image file */ char pathname[MAX_PATH]; /* pathname of image file */ U32 fileaddr; int rc = 0; /* Return codes (work) */ /* 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 */ if(fname == NULL) /* Default ipl from DASD */ fname = "HERCULES.ins"; /* from HERCULES.ins */ hostpath(pathname, fname, sizeof(pathname)); if(!(fname = set_sce_basedir(pathname))) return -1; /* Construct and check full pathname */ if(!check_sce_filepath(fname,filename)) { WRMSG(HHC00601,"E",fname,strerror(errno)); return -1; } fp = fopen(filename, "r"); if(fp == NULL) { WRMSG(HHC00600,"E", fname,"fopen()",strerror(errno)); return -1; } do { inputline = fgets(inputbuff,sizeof(inputbuff),fp); #if !defined(_MSVC_) if(inputline && *inputline == 0x1a) inputline = NULL; #endif /*!defined(_MSVC_)*/ if(inputline) { rc = sscanf(inputline,"%" QSTR(MAX_PATH) "s %i",filename,&fileaddr); } /* If no load address was found load to location zero */ if(inputline && rc < 2) fileaddr = 0; if(inputline && rc > 0 && *filename != '*' && *filename != '#') { hostpath(pathname, filename, sizeof(pathname)); /* Construct and check full pathname */ if(!check_sce_filepath(pathname,filename)) { WRMSG(HHC00602,"E",pathname,strerror(errno)); return -1; } if( ARCH_DEP(load_main) (filename, fileaddr, 0) < 0 ) { fclose(fp); HDC1(debug_cpu_state, regs); return -1; } sysblk.main_clear = sysblk.xpnd_clear = 0; } } while(inputline); fclose(fp); /* Finish up... */ return ARCH_DEP(common_load_finish) (regs); } /* end function load_hmc */
/*-------------------------------------------------------------------*/ int ARCH_DEP(system_reset) (int cpu, int clear) { int rc = 0; REGS *regs; /* Configure the cpu if it is not online */ if (!IS_CPU_ONLINE(cpu)) { if (configure_cpu(cpu) != 0) { /* ZZ FIXME: we should probably present a machine-check if we encounter any errors during the reset (rc != 0) */ return -1; } ASSERT(IS_CPU_ONLINE(cpu)); } regs = sysblk.regs[cpu]; HDC1(debug_cpu_state, regs); /* Perform system-reset-normal or system-reset-clear function */ if (!clear) { /* Reset external interrupts */ OFF_IC_SERVSIG; OFF_IC_INTKEY; /* Reset all CPUs in the configuration */ for (cpu = 0; cpu < MAX_CPU; cpu++) if (IS_CPU_ONLINE(cpu)) if (ARCH_DEP(cpu_reset) (sysblk.regs[cpu])) rc = -1; /* Perform I/O subsystem reset */ io_reset (); } else { /* Reset external interrupts */ OFF_IC_SERVSIG; OFF_IC_INTKEY; /* Reset all CPUs in the configuration */ for (cpu = 0; cpu < MAX_CPU; cpu++) { if (IS_CPU_ONLINE(cpu)) { regs=sysblk.regs[cpu]; if (ARCH_DEP(initial_cpu_reset) (regs)) { rc = -1; } /* 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)*/ } } /* Perform I/O subsystem reset */ io_reset (); /* 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)*/ /* ZZ FIXME: we should probably present a machine-check if we encounter any errors during the reset (rc != 0) */ return rc; } /* end function system_reset */
/*-------------------------------------------------------------------*/ 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 */