/*-------------------------------------------------------------------*/ 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(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(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) (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 */