Annotation of sys/arch/mvme88k/mvme88k/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.192 2007/06/06 17:15:12 deraadt Exp $ */
! 2: /*
! 3: * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr.
! 4: * Copyright (c) 1996 Nivas Madhur
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Nivas Madhur.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: *
! 32: */
! 33: /*
! 34: * Mach Operating System
! 35: * Copyright (c) 1993-1991 Carnegie Mellon University
! 36: * Copyright (c) 1991 OMRON Corporation
! 37: * All Rights Reserved.
! 38: *
! 39: * Permission to use, copy, modify and distribute this software and its
! 40: * documentation is hereby granted, provided that both the copyright
! 41: * notice and this permission notice appear in all copies of the
! 42: * software, derivative works or modified versions, and any portions
! 43: * thereof, and that both notices appear in supporting documentation.
! 44: *
! 45: */
! 46:
! 47: #include <sys/param.h>
! 48: #include <sys/systm.h>
! 49: #include <sys/kernel.h>
! 50: #include <sys/proc.h>
! 51: #include <sys/user.h>
! 52: #include <sys/buf.h>
! 53: #include <sys/reboot.h>
! 54: #include <sys/conf.h>
! 55: #include <sys/malloc.h>
! 56: #include <sys/mount.h>
! 57: #include <sys/msgbuf.h>
! 58: #include <sys/syscallargs.h>
! 59: #ifdef SYSVMSG
! 60: #include <sys/msg.h>
! 61: #endif
! 62: #include <sys/exec.h>
! 63: #include <sys/sysctl.h>
! 64: #include <sys/errno.h>
! 65: #include <sys/extent.h>
! 66: #include <sys/core.h>
! 67: #include <sys/kcore.h>
! 68:
! 69: #include <machine/asm.h>
! 70: #include <machine/asm_macro.h>
! 71: #include <machine/bug.h>
! 72: #include <machine/bugio.h>
! 73: #include <machine/cmmu.h>
! 74: #include <machine/cpu.h>
! 75: #include <machine/kcore.h>
! 76: #include <machine/reg.h>
! 77: #ifdef M88100
! 78: #include <machine/m88100.h>
! 79: #endif
! 80:
! 81: #include <dev/cons.h>
! 82:
! 83: #include <uvm/uvm_extern.h>
! 84:
! 85: #include "ksyms.h"
! 86: #if DDB
! 87: #include <machine/db_machdep.h>
! 88: #include <ddb/db_extern.h>
! 89: #include <ddb/db_interface.h>
! 90: #include <ddb/db_var.h>
! 91: #endif /* DDB */
! 92:
! 93: caddr_t allocsys(caddr_t);
! 94: void consinit(void);
! 95: void dumpconf(void);
! 96: void dumpsys(void);
! 97: int getcpuspeed(struct mvmeprom_brdid *);
! 98: u_int getipl(void);
! 99: void identifycpu(void);
! 100: void mvme_bootstrap(void);
! 101: void mvme88k_vector_init(u_int32_t *, u_int32_t *);
! 102: void myetheraddr(u_char *);
! 103: void savectx(struct pcb *);
! 104: void secondary_main(void);
! 105: void secondary_pre_main(void);
! 106: void _doboot(void);
! 107:
! 108: extern void setlevel(unsigned int);
! 109:
! 110: extern void m187_bootstrap(void);
! 111: extern vaddr_t m187_memsize(void);
! 112: extern void m187_startup(void);
! 113: extern void m188_bootstrap(void);
! 114: extern vaddr_t m188_memsize(void);
! 115: extern void m188_startup(void);
! 116: extern void m197_bootstrap(void);
! 117: extern vaddr_t m197_memsize(void);
! 118: extern void m197_startup(void);
! 119:
! 120: intrhand_t intr_handlers[NVMEINTR];
! 121:
! 122: /* board dependent pointers */
! 123: void (*md_interrupt_func_ptr)(u_int, struct trapframe *);
! 124: void (*md_init_clocks)(void);
! 125: u_int (*md_getipl)(void);
! 126: u_int (*md_setipl)(u_int);
! 127: u_int (*md_raiseipl)(u_int);
! 128: #ifdef MULTIPROCESSOR
! 129: void (*md_send_ipi)(int, cpuid_t);
! 130: #endif
! 131:
! 132: int physmem; /* available physical memory, in pages */
! 133:
! 134: struct vm_map *exec_map = NULL;
! 135: struct vm_map *phys_map = NULL;
! 136:
! 137: #ifdef MULTIPROCESSOR
! 138: __cpu_simple_lock_t cpu_mutex = __SIMPLELOCK_UNLOCKED;
! 139: #endif
! 140:
! 141: /*
! 142: * Declare these as initialized data so we can patch them.
! 143: */
! 144: #ifndef BUFCACHEPERCENT
! 145: #define BUFCACHEPERCENT 5
! 146: #endif
! 147:
! 148: #ifdef BUFPAGES
! 149: int bufpages = BUFPAGES;
! 150: #else
! 151: int bufpages = 0;
! 152: #endif
! 153: int bufcachepercent = BUFCACHEPERCENT;
! 154:
! 155: /*
! 156: * Info for CTL_HW
! 157: */
! 158: char machine[] = MACHINE; /* cpu "architecture" */
! 159: char cpu_model[120];
! 160:
! 161: #if defined(DDB) || NKSYMS > 0
! 162: extern char *esym;
! 163: #endif
! 164:
! 165: int boothowto; /* set in locore.S */
! 166: int bootdev; /* set in locore.S */
! 167: int cputyp; /* set in locore.S */
! 168: int brdtyp; /* set in locore.S */
! 169: int cpumod; /* set in mvme_bootstrap() */
! 170: int cpuspeed = 25; /* safe guess */
! 171:
! 172: vaddr_t first_addr;
! 173: vaddr_t last_addr;
! 174:
! 175: vaddr_t avail_start, avail_end;
! 176: vaddr_t virtual_avail, virtual_end;
! 177:
! 178: extern struct user *proc0paddr;
! 179:
! 180: /*
! 181: * This is to fake out the console routines, while booting.
! 182: */
! 183: cons_decl(boot);
! 184: #define bootcnpollc nullcnpollc
! 185:
! 186: struct consdev bootcons = {
! 187: NULL,
! 188: NULL,
! 189: bootcngetc,
! 190: bootcnputc,
! 191: bootcnpollc,
! 192: NULL,
! 193: makedev(14, 0),
! 194: CN_NORMAL,
! 195: };
! 196:
! 197: /*
! 198: * Early console initialization: called early on from main, before vm init.
! 199: * We want to stick to the BUG routines for now, and we'll switch to the
! 200: * real console in cpu_startup().
! 201: */
! 202: void
! 203: consinit()
! 204: {
! 205: cn_tab = &bootcons;
! 206:
! 207: #if defined(DDB)
! 208: db_machine_init();
! 209: ddb_init();
! 210: if (boothowto & RB_KDB)
! 211: Debugger();
! 212: #endif
! 213: }
! 214:
! 215: int
! 216: getcpuspeed(struct mvmeprom_brdid *brdid)
! 217: {
! 218: int speed = 0;
! 219: u_int i, c;
! 220:
! 221: for (i = 0; i < 4; i++) {
! 222: c = (u_int)brdid->speed[i];
! 223: if (c == ' ')
! 224: c = '0';
! 225: else if (c > '9' || c < '0') {
! 226: speed = 0;
! 227: break;
! 228: }
! 229: speed = speed * 10 + (c - '0');
! 230: }
! 231: speed = speed / 100;
! 232:
! 233: switch (brdtyp) {
! 234: #ifdef MVME187
! 235: case BRD_187:
! 236: case BRD_8120:
! 237: if (speed == 25 || speed == 33)
! 238: return speed;
! 239: speed = 25;
! 240: break;
! 241: #endif
! 242: #ifdef MVME188
! 243: case BRD_188:
! 244: /*
! 245: * If BUG version prior to 5.x, there is no CNFG block and
! 246: * speed can be found in the environment.
! 247: * XXX We don't process ENV data yet - assume 20MHz in this
! 248: * case.
! 249: */
! 250: if ((u_int)brdid->rev < 0x50) {
! 251: speed = 20;
! 252: } else {
! 253: if (speed == 20 || speed == 25)
! 254: return speed;
! 255: speed = 25;
! 256: }
! 257: break;
! 258: #endif
! 259: #ifdef MVME197
! 260: case BRD_197:
! 261: if (speed == 40 || speed == 50)
! 262: return speed;
! 263: speed = 50;
! 264: break;
! 265: #endif
! 266: }
! 267:
! 268: /*
! 269: * If we end up here, the board information block is damaged and
! 270: * we can't trust it.
! 271: * Suppose we are running at the most common speed for our board,
! 272: * and hope for the best (this really only affects osiop).
! 273: */
! 274: printf("WARNING: Board Configuration Data invalid, "
! 275: "replace NVRAM and restore values\n");
! 276: return speed;
! 277: }
! 278:
! 279: void
! 280: identifycpu()
! 281: {
! 282: struct mvmeprom_brdid brdid;
! 283: char suffix[4];
! 284: u_int i;
! 285:
! 286: bzero(&brdid, sizeof(brdid));
! 287: bugbrdid(&brdid);
! 288:
! 289: cpuspeed = getcpuspeed(&brdid);
! 290:
! 291: i = 0;
! 292: if (brdid.suffix[0] >= ' ' && brdid.suffix[0] < 0x7f) {
! 293: if (brdid.suffix[0] != '-')
! 294: suffix[i++] = '-';
! 295: suffix[i++] = brdid.suffix[0];
! 296: }
! 297: if (brdid.suffix[1] >= ' ' && brdid.suffix[1] < 0x7f)
! 298: suffix[i++] = brdid.suffix[1];
! 299: suffix[i++] = '\0';
! 300:
! 301: snprintf(cpu_model, sizeof cpu_model,
! 302: "Motorola MVME%x%s, %dMHz", brdtyp, suffix, cpuspeed);
! 303: }
! 304:
! 305: /*
! 306: * Set up real-time clocks.
! 307: * These function pointers are set in dev/clock.c.
! 308: */
! 309: void
! 310: cpu_initclocks()
! 311: {
! 312: (*md_init_clocks)();
! 313: }
! 314:
! 315: void
! 316: setstatclockrate(int newhz)
! 317: {
! 318: /* function stub */
! 319: }
! 320:
! 321:
! 322: void
! 323: cpu_startup()
! 324: {
! 325: caddr_t v;
! 326: int sz, i;
! 327: vaddr_t minaddr, maxaddr;
! 328:
! 329: /*
! 330: * Initialize error message buffer (at end of core).
! 331: * avail_end was pre-decremented in mvme_bootstrap() to compensate.
! 332: */
! 333: for (i = 0; i < btoc(MSGBUFSIZE); i++)
! 334: pmap_kenter_pa((paddr_t)msgbufp + i * PAGE_SIZE,
! 335: avail_end + i * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE);
! 336: pmap_update(pmap_kernel());
! 337: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
! 338:
! 339: /*
! 340: * Good {morning,afternoon,evening,night}.
! 341: */
! 342: printf(version);
! 343: identifycpu();
! 344: printf("real mem = %u (%uMB)\n", ctob(physmem),
! 345: ctob(physmem)/1024/1024);
! 346:
! 347: /*
! 348: * Find out how much space we need, allocate it,
! 349: * and then give everything true virtual addresses.
! 350: */
! 351: sz = (int)allocsys((caddr_t)0);
! 352:
! 353: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
! 354: panic("startup: no room for tables");
! 355: if (allocsys(v) - v != sz)
! 356: panic("startup: table size inconsistency");
! 357:
! 358: /*
! 359: * Grab machine dependent memory spaces
! 360: */
! 361: switch (brdtyp) {
! 362: #ifdef MVME187
! 363: case BRD_187:
! 364: case BRD_8120:
! 365: m187_startup();
! 366: break;
! 367: #endif
! 368: #ifdef MVME188
! 369: case BRD_188:
! 370: m188_startup();
! 371: break;
! 372: #endif
! 373: #ifdef MVME197
! 374: case BRD_197:
! 375: m197_startup();
! 376: break;
! 377: #endif
! 378: }
! 379:
! 380: /*
! 381: * Determine how many buffers to allocate.
! 382: * We allocate bufcachepercent% of memory for buffer space.
! 383: */
! 384: if (bufpages == 0)
! 385: bufpages = physmem * bufcachepercent / 100;
! 386:
! 387: /* Restrict to at most 25% filled kvm */
! 388: if (bufpages >
! 389: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 390: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 391: PAGE_SIZE / 4;
! 392:
! 393: /*
! 394: * Allocate a submap for exec arguments. This map effectively
! 395: * limits the number of processes exec'ing at any time.
! 396: */
! 397: minaddr = vm_map_min(kernel_map);
! 398: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 399: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 400:
! 401: /*
! 402: * Allocate map for physio.
! 403: */
! 404: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 405: VM_PHYS_SIZE, 0, FALSE, NULL);
! 406:
! 407: printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
! 408: ptoa(uvmexp.free)/1024/1024);
! 409:
! 410: /*
! 411: * Set up buffers, so they can be used to read disk labels.
! 412: */
! 413: bufinit();
! 414:
! 415: /*
! 416: * Set up interrupt handlers.
! 417: */
! 418: for (i = 0; i < NVMEINTR; i++)
! 419: SLIST_INIT(&intr_handlers[i]);
! 420:
! 421: /*
! 422: * Configure the system.
! 423: */
! 424: if (boothowto & RB_CONFIG) {
! 425: #ifdef BOOT_CONFIG
! 426: user_config();
! 427: #else
! 428: printf("kernel does not support -c; continuing..\n");
! 429: #endif
! 430: }
! 431: }
! 432:
! 433: /*
! 434: * Allocate space for system data structures. We are given
! 435: * a starting virtual address and we return a final virtual
! 436: * address; along the way we set each data structure pointer.
! 437: *
! 438: * We call allocsys() with 0 to find out how much space we want,
! 439: * allocate that much and fill it with zeroes, and then call
! 440: * allocsys() again with the correct base virtual address.
! 441: */
! 442: caddr_t
! 443: allocsys(v)
! 444: caddr_t v;
! 445: {
! 446:
! 447: #define valloc(name, type, num) \
! 448: v = (caddr_t)(((name) = (type *)v) + (num))
! 449:
! 450: #ifdef SYSVMSG
! 451: valloc(msgpool, char, msginfo.msgmax);
! 452: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 453: valloc(msghdrs, struct msg, msginfo.msgtql);
! 454: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 455: #endif
! 456:
! 457: return v;
! 458: }
! 459:
! 460: __dead void
! 461: _doboot()
! 462: {
! 463: cmmu_shutdown();
! 464: bugreturn();
! 465: /*NOTREACHED*/
! 466: for (;;); /* appease gcc */
! 467: }
! 468:
! 469: __dead void
! 470: boot(howto)
! 471: int howto;
! 472: {
! 473: /* take a snapshot before clobbering any registers */
! 474: if (curproc && curproc->p_addr)
! 475: savectx(curpcb);
! 476:
! 477: /* If system is cold, just halt. */
! 478: if (cold) {
! 479: /* (Unless the user explicitly asked for reboot.) */
! 480: if ((howto & RB_USERREQ) == 0)
! 481: howto |= RB_HALT;
! 482: goto haltsys;
! 483: }
! 484:
! 485: boothowto = howto;
! 486: if ((howto & RB_NOSYNC) == 0) {
! 487: vfs_shutdown();
! 488: /*
! 489: * If we've been adjusting the clock, the todr
! 490: * will be out of synch; adjust it now unless
! 491: * the system was sitting in ddb.
! 492: */
! 493: if ((howto & RB_TIMEBAD) == 0)
! 494: resettodr();
! 495: else
! 496: printf("WARNING: not updating battery clock\n");
! 497: }
! 498:
! 499: /* Disable interrupts. */
! 500: splhigh();
! 501:
! 502: /* If rebooting and a dump is requested, do it. */
! 503: if (howto & RB_DUMP)
! 504: dumpsys();
! 505:
! 506: haltsys:
! 507: /* Run any shutdown hooks. */
! 508: doshutdownhooks();
! 509:
! 510: if (howto & RB_HALT) {
! 511: printf("System halted. Press any key to reboot...\n\n");
! 512: cngetc();
! 513: }
! 514:
! 515: doboot();
! 516:
! 517: for (;;);
! 518: /*NOTREACHED*/
! 519: }
! 520:
! 521: unsigned dumpmag = 0x8fca0101; /* magic number for savecore */
! 522: int dumpsize = 0; /* also for savecore */
! 523: long dumplo = 0;
! 524: cpu_kcore_hdr_t cpu_kcore_hdr;
! 525:
! 526: /*
! 527: * This is called by configure to set dumplo and dumpsize.
! 528: * Dumps always skip the first PAGE_SIZE of disk space
! 529: * in case there might be a disk label stored there.
! 530: * If there is extra space, put dump at the end to
! 531: * reduce the chance that swapping trashes it.
! 532: */
! 533: void
! 534: dumpconf(void)
! 535: {
! 536: int nblks; /* size of dump area */
! 537:
! 538: if (dumpdev == NODEV ||
! 539: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
! 540: return;
! 541: if (nblks <= ctod(1))
! 542: return;
! 543:
! 544: dumpsize = physmem;
! 545:
! 546: /* mvme88k only uses a single segment. */
! 547: cpu_kcore_hdr.ram_segs[0].start = 0;
! 548: cpu_kcore_hdr.ram_segs[0].size = ctob(physmem);
! 549: cpu_kcore_hdr.cputype = cputyp;
! 550:
! 551: /*
! 552: * Don't dump on the first block
! 553: * in case the dump device includes a disk label.
! 554: */
! 555: if (dumplo < ctod(1))
! 556: dumplo = ctod(1);
! 557:
! 558: /* Put dump at end of partition, and make it fit. */
! 559: if (dumpsize + 1 > dtoc(nblks - dumplo))
! 560: dumpsize = dtoc(nblks - dumplo) - 1;
! 561: if (dumplo < nblks - ctod(dumpsize) - 1)
! 562: dumplo = nblks - ctod(dumpsize) - 1;
! 563: }
! 564:
! 565: /*
! 566: * Doadump comes here after turning off memory management and
! 567: * getting on the dump stack, either when called above, or by
! 568: * the auto-restart code.
! 569: */
! 570: void
! 571: dumpsys()
! 572: {
! 573: int maj;
! 574: int psize;
! 575: daddr64_t blkno; /* current block to write */
! 576: /* dump routine */
! 577: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 578: int pg; /* page being dumped */
! 579: paddr_t maddr; /* PA being dumped */
! 580: int error; /* error code from (*dump)() */
! 581: kcore_seg_t *kseg_p;
! 582: cpu_kcore_hdr_t *chdr_p;
! 583: char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
! 584:
! 585: extern int msgbufmapped;
! 586:
! 587: msgbufmapped = 0;
! 588:
! 589: /* Make sure dump device is valid. */
! 590: if (dumpdev == NODEV)
! 591: return;
! 592: if (dumpsize == 0) {
! 593: dumpconf();
! 594: if (dumpsize == 0)
! 595: return;
! 596: }
! 597: maj = major(dumpdev);
! 598: if (dumplo < 0) {
! 599: printf("\ndump to dev %u,%u not possible\n", maj,
! 600: minor(dumpdev));
! 601: return;
! 602: }
! 603: dump = bdevsw[maj].d_dump;
! 604: blkno = dumplo;
! 605:
! 606: printf("\ndumping to dev %u,%u offset %ld\n", maj,
! 607: minor(dumpdev), dumplo);
! 608:
! 609: /* Setup the dump header */
! 610: kseg_p = (kcore_seg_t *)dump_hdr;
! 611: chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
! 612: bzero(dump_hdr, sizeof(dump_hdr));
! 613:
! 614: CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
! 615: kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
! 616: *chdr_p = cpu_kcore_hdr;
! 617:
! 618: printf("dump ");
! 619: psize = (*bdevsw[maj].d_psize)(dumpdev);
! 620: if (psize == -1) {
! 621: printf("area unavailable\n");
! 622: return;
! 623: }
! 624:
! 625: /* Dump the header. */
! 626: error = (*dump)(dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
! 627: if (error != 0)
! 628: goto abort;
! 629:
! 630: maddr = (paddr_t)0;
! 631: for (pg = 0; pg < dumpsize; pg++) {
! 632: #define NPGMB (1024 * 1024 / PAGE_SIZE)
! 633: /* print out how many MBs we have dumped */
! 634: if (pg != 0 && (pg % NPGMB) == 0)
! 635: printf("%d ", pg / NPGMB);
! 636: #undef NPGMB
! 637: pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
! 638: VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
! 639:
! 640: error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
! 641: if (error == 0) {
! 642: maddr += PAGE_SIZE;
! 643: blkno += btodb(PAGE_SIZE);
! 644: } else
! 645: break;
! 646: }
! 647: abort:
! 648: switch (error) {
! 649: case 0:
! 650: printf("succeeded\n");
! 651: break;
! 652:
! 653: case ENXIO:
! 654: printf("device bad\n");
! 655: break;
! 656:
! 657: case EFAULT:
! 658: printf("device not ready\n");
! 659: break;
! 660:
! 661: case EINVAL:
! 662: printf("area improper\n");
! 663: break;
! 664:
! 665: case EIO:
! 666: printf("i/o error\n");
! 667: break;
! 668:
! 669: case EINTR:
! 670: printf("aborted from console\n");
! 671: break;
! 672:
! 673: default:
! 674: printf("error %d\n", error);
! 675: break;
! 676: }
! 677: }
! 678:
! 679: #ifdef MULTIPROCESSOR
! 680:
! 681: /*
! 682: * Secondary CPU early initialization routine.
! 683: * Determine CPU number and set it, then allocate the idle pcb (and stack).
! 684: *
! 685: * Running on a minimal stack here, with interrupts disabled; do nothing fancy.
! 686: */
! 687: void
! 688: secondary_pre_main()
! 689: {
! 690: struct cpu_info *ci;
! 691:
! 692: set_cpu_number(cmmu_cpu_number()); /* Determine cpu number by CMMU */
! 693: ci = curcpu();
! 694: ci->ci_curproc = &proc0;
! 695:
! 696: splhigh();
! 697:
! 698: /*
! 699: * Setup CMMUs and translation tables (shared with the master cpu).
! 700: */
! 701: pmap_bootstrap_cpu(ci->ci_cpuid);
! 702:
! 703: /*
! 704: * Allocate UPAGES contiguous pages for the idle PCB and stack.
! 705: */
! 706: ci->ci_idle_pcb = (struct pcb *)uvm_km_zalloc(kernel_map, USPACE);
! 707: if (ci->ci_idle_pcb == NULL) {
! 708: printf("cpu%d: unable to allocate idle stack\n", ci->ci_cpuid);
! 709: }
! 710: }
! 711:
! 712: /*
! 713: * Further secondary CPU initialization.
! 714: *
! 715: * We are now running on our idle stack, with proper page tables.
! 716: * There is nothing to do but display some details about the CPU and its CMMUs.
! 717: */
! 718: void
! 719: secondary_main()
! 720: {
! 721: struct cpu_info *ci = curcpu();
! 722:
! 723: cpu_configuration_print(0);
! 724: ncpus++;
! 725: __cpu_simple_unlock(&cpu_mutex);
! 726:
! 727: microuptime(&ci->ci_schedstate.spc_runtime);
! 728: ci->ci_curproc = NULL;
! 729:
! 730: /*
! 731: * Upon return, the secondary cpu bootstrap code in locore will
! 732: * enter the idle loop, waiting for some food to process on this
! 733: * processor.
! 734: */
! 735: }
! 736:
! 737: #endif /* MULTIPROCESSOR */
! 738:
! 739: /*
! 740: * Search for the first available interrupt vector in the range start, end.
! 741: * This should really only be used by VME devices.
! 742: */
! 743: int
! 744: intr_findvec(int start, int end, int skip)
! 745: {
! 746: int vec;
! 747:
! 748: #ifdef DEBUG
! 749: if (start < 0 || end >= NVMEINTR || start > end)
! 750: panic("intr_findvec(%d,%d): bad parameters", start, end);
! 751: #endif
! 752:
! 753: for (vec = start; vec <= end; vec++) {
! 754: if (vec == skip)
! 755: continue;
! 756: if (SLIST_EMPTY(&intr_handlers[vec]))
! 757: return vec;
! 758: }
! 759: #ifdef DIAGNOSTIC
! 760: printf("intr_findvec(%d,%d,%d): no vector available\n",
! 761: start, end, skip);
! 762: #endif
! 763: return -1;
! 764: }
! 765:
! 766: /*
! 767: * Try to insert ihand in the list of handlers for vector vec.
! 768: */
! 769: int
! 770: intr_establish(int vec, struct intrhand *ihand, const char *name)
! 771: {
! 772: struct intrhand *intr;
! 773: intrhand_t *list;
! 774:
! 775: if (vec < 0 || vec >= NVMEINTR) {
! 776: #ifdef DIAGNOSTIC
! 777: panic("intr_establish: vec (0x%x) not between 0x00 and 0xff",
! 778: vec);
! 779: #endif /* DIAGNOSTIC */
! 780: return (EINVAL);
! 781: }
! 782:
! 783: list = &intr_handlers[vec];
! 784: if (!SLIST_EMPTY(list)) {
! 785: intr = SLIST_FIRST(list);
! 786: if (intr->ih_ipl != ihand->ih_ipl) {
! 787: #ifdef DIAGNOSTIC
! 788: panic("intr_establish: there are other handlers with "
! 789: "vec (0x%x) at ipl %x, but you want it at %x",
! 790: vec, intr->ih_ipl, ihand->ih_ipl);
! 791: #endif /* DIAGNOSTIC */
! 792: return (EINVAL);
! 793: }
! 794: }
! 795:
! 796: evcount_attach(&ihand->ih_count, name, (void *)&ihand->ih_ipl,
! 797: &evcount_intr);
! 798: SLIST_INSERT_HEAD(list, ihand, ih_link);
! 799: return (0);
! 800: }
! 801:
! 802: void
! 803: nmihand(void *frame)
! 804: {
! 805: #ifdef DDB
! 806: printf("Abort switch pressed\n");
! 807: if (db_console) {
! 808: /*
! 809: * We can't use Debugger() here, as we are coming from an
! 810: * exception handler, and can't assume anything about the
! 811: * state we are in. Invoke the post-trap ddb entry directly.
! 812: */
! 813: extern void m88k_db_trap(int, struct trapframe *);
! 814: m88k_db_trap(T_KDB_ENTRY, (struct trapframe *)frame);
! 815: }
! 816: #endif
! 817: }
! 818:
! 819: int
! 820: cpu_exec_aout_makecmds(p, epp)
! 821: struct proc *p;
! 822: struct exec_package *epp;
! 823: {
! 824:
! 825: return (ENOEXEC);
! 826: }
! 827:
! 828: int
! 829: sys_sysarch(p, v, retval)
! 830: struct proc *p;
! 831: void *v;
! 832: register_t *retval;
! 833: {
! 834: #if 0
! 835: struct sys_sysarch_args /* {
! 836: syscallarg(int) op;
! 837: syscallarg(char *) parm;
! 838: } */ *uap = v;
! 839: #endif
! 840:
! 841: return (ENOSYS);
! 842: }
! 843:
! 844: /*
! 845: * machine dependent system variables.
! 846: */
! 847:
! 848: int
! 849: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 850: int *name;
! 851: u_int namelen;
! 852: void *oldp;
! 853: size_t *oldlenp;
! 854: void *newp;
! 855: size_t newlen;
! 856: struct proc *p;
! 857: {
! 858: dev_t consdev;
! 859:
! 860: /* all sysctl names are this level are terminal */
! 861: if (namelen != 1)
! 862: return (ENOTDIR); /* overloaded */
! 863:
! 864: switch (name[0]) {
! 865: case CPU_CONSDEV:
! 866: if (cn_tab != NULL)
! 867: consdev = cn_tab->cn_dev;
! 868: else
! 869: consdev = NODEV;
! 870: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
! 871: sizeof consdev));
! 872: default:
! 873: return (EOPNOTSUPP);
! 874: }
! 875: /*NOTREACHED*/
! 876: }
! 877:
! 878: void
! 879: myetheraddr(cp)
! 880: u_char *cp;
! 881: {
! 882: struct mvmeprom_brdid brdid;
! 883:
! 884: bugbrdid(&brdid);
! 885: bcopy(&brdid.etheraddr, cp, 6);
! 886: }
! 887:
! 888: void
! 889: mvme88k_vector_init(u_int32_t *vbr, u_int32_t *vectors)
! 890: {
! 891: extern void vector_init(u_int32_t *, u_int32_t *); /* gross */
! 892:
! 893: /* Save BUG vector */
! 894: bugvec[0] = vbr[MVMEPROM_VECTOR * 2 + 0];
! 895: bugvec[1] = vbr[MVMEPROM_VECTOR * 2 + 1];
! 896:
! 897: vector_init(vbr, vectors);
! 898:
! 899: /* Save new BUG vector */
! 900: sysbugvec[0] = vbr[MVMEPROM_VECTOR * 2 + 0];
! 901: sysbugvec[1] = vbr[MVMEPROM_VECTOR * 2 + 1];
! 902: }
! 903:
! 904: /*
! 905: * Called from locore.S during boot,
! 906: * this is the first C code that's run.
! 907: */
! 908: void
! 909: mvme_bootstrap()
! 910: {
! 911: extern int kernelstart;
! 912: extern struct consdev *cn_tab;
! 913: struct mvmeprom_brdid brdid;
! 914: #ifndef MULTIPROCESSOR
! 915: cpuid_t master_cpu;
! 916: #endif
! 917:
! 918: buginit();
! 919: bugbrdid(&brdid);
! 920: brdtyp = brdid.model;
! 921:
! 922: /*
! 923: * Use the BUG as console for now. After autoconf, we'll switch to
! 924: * real hardware.
! 925: */
! 926: cn_tab = &bootcons;
! 927:
! 928: /*
! 929: * Set up interrupt and fp exception handlers based on the machine.
! 930: */
! 931: switch (brdtyp) {
! 932: #ifdef MVME187
! 933: case BRD_187:
! 934: case BRD_8120:
! 935: m187_bootstrap();
! 936: break;
! 937: #endif
! 938: #ifdef MVME188
! 939: case BRD_188:
! 940: m188_bootstrap();
! 941: break;
! 942: #endif
! 943: #ifdef MVME197
! 944: case BRD_197:
! 945: m197_bootstrap();
! 946: break;
! 947: #endif
! 948: default:
! 949: panic("Sorry, this kernel does not support MVME%x", brdtyp);
! 950: }
! 951:
! 952: uvmexp.pagesize = PAGE_SIZE;
! 953: uvm_setpagesize();
! 954: first_addr = round_page(first_addr);
! 955:
! 956: switch (brdtyp) {
! 957: #ifdef MVME187
! 958: case BRD_187:
! 959: case BRD_8120:
! 960: last_addr = m187_memsize();
! 961: break;
! 962: #endif
! 963: #ifdef MVME188
! 964: case BRD_188:
! 965: last_addr = m188_memsize();
! 966: break;
! 967: #endif
! 968: #ifdef MVME197
! 969: case BRD_197:
! 970: last_addr = m197_memsize();
! 971: break;
! 972: #endif
! 973: }
! 974: physmem = btoc(last_addr);
! 975:
! 976: setup_board_config();
! 977: master_cpu = cmmu_init();
! 978: set_cpu_number(master_cpu);
! 979:
! 980: #ifdef M88100
! 981: if (CPU_IS88100) {
! 982: m88100_apply_patches();
! 983: }
! 984: #endif
! 985:
! 986: /*
! 987: * Now that set_cpu_number() set us with a valid cpu_info pointer,
! 988: * we need to initialize p_addr and curpcb before autoconf, for the
! 989: * fault handler to behave properly [except for badaddr() faults,
! 990: * which can be taken care of without a valid curcpu()].
! 991: */
! 992: proc0.p_addr = proc0paddr;
! 993: curproc = &proc0;
! 994: curpcb = &proc0paddr->u_pcb;
! 995:
! 996: avail_start = first_addr;
! 997: avail_end = last_addr;
! 998:
! 999: /*
! 1000: * Steal MSGBUFSIZE at the top of physical memory for msgbuf
! 1001: */
! 1002: avail_end -= round_page(MSGBUFSIZE);
! 1003:
! 1004: #ifdef DEBUG
! 1005: printf("MVME%x boot: memory from 0x%x to 0x%x\n",
! 1006: brdtyp, avail_start, avail_end);
! 1007: #endif
! 1008: pmap_bootstrap((vaddr_t)trunc_page((unsigned)&kernelstart));
! 1009:
! 1010: /*
! 1011: * Tell the VM system about available physical memory.
! 1012: *
! 1013: * The mvme88k boards only have one contiguous area, although BUG
! 1014: * could be set up to configure a non-contiguous scheme; also, we
! 1015: * might want to register ECC memory separately later on...
! 1016: */
! 1017: uvm_page_physload(atop(avail_start), atop(avail_end),
! 1018: atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
! 1019:
! 1020: /* Initialize the "u-area" pages. */
! 1021: bzero((caddr_t)curpcb, USPACE);
! 1022: #ifdef DEBUG
! 1023: printf("leaving mvme_bootstrap()\n");
! 1024: #endif
! 1025: }
! 1026:
! 1027: #ifdef MULTIPROCESSOR
! 1028: void
! 1029: cpu_boot_secondary_processors()
! 1030: {
! 1031: cpuid_t cpu;
! 1032: int rc;
! 1033: extern void secondary_start(void);
! 1034:
! 1035: switch (brdtyp) {
! 1036: #if defined(MVME188) || defined(MVME197)
! 1037: #ifdef MVME188
! 1038: case BRD_188:
! 1039: #endif
! 1040: #ifdef MVME197
! 1041: case BRD_197:
! 1042: #endif
! 1043: for (cpu = 0; cpu < max_cpus; cpu++) {
! 1044: if (cpu != curcpu()->ci_cpuid) {
! 1045: rc = spin_cpu(cpu, (vaddr_t)secondary_start);
! 1046: if (rc != 0 && rc != FORKMPU_NO_MPU)
! 1047: printf("cpu%d: spin_cpu error %d\n",
! 1048: cpu, rc);
! 1049: }
! 1050: }
! 1051: break;
! 1052: #endif
! 1053: default:
! 1054: break;
! 1055: }
! 1056: }
! 1057: #endif
! 1058:
! 1059: /*
! 1060: * Boot console routines:
! 1061: * Enables printing of boot messages before consinit().
! 1062: */
! 1063: void
! 1064: bootcnprobe(cp)
! 1065: struct consdev *cp;
! 1066: {
! 1067: cp->cn_dev = makedev(14, 0);
! 1068: cp->cn_pri = CN_NORMAL;
! 1069: }
! 1070:
! 1071: void
! 1072: bootcninit(cp)
! 1073: struct consdev *cp;
! 1074: {
! 1075: /* Nothing to do */
! 1076: }
! 1077:
! 1078: int
! 1079: bootcngetc(dev)
! 1080: dev_t dev;
! 1081: {
! 1082: return (buginchr());
! 1083: }
! 1084:
! 1085: void
! 1086: bootcnputc(dev, c)
! 1087: dev_t dev;
! 1088: int c;
! 1089: {
! 1090: if (c == '\n')
! 1091: bugpcrlf();
! 1092: else
! 1093: bugoutchr(c);
! 1094: }
! 1095:
! 1096: u_int
! 1097: getipl(void)
! 1098: {
! 1099: u_int curspl, psr;
! 1100:
! 1101: disable_interrupt(psr);
! 1102: curspl = (*md_getipl)();
! 1103: set_psr(psr);
! 1104: return curspl;
! 1105: }
! 1106:
! 1107: unsigned
! 1108: setipl(unsigned level)
! 1109: {
! 1110: u_int curspl, psr;
! 1111:
! 1112: disable_interrupt(psr);
! 1113: curspl = (*md_setipl)(level);
! 1114:
! 1115: /*
! 1116: * The flush pipeline is required to make sure the above change gets
! 1117: * through the data pipe and to the hardware; otherwise, the next
! 1118: * bunch of instructions could execute at the wrong spl protection.
! 1119: */
! 1120: flush_pipeline();
! 1121:
! 1122: set_psr(psr);
! 1123: return curspl;
! 1124: }
! 1125:
! 1126: unsigned
! 1127: raiseipl(unsigned level)
! 1128: {
! 1129: u_int curspl, psr;
! 1130:
! 1131: disable_interrupt(psr);
! 1132: curspl = (*md_raiseipl)(level);
! 1133:
! 1134: /*
! 1135: * The flush pipeline is required to make sure the above change gets
! 1136: * through the data pipe and to the hardware; otherwise, the next
! 1137: * bunch of instructions could execute at the wrong spl protection.
! 1138: */
! 1139: flush_pipeline();
! 1140:
! 1141: set_psr(psr);
! 1142: return curspl;
! 1143: }
! 1144:
! 1145: #ifdef MULTIPROCESSOR
! 1146:
! 1147: void
! 1148: m88k_send_ipi(int ipi, cpuid_t cpu)
! 1149: {
! 1150: struct cpu_info *ci;
! 1151:
! 1152: ci = &m88k_cpus[cpu];
! 1153: if (ci->ci_alive)
! 1154: (*md_send_ipi)(ipi, cpu);
! 1155: }
! 1156:
! 1157: void
! 1158: m88k_broadcast_ipi(int ipi)
! 1159: {
! 1160: struct cpu_info *ci;
! 1161: CPU_INFO_ITERATOR cii;
! 1162:
! 1163: CPU_INFO_FOREACH(cii, ci) {
! 1164: if (ci == curcpu())
! 1165: continue;
! 1166:
! 1167: if (ci->ci_alive)
! 1168: (*md_send_ipi)(ipi, ci->ci_cpuid);
! 1169: }
! 1170: }
! 1171:
! 1172: #endif
CVSweb