Annotation of sys/arch/hp300/hp300/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.115 2007/06/06 17:15:11 deraadt Exp $ */
! 2: /* $NetBSD: machdep.c,v 1.121 1999/03/26 23:41:29 mycroft Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1988 University of Utah.
! 6: * Copyright (c) 1982, 1986, 1990, 1993
! 7: * The Regents of the University of California. All rights reserved.
! 8: *
! 9: * This code is derived from software contributed to Berkeley by
! 10: * the Systems Programming Group of the University of Utah Computer
! 11: * Science Department.
! 12: *
! 13: * Redistribution and use in source and binary forms, with or without
! 14: * modification, are permitted provided that the following conditions
! 15: * are met:
! 16: * 1. Redistributions of source code must retain the above copyright
! 17: * notice, this list of conditions and the following disclaimer.
! 18: * 2. Redistributions in binary form must reproduce the above copyright
! 19: * notice, this list of conditions and the following disclaimer in the
! 20: * documentation and/or other materials provided with the distribution.
! 21: * 3. Neither the name of the University nor the names of its contributors
! 22: * may be used to endorse or promote products derived from this software
! 23: * without specific prior written permission.
! 24: *
! 25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 35: * SUCH DAMAGE.
! 36: *
! 37: * from: Utah $Hdr: machdep.c 1.74 92/12/20$
! 38: *
! 39: * @(#)machdep.c 8.10 (Berkeley) 4/20/94
! 40: */
! 41:
! 42: #include <sys/param.h>
! 43: #include <sys/systm.h>
! 44: #include <sys/buf.h>
! 45: #include <sys/timeout.h>
! 46: #include <sys/conf.h>
! 47: #include <sys/exec.h>
! 48: #include <sys/file.h>
! 49: #include <sys/ioctl.h>
! 50: #include <sys/kernel.h>
! 51: #include <sys/device.h>
! 52: #include <sys/malloc.h>
! 53: #include <sys/extent.h>
! 54: #include <sys/mbuf.h>
! 55: #include <sys/mount.h>
! 56: #include <sys/msgbuf.h>
! 57: #include <sys/proc.h>
! 58: #include <sys/reboot.h>
! 59: #include <sys/signalvar.h>
! 60: #include <sys/tty.h>
! 61: #include <sys/user.h>
! 62: #include <sys/exec.h>
! 63: #include <sys/core.h>
! 64: #include <sys/kcore.h>
! 65: #include <sys/vnode.h>
! 66: #include <sys/sysctl.h>
! 67: #include <sys/syscallargs.h>
! 68: #include <sys/syslog.h>
! 69: #ifdef SYSVMSG
! 70: #include <sys/msg.h>
! 71: #endif
! 72:
! 73: #include <machine/db_machdep.h>
! 74: #ifdef DDB
! 75: #include <ddb/db_var.h>
! 76: #endif
! 77: #include <ddb/db_sym.h>
! 78: #include <ddb/db_extern.h>
! 79:
! 80: #include <machine/autoconf.h>
! 81: #include <machine/cpu.h>
! 82: #include <machine/hp300spu.h>
! 83: #include <machine/kcore.h>
! 84: #include <machine/reg.h>
! 85: #include <machine/psl.h>
! 86: #include <machine/pte.h>
! 87:
! 88: #include <dev/cons.h>
! 89:
! 90: #include <uvm/uvm_extern.h>
! 91:
! 92: #ifdef USELEDS
! 93: #include <hp300/hp300/leds.h>
! 94: #endif
! 95:
! 96: /* the following is used externally (sysctl_hw) */
! 97: char machine[] = MACHINE; /* from <machine/param.h> */
! 98:
! 99: struct vm_map *exec_map = NULL;
! 100: struct vm_map *phys_map = NULL;
! 101:
! 102: extern paddr_t avail_start, avail_end;
! 103:
! 104: /*
! 105: * Declare these as initialized data so we can patch them.
! 106: */
! 107: #ifndef BUFCACHEPERCENT
! 108: #define BUFCACHEPERCENT 5
! 109: #endif
! 110:
! 111: #ifdef BUFPAGES
! 112: int bufpages = BUFPAGES;
! 113: #else
! 114: int bufpages = 0;
! 115: #endif
! 116: int bufcachepercent = BUFCACHEPERCENT;
! 117:
! 118: int physmem; /* size of physical memory, in pages */
! 119: /*
! 120: * safepri is a safe priority for sleep to set for a spin-wait
! 121: * during autoconfiguration or after a panic.
! 122: */
! 123: int safepri = PSL_LOWIPL;
! 124:
! 125: extern u_int lowram;
! 126: extern short exframesize[];
! 127:
! 128: #ifdef COMPAT_HPUX
! 129: extern struct emul emul_hpux;
! 130: #endif
! 131: #ifdef COMPAT_SUNOS
! 132: extern struct emul emul_sunos;
! 133: #endif
! 134:
! 135: /*
! 136: * Some storage space must be allocated statically because of the
! 137: * early console initialization.
! 138: */
! 139: char extiospace[EXTENT_FIXED_STORAGE_SIZE(8)];
! 140: extern int eiomapsize;
! 141:
! 142: /* prototypes for local functions */
! 143: caddr_t allocsys(caddr_t);
! 144: void parityenable(void);
! 145: int parityerror(struct frame *);
! 146: int parityerrorfind(void);
! 147: void identifycpu(void);
! 148: void initcpu(void);
! 149: void dumpmem(int *, int, int);
! 150: char *hexstr(int, int);
! 151:
! 152: /* functions called from locore.s */
! 153: void dumpsys(void);
! 154: void hp300_init(void);
! 155: void straytrap(int, u_short);
! 156: void nmihand(struct frame);
! 157:
! 158: /*
! 159: * Select code of console. Set to CONSCODE_INTERNAL if console is on
! 160: * "internal" framebuffer.
! 161: */
! 162: int conscode;
! 163: caddr_t conaddr; /* for drivers in cn_init() */
! 164: int convasize; /* size of mapped console device */
! 165:
! 166: /*
! 167: * Note that the value of delay_divisor is roughly
! 168: * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020
! 169: * and 68030 systems. See clock.c for the delay
! 170: * calibration algorithm.
! 171: */
! 172: int cpuspeed; /* relative cpu speed */
! 173: int delay_divisor; /* delay constant */
! 174:
! 175: /*
! 176: * Early initialization, before main() is called.
! 177: */
! 178: void
! 179: hp300_init()
! 180: {
! 181: /*
! 182: * Tell the VM system about available physical memory. The
! 183: * hp300 only has one segment.
! 184: */
! 185: uvm_page_physload(atop(avail_start), atop(avail_end),
! 186: atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
! 187:
! 188: /* Initialize the interrupt handlers. */
! 189: intr_init();
! 190:
! 191: /* Calibrate the delay loop. */
! 192: hp300_calibrate_delay();
! 193: }
! 194:
! 195: /*
! 196: * Console initialization: called early on from main,
! 197: * before vm init or startup. Do enough configuration
! 198: * to choose and initialize a console.
! 199: */
! 200: void
! 201: consinit()
! 202: {
! 203: extern struct extent *extio;
! 204: extern char *extiobase;
! 205:
! 206: /*
! 207: * Initialize some variables for sanity.
! 208: */
! 209: convasize = 0;
! 210: conscode = CONSCODE_INVALID;
! 211:
! 212: /*
! 213: * Initialize the bus resource map.
! 214: */
! 215: extio = extent_create("extio",
! 216: (u_long)extiobase, (u_long)extiobase + ctob(eiomapsize),
! 217: M_DEVBUF, extiospace, sizeof(extiospace), EX_NOWAIT);
! 218:
! 219: /*
! 220: * Initialize the console before we print anything out.
! 221: */
! 222: hp300_cninit();
! 223:
! 224: #ifdef DDB
! 225: ddb_init();
! 226: if (boothowto & RB_KDB)
! 227: Debugger();
! 228: #endif
! 229: }
! 230:
! 231: /*
! 232: * cpu_startup: allocate memory for variable-sized tables,
! 233: * initialize cpu, and do autoconfiguration.
! 234: */
! 235: void
! 236: cpu_startup()
! 237: {
! 238: extern char *etext;
! 239: unsigned i;
! 240: caddr_t v;
! 241: vaddr_t minaddr, maxaddr;
! 242: vsize_t size;
! 243: #ifdef DEBUG
! 244: extern int pmapdebug;
! 245: int opmapdebug = pmapdebug;
! 246:
! 247: pmapdebug = 0;
! 248: #endif
! 249:
! 250: /*
! 251: * Now that VM services are available, give another chance at
! 252: * console devices to initialize, if they could not before.
! 253: */
! 254: hp300_cninit();
! 255:
! 256: /*
! 257: * Initialize error message buffer (at end of core).
! 258: * avail_end was pre-decremented in pmap_bootstrap to compensate.
! 259: */
! 260: for (i = 0; i < btoc(MSGBUFSIZE); i++)
! 261: pmap_enter(pmap_kernel(), (vaddr_t)msgbufp + i * NBPG,
! 262: avail_end + i * NBPG, VM_PROT_READ|VM_PROT_WRITE,
! 263: VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
! 264: pmap_update(pmap_kernel());
! 265: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
! 266:
! 267: /*
! 268: * Good {morning,afternoon,evening,night}.
! 269: */
! 270: printf(version);
! 271: identifycpu();
! 272: printf("real mem = %u (%uMB)\n", ctob(physmem),
! 273: ctob(physmem)/1024/1024);
! 274:
! 275: /*
! 276: * Find out how much space we need, allocate it,
! 277: * and then give everything true virtual addresses.
! 278: */
! 279: size = (vsize_t)allocsys((caddr_t)0);
! 280: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(size))) == 0)
! 281: panic("startup: no room for tables");
! 282: if ((allocsys(v) - v) != size)
! 283: panic("startup: table size inconsistency");
! 284:
! 285: /*
! 286: * Determine how many buffers to allocate.
! 287: * We allocate bufcachepercent% of memory for buffer space.
! 288: */
! 289: if (bufpages == 0)
! 290: bufpages = physmem * bufcachepercent / 100;
! 291:
! 292: /* Restrict to at most 25% filled kvm */
! 293: if (bufpages >
! 294: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 295: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 296: PAGE_SIZE / 4;
! 297:
! 298: /*
! 299: * Allocate a submap for exec arguments. This map effectively
! 300: * limits the number of processes exec'ing at any time.
! 301: */
! 302: minaddr = vm_map_min(kernel_map);
! 303: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 304: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 305:
! 306: /*
! 307: * Allocate a submap for physio
! 308: */
! 309: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 310: VM_PHYS_SIZE, 0, FALSE, NULL);
! 311:
! 312: #ifdef DEBUG
! 313: pmapdebug = opmapdebug;
! 314: #endif
! 315: printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
! 316: ptoa(uvmexp.free)/1024/1024);
! 317:
! 318: /*
! 319: * Tell the VM system that page 0 isn't mapped.
! 320: *
! 321: * XXX This is bogus; should just fix KERNBASE and
! 322: * XXX VM_MIN_KERNEL_ADDRESS, but not right now.
! 323: */
! 324: if (uvm_map_protect(kernel_map, 0, NBPG, UVM_PROT_NONE, TRUE))
! 325: panic("can't mark page 0 off-limits");
! 326:
! 327: /*
! 328: * Tell the VM system that writing to kernel text isn't allowed.
! 329: * If we don't, we might end up COW'ing the text segment!
! 330: *
! 331: * XXX Should be trunc_page(&kernel_text) instead
! 332: * XXX of NBPG.
! 333: */
! 334: if (uvm_map_protect(kernel_map, NBPG, round_page((vaddr_t)&etext),
! 335: UVM_PROT_READ|UVM_PROT_EXEC, TRUE))
! 336: panic("can't protect kernel text");
! 337:
! 338: /*
! 339: * Set up CPU-specific registers, cache, etc.
! 340: */
! 341: initcpu();
! 342:
! 343: /*
! 344: * Set up buffers, so they can be used to read disk labels.
! 345: */
! 346: bufinit();
! 347:
! 348: /*
! 349: * Configure the system.
! 350: */
! 351: if (boothowto & RB_CONFIG) {
! 352: #ifdef BOOT_CONFIG
! 353: user_config();
! 354: #else
! 355: printf("kernel does not support -c; continuing..\n");
! 356: #endif
! 357: }
! 358: }
! 359:
! 360: /*
! 361: * Allocate space for system data structures. We are given
! 362: * a starting virtual address and we return a final virtual
! 363: * address; along the way we set each data structure pointer.
! 364: *
! 365: * We call allocsys() with 0 to find out how much space we want,
! 366: * allocate that much and fill it with zeroes, and then call
! 367: * allocsys() again with the correct base virtual address.
! 368: */
! 369: caddr_t
! 370: allocsys(v)
! 371: caddr_t v;
! 372: {
! 373:
! 374: #define valloc(name, type, num) \
! 375: (name) = (type *)v; v = (caddr_t)((name)+(num))
! 376: #define valloclim(name, type, num, lim) \
! 377: (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
! 378:
! 379: #ifdef SYSVMSG
! 380: valloc(msgpool, char, msginfo.msgmax);
! 381: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 382: valloc(msghdrs, struct msg, msginfo.msgtql);
! 383: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 384: #endif
! 385:
! 386: return (v);
! 387: }
! 388:
! 389: /*
! 390: * Info for CTL_HW
! 391: */
! 392: char cpu_model[120];
! 393:
! 394: /*
! 395: * Text description of models we support, indexed by machineid.
! 396: */
! 397: const char *hp300_models[] = {
! 398: "320", /* HP_320 */
! 399: "318/319/330", /* HP_330 */
! 400: "350", /* HP_350 */
! 401: "360", /* HP_360 */
! 402: "370", /* HP_370 */
! 403: "340", /* HP_340 */
! 404: "345", /* HP_345 */
! 405: "375", /* HP_375 */
! 406: "400", /* HP_400 */
! 407: "380", /* HP_380 */
! 408: "425", /* HP_425 */
! 409: "433", /* HP_433 */
! 410: "385", /* HP_385 */
! 411: "362", /* HP_362 */
! 412: "382", /* HP_382 */
! 413: };
! 414:
! 415: /* Map mmuid to single letter designation in 4xx models (e.g. 425s, 425t) */
! 416: char hp300_designations[] = " ttss e";
! 417:
! 418: void
! 419: identifycpu()
! 420: {
! 421: const char *t;
! 422: char mc, *td;
! 423: int len;
! 424: #ifdef FPSP
! 425: extern u_long fpvect_tab, fpvect_end, fpsp_tab;
! 426: #endif
! 427:
! 428: /*
! 429: * Map machineid to model name.
! 430: */
! 431: if (machineid >= sizeof(hp300_models) / sizeof(char *)) {
! 432: printf("\nunknown machineid %d\n", machineid);
! 433: goto lose;
! 434: }
! 435: t = hp300_models[machineid];
! 436:
! 437: /*
! 438: * Look up special designation (425s, 425t, etc) by mmuid.
! 439: */
! 440: if (mmuid < strlen(hp300_designations) &&
! 441: hp300_designations[mmuid] != ' ') {
! 442: td = &hp300_designations[mmuid];
! 443: td[1] = '\0';
! 444: } else
! 445: td = "";
! 446:
! 447: /*
! 448: * ...and the CPU type
! 449: */
! 450: switch (cputype) {
! 451: case CPU_68040:
! 452: mc = '4';
! 453: /* adjust cpuspeed by 3/8 on '040 boxes */
! 454: cpuspeed *= 3;
! 455: cpuspeed /= 8;
! 456: break;
! 457: case CPU_68030:
! 458: mc = '3';
! 459: break;
! 460: case CPU_68020:
! 461: mc = '2';
! 462: break;
! 463: default:
! 464: printf("\nunknown cputype %d\n", cputype);
! 465: goto lose;
! 466: }
! 467: snprintf(cpu_model, sizeof cpu_model,
! 468: "HP 9000/%s%s (%dMHz MC680%c0 CPU", t, td, cpuspeed, mc);
! 469:
! 470: /*
! 471: * ...and the MMU type.
! 472: */
! 473: switch (mmutype) {
! 474: case MMU_68040:
! 475: case MMU_68030:
! 476: strlcat(cpu_model, "+MMU", sizeof cpu_model);
! 477: break;
! 478: case MMU_68851:
! 479: strlcat(cpu_model, ", MC68851 MMU", sizeof cpu_model);
! 480: break;
! 481: case MMU_HP:
! 482: strlcat(cpu_model, ", HP MMU", sizeof cpu_model);
! 483: break;
! 484: default:
! 485: printf("%s\nunknown MMU type %d\n", cpu_model, mmutype);
! 486: panic("startup");
! 487: }
! 488:
! 489: /*
! 490: * ...and the FPU type.
! 491: */
! 492: switch (fputype) {
! 493: case FPU_68040:
! 494: strlcat(cpu_model, "+FPU", sizeof cpu_model);
! 495: break;
! 496: case FPU_68882:
! 497: len = strlen(cpu_model);
! 498: snprintf(cpu_model + len, sizeof cpu_model - len,
! 499: ", %dMHz MC68882 FPU", cpuspeed);
! 500: break;
! 501: case FPU_68881:
! 502: len = strlen(cpu_model);
! 503: snprintf(cpu_model + len, sizeof cpu_model - len,
! 504: ", %dMHz MC68881 FPU", machineid == HP_350 ? 20 : 16);
! 505: break;
! 506: default:
! 507: strlcat(cpu_model, ", unknown FPU", sizeof cpu_model);
! 508: }
! 509:
! 510: /*
! 511: * ...and finally, the cache type.
! 512: */
! 513: if (cputype == CPU_68040)
! 514: strlcat(cpu_model, ", 4k on-chip physical I/D caches",
! 515: sizeof cpu_model);
! 516: else {
! 517: len = strlen(cpu_model);
! 518: switch (ectype) {
! 519: case EC_VIRT:
! 520: snprintf(cpu_model + len, sizeof cpu_model - len,
! 521: ", %dK virtual-address cache",
! 522: machineid == HP_320 ? 16 : 32);
! 523: break;
! 524: case EC_PHYS:
! 525: snprintf(cpu_model + len, sizeof cpu_model - len,
! 526: ", %dK physical-address cache",
! 527: machineid == HP_370 ? 64 : 32);
! 528: break;
! 529: }
! 530: }
! 531:
! 532: printf("%s)\n", cpu_model);
! 533: #ifdef DEBUG
! 534: printf("cpu: delay divisor %d", delay_divisor);
! 535: if (mmuid)
! 536: printf(", mmuid %d", mmuid);
! 537: printf("\n");
! 538: #endif
! 539:
! 540: /*
! 541: * Now that we have told the user what they have,
! 542: * let them know if that machine type isn't configured.
! 543: */
! 544: switch (machineid) {
! 545: case -1: /* keep compilers happy */
! 546: #if !defined(HP320)
! 547: case HP_320:
! 548: #endif
! 549: #if !defined(HP330)
! 550: case HP_330:
! 551: #endif
! 552: #if !defined(HP340)
! 553: case HP_340:
! 554: #endif
! 555: #if !defined(HP345)
! 556: case HP_345:
! 557: #endif
! 558: #if !defined(HP350)
! 559: case HP_350:
! 560: #endif
! 561: #if !defined(HP360)
! 562: case HP_360:
! 563: #endif
! 564: #if !defined(HP362)
! 565: case HP_362:
! 566: #endif
! 567: #if !defined(HP370)
! 568: case HP_370:
! 569: #endif
! 570: #if !defined(HP375)
! 571: case HP_375:
! 572: #endif
! 573: #if !defined(HP380)
! 574: case HP_380:
! 575: #endif
! 576: #if !defined(HP382)
! 577: case HP_382:
! 578: #endif
! 579: #if !defined(HP385)
! 580: case HP_385:
! 581: #endif
! 582: #if !defined(HP400)
! 583: case HP_400:
! 584: #endif
! 585: #if !defined(HP425)
! 586: case HP_425:
! 587: #endif
! 588: #if !defined(HP433)
! 589: case HP_433:
! 590: #endif
! 591: panic("SPU type not configured for machineid %d", machineid);
! 592: default:
! 593: break;
! 594: }
! 595:
! 596: #ifdef FPSP
! 597: if (cputype == CPU_68040) {
! 598: bcopy(&fpsp_tab, &fpvect_tab,
! 599: (&fpvect_end - &fpvect_tab) * sizeof (fpvect_tab));
! 600: }
! 601: #endif
! 602:
! 603: return;
! 604: lose:
! 605: panic("startup");
! 606: }
! 607:
! 608: /*
! 609: * machine dependent system variables.
! 610: */
! 611: int
! 612: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 613: int *name;
! 614: u_int namelen;
! 615: void *oldp;
! 616: size_t *oldlenp;
! 617: void *newp;
! 618: size_t newlen;
! 619: struct proc *p;
! 620: {
! 621: dev_t consdev;
! 622:
! 623: /* all sysctl names at this level are terminal */
! 624: if (namelen != 1)
! 625: return (ENOTDIR); /* overloaded */
! 626:
! 627: switch (name[0]) {
! 628: case CPU_CONSDEV:
! 629: if (cn_tab != NULL)
! 630: consdev = cn_tab->cn_dev;
! 631: else
! 632: consdev = NODEV;
! 633: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
! 634: sizeof consdev));
! 635: case CPU_CPUSPEED:
! 636: return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
! 637: case CPU_MACHINEID:
! 638: return (sysctl_rdint(oldp, oldlenp, newp, machineid));
! 639: case CPU_MMUID:
! 640: return (sysctl_rdint(oldp, oldlenp, newp, mmuid));
! 641: default:
! 642: return (EOPNOTSUPP);
! 643: }
! 644: /* NOTREACHED */
! 645: }
! 646:
! 647: int waittime = -1;
! 648:
! 649: void
! 650: boot(howto)
! 651: int howto;
! 652: {
! 653: /* take a snap shot before clobbering any registers */
! 654: if (curproc && curproc->p_addr)
! 655: savectx(&curproc->p_addr->u_pcb);
! 656:
! 657: /* If system is cold, just halt. */
! 658: if (cold) {
! 659: /* (Unless the user explicitly asked for reboot.) */
! 660: if ((howto & RB_USERREQ) == 0)
! 661: howto |= RB_HALT;
! 662: goto haltsys;
! 663: }
! 664:
! 665: boothowto = howto;
! 666: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
! 667: waittime = 0;
! 668: vfs_shutdown();
! 669: /*
! 670: * If we've been adjusting the clock, the todr
! 671: * will be out of synch; adjust it now unless
! 672: * the system was sitting in ddb.
! 673: */
! 674: if ((howto & RB_TIMEBAD) == 0) {
! 675: resettodr();
! 676: } else {
! 677: printf("WARNING: not updating battery clock\n");
! 678: }
! 679: }
! 680:
! 681: /* Disable interrupts. */
! 682: splhigh();
! 683:
! 684: /* If rebooting and a dump is requested do it. */
! 685: if (howto & RB_DUMP)
! 686: dumpsys();
! 687:
! 688: haltsys:
! 689: /* Run any shutdown hooks. */
! 690: doshutdownhooks();
! 691:
! 692: /* Finally, halt/reboot the system. */
! 693: if (howto & RB_HALT) {
! 694: printf("System halted. Hit any key to reboot.\n\n");
! 695: while (cngetc() == 0);
! 696: }
! 697:
! 698: printf("rebooting...\n");
! 699: DELAY(1000000);
! 700: doboot();
! 701: /*NOTREACHED*/
! 702: }
! 703:
! 704: /*
! 705: * These variables are needed by /sbin/savecore
! 706: */
! 707: u_long dumpmag = 0x8fca0101; /* magic number */
! 708: int dumpsize = 0; /* pages */
! 709: long dumplo = 0; /* blocks */
! 710: cpu_kcore_hdr_t cpu_kcore_hdr;
! 711:
! 712: /*
! 713: * This is called by configure to set dumplo and dumpsize.
! 714: * Dumps always skip the first PAGE_SIZE of disk space
! 715: * in case there might be a disk label stored there.
! 716: * If there is extra space, put dump at the end to
! 717: * reduce the chance that swapping trashes it.
! 718: */
! 719: void
! 720: dumpconf(void)
! 721: {
! 722: int nblks; /* size of dump area */
! 723:
! 724: if (dumpdev == NODEV ||
! 725: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
! 726: return;
! 727: if (nblks <= ctod(1))
! 728: return;
! 729:
! 730: /*
! 731: * XXX include the final RAM page which is not included in physmem.
! 732: */
! 733: dumpsize = physmem;
! 734:
! 735: /* hp300 only uses a single segment. */
! 736: cpu_kcore_hdr.ram_segs[0].start = lowram;
! 737: cpu_kcore_hdr.ram_segs[0].size = ctob(dumpsize);
! 738: cpu_kcore_hdr.mmutype = mmutype;
! 739: cpu_kcore_hdr.kernel_pa = lowram;
! 740: cpu_kcore_hdr.sysseg_pa = pmap_kernel()->pm_stpa;
! 741:
! 742: /* Always skip the first block, in case there is a label there. */
! 743: if (dumplo < ctod(1))
! 744: dumplo = ctod(1);
! 745:
! 746: /* Put dump at end of partition, and make it fit. */
! 747: if (dumpsize > dtoc(nblks - dumplo))
! 748: dumpsize = dtoc(nblks - dumplo);
! 749: if (dumplo < nblks - ctod(dumpsize))
! 750: dumplo = nblks - ctod(dumpsize);
! 751: }
! 752:
! 753: /*
! 754: * Dump physical memory onto the dump device. Called by doadump()
! 755: * in locore.s or by boot() here in machdep.c
! 756: */
! 757: void
! 758: dumpsys()
! 759: {
! 760: daddr64_t blkno; /* current block to write */
! 761: /* dump routine */
! 762: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 763: int pg; /* page being dumped */
! 764: paddr_t maddr; /* PA being dumped */
! 765: int error; /* error code from (*dump)() */
! 766: kcore_seg_t *kseg_p;
! 767: cpu_kcore_hdr_t *chdr_p;
! 768: char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
! 769: extern int msgbufmapped;
! 770:
! 771: /* XXX initialized here because of gcc lossage */
! 772: maddr = lowram;
! 773: pg = 0;
! 774:
! 775: /* Don't put dump messages in msgbuf. */
! 776: msgbufmapped = 0;
! 777:
! 778: /* Make sure dump device is valid. */
! 779: if (dumpdev == NODEV)
! 780: return;
! 781: if (dumpsize == 0) {
! 782: dumpconf();
! 783: if (dumpsize == 0)
! 784: return;
! 785: }
! 786: if (dumplo <= 0) {
! 787: printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
! 788: minor(dumpdev));
! 789: return;
! 790: }
! 791: dump = bdevsw[major(dumpdev)].d_dump;
! 792: blkno = dumplo;
! 793:
! 794: printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
! 795: minor(dumpdev), dumplo);
! 796:
! 797: kseg_p = (kcore_seg_t *)dump_hdr;
! 798: chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
! 799: bzero(dump_hdr, sizeof(dump_hdr));
! 800:
! 801: /*
! 802: * Generate a segment header
! 803: */
! 804: CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
! 805: kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
! 806:
! 807: /*
! 808: * Add the md header
! 809: */
! 810:
! 811: *chdr_p = cpu_kcore_hdr;
! 812:
! 813: printf("dump ");
! 814: maddr = cpu_kcore_hdr.ram_segs[0].start;
! 815: /* Dump the header. */
! 816: error = (*dump) (dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
! 817: switch (error) {
! 818: case 0:
! 819: break;
! 820:
! 821: case ENXIO:
! 822: printf("device bad\n");
! 823: return;
! 824:
! 825: case EFAULT:
! 826: printf("device not ready\n");
! 827: return;
! 828:
! 829: case EINVAL:
! 830: printf("area improper\n");
! 831: return;
! 832:
! 833: case EIO:
! 834: printf("i/o error\n");
! 835: return;
! 836:
! 837: case EINTR:
! 838: printf("aborted from console\n");
! 839: return;
! 840:
! 841: default:
! 842: printf("error %d\n", error);
! 843: return;
! 844: }
! 845: for (pg = 0; pg < dumpsize; pg++) {
! 846: #define NPGMB (1024*1024/NBPG)
! 847: /* print out how many MBs we have dumped */
! 848: if (pg && (pg % NPGMB) == 0)
! 849: printf("%d ", pg / NPGMB);
! 850: #undef NPGMB
! 851: pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
! 852: VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
! 853:
! 854: pmap_update(pmap_kernel());
! 855: error = (*dump)(dumpdev, blkno, vmmap, NBPG);
! 856: switch (error) {
! 857: case 0:
! 858: maddr += NBPG;
! 859: blkno += btodb(NBPG);
! 860: break;
! 861:
! 862: case ENXIO:
! 863: printf("device bad\n");
! 864: return;
! 865:
! 866: case EFAULT:
! 867: printf("device not ready\n");
! 868: return;
! 869:
! 870: case EINVAL:
! 871: printf("area improper\n");
! 872: return;
! 873:
! 874: case EIO:
! 875: printf("i/o error\n");
! 876: return;
! 877:
! 878: case EINTR:
! 879: printf("aborted from console\n");
! 880: return;
! 881:
! 882: default:
! 883: printf("error %d\n", error);
! 884: return;
! 885: }
! 886: }
! 887: printf("succeeded\n");
! 888: }
! 889:
! 890: void
! 891: initcpu()
! 892: {
! 893:
! 894: parityenable();
! 895: #ifdef USELEDS
! 896: ledinit();
! 897: #endif
! 898: }
! 899:
! 900: void
! 901: straytrap(pc, evec)
! 902: int pc;
! 903: u_short evec;
! 904: {
! 905: printf("unexpected trap (vector offset %x) from %x\n",
! 906: evec & 0xFFF, pc);
! 907: }
! 908:
! 909: /* XXX should change the interface, and make one badaddr() function */
! 910:
! 911: int *nofault;
! 912:
! 913: int
! 914: badaddr(addr)
! 915: caddr_t addr;
! 916: {
! 917: int i;
! 918: label_t faultbuf;
! 919:
! 920: nofault = (int *) &faultbuf;
! 921: if (setjmp((label_t *)nofault)) {
! 922: nofault = (int *) 0;
! 923: return(1);
! 924: }
! 925: i = *(volatile short *)addr;
! 926: nofault = (int *) 0;
! 927: return(0);
! 928: }
! 929:
! 930: int
! 931: badbaddr(addr)
! 932: caddr_t addr;
! 933: {
! 934: int i;
! 935: label_t faultbuf;
! 936:
! 937: nofault = (int *) &faultbuf;
! 938: if (setjmp((label_t *)nofault)) {
! 939: nofault = (int *) 0;
! 940: return(1);
! 941: }
! 942: i = *(volatile char *)addr;
! 943: nofault = (int *) 0;
! 944: return(0);
! 945: }
! 946:
! 947: static int innmihand; /* simple mutex */
! 948:
! 949: /*
! 950: * Level 7 interrupts can be caused by HIL keyboards (in cooked mode only,
! 951: * but we run them in raw mode) or parity errors.
! 952: */
! 953: void
! 954: nmihand(frame)
! 955: struct frame frame;
! 956: {
! 957:
! 958: /* Prevent unwanted recursion. */
! 959: if (innmihand)
! 960: return;
! 961: innmihand = 1;
! 962:
! 963: if (parityerror(&frame)) {
! 964: innmihand = 0;
! 965: return;
! 966: }
! 967:
! 968: /* panic?? */
! 969: printf("unexpected level 7 interrupt ignored\n");
! 970:
! 971: innmihand = 0;
! 972: }
! 973:
! 974: /*
! 975: * Parity error section. Contains magic.
! 976: */
! 977: #define PARREG ((volatile short *)IIOV(0x5B0000))
! 978: static int gotparmem = 0;
! 979: #ifdef DEBUG
! 980: int ignorekperr = 0; /* ignore kernel parity errors */
! 981: #endif
! 982:
! 983: /*
! 984: * Enable parity detection
! 985: */
! 986: void
! 987: parityenable()
! 988: {
! 989: label_t faultbuf;
! 990:
! 991: nofault = (int *) &faultbuf;
! 992: if (setjmp((label_t *)nofault)) {
! 993: nofault = (int *) 0;
! 994: printf("No parity memory\n");
! 995: return;
! 996: }
! 997: *PARREG = 1;
! 998: nofault = (int *) 0;
! 999: gotparmem = 1;
! 1000: printf("Parity detection enabled\n");
! 1001: }
! 1002:
! 1003: /*
! 1004: * Determine if level 7 interrupt was caused by a parity error
! 1005: * and deal with it if it was. Returns 1 if it was a parity error.
! 1006: */
! 1007: int
! 1008: parityerror(fp)
! 1009: struct frame *fp;
! 1010: {
! 1011: if (!gotparmem)
! 1012: return(0);
! 1013: *PARREG = 0;
! 1014: DELAY(10);
! 1015: *PARREG = 1;
! 1016: if (panicstr) {
! 1017: printf("parity error after panic ignored\n");
! 1018: return (1);
! 1019: }
! 1020: if (!parityerrorfind())
! 1021: printf("WARNING: transient parity error ignored\n");
! 1022: else if (USERMODE(fp->f_sr)) {
! 1023: log(LOG_ERR, "pid %d was killed: memory parity error\n",
! 1024: curproc->p_pid);
! 1025: uprintf("sorry, pid %d killed: memory parity error\n",
! 1026: curproc->p_pid);
! 1027: psignal(curproc, SIGKILL);
! 1028: #ifdef DEBUG
! 1029: } else if (ignorekperr) {
! 1030: printf("WARNING: kernel parity error ignored\n");
! 1031: #endif
! 1032: } else {
! 1033: regdump(&(fp->F_t), 128);
! 1034: panic("kernel parity error");
! 1035: }
! 1036: return (1);
! 1037: }
! 1038:
! 1039: /*
! 1040: * Yuck! There has got to be a better way to do this!
! 1041: * Searching all of memory with interrupts blocked can lead to disaster.
! 1042: */
! 1043: int
! 1044: parityerrorfind()
! 1045: {
! 1046: static label_t parcatch;
! 1047: static int looking = 0;
! 1048: volatile int pg, o, s;
! 1049: volatile int *ip;
! 1050: int i;
! 1051: int found;
! 1052:
! 1053: #ifdef lint
! 1054: i = o = pg = 0; if (i) return(0);
! 1055: #endif
! 1056: /*
! 1057: * If looking is true we are searching for a known parity error
! 1058: * and it has just occurred. All we do is return to the higher
! 1059: * level invocation.
! 1060: */
! 1061: if (looking)
! 1062: longjmp(&parcatch);
! 1063: s = splhigh();
! 1064: /*
! 1065: * If setjmp returns true, the parity error we were searching
! 1066: * for has just occurred (longjmp above) at the current pg+o
! 1067: */
! 1068: if (setjmp(&parcatch)) {
! 1069: printf("Parity error at 0x%x\n", ctob(pg)|o);
! 1070: found = 1;
! 1071: goto done;
! 1072: }
! 1073: /*
! 1074: * If we get here, a parity error has occurred for the first time
! 1075: * and we need to find it. We turn off any external caches and
! 1076: * loop thru memory, testing every longword til a fault occurs and
! 1077: * we regain control at setjmp above. Note that because of the
! 1078: * setjmp, pg and o need to be volatile or their values will be lost.
! 1079: */
! 1080: looking = 1;
! 1081: ecacheoff();
! 1082: for (pg = btoc(lowram); pg < btoc(lowram)+physmem; pg++) {
! 1083: pmap_kenter_pa((vaddr_t)vmmap, ptoa(pg), VM_PROT_READ);
! 1084: pmap_update(pmap_kernel());
! 1085: ip = (int *)vmmap;
! 1086: for (o = 0; o < PAGE_SIZE; o += sizeof(int))
! 1087: i = *ip++;
! 1088: }
! 1089: /*
! 1090: * Getting here implies no fault was found. Should never happen.
! 1091: */
! 1092: printf("Couldn't locate parity error\n");
! 1093: found = 0;
! 1094: done:
! 1095: looking = 0;
! 1096: ecacheon(); /* pmap_kremove() may cause a cache flush */
! 1097: pmap_kremove((vaddr_t)vmmap, PAGE_SIZE);
! 1098: pmap_update(pmap_kernel());
! 1099: splx(s);
! 1100: return(found);
! 1101: }
! 1102:
! 1103: /*
! 1104: * cpu_exec_aout_makecmds():
! 1105: * cpu-dependent a.out format hook for execve().
! 1106: *
! 1107: * Determine of the given exec package refers to something which we
! 1108: * understand and, if so, set up the vmcmds for it.
! 1109: */
! 1110: int
! 1111: cpu_exec_aout_makecmds(p, epp)
! 1112: struct proc *p;
! 1113: struct exec_package *epp;
! 1114: {
! 1115: #if defined(COMPAT_44) || defined(COMPAT_SUNOS)
! 1116: u_long midmag, magic;
! 1117: u_short mid;
! 1118: int error;
! 1119: struct exec *execp = epp->ep_hdr;
! 1120: #ifdef COMPAT_SUNOS
! 1121: extern int sunos_exec_aout_makecmds(struct proc *, struct exec_package *);
! 1122: #endif
! 1123:
! 1124: midmag = ntohl(execp->a_midmag);
! 1125: mid = (midmag >> 16) & 0xffff;
! 1126: magic = midmag & 0xffff;
! 1127:
! 1128: midmag = mid << 16 | magic;
! 1129:
! 1130: switch (midmag) {
! 1131: #ifdef COMPAT_44
! 1132: case (MID_HP300 << 16) | ZMAGIC:
! 1133: error = exec_aout_prep_oldzmagic(p, epp);
! 1134: break;
! 1135: #endif
! 1136: default:
! 1137: #ifdef COMPAT_SUNOS
! 1138: /* Hand it over to the SunOS emulation package. */
! 1139: error = sunos_exec_aout_makecmds(p, epp);
! 1140: #else
! 1141: error = ENOEXEC;
! 1142: #endif
! 1143: }
! 1144:
! 1145: return error;
! 1146: #else /* !(defined(COMPAT_44) || defined(COMPAT_SUNOS)) */
! 1147: return ENOEXEC;
! 1148: #endif
! 1149: }
CVSweb