1 /* machdep.c 4.52 82/03/15 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/map.h" 8 #include "../h/reg.h" 9 #include "../h/mtpr.h" 10 #include "../h/clock.h" 11 #include "../h/pte.h" 12 #include "../h/vm.h" 13 #include "../h/proc.h" 14 #include "../h/psl.h" 15 #include "../h/buf.h" 16 #include "../h/ubavar.h" 17 #include "../h/ubareg.h" 18 #include "../h/cons.h" 19 #include "../h/reboot.h" 20 #include "../h/conf.h" 21 #include "../h/mem.h" 22 #include "../h/cpu.h" 23 #include "../h/inode.h" 24 #include "../h/file.h" 25 #include "../h/text.h" 26 #include "../h/clist.h" 27 #include "../h/callout.h" 28 #include "../h/cmap.h" 29 #include <frame.h> 30 #include "../h/mbuf.h" 31 #include "../h/rpb.h" 32 #include "../h/msgbuf.h" 33 34 int icode[] = 35 { 36 0x9f19af9f, /* pushab [&"init",0]; pushab */ 37 0x02dd09af, /* "/etc/init"; pushl $2 */ 38 0xbc5c5ed0, /* movl sp,ap; chmk */ 39 0x2ffe110b, /* $exec; brb .; "/ */ 40 0x2f637465, /* etc/ */ 41 0x74696e69, /* init" */ 42 0x00000000, /* \0\0\0"; 0 */ 43 0x00000014, /* [&"init", */ 44 0x00000000, /* 0] */ 45 }; 46 int szicode = sizeof(icode); 47 48 /* 49 * Declare these as initialized data so we can patch them. 50 */ 51 int nbuf = 0; 52 int nswbuf = 0; 53 54 /* 55 * Machine-dependent startup code 56 */ 57 startup(firstaddr) 58 int firstaddr; 59 { 60 register int unixsize; 61 register unsigned i; 62 register struct pte *pte; 63 register caddr_t v; 64 65 /* 66 * Initialize error message buffer (at end of core). 67 */ 68 maxmem -= btoc(sizeof (struct msgbuf)); 69 pte = msgbufmap; 70 for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) 71 *(int *)pte++ = PG_V | PG_KW | (maxmem + i); 72 mtpr(TBIA, 1); 73 74 /* 75 * Good {morning,afternoon,evening,night}. 76 */ 77 printf(version); 78 printf("real mem = %d\n", ctob(maxmem)); 79 80 /* 81 * First determine how many buffers are reasonable. 82 * Current alg is 32 per megabyte, with min of 32. 83 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 84 */ 85 if (nbuf == 0) { 86 nbuf = (32 * physmem) / btoc(1024*1024); 87 if (nbuf < 32) 88 nbuf = 32; 89 } 90 if (nswbuf == 0) { 91 nswbuf = (nbuf / 2) &~ 1; /* force even */ 92 if (nswbuf > 256) 93 nswbuf = 256; /* sanity */ 94 } 95 96 /* 97 * Allocate space for system data structures. 98 */ 99 v = (caddr_t)(0x80000000 | (firstaddr * NBPG)); 100 #define valloc(name, type, num) \ 101 (name) = (type *)(v); (v) = (caddr_t)((name)+(num)) 102 #define valloclim(name, type, num, lim) \ 103 (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num))) 104 valloc(buffers, char, BSIZE*nbuf); 105 valloc(buf, struct buf, nbuf); 106 valloc(swbuf, struct buf, nswbuf); 107 valloc(swsize, short, nswbuf); /* note: nswbuf is even */ 108 valloc(swpf, int, nswbuf); 109 valloclim(inode, struct inode, ninode, inodeNINODE); 110 valloclim(file, struct file, nfile, fileNFILE); 111 valloclim(proc, struct proc, nproc, procNPROC); 112 valloclim(text, struct text, ntext, textNTEXT); 113 valloc(cfree, struct cblock, nclist); 114 valloc(callout, struct callout, ncallout); 115 valloc(swapmap, struct map, nswapmap = nproc * 2); 116 valloc(argmap, struct map, ARGMAPSIZE); 117 valloc(kernelmap, struct map, nproc); 118 valloc(mbmap, struct map, nmbclusters/4); 119 /* 120 * Now allocate space for core map 121 */ 122 ncmap = (physmem*NBPG - ((int)v &~ 0x80000000)) / 123 (NBPG*CLSIZE + sizeof (struct cmap)); 124 valloclim(cmap, struct cmap, ncmap, ecmap); 125 if ((((int)(ecmap+1))&~0x80000000) > SYSPTSIZE*NBPG) 126 panic("sys pt too small"); 127 128 /* 129 * Clear allocated space, and make r/w entries 130 * for the space in the kernel map. 131 */ 132 unixsize = btoc((int)(ecmap+1) &~ 0x80000000); 133 if (unixsize >= physmem - 8*UPAGES) 134 panic("no memory"); 135 pte = &Sysmap[firstaddr]; 136 for (i = firstaddr; i < unixsize; i++) { 137 *(int *)(&Sysmap[i]) = PG_V | PG_KW | i; 138 clearseg(i); 139 } 140 mtpr(TBIA, 1); 141 142 /* 143 * Initialize callouts 144 */ 145 callfree = callout; 146 for (i = 1; i < ncallout; i++) 147 callout[i-1].c_next = &callout[i]; 148 149 /* 150 * Initialize memory allocator and swap 151 * and user page table maps. 152 * 153 * THE USER PAGE TABLE MAP IS CALLED ``kernelmap'' 154 * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME. 155 */ 156 meminit(unixsize, maxmem); 157 maxmem = freemem; 158 printf("avail mem = %d\n", ctob(maxmem)); 159 rminit(kernelmap, USRPTSIZE, 1, "usrpt", nproc); 160 rminit(mbmap, nmbclusters-CLSIZE, CLSIZE, "mbclusters", nmbclusters/4); 161 162 /* 163 * Configure the system. 164 */ 165 configure(); 166 167 /* 168 * Clear restart inhibit flags. 169 */ 170 tocons(TXDB_CWSI); 171 tocons(TXDB_CCSI); 172 } 173 174 /* 175 * set up a physical address 176 * into users virtual address space. 177 */ 178 sysphys() 179 { 180 181 if(!suser()) 182 return; 183 u.u_error = EINVAL; 184 } 185 186 /* 187 * Initialze the clock, based on the time base which is, e.g. 188 * from a filesystem. Base provides the time to within six months, 189 * and the time of year clock provides the rest. 190 */ 191 clkinit(base) 192 time_t base; 193 { 194 register unsigned todr = mfpr(TODR); 195 long deltat; 196 int year = YRREF; 197 198 if (base < 5*SECYR) { 199 printf("WARNING: preposterous time in file system"); 200 time = 6*SECYR + 186*SECDAY + SECDAY/2; 201 clkset(); 202 goto check; 203 } 204 /* 205 * Have been told that VMS keeps time internally with base TODRZERO. 206 * If this is correct, then this routine and VMS should maintain 207 * the same date, and switching shouldn't be painful. 208 * (Unfortunately, VMS keeps local time, so when you run UNIX 209 * and VMS, VMS runs on GMT...). 210 */ 211 if (todr < TODRZERO) { 212 printf("WARNING: todr too small"); 213 time = base; 214 /* 215 * Believe the time in the file system for lack of 216 * anything better, resetting the TODR. 217 */ 218 clkset(); 219 goto check; 220 } 221 /* 222 * Sneak to within 6 month of the time in the filesystem, 223 * by starting with the time of the year suggested by the TODR, 224 * and advancing through succesive years. Adding the number of 225 * seconds in the current year takes us to the end of the current year 226 * and then around into the next year to the same position. 227 */ 228 for (time = (todr-TODRZERO)/100; time < base-SECYR/2; time += SECYR) { 229 if (LEAPYEAR(year)) 230 time += SECDAY; 231 year++; 232 } 233 234 /* 235 * See if we gained/lost two or more days; 236 * if so, assume something is amiss. 237 */ 238 deltat = time - base; 239 if (deltat < 0) 240 deltat = -deltat; 241 if (deltat < 2*SECDAY) 242 return; 243 printf("WARNING: clock %s %d days", 244 time < base ? "lost" : "gained", deltat / SECDAY); 245 check: 246 printf(" -- CHECK AND RESET THE DATE!\n"); 247 } 248 249 /* 250 * Reset the TODR based on the time value; used when the TODR 251 * has a preposterous value and also when the time is reset 252 * by the stime system call. Also called when the TODR goes past 253 * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) 254 * to wrap the TODR around. 255 */ 256 clkset() 257 { 258 int year = YRREF; 259 unsigned secyr; 260 unsigned yrtime = time; 261 262 /* 263 * Whittle the time down to an offset in the current year, 264 * by subtracting off whole years as long as possible. 265 */ 266 for (;;) { 267 secyr = SECYR; 268 if (LEAPYEAR(year)) 269 secyr += SECDAY; 270 if (yrtime < secyr) 271 break; 272 yrtime -= secyr; 273 year++; 274 } 275 mtpr(TODR, TODRZERO + yrtime*100); 276 } 277 278 #ifdef PGINPROF 279 /* 280 * Return the difference (in microseconds) 281 * between the current time and a previous 282 * time as represented by the arguments. 283 * If there is a pending clock interrupt 284 * which has not been serviced due to high 285 * ipl, return error code. 286 */ 287 vmtime(otime, olbolt, oicr) 288 register int otime, olbolt, oicr; 289 { 290 291 if (mfpr(ICCS)&ICCS_INT) 292 return(-1); 293 else 294 return(((time-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr); 295 } 296 #endif 297 298 /* 299 * Send an interrupt to process 300 * 301 * SHOULD CHANGE THIS TO PASS ONE MORE WORK SO THAT ALL INFORMATION 302 * PROVIDED BY HARDWARE IS AVAILABLE TO THE USER PROCESS. 303 */ 304 sendsig(p, n) 305 int (*p)(); 306 { 307 register int *usp, *regs; 308 309 regs = u.u_ar0; 310 usp = (int *)regs[SP]; 311 usp -= 5; 312 if ((int)usp <= USRSTACK - ctob(u.u_ssize)) 313 (void) grow((unsigned)usp); 314 ; /* Avoid asm() label botch */ 315 #ifndef lint 316 asm("probew $3,$20,(r11)"); 317 asm("beql bad"); 318 #else 319 if (useracc((caddr_t)usp, 0x20, 1)) 320 goto bad; 321 #endif 322 *usp++ = n; 323 if (n == SIGILL || n == SIGFPE) { 324 *usp++ = u.u_code; 325 u.u_code = 0; 326 } else 327 *usp++ = 0; 328 *usp++ = (int)p; 329 *usp++ = regs[PC]; 330 *usp++ = regs[PS]; 331 regs[SP] = (int)(usp - 5); 332 regs[PS] &= ~(PSL_CM|PSL_FPD); 333 regs[PC] = (int)u.u_pcb.pcb_sigc; 334 return; 335 336 asm("bad:"); 337 bad: 338 /* 339 * Process has trashed its stack; give it an illegal 340 * instruction to halt it in its tracks. 341 */ 342 u.u_signal[SIGILL] = SIG_DFL; 343 u.u_procp->p_siga0 &= ~(1<<(SIGILL-1)); 344 u.u_procp->p_siga1 &= ~(1<<(SIGILL-1)); 345 psignal(u.u_procp, SIGILL); 346 } 347 348 dorti() 349 { 350 struct frame frame; 351 register int sp; 352 register int reg, mask; 353 extern int ipcreg[]; 354 355 (void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame)); 356 sp = u.u_ar0[FP] + sizeof (frame); 357 u.u_ar0[PC] = frame.fr_savpc; 358 u.u_ar0[FP] = frame.fr_savfp; 359 u.u_ar0[AP] = frame.fr_savap; 360 mask = frame.fr_mask; 361 for (reg = 0; reg <= 11; reg++) { 362 if (mask&1) { 363 u.u_ar0[ipcreg[reg]] = fuword((caddr_t)sp); 364 sp += 4; 365 } 366 mask >>= 1; 367 } 368 sp += frame.fr_spa; 369 u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.fr_psw; 370 if (frame.fr_s) 371 sp += 4 + 4 * (fuword((caddr_t)sp) & 0xff); 372 /* phew, now the rei */ 373 u.u_ar0[PC] = fuword((caddr_t)sp); 374 sp += 4; 375 u.u_ar0[PS] = fuword((caddr_t)sp); 376 sp += 4; 377 u.u_ar0[PS] |= PSL_USERSET; 378 u.u_ar0[PS] &= ~PSL_USERCLR; 379 u.u_ar0[SP] = (int)sp; 380 } 381 382 /* 383 * Memenable enables the memory controlle corrected data reporting. 384 * This runs at regular intervals, turning on the interrupt. 385 * The interrupt is turned off, per memory controller, when error 386 * reporting occurs. Thus we report at most once per memintvl. 387 */ 388 int memintvl = MEMINTVL; 389 390 memenable() 391 { 392 register struct mcr *mcr; 393 register int m; 394 395 for (m = 0; m < nmcr; m++) { 396 mcr = mcraddr[m]; 397 switch (cpu) { 398 #if VAX780 399 case VAX_780: 400 M780_ENA(mcr); 401 break; 402 #endif 403 #if VAX750 404 case VAX_750: 405 M750_ENA(mcr); 406 break; 407 #endif 408 #if VAX7ZZ 409 case VAX_7ZZ: 410 M7ZZ_ENA(mcr); 411 break; 412 #endif 413 } 414 } 415 if (memintvl > 0) 416 timeout(memenable, (caddr_t)0, memintvl); 417 } 418 419 /* 420 * Memerr is the interrupt routine for corrected read data 421 * interrupts. It looks to see which memory controllers have 422 * unreported errors, reports them, and disables further 423 * reporting for a time on those controller. 424 */ 425 memerr() 426 { 427 register struct mcr *mcr; 428 register int m; 429 430 for (m = 0; m < nmcr; m++) { 431 mcr = mcraddr[m]; 432 switch (cpu) { 433 #if VAX780 434 case VAX_780: 435 if (M780_ERR(mcr)) { 436 printf("mcr%d: soft ecc addr %x syn %x\n", 437 m, M780_ADDR(mcr), M780_SYN(mcr)); 438 M780_INH(mcr); 439 } 440 break; 441 #endif 442 #if VAX750 443 case VAX_750: 444 if (M750_ERR(mcr)) { 445 printf("mcr%d: soft ecc addr %x syn %x\n", 446 m, M750_ADDR(mcr), M750_SYN(mcr)); 447 M750_INH(mcr); 448 } 449 break; 450 #endif 451 #if VAX7ZZ 452 case VAX_7ZZ: 453 if (M7ZZ_ERR(mcr)) { 454 struct mcr amcr; 455 amcr.mc_reg[0] = mcr->mc_reg[0]; 456 printf("mcr%d: soft ecc addr %x syn %x\n", 457 m, M7ZZ_ADDR(&amcr), M7ZZ_SYN(&amcr)); 458 M7ZZ_INH(mcr); 459 } 460 break; 461 #endif 462 } 463 } 464 } 465 466 /* 467 * Invalidate single all pte's in a cluster 468 */ 469 tbiscl(v) 470 unsigned v; 471 { 472 register caddr_t addr; /* must be first reg var */ 473 register int i; 474 475 asm(".set TBIS,58"); 476 addr = ptob(v); 477 for (i = 0; i < CLSIZE; i++) { 478 #ifdef lint 479 mtpr(TBIS, addr); 480 #else 481 asm("mtpr r11,$TBIS"); 482 #endif 483 addr += NBPG; 484 } 485 } 486 487 int waittime = -1; 488 489 boot(paniced, arghowto) 490 int paniced, arghowto; 491 { 492 register int howto; /* r11 == how to boot */ 493 register int devtype; /* r10 == major of root dev */ 494 495 #ifdef lint 496 howto = 0; devtype = 0; 497 printf("howto %d, devtype %d\n", arghowto, devtype); 498 #endif 499 (void) spl1(); 500 howto = arghowto; 501 if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) { 502 waittime = 0; 503 update(1); 504 printf("syncing disks... "); 505 #ifdef notdef 506 { register struct buf *bp; 507 int iter, nbusy; 508 509 for (iter = 0; iter < 10; iter++) { 510 nbusy = 0; 511 for (bp = &buf[nbuf]; --bp >= buf; ) 512 if (bp->b_flags & B_BUSY) 513 nbusy++; 514 if (nbusy == 0) 515 break; 516 printf("%d ", nbusy); 517 } 518 } 519 #else 520 DELAY(10000000); 521 #endif 522 printf("done\n"); 523 } 524 splx(0x1f); /* extreme priority */ 525 devtype = major(rootdev); 526 if (howto&RB_HALT) { 527 printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n"); 528 mtpr(IPL, 0x1f); 529 for (;;) 530 ; 531 } else { 532 if (paniced == RB_PANIC) { 533 doadump(); /* TXDB_BOOT's itsself */ 534 /*NOTREACHED*/ 535 } 536 tocons(TXDB_BOOT); 537 } 538 #if defined(VAX750) || defined(VAX7ZZ) 539 if (cpu != VAX_780) 540 { asm("movl r11,r5"); } /* boot flags go in r5 */ 541 #endif 542 for (;;) 543 asm("halt"); 544 /*NOTREACHED*/ 545 } 546 547 tocons(c) 548 { 549 550 while ((mfpr(TXCS)&TXCS_RDY) == 0) 551 continue; 552 mtpr(TXDB, c); 553 } 554 555 /* 556 * Doadump comes here after turning off memory management and 557 * getting on the dump stack, either when called above, or by 558 * the auto-restart code. 559 */ 560 dumpsys() 561 { 562 563 rpb.rp_flag = 1; 564 if ((minor(dumpdev)&07) != 1) 565 return; 566 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 567 printf("dump "); 568 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 569 570 case ENXIO: 571 printf("device bad\n"); 572 break; 573 574 case EFAULT: 575 printf("device not ready\n"); 576 break; 577 578 case EINVAL: 579 printf("area improper\n"); 580 break; 581 582 case EIO: 583 printf("i/o error"); 584 break; 585 586 default: 587 printf("succeeded"); 588 break; 589 } 590 } 591 592 /* 593 * Machine check error recovery code. 594 * Print out the machine check frame and then give up. 595 */ 596 #if defined(VAX780) || defined(VAX750) 597 char *mc780[] = { 598 "cp read", "ctrl str par", "cp tbuf par", "cp cache par", 599 "cp rdtimo", "cp rds", "ucode lost", 0, 600 0, 0, "ib tbuf par", 0, 601 "ib rds", "ib rd timo", 0, "ib cache par" 602 }; 603 #endif 604 #if VAX7ZZ 605 #define NMC7ZZ 12 606 char *mc7ZZ[] = { 607 "tb par", "bad retry", "bad intr id", "cant write ptem", 608 "unkn mcr err", "iib rd err", "nxm ref", "cp rds", 609 "unalgn ioref", "nonlw ioref", "bad ioaddr", "unalgn ubaddr", 610 }; 611 #endif 612 613 /* 614 * Frame for each cpu 615 */ 616 struct mc780frame { 617 int mc8_bcnt; /* byte count == 0x28 */ 618 int mc8_summary; /* summary parameter (as above) */ 619 int mc8_cpues; /* cpu error status */ 620 int mc8_upc; /* micro pc */ 621 int mc8_vaviba; /* va/viba register */ 622 int mc8_dreg; /* d register */ 623 int mc8_tber0; /* tbuf error reg 0 */ 624 int mc8_tber1; /* tbuf error reg 1 */ 625 int mc8_timo; /* timeout address divided by 4 */ 626 int mc8_parity; /* parity */ 627 int mc8_sbier; /* sbi error register */ 628 int mc8_pc; /* trapped pc */ 629 int mc8_psl; /* trapped psl */ 630 }; 631 struct mc750frame { 632 int mc5_bcnt; /* byte count == 0x28 */ 633 int mc5_summary; /* summary parameter (as above) */ 634 int mc5_va; /* virtual address register */ 635 int mc5_errpc; /* error pc */ 636 int mc5_mdr; 637 int mc5_svmode; /* saved mode register */ 638 int mc5_rdtimo; /* read lock timeout */ 639 int mc5_tbgpar; /* tb group parity error register */ 640 int mc5_cacherr; /* cache error register */ 641 int mc5_buserr; /* bus error register */ 642 int mc5_mcesr; /* machine check status register */ 643 int mc5_pc; /* trapped pc */ 644 int mc5_psl; /* trapped psl */ 645 }; 646 struct mc7ZZframe { 647 int mc3_bcnt; /* byte count == 0xc */ 648 int mc3_summary; /* summary parameter */ 649 int mc3_parm[2]; /* parameter 1 and 2 */ 650 int mc3_pc; /* trapped pc */ 651 int mc3_psl; /* trapped psl */ 652 }; 653 654 machinecheck(cmcf) 655 caddr_t cmcf; 656 { 657 register u_int type = ((struct mc780frame *)cmcf)->mc8_summary; 658 659 printf("machine check %x: ", type); 660 switch (cpu) { 661 #if VAX780 662 case VAX_780: 663 #endif 664 #if VAX750 665 case VAX_750: 666 #endif 667 #if defined(VAX780) || defined(VAX750) 668 printf("%s%s\n", mc780[type&0xf], 669 (type&0xf0) ? " abort" : " fault"); 670 break; 671 #endif 672 #if VAX7ZZ 673 case VAX_7ZZ: 674 if (type < NMC7ZZ) 675 printf("%s", mc7ZZ[type]); 676 printf("\n"); 677 break; 678 #endif 679 } 680 switch (cpu) { 681 #if VAX780 682 case VAX_780: { 683 register struct mc780frame *mcf = (struct mc780frame *)cmcf; 684 register int sbifs; 685 printf("\tcpues %x upc %x va/viba %x dreg %x tber %x %x\n", 686 mcf->mc8_cpues, mcf->mc8_upc, mcf->mc8_vaviba, 687 mcf->mc8_dreg, mcf->mc8_tber0, mcf->mc8_tber1); 688 sbifs = mfpr(SBIFS); 689 printf("\ttimo %x parity %x sbier %x pc %x psl %x sbifs %x\n", 690 mcf->mc8_timo*4, mcf->mc8_parity, mcf->mc8_sbier, 691 mcf->mc8_pc, mcf->mc8_psl, sbifs); 692 /* THE FUNNY BITS IN THE FOLLOWING ARE FROM THE ``BLACK */ 693 /* BOOK AND SHOULD BE PUT IN AN ``sbi.h'' */ 694 mtpr(SBIFS, sbifs &~ 0x2000000); 695 mtpr(SBIER, mfpr(SBIER) | 0x70c0); 696 break; 697 } 698 #endif 699 #if VAX750 700 case VAX_750: { 701 register struct mc750frame *mcf = (struct mc750frame *)cmcf; 702 printf("\tva %x errpc %x mdr %x smr %x rdtimo %x tbgpar %x cacherr %x\n", 703 mcf->mc5_va, mcf->mc5_errpc, mcf->mc5_mdr, mcf->mc5_svmode, 704 mcf->mc5_rdtimo, mcf->mc5_tbgpar, mcf->mc5_cacherr); 705 printf("\tbuserr %x mcesr %x pc %x psl %x mcsr %x\n", 706 mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl, 707 mfpr(MCSR)); 708 mtpr(MCESR, 0xf); 709 break; 710 } 711 #endif 712 #if VAX7ZZ 713 case VAX_7ZZ: { 714 register struct mc7ZZframe *mcf = (struct mc7ZZframe *)cmcf; 715 printf("params %x,%x pc %x psl %x mcesr %x\n", 716 mcf->mc3_parm[0], mcf->mc3_parm[1], 717 mcf->mc3_pc, mcf->mc3_psl, mfpr(MCESR)); 718 mtpr(MCESR, 0xf); 719 break; 720 } 721 #endif 722 } 723 memerr(); 724 panic("mchk"); 725 } 726