1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
|
/* MACHCHK.C (c) Copyright Jan Jaeger, 2000-2009 */
/* ESA/390 Machine Check Functions */
/* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */
// $Id: machchk.c 5126 2009-01-23 13:05:56Z bernard $
/*-------------------------------------------------------------------*/
/* The machine check function supports dynamic I/O configuration. */
/* When a subchannel is added/changed/deleted an ancillary */
/* channel report is made pending. This ancillary channel */
/* report can be read by the store channel report word I/O */
/* instruction. Changes to the availability will result in */
/* Messages IOS150I and IOS151I (device xxxx now/not available) */
/* Added Instruction processing damage machine check function such */
/* that abends/waits/loops in instructions will be reflected to the */
/* system running under hercules as a machine malfunction. This */
/* includes the machine check, checkstop, and malfunction alert */
/* external interrupt as defined in the architecture. - 6/8/01 *JJ */
/*-------------------------------------------------------------------*/
// $Log$
// Revision 1.51 2009/01/15 17:36:44 jj
// Change http server startup
//
// Revision 1.50 2007/06/23 00:04:14 ivan
// Update copyright notices to include current year (2007)
//
// Revision 1.49 2007/01/16 01:45:33 gsmith
// Tweaks to instruction stepping/tracing
//
// Revision 1.48 2006/12/08 09:43:28 jj
// Add CVS message log
//
#include "hstdinc.h"
#if !defined(_HENGINE_DLL_)
#define _HENGINE_DLL_
#endif
#if !defined(_MACHCHK_C_)
#define _MACHCHK_C_
#endif
#include "hercules.h"
#include "opcode.h"
#if !defined(_MACHCHK_C)
#define _MACHCHK_C
/*-------------------------------------------------------------------*/
/* Return pending channel report */
/* */
/* Returns zero if no device has CRW pending. Otherwise returns */
/* the channel report word for the first channel path or device */
/* which has a CRW pending, and resets the CRW for that device. */
/*-------------------------------------------------------------------*/
U32 channel_report(REGS *regs)
{
DEVBLK *dev;
U32 i,j;
/* Scan for channel path reset CRW's */
for(i = 0; i < 8; i++)
{
if(sysblk.chp_reset[i])
{
OBTAIN_INTLOCK(regs);
for(j = 0; j < 32; j++)
{
if(sysblk.chp_reset[i] & (0x80000000 >> j))
{
sysblk.chp_reset[i] &= ~(0x80000000 >> j);
RELEASE_INTLOCK(regs);
return CRW_SOL | CRW_CHPID | CRW_AR | CRW_INIT | ((i*32)+j);
}
}
RELEASE_INTLOCK(regs);
}
}
/* Scan for subchannel alert CRW's */
for(dev = sysblk.firstdev; dev!= NULL; dev = dev->nextdev)
{
if(dev->crwpending)
{
obtain_lock(&dev->lock);
if(dev->crwpending)
{
dev->crwpending = 0;
release_lock(&dev->lock);
return CRW_SUBCH | CRW_AR | CRW_ALERT | dev->subchan;
}
release_lock(&dev->lock);
}
}
return 0;
} /* end function channel_report */
/*-------------------------------------------------------------------*/
/* Indicate crw pending */
/*-------------------------------------------------------------------*/
void machine_check_crwpend()
{
/* Signal waiting CPUs that an interrupt may be pending */
OBTAIN_INTLOCK(NULL);
ON_IC_CHANRPT;
WAKEUP_CPUS_MASK (sysblk.waiting_mask);
RELEASE_INTLOCK(NULL);
} /* end function machine_check_crwpend */
#endif /*!defined(_MACHCHK_C)*/
/*-------------------------------------------------------------------*/
/* Present Machine Check Interrupt */
/* Input: */
/* regs Pointer to the CPU register context */
/* Output: */
/* mcic Machine check interrupt code */
/* xdmg External damage code */
/* fsta Failing storage address */
/* Return code: */
/* 0=No machine check, 1=Machine check presented */
/* */
/* Generic machine check function. At the momement the only */
/* supported machine check is the channel report. */
/* */
/* This routine must be called with the sysblk.intlock held */
/*-------------------------------------------------------------------*/
int ARCH_DEP(present_mck_interrupt)(REGS *regs, U64 *mcic, U32 *xdmg, RADR *fsta)
{
int rc = 0;
UNREFERENCED_370(regs);
UNREFERENCED_370(mcic);
UNREFERENCED_370(xdmg);
UNREFERENCED_370(fsta);
#ifdef FEATURE_CHANNEL_SUBSYSTEM
/* If there is a crw pending and we are enabled for the channel
report interrupt subclass then process the interrupt */
if( OPEN_IC_CHANRPT(regs) )
{
*mcic = MCIC_CP |
MCIC_WP |
MCIC_MS |
MCIC_PM |
MCIC_IA |
#ifdef FEATURE_HEXADECIMAL_FLOATING_POINT
MCIC_FP |
#endif /*FEATURE_HEXADECIMAL_FLOATING_POINT*/
MCIC_GR |
MCIC_CR |
MCIC_ST |
#ifdef FEATURE_ACCESS_REGISTERS
MCIC_AR |
#endif /*FEATURE_ACCESS_REGISTERS*/
#if defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)
MCIC_PR |
#endif /*defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)*/
#if defined(FEATURE_BINARY_FLOATING_POINT)
MCIC_XF |
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
MCIC_AP |
MCIC_CT |
MCIC_CC ;
*xdmg = 0;
*fsta = 0;
OFF_IC_CHANRPT;
rc = 1;
}
if(!IS_IC_CHANRPT)
#endif /*FEATURE_CHANNEL_SUBSYSTEM*/
OFF_IC_CHANRPT;
return rc;
} /* end function present_mck_interrupt */
void ARCH_DEP(sync_mck_interrupt) (REGS *regs)
{
int rc; /* Return code */
PSA *psa; /* -> Prefixed storage area */
U64 mcic = MCIC_P | /* Instruction processing damage */
MCIC_WP |
MCIC_MS |
MCIC_PM |
MCIC_IA |
#ifdef FEATURE_HEXADECIMAL_FLOATING_POINT
MCIC_FP |
#endif /*FEATURE_HEXADECIMAL_FLOATING_POINT*/
MCIC_GR |
MCIC_CR |
MCIC_ST |
#ifdef FEATURE_ACCESS_REGISTERS
MCIC_AR |
#endif /*FEATURE_ACCESS_REGISTERS*/
#if defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)
MCIC_PR |
#endif /*defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)*/
#if defined(FEATURE_BINARY_FLOATING_POINT)
MCIC_XF |
#endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/
MCIC_CT |
MCIC_CC ;
U32 xdmg = 0;
RADR fsta = 0;
/* Release intlock if held */
if (regs->cpuad == sysblk.intowner)
RELEASE_INTLOCK(regs);
/* Release mainlock if held */
if (regs->cpuad == sysblk.mainowner)
RELEASE_MAINLOCK(regs);
/* Exit SIE when active */
#if defined(FEATURE_INTERPRETIVE_EXECUTION)
if(regs->sie_active)
ARCH_DEP(sie_exit) (regs, SIE_HOST_INTERRUPT);
#endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/
/* Set the main storage reference and change bits */
STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE);
/* Point to the PSA in main storage */
psa = (void*)(regs->mainstor + regs->PX);
/* Store registers in machine check save area */
ARCH_DEP(store_status) (regs, regs->PX);
#if !defined(FEATURE_ESAME)
// ZZ
/* Set the extended logout area to zeros */
memset(psa->storepsw, 0, 16);
#endif
/* Store the machine check interrupt code at PSA+232 */
STORE_DW(psa->mckint, mcic);
/* Trace the machine check interrupt */
if (CPU_STEPPING_OR_TRACING(regs, 0))
logmsg (_("HHCCP019I Machine Check code=%16.16" I64_FMT "u\n"),
(long long)mcic);
/* Store the external damage code at PSA+244 */
STORE_FW(psa->xdmgcode, xdmg);
#if defined(FEATURE_ESAME)
/* Store the failing storage address at PSA+248 */
STORE_DW(psa->mcstorad, fsta);
#else /*!defined(FEATURE_ESAME)*/
/* Store the failing storage address at PSA+248 */
STORE_FW(psa->mcstorad, fsta);
#endif /*!defined(FEATURE_ESAME)*/
/* Store current PSW at PSA+X'30' */
ARCH_DEP(store_psw) ( regs, psa->mckold );
/* Load new PSW from PSA+X'70' */
rc = ARCH_DEP(load_psw) ( regs, psa->mcknew );
if ( rc )
ARCH_DEP(program_interrupt) (regs, rc);
} /* end function sync_mck_interrupt */
#if !defined(_GEN_ARCH)
#if defined(_ARCHMODE2)
#define _GEN_ARCH _ARCHMODE2
#include "machchk.c"
#endif
#if defined(_ARCHMODE3)
#undef _GEN_ARCH
#define _GEN_ARCH _ARCHMODE3
#include "machchk.c"
#endif
#if !defined(NO_SIGABEND_HANDLER)
void sigabend_handler (int signo)
{
REGS *regs = NULL;
TID tid;
int i;
tid = thread_id();
if( signo == SIGUSR2 )
{
DEVBLK *dev;
if ( equal_threads( tid, sysblk.cnsltid ) ||
equal_threads( tid, sysblk.socktid ) ||
equal_threads( tid, sysblk.httptid ) )
return;
for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
if ( equal_threads( dev->tid, tid ) ||
equal_threads( dev->shrdtid, tid ) )
break;
if( dev == NULL)
{
if (!sysblk.shutdown)
logmsg(_("HHCCP020E signal USR2 received for "
"undetermined device\n"));
}
else
if(dev->ccwtrace)
logmsg(_("HHCCP021E signal USR2 received for device "
"%4.4X\n"),dev->devnum);
return;
}
for (i = 0; i < MAX_CPU; i++)
{
if ( equal_threads( sysblk.cputid[i], tid ) )
{
regs = sysblk.regs[i];
break;
}
}
if (regs == NULL)
{
signal(signo, SIG_DFL);
raise(signo);
return;
}
if(MACHMASK(®s->psw))
{
#if defined(_FEATURE_SIE)
logmsg(_("HHCCP017I CPU%4.4X: Machine check due to host error: %s\n"),
regs->sie_active ? regs->guestregs->cpuad : regs->cpuad,
strsignal(signo));
#else /*!defined(_FEATURE_SIE)*/
logmsg(_("HHCCP017I CPU%4.4X: Machine check due to host error: %s\n"),
regs->cpuad, strsignal(signo));
#endif /*!defined(_FEATURE_SIE)*/
display_inst(
#if defined(_FEATURE_SIE)
regs->sie_active ? regs->guestregs :
#endif /*defined(_FEATURE_SIE)*/
regs,
#if defined(_FEATURE_SIE)
regs->sie_active ? regs->guestregs->ip :
#endif /*defined(_FEATURE_SIE)*/
regs->ip);
switch(regs->arch_mode) {
#if defined(_370)
case ARCH_370:
s370_sync_mck_interrupt(regs);
break;
#endif
#if defined(_390)
case ARCH_390:
s390_sync_mck_interrupt(regs);
break;
#endif
#if defined(_900)
case ARCH_900:
z900_sync_mck_interrupt(regs);
break;
#endif
}
}
else
{
#if defined(_FEATURE_SIE)
logmsg(_("HHCCP018I CPU%4.4X: Check-Stop due to host error: %s\n"),
regs->sie_active ? regs->guestregs->cpuad : regs->cpuad,
strsignal(signo));
#else /*!defined(_FEATURE_SIE)*/
logmsg(_("HHCCP018I CPU%4.4X: Check-Stop due to host error: %s\n"),
regs->cpuad, strsignal(signo));
#endif /*!defined(_FEATURE_SIE)*/
display_inst(
#if defined(_FEATURE_SIE)
regs->sie_active ? regs->guestregs :
#endif /*defined(_FEATURE_SIE)*/
regs,
#if defined(_FEATURE_SIE)
regs->sie_active ? regs->guestregs->ip :
#endif /*defined(_FEATURE_SIE)*/
regs->ip);
regs->cpustate = CPUSTATE_STOPPING;
regs->checkstop = 1;
ON_IC_INTERRUPT(regs);
/* Notify other CPU's by means of a malfuction alert if possible */
if (!try_obtain_lock(&sysblk.sigplock))
{
if(!try_obtain_lock(&sysblk.intlock))
{
for (i = 0; i < MAX_CPU; i++)
if (i != regs->cpuad && IS_CPU_ONLINE(i))
{
ON_IC_MALFALT(sysblk.regs[i]);
sysblk.regs[i]->malfcpu[regs->cpuad] = 1;
}
release_lock(&sysblk.intlock);
}
release_lock(&sysblk.sigplock);
}
}
longjmp (regs->progjmp, SIE_INTERCEPT_MCK);
}
#endif /*!defined(NO_SIGABEND_HANDLER)*/
#endif /*!defined(_GEN_ARCH)*/
|