2012-03-24 18:41:51 +11:00
|
|
|
/* SIE.C (c) Copyright Jan Jaeger, 1999-2012 */
|
2001-02-23 20:49:19 +00:00
|
|
|
/* Interpretive Execution */
|
2010-04-29 13:50:02 +00:00
|
|
|
/* */
|
2012-03-24 18:41:51 +11:00
|
|
|
/* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2012 */
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* This module contains the SIE instruction as */
|
|
|
|
|
/* described in IBM S/370 Extended Architecture */
|
|
|
|
|
/* Interpretive Execution, SA22-7095-01 */
|
|
|
|
|
/* and */
|
|
|
|
|
/* Enterprise Systems Architecture / Extended Configuration */
|
|
|
|
|
/* Principles of Operation, SC24-5594-02 and SC24-5965-00 */
|
|
|
|
|
|
|
|
|
|
|
2005-09-24 16:17:46 +00:00
|
|
|
#include "hstdinc.h"
|
|
|
|
|
|
2001-03-06 18:04:21 +00:00
|
|
|
// #define SIE_DEBUG
|
2005-11-13 22:29:03 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#if !defined(_HENGINE_DLL_)
|
|
|
|
|
#define _HENGINE_DLL_
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if !defined(_SIE_C_)
|
|
|
|
|
#define _SIE_C_
|
|
|
|
|
#endif
|
2001-03-06 18:04:21 +00:00
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
#include "hercules.h"
|
|
|
|
|
#include "opcode.h"
|
|
|
|
|
#include "inline.h"
|
|
|
|
|
|
2002-06-24 08:36:57 +00:00
|
|
|
#if defined(_FEATURE_SIE)
|
|
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
#if !defined(_SIE_C)
|
|
|
|
|
|
|
|
|
|
#define _SIE_C
|
|
|
|
|
|
2011-08-15 12:41:45 +00:00
|
|
|
static int s370_run_sie (REGS *regs);
|
|
|
|
|
static int s390_run_sie (REGS *regs);
|
2001-12-28 09:00:31 +00:00
|
|
|
#if defined(_900)
|
2011-08-15 12:41:45 +00:00
|
|
|
static int z900_run_sie (REGS *regs);
|
2001-12-28 09:00:31 +00:00
|
|
|
#endif /*defined(_900)*/
|
2001-08-18 19:07:23 +00:00
|
|
|
static int (* run_sie[GEN_MAXARCH]) (REGS *regs) =
|
2001-12-28 09:00:31 +00:00
|
|
|
{
|
|
|
|
|
#if defined(_370)
|
|
|
|
|
s370_run_sie,
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(_390)
|
|
|
|
|
s390_run_sie,
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(_900)
|
|
|
|
|
z900_run_sie
|
|
|
|
|
#endif
|
|
|
|
|
};
|
2001-08-18 19:07:23 +00:00
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
#define GUESTREGS (regs->guestregs)
|
2004-08-27 13:43:16 +00:00
|
|
|
#define STATEBK ((SIEBK *)GUESTREGS->siebk)
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
#define SIE_I_STOP(_guestregs) \
|
|
|
|
|
((_guestregs)->siebk->v & SIE_V_STOP)
|
|
|
|
|
|
|
|
|
|
#define SIE_I_EXT(_guestregs) \
|
|
|
|
|
(((_guestregs)->siebk->v & SIE_V_EXT) \
|
|
|
|
|
&& ((_guestregs)->psw.sysmask & PSW_EXTMASK))
|
|
|
|
|
|
2001-05-25 18:27:56 +00:00
|
|
|
#define SIE_I_HOST(_hostregs) IC_INTERRUPT_CPU(_hostregs)
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2003-11-25 19:10:39 +00:00
|
|
|
#if defined(SIE_DEBUG_PERFMON)
|
|
|
|
|
#define SIE_PERF_MAXNEG 0x1F
|
|
|
|
|
static int sie_perfmon[0x41 + SIE_PERF_MAXNEG];
|
|
|
|
|
#define SIE_PERFMON(_code) \
|
|
|
|
|
do { \
|
|
|
|
|
sie_perfmon[(_code) + SIE_PERF_MAXNEG] ++; \
|
|
|
|
|
} while(0)
|
|
|
|
|
#define SIE_PERF_PGMINT \
|
|
|
|
|
(code <= 0 ? code : (((code-1) & 0x3F)+1))
|
|
|
|
|
void *sie_perfmon_disp()
|
|
|
|
|
{
|
|
|
|
|
static char *dbg_name[] = {
|
|
|
|
|
/* -31 */ "SIE re-dispatch state descriptor",
|
|
|
|
|
/* -30 */ "SIE exit",
|
|
|
|
|
/* -29 */ "SIE run",
|
|
|
|
|
/* -28 */ "SIE runloop 1",
|
|
|
|
|
/* -27 */ "SIE runloop 2",
|
|
|
|
|
/* -26 */ "SIE interrupt check",
|
|
|
|
|
/* -25 */ "SIE execute instruction",
|
|
|
|
|
/* -24 */ "SIE unrolled execute",
|
|
|
|
|
/* -23 */ NULL,
|
|
|
|
|
/* -22 */ NULL,
|
|
|
|
|
/* -21 */ NULL,
|
|
|
|
|
/* -20 */ NULL,
|
|
|
|
|
/* -19 */ NULL,
|
|
|
|
|
/* -18 */ NULL,
|
|
|
|
|
/* -17 */ "SIE intercept I/O instruction",
|
|
|
|
|
/* -16 */ "SIE intercept I/O interrupt pending",
|
|
|
|
|
/* -15 */ "SIE intercept I/O interrupt",
|
|
|
|
|
/* -14 */ "SIE intercept PER interrupt",
|
|
|
|
|
/* -13 */ "SIE validity check",
|
|
|
|
|
/* -12 */ "SIE intercept external interrupt pending",
|
|
|
|
|
/* -11 */ "SIE intercept machine check interrupt",
|
|
|
|
|
/* -10 */ "SIE intercept restart interrupt",
|
|
|
|
|
/* -9 */ "SIE intercept stop request",
|
|
|
|
|
/* -8 */ "SIE intercept virtual machine wait",
|
|
|
|
|
/* -7 */ "SIE intercept I/O interrupt request",
|
|
|
|
|
/* -6 */ "SIE intercept external interrupt request",
|
|
|
|
|
/* -5 */ "SIE intercept instruction completion",
|
|
|
|
|
/* -4 */ "SIE intercept instruction",
|
|
|
|
|
/* -3 */ "SIE host program interrupt",
|
|
|
|
|
/* -2 */ "SIE host interrupt",
|
|
|
|
|
/* -1 */ "SIE no intercept",
|
|
|
|
|
/* 0 */ "SIE entry",
|
|
|
|
|
/* 01 */ "SIE intercept Operation exception",
|
|
|
|
|
/* 02 */ "SIE intercept Privileged-operation exception",
|
|
|
|
|
/* 03 */ "SIE intercept Execute exception",
|
|
|
|
|
/* 04 */ "SIE intercept Protection exception",
|
|
|
|
|
/* 05 */ "SIE intercept Addressing exception",
|
|
|
|
|
/* 06 */ "SIE intercept Specification exception",
|
|
|
|
|
/* 07 */ "SIE intercept Data exception",
|
|
|
|
|
/* 08 */ "SIE intercept Fixed-point-overflow exception",
|
|
|
|
|
/* 09 */ "SIE intercept Fixed-point-divide exception",
|
|
|
|
|
/* 0A */ "SIE intercept Decimal-overflow exception",
|
|
|
|
|
/* 0B */ "SIE intercept Decimal-divide exception",
|
|
|
|
|
/* 0C */ "SIE intercept HFP-exponent-overflow exception",
|
|
|
|
|
/* 0D */ "SIE intercept HFP-exponent-underflow exception",
|
|
|
|
|
/* 0E */ "SIE intercept HFP-significance exception",
|
|
|
|
|
/* 0F */ "SIE intercept HFP-floating-point-divide exception",
|
|
|
|
|
/* 10 */ "SIE intercept Segment-translation exception",
|
|
|
|
|
/* 11 */ "SIE intercept Page-translation exception",
|
|
|
|
|
/* 12 */ "SIE intercept Translation-specification exception",
|
|
|
|
|
/* 13 */ "SIE intercept Special-operation exception",
|
|
|
|
|
/* 14 */ "SIE intercept Pseudo-page-fault exception",
|
|
|
|
|
/* 15 */ "SIE intercept Operand exception",
|
|
|
|
|
/* 16 */ "SIE intercept Trace-table exception",
|
|
|
|
|
/* 17 */ "SIE intercept ASN-translation exception",
|
|
|
|
|
/* 18 */ "SIE intercept Page access exception",
|
|
|
|
|
/* 19 */ "SIE intercept Vector/Crypto operation exception",
|
|
|
|
|
/* 1A */ "SIE intercept Page state exception",
|
|
|
|
|
/* 1B */ "SIE intercept Page transition exception",
|
|
|
|
|
/* 1C */ "SIE intercept Space-switch event",
|
|
|
|
|
/* 1D */ "SIE intercept Square-root exception",
|
|
|
|
|
/* 1E */ "SIE intercept Unnormalized-operand exception",
|
|
|
|
|
/* 1F */ "SIE intercept PC-translation specification exception",
|
|
|
|
|
/* 20 */ "SIE intercept AFX-translation exception",
|
|
|
|
|
/* 21 */ "SIE intercept ASX-translation exception",
|
|
|
|
|
/* 22 */ "SIE intercept LX-translation exception",
|
|
|
|
|
/* 23 */ "SIE intercept EX-translation exception",
|
|
|
|
|
/* 24 */ "SIE intercept Primary-authority exception",
|
2005-10-16 15:38:45 +00:00
|
|
|
/* 25 */ "SIE intercept LFX-translation exception",
|
|
|
|
|
/* 26 */ "SIE intercept LSX-translation exception",
|
2003-11-25 19:10:39 +00:00
|
|
|
/* 27 */ "SIE intercept Control-switch exception",
|
|
|
|
|
/* 28 */ "SIE intercept ALET-specification exception",
|
|
|
|
|
/* 29 */ "SIE intercept ALEN-translation exception",
|
|
|
|
|
/* 2A */ "SIE intercept ALE-sequence exception",
|
|
|
|
|
/* 2B */ "SIE intercept ASTE-validity exception",
|
|
|
|
|
/* 2C */ "SIE intercept ASTE-sequence exception",
|
|
|
|
|
/* 2D */ "SIE intercept Extended-authority exception",
|
2005-10-16 15:38:45 +00:00
|
|
|
/* 2E */ "SIE intercept LSTE-sequence exception",
|
|
|
|
|
/* 2F */ "SIE intercept ASTE-instance exception",
|
2003-11-25 19:10:39 +00:00
|
|
|
/* 30 */ "SIE intercept Stack-full exception",
|
|
|
|
|
/* 31 */ "SIE intercept Stack-empty exception",
|
|
|
|
|
/* 32 */ "SIE intercept Stack-specification exception",
|
|
|
|
|
/* 33 */ "SIE intercept Stack-type exception",
|
|
|
|
|
/* 34 */ "SIE intercept Stack-operation exception",
|
|
|
|
|
/* 35 */ NULL,
|
|
|
|
|
/* 36 */ NULL,
|
|
|
|
|
/* 37 */ NULL,
|
|
|
|
|
/* 38 */ "SIE intercept ASCE-type exception",
|
|
|
|
|
/* 39 */ "SIE intercept Region-first-translation exception",
|
|
|
|
|
/* 3A */ "SIE intercept Region-second-translation exception",
|
|
|
|
|
/* 3B */ "SIE intercept Region-third-translation exception",
|
|
|
|
|
/* 3C */ NULL,
|
|
|
|
|
/* 3D */ NULL,
|
|
|
|
|
/* 3E */ NULL,
|
|
|
|
|
/* 3F */ NULL,
|
|
|
|
|
/* 40 */ "SIE intercept Monitor event" };
|
|
|
|
|
|
|
|
|
|
if(sie_perfmon[SIE_PERF_ENTER+SIE_PERF_MAXNEG])
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for(i = 0; i < 0x61; i++)
|
|
|
|
|
if(sie_perfmon[i])
|
2011-09-04 04:51:30 +00:00
|
|
|
logmsg(MSG(HHC02285, "I" ,sie_perfmon[i],dbg_name[i]));
|
2012-07-20 11:05:06 +02:00
|
|
|
logmsg(MSG(HHC02286, "I",
|
2003-11-25 19:10:39 +00:00
|
|
|
(sie_perfmon[SIE_PERF_EXEC+SIE_PERF_MAXNEG] +
|
|
|
|
|
sie_perfmon[SIE_PERF_EXEC_U+SIE_PERF_MAXNEG]*7) /
|
2011-09-04 04:51:30 +00:00
|
|
|
sie_perfmon[SIE_PERF_ENTER+SIE_PERF_MAXNEG]));
|
2003-11-25 19:10:39 +00:00
|
|
|
}
|
|
|
|
|
else
|
2011-09-04 04:51:30 +00:00
|
|
|
logmsg(MSG(HHC02287, "I"));
|
2003-11-25 19:10:39 +00:00
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
#define SIE_PERFMON(_code)
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
#endif /*!defined(_SIE_C)*/
|
|
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
#undef SIE_I_WAIT
|
|
|
|
|
#if defined(_FEATURE_WAITSTATE_ASSIST)
|
|
|
|
|
#define SIE_I_WAIT(_guestregs) \
|
2004-02-17 22:38:48 +00:00
|
|
|
(WAITSTATE(&(_guestregs)->psw) && !((_guestregs)->siebk->ec[0] & SIE_EC0_WAIA))
|
2003-01-07 21:35:24 +00:00
|
|
|
#else
|
|
|
|
|
#define SIE_I_WAIT(_guestregs) \
|
2004-02-17 22:38:48 +00:00
|
|
|
(WAITSTATE(&(_guestregs)->psw))
|
2003-01-07 21:35:24 +00:00
|
|
|
#endif
|
|
|
|
|
|
2001-03-24 17:14:23 +00:00
|
|
|
#undef SIE_I_IO
|
2002-06-25 18:29:35 +00:00
|
|
|
#if defined(FEATURE_BCMODE)
|
2001-03-24 17:14:23 +00:00
|
|
|
#define SIE_I_IO(_guestregs) \
|
|
|
|
|
(((_guestregs)->siebk->v & SIE_V_IO) \
|
|
|
|
|
&& ((_guestregs)->psw.sysmask \
|
2004-02-17 22:38:48 +00:00
|
|
|
& (ECMODE(&(_guestregs)->psw) ? PSW_IOMASK : 0xFE) ))
|
2002-06-25 18:29:35 +00:00
|
|
|
#else /*!defined(FEATURE_BCMODE)*/
|
2001-03-24 17:14:23 +00:00
|
|
|
#define SIE_I_IO(_guestregs) \
|
|
|
|
|
(((_guestregs)->siebk->v & SIE_V_IO) \
|
|
|
|
|
&& ((_guestregs)->psw.sysmask & PSW_IOMASK ))
|
2002-06-25 18:29:35 +00:00
|
|
|
#endif /*!defined(FEATURE_BCMODE)*/
|
2001-03-24 17:14:23 +00:00
|
|
|
|
2001-12-28 09:00:31 +00:00
|
|
|
#endif /*defined(_FEATURE_SIE)*/
|
2001-02-23 20:49:19 +00:00
|
|
|
#if defined(FEATURE_INTERPRETIVE_EXECUTION)
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
/* B214 SIE - Start Interpretive Execution [S] */
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
DEF_INST(start_interpretive_execution)
|
|
|
|
|
{
|
|
|
|
|
int b2; /* Values of R fields */
|
2001-06-11 09:54:09 +00:00
|
|
|
RADR effective_addr2; /* address of state desc. */
|
2001-02-23 20:49:19 +00:00
|
|
|
int n; /* Loop counter */
|
|
|
|
|
U16 lhcpu; /* Last Host CPU address */
|
2010-07-25 11:18:18 +00:00
|
|
|
volatile int icode; /* Interception code */
|
2005-12-31 20:14:56 +00:00
|
|
|
U64 dreg;
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2004-02-17 22:38:48 +00:00
|
|
|
S(inst, regs, b2, effective_addr2);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2005-12-29 22:28:49 +00:00
|
|
|
SIE_INTERCEPT(regs);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
|
|
2015-01-24 06:16:05 -08:00
|
|
|
PTT_SIE("SIE", regs->GR_L(14), regs->GR_L(15), (U32)(effective_addr2 & 0xffffffff));
|
2009-03-05 21:33:26 +00:00
|
|
|
|
2003-11-25 19:10:39 +00:00
|
|
|
SIE_PERFMON(SIE_PERF_ENTER);
|
|
|
|
|
|
2005-11-03 18:49:15 +00:00
|
|
|
#if !defined(FEATURE_ESAME) && !defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)
|
|
|
|
|
if(!regs->psw.amode || !PRIMARY_SPACE_MODE(&(regs->psw)))
|
2001-02-23 20:49:19 +00:00
|
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
|
2005-11-03 18:49:15 +00:00
|
|
|
#endif
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
if((effective_addr2 & (sizeof(SIEBK)-1)) != 0
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
|
|
|
|
|| (effective_addr2 & 0xFFFFFFFFFFFFF000ULL) == 0
|
|
|
|
|
|| (effective_addr2 & 0xFFFFFFFFFFFFF000ULL) == regs->PX)
|
|
|
|
|
#else /*!defined(FEATURE_ESAME)*/
|
|
|
|
|
|| (effective_addr2 & 0x7FFFF000) == 0
|
|
|
|
|
|| (effective_addr2 & 0x7FFFF000) == regs->PX)
|
|
|
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
|
|
|
|
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
|
|
|
|
|
|
|
|
|
|
/* Perform serialization and checkpoint synchronization */
|
|
|
|
|
PERFORM_SERIALIZATION (regs);
|
|
|
|
|
PERFORM_CHKPT_SYNC (regs);
|
|
|
|
|
|
2001-03-06 18:04:21 +00:00
|
|
|
#if defined(SIE_DEBUG)
|
2011-08-12 23:28:17 +00:00
|
|
|
logmsg(_("SIE: state descriptor " F_RADR "\n"),effective_addr2);
|
2006-11-07 01:02:58 +00:00
|
|
|
ARCH_DEP(display_inst) (regs, regs->instinvalid ? NULL : regs->ip);
|
2001-03-06 18:04:21 +00:00
|
|
|
#endif /*defined(SIE_DEBUG)*/
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2002-12-05 13:27:27 +00:00
|
|
|
if(effective_addr2 > regs->mainlim - (sizeof(SIEBK)-1))
|
2002-07-14 10:25:49 +00:00
|
|
|
ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);
|
2001-12-16 19:19:48 +00:00
|
|
|
|
2004-12-26 07:47:16 +00:00
|
|
|
/*
|
|
|
|
|
* As long as regs->sie_active is off, no serialization is
|
|
|
|
|
* required for GUESTREGS. sie_active should always be off here.
|
|
|
|
|
* Any other thread looking at sie_active holds the intlock.
|
|
|
|
|
*/
|
|
|
|
|
if (regs->sie_active)
|
|
|
|
|
{
|
2006-04-12 10:33:41 +00:00
|
|
|
OBTAIN_INTLOCK(regs);
|
2004-12-26 07:47:16 +00:00
|
|
|
regs->sie_active = 0;
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2004-12-26 07:47:16 +00:00
|
|
|
}
|
2004-05-13 04:33:47 +00:00
|
|
|
|
2005-09-24 16:17:46 +00:00
|
|
|
/* Initialize guestregs if first time */
|
|
|
|
|
if (GUESTREGS == NULL)
|
2013-03-19 09:25:09 -07:00
|
|
|
{
|
2013-03-20 15:41:11 -07:00
|
|
|
GUESTREGS = calloc_aligned(sizeof(REGS), 4096);
|
2004-12-26 07:47:16 +00:00
|
|
|
if (GUESTREGS == NULL)
|
2013-03-19 09:25:09 -07:00
|
|
|
{
|
|
|
|
|
logmsg(MSG(HHC00813, "E", PTYPSTR(regs->cpuad), regs->cpuad, "calloc()", strerror(errno)));
|
2005-09-24 16:17:46 +00:00
|
|
|
#if !defined(NO_SIGABEND_HANDLER)
|
2013-03-19 09:25:09 -07:00
|
|
|
signal_thread(sysblk.cputid[regs->cpuad], SIGUSR1);
|
2005-09-24 16:17:46 +00:00
|
|
|
#endif
|
2013-03-19 09:25:09 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2004-12-26 07:47:16 +00:00
|
|
|
cpu_init (regs->cpuad, GUESTREGS, regs);
|
2005-09-24 16:17:46 +00:00
|
|
|
}
|
2004-05-13 04:33:47 +00:00
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
/* Direct pointer to state descriptor block */
|
2004-08-27 13:43:16 +00:00
|
|
|
GUESTREGS->siebk = (void*)(regs->mainstor + effective_addr2);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
2004-12-26 07:47:16 +00:00
|
|
|
if (STATEBK->mx & SIE_MX_ESAME)
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
|
|
|
|
GUESTREGS->arch_mode = ARCH_900;
|
2007-01-04 23:12:04 +00:00
|
|
|
GUESTREGS->program_interrupt = &z900_program_interrupt;
|
|
|
|
|
GUESTREGS->trace_br = (func)&z900_trace_br;
|
2003-01-07 21:35:24 +00:00
|
|
|
icode = z900_load_psw(GUESTREGS, STATEBK->psw);
|
2001-02-23 20:49:19 +00:00
|
|
|
}
|
|
|
|
|
#else /*!defined(FEATURE_ESAME)*/
|
2004-12-26 07:47:16 +00:00
|
|
|
if (STATEBK->m & SIE_M_370)
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
2001-12-28 09:00:31 +00:00
|
|
|
#if defined(_370)
|
2001-02-23 20:49:19 +00:00
|
|
|
GUESTREGS->arch_mode = ARCH_370;
|
2007-01-04 23:12:04 +00:00
|
|
|
GUESTREGS->program_interrupt = &s370_program_interrupt;
|
2003-01-07 21:35:24 +00:00
|
|
|
icode = s370_load_psw(GUESTREGS, STATEBK->psw);
|
2001-12-28 09:00:31 +00:00
|
|
|
#else
|
2002-06-27 18:00:29 +00:00
|
|
|
/* Validity intercept when 370 mode not installed */
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
|
|
|
|
SIE_VI_WHY_370NI, GUESTREGS);
|
|
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
|
|
|
|
return;
|
2001-12-28 09:00:31 +00:00
|
|
|
#endif
|
2001-02-23 20:49:19 +00:00
|
|
|
}
|
|
|
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
|
|
|
|
else
|
2002-12-05 13:27:27 +00:00
|
|
|
#if !defined(FEATURE_ESAME)
|
2004-12-26 07:47:16 +00:00
|
|
|
if (STATEBK->m & SIE_M_XA)
|
2002-12-05 13:27:27 +00:00
|
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
|
|
|
|
GUESTREGS->arch_mode = ARCH_390;
|
2007-01-04 23:12:04 +00:00
|
|
|
GUESTREGS->program_interrupt = &s390_program_interrupt;
|
|
|
|
|
GUESTREGS->trace_br = (func)&s390_trace_br;
|
2003-01-07 21:35:24 +00:00
|
|
|
icode = s390_load_psw(GUESTREGS, STATEBK->psw);
|
2001-02-23 20:49:19 +00:00
|
|
|
}
|
2002-12-05 13:27:27 +00:00
|
|
|
#if !defined(FEATURE_ESAME)
|
2001-12-16 19:19:48 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Validity intercept for invalid mode */
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2004-12-26 07:47:16 +00:00
|
|
|
SIE_VI_WHY_MODE, GUESTREGS);
|
2002-01-30 22:06:45 +00:00
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
2001-12-16 19:19:48 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2002-12-05 13:27:27 +00:00
|
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* Prefered guest indication */
|
|
|
|
|
GUESTREGS->sie_pref = (STATEBK->m & SIE_M_VR) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
/* Load prefix from state descriptor */
|
|
|
|
|
FETCH_FW(GUESTREGS->PX, STATEBK->prefix);
|
2001-04-22 06:20:08 +00:00
|
|
|
GUESTREGS->PX &=
|
|
|
|
|
#if !defined(FEATURE_ESAME)
|
|
|
|
|
PX_MASK;
|
|
|
|
|
#else /*defined(FEATURE_ESAME)*/
|
|
|
|
|
(GUESTREGS->arch_mode == ARCH_900) ? PX_MASK : 0x7FFFF000;
|
|
|
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
#if defined(FEATURE_REGION_RELOCATE)
|
|
|
|
|
if(STATEBK->mx & SIE_MX_RRF)
|
|
|
|
|
{
|
|
|
|
|
RADR mso, msl, eso = 0, esl = 0;
|
2005-09-24 16:17:46 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
if(STATEBK->zone >= FEATURE_SIE_MAXZONES)
|
|
|
|
|
{
|
|
|
|
|
/* Validity intercept for invalid zone */
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
|
|
|
|
SIE_VI_WHY_AZNNI, GUESTREGS);
|
|
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-09-24 16:17:46 +00:00
|
|
|
|
2010-11-09 19:36:31 +00:00
|
|
|
mso = (sysblk.zpb[STATEBK->zone].mso & 0xFFFFF) << 20;
|
|
|
|
|
msl = (sysblk.zpb[STATEBK->zone].msl & 0xFFFFF) << 20;
|
|
|
|
|
eso = (sysblk.zpb[STATEBK->zone].eso & 0xFFFFF) << 20;
|
|
|
|
|
esl = (sysblk.zpb[STATEBK->zone].esl & 0xFFFFF) << 20;
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
if(mso > msl)
|
|
|
|
|
{
|
|
|
|
|
/* Validity intercept for invalid zone */
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
|
|
|
|
SIE_VI_WHY_MSDEF, GUESTREGS);
|
|
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-09-24 16:17:46 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Ensure addressing exceptions on incorrect zone defs */
|
|
|
|
|
if(mso > regs->mainlim || msl > regs->mainlim)
|
|
|
|
|
mso = msl = 0;
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2001-03-06 18:04:21 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
#if defined(SIE_DEBUG)
|
2011-08-12 23:28:17 +00:00
|
|
|
logmsg(_("SIE: zone %d: mso=" F_RADR " msl=" F_RADR "\n"),
|
2003-01-07 21:35:24 +00:00
|
|
|
STATEBK->zone, mso, msl);
|
|
|
|
|
#endif /*defined(SIE_DEBUG)*/
|
|
|
|
|
|
|
|
|
|
GUESTREGS->sie_pref = 1;
|
|
|
|
|
GUESTREGS->sie_mso = 0;
|
|
|
|
|
GUESTREGS->mainstor = &(sysblk.mainstor[mso]);
|
|
|
|
|
GUESTREGS->mainlim = msl - mso;
|
|
|
|
|
GUESTREGS->storkeys = &(STORAGE_KEY(mso, &sysblk));
|
|
|
|
|
GUESTREGS->sie_xso = eso;
|
|
|
|
|
GUESTREGS->sie_xsl = esl;
|
|
|
|
|
GUESTREGS->sie_xso *= (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT);
|
|
|
|
|
GUESTREGS->sie_xsl *= (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT);
|
2001-12-18 12:16:57 +00:00
|
|
|
}
|
2003-01-07 21:35:24 +00:00
|
|
|
else
|
|
|
|
|
#endif /*defined(FEATURE_REGION_RELOCATE)*/
|
|
|
|
|
{
|
|
|
|
|
GUESTREGS->mainstor = sysblk.mainstor;
|
|
|
|
|
GUESTREGS->storkeys = sysblk.storkeys;
|
|
|
|
|
|
|
|
|
|
if(STATEBK->zone)
|
|
|
|
|
{
|
|
|
|
|
/* Validity intercept for invalid zone */
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2004-12-26 07:47:16 +00:00
|
|
|
SIE_VI_WHY_AZNNZ, GUESTREGS);
|
2003-01-07 21:35:24 +00:00
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-12-18 12:16:57 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
#if defined(FEATURE_ESAME)
|
|
|
|
|
/* Load main storage origin */
|
|
|
|
|
FETCH_DW(GUESTREGS->sie_mso,STATEBK->mso);
|
|
|
|
|
GUESTREGS->sie_mso &= SIE2_MS_MASK;
|
2001-12-18 12:16:57 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Load main storage extend */
|
|
|
|
|
FETCH_DW(GUESTREGS->mainlim,STATEBK->mse);
|
|
|
|
|
GUESTREGS->mainlim |= ~SIE2_MS_MASK;
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
if(GUESTREGS->sie_mso > GUESTREGS->mainlim)
|
|
|
|
|
{
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2004-12-26 07:47:16 +00:00
|
|
|
SIE_VI_WHY_MSDEF, GUESTREGS);
|
2003-01-07 21:35:24 +00:00
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Calculate main storage size */
|
|
|
|
|
GUESTREGS->mainlim -= GUESTREGS->sie_mso;
|
|
|
|
|
|
|
|
|
|
#else /*!defined(FEATURE_ESAME)*/
|
|
|
|
|
/* Load main storage origin */
|
|
|
|
|
FETCH_HW(GUESTREGS->sie_mso,STATEBK->mso);
|
|
|
|
|
GUESTREGS->sie_mso <<= 16;
|
2005-09-24 16:17:46 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Load main storage extend */
|
|
|
|
|
FETCH_HW(GUESTREGS->mainlim,STATEBK->mse);
|
|
|
|
|
GUESTREGS->mainlim = ((GUESTREGS->mainlim + 1) << 16) - 1;
|
2001-02-23 20:49:19 +00:00
|
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
|
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Load expanded storage origin */
|
|
|
|
|
GUESTREGS->sie_xso = STATEBK->xso[0] << 16
|
|
|
|
|
| STATEBK->xso[1] << 8
|
|
|
|
|
| STATEBK->xso[2];
|
|
|
|
|
GUESTREGS->sie_xso *= (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT);
|
2005-09-24 16:17:46 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Load expanded storage limit */
|
|
|
|
|
GUESTREGS->sie_xsl = STATEBK->xsl[0] << 16
|
|
|
|
|
| STATEBK->xsl[1] << 8
|
|
|
|
|
| STATEBK->xsl[2];
|
|
|
|
|
GUESTREGS->sie_xsl *= (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT);
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-18 12:16:57 +00:00
|
|
|
/* Validate Guest prefix */
|
2002-12-05 13:27:27 +00:00
|
|
|
if(GUESTREGS->PX > GUESTREGS->mainlim)
|
2001-12-18 12:16:57 +00:00
|
|
|
{
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2004-12-26 07:47:16 +00:00
|
|
|
SIE_VI_WHY_PFOUT, GUESTREGS);
|
2002-01-30 22:06:45 +00:00
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
2001-12-18 12:16:57 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* System Control Area Origin */
|
|
|
|
|
FETCH_FW(GUESTREGS->sie_scao, STATEBK->scao);
|
2010-11-09 19:36:31 +00:00
|
|
|
#if defined(FEATURE_ESAME)
|
|
|
|
|
{
|
|
|
|
|
U32 sie_scaoh;
|
|
|
|
|
/* For ESAME insert the high word of the address */
|
|
|
|
|
FETCH_FW(sie_scaoh, STATEBK->scaoh);
|
|
|
|
|
GUESTREGS->sie_scao |= (RADR)sie_scaoh << 32;
|
|
|
|
|
}
|
|
|
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
if(GUESTREGS->sie_scao > regs->mainlim)
|
|
|
|
|
{
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2004-12-26 07:47:16 +00:00
|
|
|
SIE_VI_WHY_SCADR, GUESTREGS);
|
2003-01-07 21:35:24 +00:00
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Validate MSO */
|
2004-12-26 07:47:16 +00:00
|
|
|
if (GUESTREGS->sie_mso)
|
2001-12-18 12:16:57 +00:00
|
|
|
{
|
|
|
|
|
/* Preferred guest must have zero MSO */
|
2004-12-26 07:47:16 +00:00
|
|
|
if (GUESTREGS->sie_pref)
|
2001-12-18 12:16:57 +00:00
|
|
|
{
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2005-09-24 16:17:46 +00:00
|
|
|
SIE_VI_WHY_MSONZ, GUESTREGS);
|
|
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
2001-12-18 12:16:57 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* MCDS guest must have zero MSO */
|
2004-12-26 07:47:16 +00:00
|
|
|
if (STATEBK->mx & SIE_MX_XC)
|
2001-12-18 12:16:57 +00:00
|
|
|
{
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2004-12-26 07:47:16 +00:00
|
|
|
SIE_VI_WHY_MSODS, GUESTREGS);
|
2002-01-30 22:06:45 +00:00
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
2001-12-18 12:16:57 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-29 13:49:50 +00:00
|
|
|
#if defined(FEATURE_VIRTUAL_ARCHITECTURE_LEVEL)
|
|
|
|
|
/* Set Virtual Architecture Level (Facility List) */
|
|
|
|
|
{
|
|
|
|
|
U32 fld;
|
|
|
|
|
int i;
|
|
|
|
|
BYTE *facility_mask;
|
|
|
|
|
|
2010-09-01 20:36:35 +00:00
|
|
|
for(i = 0; i < STFL_HBYTESIZE; i++)
|
2010-08-29 13:49:50 +00:00
|
|
|
GUESTREGS->facility_list[i] = regs->facility_list[i];
|
|
|
|
|
|
|
|
|
|
FETCH_FW(fld,STATEBK->fld);
|
|
|
|
|
|
|
|
|
|
if(fld > regs->mainlim)
|
|
|
|
|
{
|
|
|
|
|
// SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
|
|
|
|
// ZZ: FIXME SIE_VI_WHY_??ADR, GUESTREGS);
|
|
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(fld & 0x7ffffff8)
|
|
|
|
|
{
|
2010-09-06 18:00:08 +00:00
|
|
|
facility_mask = &(regs->mainstor[fld]);
|
2012-07-20 17:18:03 +10:00
|
|
|
GUESTREGS->facility_list[0] &= (facility_mask[0]
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
2012-07-20 11:05:06 +02:00
|
|
|
/* Prevent current architecture mode being masked */ | 0x40
|
2012-07-20 17:18:03 +10:00
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
for(i = 1; i < STFL_BYTESIZE; i++)
|
2010-08-29 13:49:50 +00:00
|
|
|
GUESTREGS->facility_list[i] &= facility_mask[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /*defined(FEATURE_VIRTUAL_ARCHITECTURE_LEVEL)*/
|
|
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
#if !defined(FEATURE_ESAME)
|
|
|
|
|
/* Reference and Change Preservation Origin */
|
|
|
|
|
FETCH_FW(GUESTREGS->sie_rcpo, STATEBK->rcpo);
|
2004-12-26 07:47:16 +00:00
|
|
|
if (!GUESTREGS->sie_rcpo && !GUESTREGS->sie_pref)
|
2003-01-07 21:35:24 +00:00
|
|
|
{
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2004-12-26 07:47:16 +00:00
|
|
|
SIE_VI_WHY_RCZER, GUESTREGS);
|
2003-01-07 21:35:24 +00:00
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* Load the CPU timer */
|
2005-12-31 20:14:56 +00:00
|
|
|
FETCH_DW(dreg, STATEBK->cputimer);
|
|
|
|
|
set_cpu_timer(GUESTREGS, dreg);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* Load the TOD clock offset for this guest */
|
|
|
|
|
FETCH_DW(GUESTREGS->sie_epoch, STATEBK->epoch);
|
2012-12-22 11:46:52 -08:00
|
|
|
GUESTREGS->tod_epoch = regs->tod_epoch + tod2etod(GUESTREGS->sie_epoch);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* Load the clock comparator */
|
|
|
|
|
FETCH_DW(GUESTREGS->clkc, STATEBK->clockcomp);
|
2012-12-22 11:46:52 -08:00
|
|
|
GUESTREGS->clkc = tod2etod(GUESTREGS->clkc); /* Internal Hercules format */
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* Load TOD Programmable Field */
|
|
|
|
|
FETCH_HW(GUESTREGS->todpr, STATEBK->todpf);
|
|
|
|
|
|
|
|
|
|
/* Load the guest registers */
|
2005-09-24 16:17:46 +00:00
|
|
|
memcpy(GUESTREGS->gr, regs->gr, 14 * sizeof(regs->gr[0]));
|
|
|
|
|
memcpy(GUESTREGS->ar, regs->ar, 16 * sizeof(regs->ar[0]));
|
|
|
|
|
memcpy(GUESTREGS->fpr, regs->fpr, 32 * sizeof(regs->fpr[0]));
|
2001-10-07 17:09:57 +00:00
|
|
|
#if defined(FEATURE_BINARY_FLOATING_POINT)
|
|
|
|
|
GUESTREGS->fpc = regs->fpc;
|
|
|
|
|
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* Load GR14 */
|
|
|
|
|
FETCH_W(GUESTREGS->GR(14), STATEBK->gr14);
|
|
|
|
|
|
|
|
|
|
/* Load GR15 */
|
|
|
|
|
FETCH_W(GUESTREGS->GR(15), STATEBK->gr15);
|
|
|
|
|
|
|
|
|
|
/* Load control registers */
|
|
|
|
|
for(n = 0;n < 16; n++)
|
|
|
|
|
FETCH_W(GUESTREGS->CR(n), STATEBK->cr[n]);
|
|
|
|
|
|
|
|
|
|
FETCH_HW(lhcpu, STATEBK->lhcpu);
|
2004-12-26 07:47:16 +00:00
|
|
|
/*
|
|
|
|
|
* If this is not the last host cpu that dispatched this state
|
|
|
|
|
* descriptor then clear the guest TLB entries
|
|
|
|
|
*/
|
|
|
|
|
if (regs->cpuad != lhcpu
|
|
|
|
|
|| SIE_STATE(GUESTREGS) != effective_addr2)
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
2003-11-25 19:10:39 +00:00
|
|
|
SIE_PERFMON(SIE_PERF_ENTER_F);
|
|
|
|
|
|
2001-05-31 16:01:20 +00:00
|
|
|
/* Absolute address of state descriptor block */
|
2004-02-04 09:10:47 +00:00
|
|
|
SIE_STATE(GUESTREGS) = effective_addr2;
|
2001-05-31 16:01:20 +00:00
|
|
|
|
|
|
|
|
/* Update Last Host CPU address */
|
|
|
|
|
STORE_HW(STATEBK->lhcpu, regs->cpuad);
|
|
|
|
|
|
|
|
|
|
/* Purge guest TLB entries */
|
2001-02-23 20:49:19 +00:00
|
|
|
ARCH_DEP(purge_tlb) (GUESTREGS);
|
|
|
|
|
ARCH_DEP(purge_alb) (GUESTREGS);
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-26 07:47:16 +00:00
|
|
|
/* Initialize interrupt mask and state */
|
|
|
|
|
SET_IC_MASK(GUESTREGS);
|
|
|
|
|
SET_IC_INITIAL_STATE(GUESTREGS);
|
2007-02-09 23:59:58 +00:00
|
|
|
SET_IC_PER(GUESTREGS);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
|
|
|
|
/* Initialize accelerated address lookup values */
|
|
|
|
|
SET_AEA_MODE(GUESTREGS);
|
|
|
|
|
SET_AEA_COMMON(GUESTREGS);
|
|
|
|
|
INVALIDATE_AIA(GUESTREGS);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2006-11-07 01:02:58 +00:00
|
|
|
GUESTREGS->tracing = regs->tracing;
|
|
|
|
|
|
2004-12-26 07:47:16 +00:00
|
|
|
/*
|
|
|
|
|
* Do setjmp(progjmp) because translate_addr() may result in
|
|
|
|
|
* longjmp(progjmp) for addressing exceptions.
|
|
|
|
|
*/
|
2003-01-07 21:35:24 +00:00
|
|
|
if(!setjmp(GUESTREGS->progjmp))
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
2004-12-26 07:47:16 +00:00
|
|
|
/*
|
|
|
|
|
* Set sie_active to 1. This means other threads may now
|
|
|
|
|
* access guestregs when holding intlock.
|
|
|
|
|
* This is the *only* place sie_active is set to one.
|
|
|
|
|
*/
|
2006-04-12 10:33:41 +00:00
|
|
|
OBTAIN_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
regs->sie_active = 1;
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Get PSA pointer and ensure PSA is paged in */
|
|
|
|
|
if(GUESTREGS->sie_pref)
|
2004-11-28 22:07:17 +00:00
|
|
|
{
|
2006-01-08 13:07:32 +00:00
|
|
|
GUESTREGS->psa = (PSA_3XX*)(GUESTREGS->mainstor + GUESTREGS->PX);
|
2004-11-28 22:07:17 +00:00
|
|
|
GUESTREGS->sie_px = GUESTREGS->PX;
|
|
|
|
|
}
|
2002-02-15 06:55:23 +00:00
|
|
|
else
|
2003-01-07 21:35:24 +00:00
|
|
|
{
|
|
|
|
|
if (ARCH_DEP(translate_addr) (GUESTREGS->sie_mso + GUESTREGS->PX,
|
2004-02-29 00:10:17 +00:00
|
|
|
USE_PRIMARY_SPACE, regs, ACCTYPE_SIE))
|
2003-01-07 21:35:24 +00:00
|
|
|
{
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2004-12-26 07:47:16 +00:00
|
|
|
SIE_VI_WHY_PFACC, GUESTREGS);
|
2003-01-07 21:35:24 +00:00
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
2006-04-12 10:33:41 +00:00
|
|
|
OBTAIN_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
regs->sie_active = 0;
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2004-12-26 07:47:16 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Convert host real address to host absolute address */
|
2004-11-28 22:07:17 +00:00
|
|
|
GUESTREGS->sie_px = APPLY_PREFIXING (regs->dat.raddr, regs->PX);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
2004-11-28 22:07:17 +00:00
|
|
|
if (regs->dat.protect || GUESTREGS->sie_px > regs->mainlim)
|
2003-01-07 21:35:24 +00:00
|
|
|
{
|
|
|
|
|
SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT,
|
2004-12-26 07:47:16 +00:00
|
|
|
SIE_VI_WHY_PFACC, GUESTREGS);
|
2003-01-07 21:35:24 +00:00
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
2006-04-12 10:33:41 +00:00
|
|
|
OBTAIN_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
regs->sie_active = 0;
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2006-01-08 13:07:32 +00:00
|
|
|
GUESTREGS->psa = (PSA_3XX*)(GUESTREGS->mainstor + GUESTREGS->sie_px);
|
2003-01-07 21:35:24 +00:00
|
|
|
}
|
2004-12-26 07:47:16 +00:00
|
|
|
|
|
|
|
|
/* Intialize guest timers */
|
2006-04-12 10:33:41 +00:00
|
|
|
OBTAIN_INTLOCK(regs);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
|
|
|
|
/* CPU timer */
|
2012-12-22 11:46:52 -08:00
|
|
|
if(cpu_timer(GUESTREGS) < 0)
|
2004-12-26 07:47:16 +00:00
|
|
|
ON_IC_PTIMER(GUESTREGS);
|
|
|
|
|
|
|
|
|
|
/* Clock comparator */
|
2005-12-04 11:38:43 +00:00
|
|
|
if( TOD_CLOCK(GUESTREGS) > GUESTREGS->clkc )
|
2004-12-26 07:47:16 +00:00
|
|
|
ON_IC_CLKC(GUESTREGS);
|
|
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
#if !defined(FEATURE_ESAME)
|
2004-12-26 07:47:16 +00:00
|
|
|
/* Interval timer if S/370 and timer is enabled */
|
|
|
|
|
if((STATEBK->m & SIE_M_370) && !(STATEBK->m & SIE_M_ITMOF))
|
2003-01-07 21:35:24 +00:00
|
|
|
{
|
2005-09-24 16:17:46 +00:00
|
|
|
S32 itimer, olditimer;
|
|
|
|
|
U32 residue;
|
2004-12-26 07:47:16 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Set the interval timer pending according to the T bit
|
|
|
|
|
in the state control */
|
|
|
|
|
if(STATEBK->s & SIE_S_T)
|
|
|
|
|
ON_IC_ITIMER(GUESTREGS);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Fetch the residu from the state descriptor */
|
|
|
|
|
FETCH_FW(residue,STATEBK->residue);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Fetch the timer value from location 80 */
|
2006-01-08 13:07:32 +00:00
|
|
|
FETCH_FW(olditimer,GUESTREGS->psa->inttimer);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
|
|
|
|
/* Bit position 23 of the interval timer is decremented
|
|
|
|
|
once for each multiple of 3,333 usecs containded in
|
2003-01-07 21:35:24 +00:00
|
|
|
bit position 0-19 of the residue counter */
|
|
|
|
|
itimer = olditimer - ((residue / 3333) >> 4);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Store the timer back */
|
2006-01-08 13:07:32 +00:00
|
|
|
STORE_FW(GUESTREGS->psa->inttimer, itimer);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Set interrupt flag and interval timer interrupt pending
|
|
|
|
|
if the interval timer went from positive to negative */
|
|
|
|
|
if (itimer < 0 && olditimer >= 0)
|
|
|
|
|
ON_IC_ITIMER(GUESTREGS);
|
|
|
|
|
}
|
2006-01-01 21:37:32 +00:00
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
2004-12-26 07:47:16 +00:00
|
|
|
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
|
|
|
|
/* Early exceptions associated with the guest load_psw() */
|
2003-01-07 21:35:24 +00:00
|
|
|
if(icode)
|
2007-01-04 23:12:04 +00:00
|
|
|
GUESTREGS->program_interrupt (GUESTREGS, icode);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
/* Run SIE in guests architecture mode */
|
|
|
|
|
icode = run_sie[GUESTREGS->arch_mode] (regs);
|
2004-12-26 07:47:16 +00:00
|
|
|
|
|
|
|
|
} /* if (setjmp(GUESTREGS->progjmp)) */
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
ARCH_DEP(sie_exit) (regs, icode);
|
|
|
|
|
|
|
|
|
|
/* Perform serialization and checkpoint synchronization */
|
|
|
|
|
PERFORM_SERIALIZATION (regs);
|
|
|
|
|
PERFORM_CHKPT_SYNC (regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
longjmp(regs->progjmp, SIE_NO_INTERCEPT);
|
2004-12-26 07:47:16 +00:00
|
|
|
}
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Exit SIE state, restore registers and update the state descriptor */
|
|
|
|
|
void ARCH_DEP(sie_exit) (REGS *regs, int code)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
|
2009-03-06 15:33:02 +00:00
|
|
|
if(pttclass & PTT_CL_SIE)
|
|
|
|
|
{
|
|
|
|
|
U32 nt1 = 0, nt2 = 0;
|
|
|
|
|
BYTE *ip;
|
|
|
|
|
if(!GUESTREGS->instinvalid)
|
|
|
|
|
{
|
|
|
|
|
if(GUESTREGS->ip[0] == 0x44
|
|
|
|
|
#if defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)
|
|
|
|
|
|| (GUESTREGS->ip[0] == 0xc6 && !(GUESTREGS->ip[1] & 0x0f))
|
|
|
|
|
#endif /*defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)*/
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
ip = GUESTREGS->exinst;
|
|
|
|
|
nt2 = (GUESTREGS->ip[0] == 0x44) ? 0x44 : ((0xc6 << 8) | (GUESTREGS->ip[1] & 0x0f));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ip = GUESTREGS->ip;
|
|
|
|
|
nt1 = (ip[0] << 24) | (ip[1] << 16);
|
|
|
|
|
if(ILC(ip[0]) > 2)
|
|
|
|
|
nt1 |= (ip[2] << 8) | ip[3];
|
|
|
|
|
if(ILC(ip[0]) > 4)
|
|
|
|
|
nt2 |= (ip[4] << 24) | (ip[5] << 16);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-24 06:16:05 -08:00
|
|
|
PTT_SIE("*SIE", nt1, nt2, code);
|
2009-03-06 15:33:02 +00:00
|
|
|
}
|
2009-03-01 15:06:53 +00:00
|
|
|
|
2001-03-06 18:04:21 +00:00
|
|
|
#if defined(SIE_DEBUG)
|
2011-08-12 23:28:17 +00:00
|
|
|
logmsg(_("SIE: interception code %d\n"),code);
|
2006-11-07 01:02:58 +00:00
|
|
|
ARCH_DEP(display_inst) (GUESTREGS,
|
|
|
|
|
GUESTREGS->instinvalid ? NULL : GUESTREGS->ip);
|
2001-03-06 18:04:21 +00:00
|
|
|
#endif /*defined(SIE_DEBUG)*/
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2003-11-25 19:10:39 +00:00
|
|
|
SIE_PERFMON(SIE_PERF_EXIT);
|
|
|
|
|
SIE_PERFMON(SIE_PERF_PGMINT);
|
|
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
/* Indicate we have left SIE mode */
|
2006-04-12 10:33:41 +00:00
|
|
|
OBTAIN_INTLOCK(regs);
|
2001-02-23 20:49:19 +00:00
|
|
|
regs->sie_active = 0;
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* zeroize interception status */
|
|
|
|
|
STATEBK->f = 0;
|
|
|
|
|
|
2004-04-17 19:57:49 +00:00
|
|
|
switch(code > 0 ? code & ~PGM_PER_EVENT : code)
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
|
|
|
|
case SIE_HOST_INTERRUPT:
|
|
|
|
|
/* If a host interrupt is pending
|
|
|
|
|
then backup the psw and exit */
|
2006-12-20 04:26:20 +00:00
|
|
|
SET_PSW_IA(regs);
|
|
|
|
|
UPD_PSW_IA (regs, regs->psw.IA -REAL_ILC(regs));
|
2001-02-23 20:49:19 +00:00
|
|
|
break;
|
|
|
|
|
case SIE_HOST_PGMINT:
|
|
|
|
|
break;
|
|
|
|
|
case SIE_INTERCEPT_INST:
|
|
|
|
|
STATEBK->c = SIE_C_INST;
|
|
|
|
|
break;
|
2001-12-09 18:59:59 +00:00
|
|
|
case SIE_INTERCEPT_PER:
|
|
|
|
|
STATEBK->f |= SIE_F_IF;
|
|
|
|
|
/*fallthru*/
|
2001-02-23 20:49:19 +00:00
|
|
|
case SIE_INTERCEPT_INSTCOMP:
|
|
|
|
|
STATEBK->c = SIE_C_PGMINST;
|
|
|
|
|
break;
|
|
|
|
|
case SIE_INTERCEPT_WAIT:
|
|
|
|
|
STATEBK->c = SIE_C_WAIT;
|
|
|
|
|
break;
|
|
|
|
|
case SIE_INTERCEPT_STOPREQ:
|
|
|
|
|
STATEBK->c = SIE_C_STOPREQ;
|
|
|
|
|
break;
|
|
|
|
|
case SIE_INTERCEPT_IOREQ:
|
|
|
|
|
STATEBK->c = SIE_C_IOREQ;
|
|
|
|
|
break;
|
|
|
|
|
case SIE_INTERCEPT_EXTREQ:
|
|
|
|
|
STATEBK->c = SIE_C_EXTREQ;
|
|
|
|
|
break;
|
|
|
|
|
case SIE_INTERCEPT_EXT:
|
|
|
|
|
STATEBK->c = SIE_C_EXTINT;
|
|
|
|
|
break;
|
|
|
|
|
case SIE_INTERCEPT_VALIDITY:
|
|
|
|
|
STATEBK->c = SIE_C_VALIDITY;
|
|
|
|
|
break;
|
2003-01-07 21:35:24 +00:00
|
|
|
case SIE_INTERCEPT_IOINT:
|
|
|
|
|
case SIE_INTERCEPT_IOINTP:
|
|
|
|
|
STATEBK->c = SIE_C_IOINT;
|
|
|
|
|
break;
|
|
|
|
|
case SIE_INTERCEPT_IOINST:
|
|
|
|
|
STATEBK->c = SIE_C_IOINST;
|
|
|
|
|
break;
|
2001-02-23 20:49:19 +00:00
|
|
|
case PGM_OPERATION_EXCEPTION:
|
|
|
|
|
STATEBK->c = SIE_C_OPEREXC;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
STATEBK->c = SIE_C_PGMINT;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Save CPU timer */
|
2006-01-08 13:07:32 +00:00
|
|
|
STORE_DW(STATEBK->cputimer, cpu_timer(GUESTREGS));
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* Save clock comparator */
|
2012-12-22 11:46:52 -08:00
|
|
|
STORE_DW(STATEBK->clockcomp, etod2tod(GUESTREGS->clkc));
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2006-01-10 20:34:16 +00:00
|
|
|
#if defined(_FEATURE_INTERVAL_TIMER) && !defined(FEATURE_ESAME)
|
2002-02-15 06:55:23 +00:00
|
|
|
/* If this is a S/370 guest, and the interval timer is enabled
|
|
|
|
|
then save the timer state control bit */
|
|
|
|
|
if( (STATEBK->m & SIE_M_370)
|
|
|
|
|
&& !(STATEBK->m & SIE_M_ITMOF))
|
|
|
|
|
{
|
2006-01-10 20:34:16 +00:00
|
|
|
/* Save the shadow interval timer */
|
|
|
|
|
s370_store_int_timer(regs);
|
|
|
|
|
|
2002-02-15 06:55:23 +00:00
|
|
|
if(IS_IC_ITIMER(GUESTREGS))
|
|
|
|
|
STATEBK->s |= SIE_S_T;
|
|
|
|
|
else
|
|
|
|
|
STATEBK->s &= ~SIE_S_T;
|
|
|
|
|
}
|
2006-01-10 20:34:16 +00:00
|
|
|
#endif /*defined(_FEATURE_INTERVAL_TIMER) && !defined(FEATURE_ESAME)*/
|
2002-02-15 06:55:23 +00:00
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
/* Save TOD Programmable Field */
|
|
|
|
|
STORE_HW(STATEBK->todpf, GUESTREGS->todpr);
|
|
|
|
|
|
|
|
|
|
/* Save GR14 */
|
|
|
|
|
STORE_W(STATEBK->gr14, GUESTREGS->GR(14));
|
|
|
|
|
|
|
|
|
|
/* Save GR15 */
|
|
|
|
|
STORE_W(STATEBK->gr15, GUESTREGS->GR(15));
|
|
|
|
|
|
|
|
|
|
/* Store the PSW */
|
2001-03-06 18:04:21 +00:00
|
|
|
if(GUESTREGS->arch_mode == ARCH_390)
|
|
|
|
|
s390_store_psw (GUESTREGS, STATEBK->psw);
|
2001-12-28 09:00:31 +00:00
|
|
|
#if defined(_370) || defined(_900)
|
2001-03-06 18:04:21 +00:00
|
|
|
else
|
2001-12-28 09:00:31 +00:00
|
|
|
#endif
|
2001-03-06 18:04:21 +00:00
|
|
|
#if defined(FEATURE_ESAME)
|
|
|
|
|
z900_store_psw (GUESTREGS, STATEBK->psw);
|
|
|
|
|
#else /*!defined(FEATURE_ESAME)*/
|
2001-12-28 09:00:31 +00:00
|
|
|
#if defined(_370)
|
2001-03-06 18:04:21 +00:00
|
|
|
s370_store_psw (GUESTREGS, STATEBK->psw);
|
2001-12-28 09:00:31 +00:00
|
|
|
#endif
|
2001-03-06 18:04:21 +00:00
|
|
|
#endif /*!defined(FEATURE_ESAME)*/
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* save control registers */
|
|
|
|
|
for(n = 0;n < 16; n++)
|
|
|
|
|
STORE_W(STATEBK->cr[n], GUESTREGS->CR(n));
|
|
|
|
|
|
|
|
|
|
/* Update the approprate host registers */
|
2005-09-24 16:17:46 +00:00
|
|
|
memcpy(regs->gr, GUESTREGS->gr, 14 * sizeof(regs->gr[0]));
|
|
|
|
|
memcpy(regs->ar, GUESTREGS->ar, 16 * sizeof(regs->ar[0]));
|
|
|
|
|
memcpy(regs->fpr, GUESTREGS->fpr, 32 * sizeof(regs->fpr[0]));
|
2001-10-07 17:09:57 +00:00
|
|
|
#if defined(FEATURE_BINARY_FLOATING_POINT)
|
|
|
|
|
regs->fpc = GUESTREGS->fpc;
|
|
|
|
|
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
|
2006-12-20 04:26:20 +00:00
|
|
|
INVALIDATE_AIA(regs);
|
2004-11-29 20:30:23 +00:00
|
|
|
SET_AEA_MODE(regs);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
/* Zeroize the interruption parameters */
|
2011-07-22 19:23:35 +00:00
|
|
|
memset(STATEBK->ipa, 0, 10);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
if( STATEBK->c == SIE_C_INST
|
|
|
|
|
|| STATEBK->c == SIE_C_PGMINST
|
2003-01-07 21:35:24 +00:00
|
|
|
|| STATEBK->c == SIE_C_OPEREXC
|
|
|
|
|
|| STATEBK->c == SIE_C_IOINST )
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
|
|
|
|
/* Indicate interception format 2 */
|
|
|
|
|
STATEBK->f |= SIE_F_IN;
|
|
|
|
|
|
2001-12-16 21:52:35 +00:00
|
|
|
#if defined(_FEATURE_PER)
|
2001-12-12 07:52:53 +00:00
|
|
|
/* Handle PER or concurrent PER event */
|
2006-11-05 16:41:20 +00:00
|
|
|
if( OPEN_IC_PER(GUESTREGS)
|
2004-04-17 19:57:49 +00:00
|
|
|
&& ECMODE(&GUESTREGS->psw)
|
2001-12-12 10:23:24 +00:00
|
|
|
&& (GUESTREGS->psw.sysmask & PSW_PERMODE) )
|
2001-12-12 07:52:53 +00:00
|
|
|
{
|
2005-09-24 16:17:46 +00:00
|
|
|
PSA *psa;
|
2001-12-16 21:52:35 +00:00
|
|
|
#if defined(_FEATURE_PER2)
|
2006-11-05 16:41:20 +00:00
|
|
|
GUESTREGS->perc |= OPEN_IC_PER(GUESTREGS) >> ((32 - IC_CR9_SHIFT) - 16);
|
2001-12-14 18:17:45 +00:00
|
|
|
/* Positions 14 and 15 contain zeros if a storage alteration
|
|
|
|
|
event was not indicated */
|
2006-11-05 16:41:20 +00:00
|
|
|
if( !(OPEN_IC_PER_SA(GUESTREGS))
|
|
|
|
|
|| (OPEN_IC_PER_STURA(GUESTREGS)) )
|
2001-12-14 18:17:45 +00:00
|
|
|
GUESTREGS->perc &= 0xFFFC;
|
|
|
|
|
|
2001-12-16 21:52:35 +00:00
|
|
|
#endif /*defined(_FEATURE_PER2)*/
|
2001-12-12 07:52:53 +00:00
|
|
|
/* Point to PSA fields in state descriptor */
|
2004-02-04 09:10:47 +00:00
|
|
|
psa = (void*)(regs->mainstor + SIE_STATE(GUESTREGS) + SIE_IP_PSA_OFFSET);
|
2001-12-12 07:52:53 +00:00
|
|
|
STORE_HW(psa->perint, GUESTREGS->perc);
|
|
|
|
|
STORE_W(psa->peradr, GUESTREGS->peradr);
|
2002-02-04 23:02:55 +00:00
|
|
|
}
|
2001-12-12 07:52:53 +00:00
|
|
|
|
2002-02-04 23:02:55 +00:00
|
|
|
if (IS_IC_PER_IF(GUESTREGS))
|
2001-12-12 10:23:24 +00:00
|
|
|
STATEBK->f |= SIE_F_IF;
|
2002-02-04 23:02:55 +00:00
|
|
|
|
2004-04-17 19:57:49 +00:00
|
|
|
/* Reset any pending PER indication */
|
|
|
|
|
OFF_IC_PER(GUESTREGS);
|
2001-12-16 21:52:35 +00:00
|
|
|
#endif /*defined(_FEATURE_PER)*/
|
2001-12-09 18:59:59 +00:00
|
|
|
|
2006-12-20 04:26:20 +00:00
|
|
|
/* Backup to the previous instruction */
|
|
|
|
|
GUESTREGS->ip -= REAL_ILC(GUESTREGS);
|
|
|
|
|
if (GUESTREGS->ip < GUESTREGS->aip)
|
|
|
|
|
GUESTREGS->ip = GUESTREGS->inst;
|
|
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
/* Update interception parameters in the state descriptor */
|
2008-04-09 09:03:58 +00:00
|
|
|
if(GUESTREGS->ip[0] == 0x44
|
|
|
|
|
#if defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)
|
|
|
|
|
|| (GUESTREGS->ip[0] == 0xc6 && !(GUESTREGS->ip[1] & 0x0f))
|
|
|
|
|
#endif /*defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)*/
|
|
|
|
|
)
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
|
|
|
|
int exilc;
|
|
|
|
|
STATEBK->f |= SIE_F_EX;
|
2004-01-17 04:21:49 +00:00
|
|
|
exilc = ILC(GUESTREGS->exinst[0]);
|
2001-02-23 20:49:19 +00:00
|
|
|
memcpy(STATEBK->ipa, GUESTREGS->exinst, exilc);
|
|
|
|
|
}
|
2008-04-09 09:03:58 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(!GUESTREGS->instinvalid)
|
|
|
|
|
memcpy(STATEBK->ipa, GUESTREGS->ip, ILC(GUESTREGS->ip[0]));
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
}
|
2001-12-12 10:23:24 +00:00
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
}
|
|
|
|
|
#endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(_FEATURE_SIE)
|
|
|
|
|
/* Execute guest instructions */
|
2011-08-15 12:41:45 +00:00
|
|
|
static int ARCH_DEP(run_sie) (REGS *regs)
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
2010-11-26 13:14:42 +00:00
|
|
|
int i;
|
2004-12-24 17:10:59 +00:00
|
|
|
int icode; /* SIE longjmp intercept code */
|
|
|
|
|
BYTE oldv; /* siebk->v change check reference */
|
2006-12-20 04:26:20 +00:00
|
|
|
BYTE *ip; /* instruction pointer */
|
2010-10-31 08:39:36 +00:00
|
|
|
const zz_func *current_opcode_table;
|
2010-11-18 00:13:22 +00:00
|
|
|
register int *caplocked = &sysblk.caplocked[regs->cpuad];
|
|
|
|
|
LOCK *caplock = &sysblk.caplock[regs->cpuad];
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2003-11-25 19:10:39 +00:00
|
|
|
SIE_PERFMON(SIE_PERF_RUNSIE);
|
|
|
|
|
|
2001-12-16 21:52:35 +00:00
|
|
|
#if defined(_FEATURE_PER)
|
2001-12-12 10:23:24 +00:00
|
|
|
/* Reset any PER pending indication */
|
|
|
|
|
OFF_IC_PER(GUESTREGS);
|
2001-12-16 21:52:35 +00:00
|
|
|
#endif /*defined(_FEATURE_PER)*/
|
2001-05-08 15:38:00 +00:00
|
|
|
|
2006-01-08 13:07:32 +00:00
|
|
|
#ifdef FEATURE_INTERVAL_TIMER
|
|
|
|
|
/* Load the shadow interval timer */
|
|
|
|
|
{
|
|
|
|
|
S32 itimer;
|
|
|
|
|
FETCH_FW(itimer,GUESTREGS->psa->inttimer);
|
|
|
|
|
set_int_timer(GUESTREGS, itimer);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
do {
|
2003-11-25 19:10:39 +00:00
|
|
|
SIE_PERFMON(SIE_PERF_RUNLOOP_1);
|
2001-02-23 20:49:19 +00:00
|
|
|
if(!(icode = setjmp(GUESTREGS->progjmp)))
|
2003-01-07 21:35:24 +00:00
|
|
|
do
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
2003-11-25 19:10:39 +00:00
|
|
|
SIE_PERFMON(SIE_PERF_RUNLOOP_2);
|
|
|
|
|
|
2004-12-24 17:10:59 +00:00
|
|
|
/* Keep a copy if SIEBK 'v' field for later checks */
|
|
|
|
|
oldv=GUESTREGS->siebk->v;
|
|
|
|
|
|
2004-02-17 22:38:48 +00:00
|
|
|
/* Set `execflag' to 0 in case EXecuted instruction did progjmp */
|
|
|
|
|
GUESTREGS->execflag = 0;
|
|
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
if(
|
|
|
|
|
SIE_I_STOP(GUESTREGS)
|
|
|
|
|
|| SIE_I_EXT(GUESTREGS)
|
|
|
|
|
|| SIE_I_IO(GUESTREGS)
|
|
|
|
|
)
|
|
|
|
|
break;
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2001-05-25 18:27:56 +00:00
|
|
|
if( SIE_IC_INTERRUPT_CPU(GUESTREGS) )
|
2001-05-24 12:13:39 +00:00
|
|
|
{
|
2003-11-25 19:10:39 +00:00
|
|
|
SIE_PERFMON(SIE_PERF_INTCHECK);
|
|
|
|
|
|
2001-12-06 19:51:33 +00:00
|
|
|
/* Process PER program interrupts */
|
2006-11-05 16:41:20 +00:00
|
|
|
if( OPEN_IC_PER(GUESTREGS) )
|
2001-12-09 18:59:59 +00:00
|
|
|
ARCH_DEP(program_interrupt) (GUESTREGS, PGM_PER_EVENT);
|
2001-12-16 19:19:48 +00:00
|
|
|
|
2006-04-12 10:33:41 +00:00
|
|
|
OBTAIN_INTLOCK(regs);
|
2004-12-24 17:10:59 +00:00
|
|
|
OFF_IC_INTERRUPT(GUESTREGS);
|
|
|
|
|
|
2006-12-20 04:26:20 +00:00
|
|
|
/* Set psw.IA and invalidate the aia */
|
|
|
|
|
INVALIDATE_AIA(GUESTREGS);
|
|
|
|
|
|
2001-12-12 10:23:24 +00:00
|
|
|
if( OPEN_IC_EXTPENDING(GUESTREGS) )
|
2001-05-25 18:27:56 +00:00
|
|
|
ARCH_DEP(perform_external_interrupt) (GUESTREGS);
|
|
|
|
|
|
2012-03-27 22:27:04 +11:00
|
|
|
if( ((STATEBK->ec[0] & SIE_EC0_IOA) || (STATEBK->ec[3] & SIE_EC3_SIGAA))
|
|
|
|
|
&& OPEN_IC_IOPENDING(GUESTREGS) )
|
2003-01-07 21:35:24 +00:00
|
|
|
{
|
|
|
|
|
PERFORM_SERIALIZATION (GUESTREGS);
|
|
|
|
|
PERFORM_CHKPT_SYNC (GUESTREGS);
|
|
|
|
|
ARCH_DEP (perform_io_interrupt) (GUESTREGS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(_FEATURE_WAITSTATE_ASSIST)
|
|
|
|
|
/* Wait state assist */
|
2004-02-17 22:38:48 +00:00
|
|
|
if (WAITSTATE(&GUESTREGS->psw) && (STATEBK->ec[0] & SIE_EC0_WAIA))
|
2003-01-07 21:35:24 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/* Test for disabled wait PSW and issue message */
|
|
|
|
|
if( IS_IC_DISABLED_WAIT_PSW(GUESTREGS) )
|
|
|
|
|
{
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
longjmp(GUESTREGS->progjmp, SIE_INTERCEPT_WAIT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(
|
|
|
|
|
SIE_I_STOP(GUESTREGS)
|
|
|
|
|
|| SIE_I_EXT(GUESTREGS)
|
|
|
|
|
|| SIE_I_IO(GUESTREGS)
|
|
|
|
|
|| SIE_I_HOST(regs)
|
|
|
|
|
)
|
|
|
|
|
{
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-17 19:25:30 +00:00
|
|
|
SET_AEA_MODE(GUESTREGS);
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
{
|
2007-12-10 23:12:02 +00:00
|
|
|
struct timespec waittime;
|
|
|
|
|
U64 now = host_tod();
|
|
|
|
|
waittime.tv_sec = now / 1000000;
|
|
|
|
|
waittime.tv_nsec = ((now % 1000000) + 3333) * 1000;
|
2006-12-21 22:39:39 +00:00
|
|
|
#ifdef OPTION_MIPS_COUNTING
|
2007-12-10 23:12:02 +00:00
|
|
|
regs->waittod = now;
|
2006-12-21 22:39:39 +00:00
|
|
|
#endif
|
2006-04-12 10:33:41 +00:00
|
|
|
sysblk.waiting_mask |= regs->cpubit;
|
2006-12-21 22:39:39 +00:00
|
|
|
sysblk.intowner = LOCK_OWNER_NONE;
|
2010-05-13 02:16:39 +00:00
|
|
|
timed_wait_condition
|
|
|
|
|
( ®s->intcond, &sysblk.intlock, &waittime );
|
2007-06-06 22:14:58 +00:00
|
|
|
while (sysblk.syncing)
|
|
|
|
|
wait_condition (&sysblk.sync_bc_cond, &sysblk.intlock);
|
2006-12-21 22:39:39 +00:00
|
|
|
sysblk.intowner = regs->cpuad;
|
2013-06-03 17:48:58 -07:00
|
|
|
|
|
|
|
|
/* Remove CPU from the waiting mask; AND
|
|
|
|
|
* must be used to handle the rare case
|
|
|
|
|
* where the CPU was already removed from
|
|
|
|
|
* sysblk.waiting_mask during
|
|
|
|
|
* wait_condition.
|
|
|
|
|
*/
|
|
|
|
|
sysblk.waiting_mask &= ~(regs->cpubit);
|
|
|
|
|
|
2006-12-21 22:39:39 +00:00
|
|
|
#ifdef OPTION_MIPS_COUNTING
|
2007-12-10 23:12:02 +00:00
|
|
|
regs->waittime += host_tod() - regs->waittod;
|
2006-12-21 22:39:39 +00:00
|
|
|
regs->waittod = 0;
|
|
|
|
|
#endif
|
2003-01-07 21:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
} /* end if(wait) */
|
|
|
|
|
#endif
|
|
|
|
|
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2001-02-23 20:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
if(
|
|
|
|
|
SIE_I_WAIT(GUESTREGS)
|
|
|
|
|
)
|
|
|
|
|
break;
|
|
|
|
|
|
2006-12-20 04:26:20 +00:00
|
|
|
ip = INSTRUCTION_FETCH(GUESTREGS, 0);
|
2010-10-29 15:23:12 +00:00
|
|
|
current_opcode_table=GUESTREGS->ARCH_DEP(runtime_opcode_xxxx);
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2001-03-06 18:04:21 +00:00
|
|
|
#if defined(SIE_DEBUG)
|
2001-02-23 20:49:19 +00:00
|
|
|
/* Display the instruction */
|
2006-11-07 01:02:58 +00:00
|
|
|
ARCH_DEP(display_inst) (GUESTREGS,
|
2006-12-20 04:26:20 +00:00
|
|
|
GUESTREGS->instinvalid ? NULL : ip);
|
2001-03-06 18:04:21 +00:00
|
|
|
#endif /*defined(SIE_DEBUG)*/
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2003-11-25 19:10:39 +00:00
|
|
|
SIE_PERFMON(SIE_PERF_EXEC);
|
2010-11-17 02:30:20 +00:00
|
|
|
|
2010-11-29 21:21:33 +00:00
|
|
|
//regs->instcount++;
|
2010-08-11 15:45:45 +00:00
|
|
|
EXECUTE_INSTRUCTION(current_opcode_table, ip, GUESTREGS);
|
2010-11-29 21:21:33 +00:00
|
|
|
regs->instcount++;
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2010-11-26 13:14:42 +00:00
|
|
|
SIE_PERFMON(SIE_PERF_EXEC_U);
|
2006-11-07 01:02:58 +00:00
|
|
|
|
2010-12-15 16:30:23 +00:00
|
|
|
/* BHe: I have tried several settings. But 2 unrolled */
|
|
|
|
|
/* executes gives (core i7 at my place) the best results. */
|
|
|
|
|
/* Even a do { } while(0); with several unrolled executes */
|
2012-07-20 11:05:06 +02:00
|
|
|
/* and without the 'i' was slower. That surprised me. */
|
2010-12-15 16:30:23 +00:00
|
|
|
for(i = 0; i < 128; i++)
|
2010-11-26 13:14:42 +00:00
|
|
|
{
|
2010-08-11 15:45:45 +00:00
|
|
|
UNROLLED_EXECUTE(current_opcode_table, GUESTREGS);
|
2010-12-15 16:30:23 +00:00
|
|
|
UNROLLED_EXECUTE(current_opcode_table, GUESTREGS);
|
2010-11-26 13:14:42 +00:00
|
|
|
}
|
2010-12-15 16:30:23 +00:00
|
|
|
regs->instcount += i * 2;
|
2006-11-07 01:02:58 +00:00
|
|
|
|
2010-11-26 13:14:42 +00:00
|
|
|
if (caplocked[0])
|
|
|
|
|
{
|
|
|
|
|
obtain_lock(caplock);
|
|
|
|
|
/* Greg must be proud of me */
|
|
|
|
|
release_lock(caplock);
|
|
|
|
|
}
|
2010-11-17 02:30:20 +00:00
|
|
|
|
2004-07-30 09:04:15 +00:00
|
|
|
} while( unlikely(!SIE_I_HOST(regs)
|
2004-12-02 18:05:15 +00:00
|
|
|
&& !SIE_I_WAIT(GUESTREGS)
|
|
|
|
|
&& !SIE_I_EXT(GUESTREGS)
|
|
|
|
|
&& !SIE_I_IO(GUESTREGS)
|
2006-11-05 16:41:20 +00:00
|
|
|
&& !SIE_INTERRUPT_PENDING(GUESTREGS)));
|
2004-12-24 17:10:59 +00:00
|
|
|
/******************************************/
|
|
|
|
|
/* ABOVE : Remain in SIE until... */
|
|
|
|
|
/* - A Host Interrupt is made pending */
|
|
|
|
|
/* - A Sie defined irpt becomes enabled */
|
|
|
|
|
/* - A guest interrupt is made pending */
|
|
|
|
|
/******************************************/
|
2004-07-30 09:04:15 +00:00
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2001-05-25 18:27:56 +00:00
|
|
|
if(icode == 0 || icode == SIE_NO_INTERCEPT)
|
2001-02-23 20:49:19 +00:00
|
|
|
{
|
2002-02-22 23:27:46 +00:00
|
|
|
/* Check PER first, higher priority */
|
2006-11-05 16:41:20 +00:00
|
|
|
if( OPEN_IC_PER(GUESTREGS) )
|
2002-02-22 23:27:46 +00:00
|
|
|
ARCH_DEP(program_interrupt) (GUESTREGS, PGM_PER_EVENT);
|
|
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
if( SIE_I_EXT(GUESTREGS) )
|
|
|
|
|
icode = SIE_INTERCEPT_EXTREQ;
|
|
|
|
|
else
|
|
|
|
|
if( SIE_I_IO(GUESTREGS) )
|
|
|
|
|
icode = SIE_INTERCEPT_IOREQ;
|
|
|
|
|
else
|
|
|
|
|
if( SIE_I_STOP(GUESTREGS) )
|
|
|
|
|
icode = SIE_INTERCEPT_STOPREQ;
|
|
|
|
|
else
|
|
|
|
|
if( SIE_I_WAIT(GUESTREGS) )
|
|
|
|
|
icode = SIE_INTERCEPT_WAIT;
|
|
|
|
|
else
|
|
|
|
|
if( SIE_I_HOST(regs) )
|
|
|
|
|
icode = SIE_HOST_INTERRUPT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} while(icode == 0 || icode == SIE_NO_INTERCEPT);
|
|
|
|
|
|
|
|
|
|
return icode;
|
|
|
|
|
}
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(FEATURE_INTERPRETIVE_EXECUTION)
|
|
|
|
|
#if defined(FEATURE_REGION_RELOCATE)
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
/* B23D STZP - Store Zone Parameter [S] */
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
DEF_INST(store_zone_parameter)
|
|
|
|
|
{
|
|
|
|
|
int b2; /* Values of R fields */
|
|
|
|
|
RADR effective_addr2; /* address of state desc. */
|
|
|
|
|
ZPB zpb; /* Zone Parameter Block */
|
|
|
|
|
int zone; /* Zone number */
|
|
|
|
|
|
2004-02-17 22:38:48 +00:00
|
|
|
S(inst, regs, b2, effective_addr2);
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
|
|
|
|
|
|
SIE_INTERCEPT(regs);
|
|
|
|
|
|
2015-01-24 06:16:05 -08:00
|
|
|
PTT_IO("STZP", regs->GR_L(1), regs->GR_L(2),regs->psw.IA_L);
|
2009-03-06 15:33:02 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
FW_CHECK(regs->GR(2), regs);
|
|
|
|
|
|
|
|
|
|
zone = regs->GR_LHLCL(1);
|
|
|
|
|
|
|
|
|
|
if(zone >= FEATURE_SIE_MAXZONES)
|
|
|
|
|
{
|
2015-01-24 06:16:05 -08:00
|
|
|
PTT_ERR("*STZP", regs->GR_L(1), regs->GR_L(2),regs->psw.IA_L);
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 3;
|
2003-01-07 21:35:24 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
STORE_W(zpb.mso,sysblk.zpb[zone].mso);
|
|
|
|
|
STORE_W(zpb.msl,sysblk.zpb[zone].msl);
|
|
|
|
|
STORE_W(zpb.eso,sysblk.zpb[zone].eso);
|
|
|
|
|
STORE_W(zpb.esl,sysblk.zpb[zone].esl);
|
|
|
|
|
|
|
|
|
|
ARCH_DEP(vstorec(&zpb, sizeof(ZPB)-1,regs->GR(2), 2, regs));
|
|
|
|
|
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 0;
|
2003-01-07 21:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
/* B23E SZP - Set Zone Parameter [S] */
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
DEF_INST(set_zone_parameter)
|
|
|
|
|
{
|
|
|
|
|
int b2; /* Values of R fields */
|
|
|
|
|
RADR effective_addr2; /* address of state desc. */
|
|
|
|
|
ZPB zpb; /* Zone Parameter Block */
|
|
|
|
|
int zone; /* Zone number */
|
|
|
|
|
RADR mso, /* Main Storage Origin */
|
|
|
|
|
msl, /* Main Storage Length */
|
|
|
|
|
eso, /* Expanded Storage Origin */
|
|
|
|
|
esl; /* Expanded Storage Length */
|
|
|
|
|
|
2004-02-17 22:38:48 +00:00
|
|
|
S(inst, regs, b2, effective_addr2);
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
|
|
|
|
|
|
SIE_INTERCEPT(regs);
|
|
|
|
|
|
2015-01-24 06:16:05 -08:00
|
|
|
PTT_IO("SZP", regs->GR_L(1), regs->GR_L(2),regs->psw.IA_L);
|
2009-03-06 15:33:02 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
FW_CHECK(regs->GR(2), regs);
|
|
|
|
|
|
|
|
|
|
zone = regs->GR_LHLCL(1);
|
|
|
|
|
|
|
|
|
|
if(zone == 0 || zone >= FEATURE_SIE_MAXZONES)
|
|
|
|
|
{
|
2015-01-24 06:16:05 -08:00
|
|
|
PTT_ERR("*SZP", regs->GR_L(1), regs->GR_L(2),regs->psw.IA_L);
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 3;
|
2003-01-07 21:35:24 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARCH_DEP(vfetchc(&zpb, sizeof(ZPB)-1,regs->GR(2), 2, regs));
|
|
|
|
|
|
|
|
|
|
FETCH_W(mso,zpb.mso);
|
|
|
|
|
FETCH_W(msl,zpb.msl);
|
|
|
|
|
FETCH_W(eso,zpb.eso);
|
|
|
|
|
FETCH_W(esl,zpb.esl);
|
|
|
|
|
|
|
|
|
|
#if defined(FEATURE_ESAME)
|
2003-06-02 13:16:07 +00:00
|
|
|
if( (mso & ~ZPB2_MS_VALID)
|
|
|
|
|
|| (msl & ~ZPB2_MS_VALID)
|
|
|
|
|
|| (eso & ~ZPB2_ES_VALID)
|
|
|
|
|
|| (esl & ~ZPB2_ES_VALID) )
|
2003-01-07 21:35:24 +00:00
|
|
|
ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION);
|
|
|
|
|
#endif /*defined(FEATURE_ESAME)*/
|
|
|
|
|
|
|
|
|
|
sysblk.zpb[zone].mso = mso;
|
|
|
|
|
sysblk.zpb[zone].msl = msl;
|
|
|
|
|
sysblk.zpb[zone].eso = eso;
|
|
|
|
|
sysblk.zpb[zone].esl = esl;
|
|
|
|
|
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 0;
|
2003-01-07 21:35:24 +00:00
|
|
|
}
|
|
|
|
|
#endif /*defined(FEATURE_REGION_RELOCATE)*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(FEATURE_IO_ASSIST)
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
/* B23F TPZI - Test Pending Zone Interrupt [S] */
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
DEF_INST(test_pending_zone_interrupt)
|
|
|
|
|
{
|
|
|
|
|
int b2; /* Values of R fields */
|
|
|
|
|
RADR effective_addr2; /* address of state desc. */
|
|
|
|
|
U32 ioid; /* I/O interruption address */
|
|
|
|
|
U32 ioparm; /* I/O interruption parameter*/
|
|
|
|
|
U32 iointid; /* I/O interruption ident */
|
|
|
|
|
FWORD tpziid[3];
|
|
|
|
|
int zone; /* Zone number */
|
|
|
|
|
|
2004-02-17 22:38:48 +00:00
|
|
|
S(inst, regs, b2, effective_addr2);
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
PRIV_CHECK(regs);
|
|
|
|
|
|
|
|
|
|
SIE_INTERCEPT(regs);
|
|
|
|
|
|
2015-01-24 06:16:05 -08:00
|
|
|
PTT_IO("TPZI", regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff),regs->psw.IA_L);
|
2009-03-06 15:33:02 +00:00
|
|
|
|
2003-01-07 21:35:24 +00:00
|
|
|
FW_CHECK(regs->GR(2), regs);
|
|
|
|
|
|
|
|
|
|
/* Perform serialization and checkpoint-synchronization */
|
|
|
|
|
PERFORM_SERIALIZATION (regs);
|
|
|
|
|
PERFORM_CHKPT_SYNC (regs);
|
|
|
|
|
|
|
|
|
|
zone = regs->GR_LHLCL(1);
|
|
|
|
|
|
|
|
|
|
if(zone >= FEATURE_SIE_MAXZONES)
|
|
|
|
|
{
|
2015-01-24 06:16:05 -08:00
|
|
|
PTT_ERR("*TPZI", regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff),regs->psw.IA_L);
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 0;
|
2003-01-07 21:35:24 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( IS_IC_IOPENDING )
|
|
|
|
|
{
|
|
|
|
|
/* Obtain the interrupt lock */
|
2006-04-12 10:33:41 +00:00
|
|
|
OBTAIN_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
|
2008-08-21 18:34:48 +00:00
|
|
|
/* Test (but don't clear!) pending interrupt, and set condition code */
|
2003-01-07 21:35:24 +00:00
|
|
|
if( ARCH_DEP(present_zone_io_interrupt) (&ioid, &ioparm,
|
|
|
|
|
&iointid, zone) )
|
|
|
|
|
|
|
|
|
|
/* Store the SSID word and I/O parameter if an interrupt was pending */
|
|
|
|
|
{
|
|
|
|
|
/* Store interruption parms */
|
|
|
|
|
STORE_FW(tpziid[0],ioid);
|
|
|
|
|
STORE_FW(tpziid[1],ioparm);
|
|
|
|
|
STORE_FW(tpziid[2],iointid);
|
|
|
|
|
|
|
|
|
|
/* Release the interrupt lock */
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
ARCH_DEP(vstorec(&tpziid, sizeof(tpziid)-1,regs->GR(2), 2, regs));
|
|
|
|
|
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 1;
|
2003-01-07 21:35:24 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Release the interrupt lock */
|
2006-04-12 10:33:41 +00:00
|
|
|
RELEASE_INTLOCK(regs);
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 0;
|
2003-01-07 21:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 0;
|
2003-01-07 21:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
/* DIAG 002 - Update Interrupt Interlock Control Bit in PMCW */
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
void ARCH_DEP(diagnose_002) (REGS *regs, int r1, int r3)
|
|
|
|
|
{
|
|
|
|
|
DEVBLK *dev;
|
|
|
|
|
U32 newgr1;
|
|
|
|
|
|
2006-02-25 17:50:17 +00:00
|
|
|
/* Program check if the ssid including lcss is invalid */
|
|
|
|
|
SSID_CHECK(regs);
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
/* Locate the device block for this subchannel */
|
2006-02-25 21:56:58 +00:00
|
|
|
dev = find_device_by_subchan (regs->GR_L(1));
|
2003-01-07 21:35:24 +00:00
|
|
|
|
|
|
|
|
/* Condition code 3 if subchannel does not exist,
|
|
|
|
|
is not valid, or is not enabled */
|
|
|
|
|
if (dev == NULL
|
|
|
|
|
|| (dev->pmcw.flag5 & PMCW5_V) == 0
|
|
|
|
|
|| (dev->pmcw.flag5 & PMCW5_E) == 0)
|
|
|
|
|
{
|
2015-01-24 06:16:05 -08:00
|
|
|
PTT_ERR("*DIAG002", regs->GR_L(r1),regs->GR_L(r3),regs->GR_L(1));
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 3;
|
2003-01-07 21:35:24 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Obtain the device lock */
|
|
|
|
|
obtain_lock (&dev->lock);
|
|
|
|
|
|
|
|
|
|
/* Set newgr1 to the current value of pending and interlock control */
|
|
|
|
|
newgr1 = ((dev->scsw.flag3 & SCSW3_SC_PEND)
|
|
|
|
|
|| (dev->pciscsw.flag3 & SCSW3_SC_PEND)) ? 0x02 : 0;
|
|
|
|
|
if(dev->pmcw.flag27 & PMCW27_I)
|
|
|
|
|
newgr1 |= 0x01;
|
|
|
|
|
|
|
|
|
|
/* Do a compare-and-swap operation on the interrupt interlock
|
|
|
|
|
control bit where both interlock and pending bits are
|
|
|
|
|
compared, but only the interlock bit is swapped */
|
|
|
|
|
if((regs->GR_L(r1) & 0x03) == newgr1)
|
|
|
|
|
{
|
|
|
|
|
dev->pmcw.flag27 &= ~PMCW27_I;
|
|
|
|
|
dev->pmcw.flag27 |= (regs->GR_L(r3) & 0x01) ? PMCW27_I : 0;
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 0;
|
2003-01-07 21:35:24 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
regs->GR_L(r1) &= ~0x03;
|
|
|
|
|
regs->GR_L(r1) |= newgr1;
|
2007-01-13 07:30:02 +00:00
|
|
|
regs->psw.cc = 1;
|
2003-01-07 21:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Release the device lock */
|
|
|
|
|
release_lock (&dev->lock);
|
|
|
|
|
}
|
|
|
|
|
#endif /*defined(FEATURE_IO_ASSIST)*/
|
|
|
|
|
#endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/
|
|
|
|
|
|
|
|
|
|
|
2001-02-23 20:49:19 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(_GEN_ARCH)
|
|
|
|
|
|
2001-12-28 09:00:31 +00:00
|
|
|
#if defined(_ARCHMODE2)
|
|
|
|
|
#define _GEN_ARCH _ARCHMODE2
|
|
|
|
|
#include "sie.c"
|
|
|
|
|
#endif
|
2001-02-23 20:49:19 +00:00
|
|
|
|
2001-12-28 09:00:31 +00:00
|
|
|
#if defined(_ARCHMODE3)
|
|
|
|
|
#undef _GEN_ARCH
|
|
|
|
|
#define _GEN_ARCH _ARCHMODE3
|
|
|
|
|
#include "sie.c"
|
|
|
|
|
#endif
|
2001-02-23 20:49:19 +00:00
|
|
|
|
|
|
|
|
#endif /*!defined(_GEN_ARCH)*/
|