mirror of
https://github.com/SDL-Hercules-390/hyperion.git
synced 2026-04-13 15:35:41 +02:00
PTF request vertical polarization Add PTF (Perform Topology Function) testcase STSI 15.1.2 Mag2 and vertical polarization STSI 15.1.2 fix attribution
868 lines
27 KiB
C
868 lines
27 KiB
C
/* IPL.C (c) Copyright Roger Bowler, 1999-2012 */
|
|
/* ESA/390 Initial Program Loader */
|
|
/* */
|
|
/* Released under "The Q Public License Version 1" */
|
|
/* (http://www.hercules-390.org/herclic.html) as modifications to */
|
|
/* Hercules. */
|
|
/* */
|
|
/* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2012 */
|
|
/* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2012 */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* This module implements the Initial Program Load (IPL) function of */
|
|
/* the S/370, ESA/390 and z/Architectures, described in the manuals: */
|
|
/* */
|
|
/* GA22-7000 System/370 Principles of Operation */
|
|
/* SA22-7201 ESA/390 Principles of Operation */
|
|
/* SA22-7832 z/Architecture Principles of Operation. */
|
|
/* */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
#include "hstdinc.h"
|
|
|
|
#define _IPL_C
|
|
#define _HENGINE_DLL_
|
|
|
|
#include "hercules.h"
|
|
#include "opcode.h"
|
|
#include "inline.h"
|
|
#ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_3
|
|
#include "hexterns.h"
|
|
#endif
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Function to reset instruction count and CPU time */
|
|
/*-------------------------------------------------------------------*/
|
|
#if !defined(_reset_instcount_)
|
|
#define _reset_instcount_
|
|
INLINE void
|
|
cpu_reset_instcount_and_cputime(REGS* regs)
|
|
{
|
|
/* Reset instruction counts, I/O counts and real CPU time */
|
|
regs->prevcount = 0;
|
|
regs->instcount = 0;
|
|
regs->mipsrate = 0;
|
|
regs->siocount = 0;
|
|
regs->siosrate = 0;
|
|
regs->siototal = 0;
|
|
regs->cpupct = 0;
|
|
regs->rcputime = 0;
|
|
regs->bcputime = thread_cputime_us(regs);
|
|
}
|
|
#endif
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Function to perform Subystem Reset */
|
|
/*-------------------------------------------------------------------*/
|
|
/* Locks held on entry/exit: */
|
|
/* sysblk.intlock */
|
|
/*-------------------------------------------------------------------*/
|
|
#if !defined(_subsystem_reset_)
|
|
#define _subsystem_reset_
|
|
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);
|
|
}
|
|
#endif
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Function to perform System Reset (either 'normal' or 'clear') */
|
|
/*-------------------------------------------------------------------*/
|
|
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]);
|
|
}
|
|
}
|
|
|
|
/* If IPL or system-reset-clear, clear system instruction counter,
|
|
* rates, and IPLed indicator.
|
|
*/
|
|
if (flags & 0x03)
|
|
{
|
|
/* Clear system instruction counter and CPU rates */
|
|
sysblk.instcount = 0;
|
|
sysblk.mipsrate = 0;
|
|
sysblk.siosrate = 0;
|
|
|
|
sysblk.ipled = FALSE;
|
|
}
|
|
|
|
#if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)
|
|
/* Set horizontal polarization */
|
|
sysblk.topology = TOPOLOGY_HORIZ;
|
|
|
|
/* 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 */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* LOAD (aka IPL) functions... */
|
|
/*-------------------------------------------------------------------*/
|
|
/* Performing an Initial Program Load (aka IPL) involves three */
|
|
/* distinct phases: in phase 1 the system is reset (registers */
|
|
/* and, for load-clear, storage), and in phase two the actual */
|
|
/* Initial Program Loading from the IPL device takes place. Finally,*/
|
|
/* in phase three, the IPL PSW is loaded and the CPU is started. */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
int orig_arch_mode; /* Saved architecture mode */
|
|
PSW captured_zpsw; /* Captured z/Arch PSW */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Common LOAD (IPL) begin: system-reset (register/storage clearing) */
|
|
/*-------------------------------------------------------------------*/
|
|
int ARCH_DEP(common_load_begin) (int cpu, int clear)
|
|
{
|
|
int capture;
|
|
int rc;
|
|
|
|
/* Save the original architecture mode for later */
|
|
orig_arch_mode = sysblk.dummyregs.arch_mode = sysblk.arch_mode;
|
|
|
|
capture = (!clear) && IS_CPU_ONLINE(cpu) && sysblk.arch_mode == ARCH_900;
|
|
|
|
/* Capture the z/Arch PSW if this is a Load-normal IPL */
|
|
if (capture)
|
|
captured_zpsw = sysblk.regs[cpu]->psw;
|
|
|
|
/* Perform system-reset-normal or system-reset-clear function;
|
|
* architecture mode updated, if necessary. The clear indicator is
|
|
* cleaned with an initial CPU reset added.
|
|
*
|
|
* SA22-7085-0 IBM System/370 Extended Architecture Principles of
|
|
* Operation, Chapter 12, Operator Facilities, LOAD-
|
|
* CLEAR KEY and LOAD-NORMAL KEY, p. 12-3.
|
|
*/
|
|
if ( (rc = ARCH_DEP(system_reset(cpu, ((clear & 0x01) | 0x02),
|
|
sysblk.arch_mode > ARCH_390 ?
|
|
ARCH_390 : sysblk.arch_mode))) )
|
|
return (rc);
|
|
|
|
/* Save our captured-z/Arch-PSW if this is a Load-normal IPL
|
|
since the initial_cpu_reset call cleared it to zero. */
|
|
if (capture)
|
|
sysblk.regs[cpu]->captured_zpsw = captured_zpsw;
|
|
|
|
/* The actual IPL (load) now begins... */
|
|
sysblk.regs[cpu]->loadstate = 1;
|
|
|
|
return 0;
|
|
} /* end function common_load_begin */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Function to run initial CCW chain from IPL device and load IPLPSW */
|
|
/* Returns 0 if successful, -1 if error */
|
|
/* intlock MUST be held on entry */
|
|
/*-------------------------------------------------------------------*/
|
|
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%2.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 */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Common LOAD (IPL) finish: load IPL PSW and start CPU */
|
|
/*-------------------------------------------------------------------*/
|
|
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 */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Function to perform CPU Reset */
|
|
/*-------------------------------------------------------------------*/
|
|
int ARCH_DEP(cpu_reset) (REGS *regs)
|
|
{
|
|
int i, rc = 0; /* Array subscript */
|
|
|
|
regs->ip = regs->inst;
|
|
|
|
/* Clear indicators */
|
|
regs->loadstate = 0;
|
|
regs->checkstop = 0;
|
|
regs->sigpreset = 0;
|
|
regs->extccpu = 0;
|
|
for (i = 0; i < sysblk.maxcpu; i++)
|
|
regs->emercpu[i] = 0;
|
|
regs->instinvalid = 1;
|
|
|
|
/* Clear interrupts */
|
|
SET_IC_INITIAL_MASK(regs);
|
|
SET_IC_INITIAL_STATE(regs);
|
|
|
|
/* Clear the translation exception identification */
|
|
regs->EA_G = 0;
|
|
regs->excarid = 0;
|
|
|
|
/* Clear monitor code */
|
|
regs->MC_G = 0;
|
|
|
|
/* Purge the lookaside buffers */
|
|
ARCH_DEP(purge_tlb) (regs);
|
|
|
|
#if defined(FEATURE_ACCESS_REGISTERS)
|
|
ARCH_DEP(purge_alb) (regs);
|
|
#endif /*defined(FEATURE_ACCESS_REGISTERS)*/
|
|
|
|
if(regs->host)
|
|
{
|
|
/* Put the CPU into the stopped state */
|
|
regs->opinterv = 0;
|
|
regs->cpustate = CPUSTATE_STOPPED;
|
|
ON_IC_INTERRUPT(regs);
|
|
}
|
|
|
|
#ifdef FEATURE_INTERVAL_TIMER
|
|
ARCH_DEP(store_int_timer_nolock) (regs);
|
|
#endif
|
|
|
|
if(regs->host && regs->guestregs)
|
|
{
|
|
rc = ARCH_DEP(cpu_reset)(regs->guestregs);
|
|
/* CPU state of SIE copy cannot be controlled */
|
|
regs->guestregs->opinterv = 0;
|
|
regs->guestregs->cpustate = CPUSTATE_STARTED;
|
|
}
|
|
|
|
/* Initialize Architecture Level Set */
|
|
init_als(regs);
|
|
|
|
return rc;
|
|
} /* end function cpu_reset */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Function to perform Initial CPU Reset */
|
|
/*-------------------------------------------------------------------*/
|
|
int ARCH_DEP(initial_cpu_reset) (REGS *regs)
|
|
{
|
|
int rc1 = 0, rc;
|
|
|
|
/* Clear reset pending indicators */
|
|
regs->sigpireset = regs->sigpreset = 0;
|
|
|
|
/* Clear the registers */
|
|
memset ( ®s->psw, 0, sizeof(regs->psw) );
|
|
memset ( ®s->captured_zpsw, 0, sizeof(regs->captured_zpsw) );
|
|
#ifndef NOCHECK_AEA_ARRAY_BOUNDS
|
|
memset ( ®s->cr_struct, 0, sizeof(regs->cr_struct) );
|
|
#else
|
|
memset ( ®s->cr, 0, sizeof(regs->cr) );
|
|
#endif
|
|
regs->fpc = 0;
|
|
regs->PX = 0;
|
|
regs->psw.AMASK_G = AMASK24;
|
|
|
|
/* Ensure memory sizes are properly indicated */
|
|
regs->mainstor = sysblk.mainstor;
|
|
regs->storkeys = sysblk.storkeys;
|
|
regs->mainlim = sysblk.mainsize ? (sysblk.mainsize - 1) : 0;
|
|
regs->psa = (PSA_3XX*)regs->mainstor;
|
|
|
|
/* Perform a CPU reset (after setting PSA) */
|
|
rc1 = ARCH_DEP(cpu_reset) (regs);
|
|
|
|
regs->todpr = 0;
|
|
regs->clkc = 0;
|
|
set_cpu_timer(regs, 0);
|
|
#ifdef _FEATURE_INTERVAL_TIMER
|
|
set_int_timer(regs, 0);
|
|
#endif
|
|
|
|
/* The breaking event address register is initialised to 1 */
|
|
regs->bear = 1;
|
|
|
|
/* Initialize external interrupt masks in control register 0 */
|
|
regs->CR(0) = CR0_XM_INTKEY | CR0_XM_EXTSIG |
|
|
(FACILITY_ENABLED(INTERVAL_TIMER, regs) ? CR0_XM_ITIMER : 0);
|
|
|
|
#if defined(FEATURE_S370_CHANNEL) && !defined(FEATURE_ACCESS_REGISTERS)
|
|
/* For S/370 initialize the channel masks in CR2 */
|
|
regs->CR(2) = 0xFFFFFFFF;
|
|
#endif /* defined(FEATURE_S370_CHANNEL) && !defined(FEATURE_ACCESS_REGISTERS) */
|
|
|
|
regs->chanset =
|
|
#if defined(FEATURE_CHANNEL_SWITCHING)
|
|
regs->cpuad < FEATURE_LCSS_MAX ? regs->cpuad :
|
|
#endif /*defined(FEATURE_CHANNEL_SWITCHING)*/
|
|
0xFFFF;
|
|
|
|
/* Initialize the machine check masks in control register 14 */
|
|
regs->CR(14) = CR14_CHKSTOP | CR14_SYNCMCEL | CR14_XDMGRPT;
|
|
|
|
#ifndef FEATURE_LINKAGE_STACK
|
|
/* For S/370 initialize the MCEL address in CR15 */
|
|
regs->CR(15) = 512;
|
|
#endif /*!FEATURE_LINKAGE_STACK*/
|
|
|
|
if(regs->host && regs->guestregs)
|
|
if( (rc = ARCH_DEP(initial_cpu_reset)(regs->guestregs)) )
|
|
rc1 = rc;
|
|
|
|
#ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_3
|
|
renew_wrapping_keys();
|
|
#endif /* FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_3 */
|
|
|
|
return rc1;
|
|
} /* end function initial_cpu_reset */
|
|
|
|
#if !defined(_GEN_ARCH)
|
|
|
|
#if defined(_ARCHMODE2)
|
|
#define _GEN_ARCH _ARCHMODE2
|
|
#include "ipl.c"
|
|
#endif
|
|
|
|
#if defined(_ARCHMODE3)
|
|
#undef _GEN_ARCH
|
|
#define _GEN_ARCH _ARCHMODE3
|
|
#include "ipl.c"
|
|
#endif
|
|
|
|
/*********************************************************************/
|
|
/* Externally Initiated Functions... */
|
|
/*********************************************************************/
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Load / IPL (Load Normal -or- Load Clear) */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
int load_ipl (U16 lcss, U16 devnum, int cpu, int clear)
|
|
{
|
|
int rc;
|
|
|
|
switch (sysblk.arch_mode)
|
|
{
|
|
#if defined(_370)
|
|
case ARCH_370:
|
|
rc = s370_load_ipl (lcss, devnum, cpu, clear);
|
|
break;
|
|
#endif
|
|
#if defined(_390)
|
|
case ARCH_390:
|
|
rc = s390_load_ipl (lcss, devnum, cpu, clear);
|
|
break;
|
|
#endif
|
|
#if defined(_900)
|
|
case ARCH_900:
|
|
/* z/Arch always starts out in ESA390 mode */
|
|
rc = s390_load_ipl (lcss, devnum, cpu, clear);
|
|
break;
|
|
#endif
|
|
default:
|
|
rc = -1;
|
|
break;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Initial CPU Reset */
|
|
/*-------------------------------------------------------------------*/
|
|
int initial_cpu_reset (REGS *regs)
|
|
{
|
|
int rc;
|
|
|
|
switch (regs->arch_mode)
|
|
{
|
|
#if defined(_370)
|
|
case ARCH_370:
|
|
rc = s370_initial_cpu_reset (regs);
|
|
break;
|
|
#endif
|
|
#if defined(_390)
|
|
case ARCH_390:
|
|
rc = s390_initial_cpu_reset (regs);
|
|
break;
|
|
#endif
|
|
#if defined(_900)
|
|
case ARCH_900:
|
|
/* z/Arch always starts out in ESA390 mode */
|
|
rc = s390_initial_cpu_reset (regs);
|
|
break;
|
|
#endif
|
|
default:
|
|
rc = -1;
|
|
break;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* System Reset ( Normal reset or Clear reset ) */
|
|
/*-------------------------------------------------------------------*/
|
|
int system_reset (const int cpu, const int flags, const int target_mode)
|
|
{
|
|
int rc;
|
|
|
|
switch (sysblk.arch_mode)
|
|
{
|
|
#if defined(_370)
|
|
case ARCH_370:
|
|
rc = s370_system_reset (cpu, flags, target_mode);
|
|
break;
|
|
#endif
|
|
#if defined(_390)
|
|
case ARCH_390:
|
|
rc = s390_system_reset (cpu, flags, target_mode);
|
|
break;
|
|
#endif
|
|
#if defined(_900)
|
|
case ARCH_900:
|
|
rc = z900_system_reset (cpu, flags, target_mode);
|
|
break;
|
|
#endif
|
|
default:
|
|
rc = -1;
|
|
break;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* ordinary CPU Reset (no clearing takes place) */
|
|
/*-------------------------------------------------------------------*/
|
|
int cpu_reset (REGS *regs)
|
|
{
|
|
int rc;
|
|
|
|
switch (regs->arch_mode)
|
|
{
|
|
#if defined(_370)
|
|
case ARCH_370:
|
|
rc = s370_cpu_reset (regs);
|
|
break;
|
|
#endif
|
|
#if defined(_390)
|
|
case ARCH_390:
|
|
rc = s390_cpu_reset (regs);
|
|
break;
|
|
#endif
|
|
#if defined(_900)
|
|
case ARCH_900:
|
|
rc = z900_cpu_reset (regs);
|
|
break;
|
|
#endif
|
|
default:
|
|
rc = -1;
|
|
break;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Function to clear main storage */
|
|
/*-------------------------------------------------------------------*/
|
|
void storage_clear()
|
|
{
|
|
if (!sysblk.main_clear)
|
|
{
|
|
if (sysblk.mainstor) memset( sysblk.mainstor, 0x00, sysblk.mainsize );
|
|
if (sysblk.storkeys) memset( sysblk.storkeys, 0x00, sysblk.mainsize / STORAGE_KEY_UNITSIZE );
|
|
sysblk.main_clear = 1;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Function to clear expanded storage */
|
|
/*-------------------------------------------------------------------*/
|
|
void xstorage_clear()
|
|
{
|
|
if (!sysblk.xpnd_clear)
|
|
{
|
|
if (sysblk.xpndstor)
|
|
memset( sysblk.xpndstor, 0x00, (size_t)sysblk.xpndsize * XSTORE_PAGESIZE );
|
|
|
|
sysblk.xpnd_clear = 1;
|
|
}
|
|
}
|
|
|
|
#endif /*!defined(_GEN_ARCH)*/
|