Annotation of sys/arch/aviion/aviion/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.10 2007/06/06 17:15:11 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/autoconf.h>
! 72: #include <machine/board.h>
! 73: #include <machine/cmmu.h>
! 74: #include <machine/cpu.h>
! 75: #include <machine/kcore.h>
! 76: #include <machine/prom.h>
! 77: #include <machine/reg.h>
! 78: #include <machine/trap.h>
! 79:
! 80: #include <dev/cons.h>
! 81:
! 82: #include <uvm/uvm_extern.h>
! 83:
! 84: #include "ksyms.h"
! 85: #if DDB
! 86: #include <machine/db_machdep.h>
! 87: #include <ddb/db_extern.h>
! 88: #include <ddb/db_interface.h>
! 89: #include <ddb/db_var.h>
! 90: #endif /* DDB */
! 91:
! 92: caddr_t allocsys(caddr_t);
! 93: void aviion_bootstrap(void);
! 94: int aviion_identify(void);
! 95: void consinit(void);
! 96: __dead void doboot(void);
! 97: void dumpconf(void);
! 98: void dumpsys(void);
! 99: u_int getipl(void);
! 100: void identifycpu(void);
! 101: void savectx(struct pcb *);
! 102: void secondary_main(void);
! 103: void secondary_pre_main(void);
! 104:
! 105: intrhand_t intr_handlers[NVMEINTR];
! 106:
! 107: int physmem; /* available physical memory, in pages */
! 108:
! 109: struct vm_map *exec_map = NULL;
! 110: struct vm_map *phys_map = NULL;
! 111:
! 112: #ifdef MULTIPROCESSOR
! 113: __cpu_simple_lock_t cpu_mutex = __SIMPLELOCK_UNLOCKED;
! 114: #endif
! 115:
! 116: /*
! 117: * Declare these as initialized data so we can patch them.
! 118: */
! 119: #ifndef BUFCACHEPERCENT
! 120: #define BUFCACHEPERCENT 5
! 121: #endif
! 122:
! 123: #ifdef BUFPAGES
! 124: int bufpages = BUFPAGES;
! 125: #else
! 126: int bufpages = 0;
! 127: #endif
! 128: int bufcachepercent = BUFCACHEPERCENT;
! 129:
! 130: /*
! 131: * Info for CTL_HW
! 132: */
! 133: char machine[] = MACHINE; /* cpu "architecture" */
! 134: char cpu_model[120];
! 135:
! 136: #if defined(DDB) || NKSYMS > 0
! 137: extern vaddr_t esym;
! 138: #endif
! 139:
! 140: const char *prom_bootargs; /* set in locore.S */
! 141: char bootargs[256]; /* local copy */
! 142: u_int bootdev, bootunit, bootpart; /* set in locore.S */
! 143:
! 144: int cputyp; /* set in locore.S */
! 145: int cpuspeed = 20; /* safe guess */
! 146: int avtyp;
! 147: const struct board *platform;
! 148:
! 149: vaddr_t first_addr;
! 150: vaddr_t last_addr;
! 151:
! 152: vaddr_t avail_start, avail_end;
! 153: vaddr_t virtual_avail, virtual_end;
! 154:
! 155: extern struct user *proc0paddr;
! 156:
! 157: /*
! 158: * This is to fake out the console routines, while booting.
! 159: * We could use directly the bugtty console, but we want to be able to
! 160: * configure a kernel without bugtty since we do not necessarily need a
! 161: * full-blown console driver.
! 162: */
! 163: cons_decl(boot);
! 164:
! 165: struct consdev bootcons = {
! 166: NULL,
! 167: NULL,
! 168: bootcngetc,
! 169: bootcnputc,
! 170: nullcnpollc,
! 171: NULL,
! 172: makedev(14, 0),
! 173: CN_NORMAL
! 174: };
! 175:
! 176: /*
! 177: * Early console initialization: called early on from main, before vm init.
! 178: * We want to stick to the BUG routines for now, and we'll switch to the
! 179: * real console in cpu_startup().
! 180: */
! 181: void
! 182: consinit()
! 183: {
! 184: cn_tab = NULL;
! 185: cninit();
! 186:
! 187: #if defined(DDB)
! 188: db_machine_init();
! 189: ddb_init();
! 190: if (boothowto & RB_KDB)
! 191: Debugger();
! 192: #endif
! 193: }
! 194:
! 195: void
! 196: identifycpu()
! 197: {
! 198: #if 0
! 199: /* XXX FILL ME */
! 200: cpuspeed = getcpuspeed(&brdid);
! 201: #endif
! 202:
! 203: strlcpy(cpu_model, platform->descr, sizeof cpu_model);
! 204: }
! 205:
! 206: /*
! 207: * Set up real-time clocks.
! 208: * These function pointers are set in dev/clock.c.
! 209: */
! 210: void
! 211: cpu_initclocks()
! 212: {
! 213: platform->init_clocks();
! 214: }
! 215:
! 216: void
! 217: setstatclockrate(int newhz)
! 218: {
! 219: /* function stub */
! 220: }
! 221:
! 222:
! 223: void
! 224: cpu_startup()
! 225: {
! 226: caddr_t v;
! 227: int sz, i;
! 228: vsize_t size;
! 229: int base, residual;
! 230: vaddr_t minaddr, maxaddr;
! 231:
! 232: /*
! 233: * Initialize error message buffer (at end of core).
! 234: * avail_end was pre-decremented in aviion_bootstrap() to compensate.
! 235: */
! 236: for (i = 0; i < btoc(MSGBUFSIZE); i++)
! 237: pmap_kenter_pa((paddr_t)msgbufp + i * PAGE_SIZE,
! 238: avail_end + i * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE);
! 239: pmap_update(pmap_kernel());
! 240: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
! 241:
! 242: /*
! 243: * Good {morning,afternoon,evening,night}.
! 244: */
! 245: printf(version);
! 246: identifycpu();
! 247: printf("real mem = %d\n", ctob(physmem));
! 248:
! 249: /*
! 250: * Find out how much space we need, allocate it,
! 251: * and then give everything true virtual addresses.
! 252: */
! 253: sz = (int)allocsys((caddr_t)0);
! 254:
! 255: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
! 256: panic("startup: no room for tables");
! 257: if (allocsys(v) - v != sz)
! 258: panic("startup: table size inconsistency");
! 259:
! 260: /*
! 261: * Grab machine dependent memory spaces
! 262: */
! 263: platform->startup();
! 264:
! 265: /*
! 266: * Determine how many buffers to allocate.
! 267: * We allocate bufcachepercent% of memory for buffer space.
! 268: */
! 269: if (bufpages == 0)
! 270: bufpages = physmem * bufcachepercent / 100;
! 271:
! 272: /* Restrict to at most 25% filled kvm */
! 273: if (bufpages >
! 274: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 275: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 276: PAGE_SIZE / 4;
! 277:
! 278: /*
! 279: * Allocate a submap for exec arguments. This map effectively
! 280: * limits the number of processes exec'ing at any time.
! 281: */
! 282: minaddr = vm_map_min(kernel_map);
! 283: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 284: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 285:
! 286: /*
! 287: * Allocate map for physio.
! 288: */
! 289: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 290: VM_PHYS_SIZE, 0, FALSE, NULL);
! 291:
! 292: printf("avail mem = %ld (%d pages)\n", ptoa(uvmexp.free), uvmexp.free);
! 293:
! 294: /*
! 295: * Set up buffers, so they can be used to read disk labels.
! 296: */
! 297: bufinit();
! 298:
! 299: /*
! 300: * Set up interrupt handlers.
! 301: */
! 302: for (i = 0; i < NVMEINTR; i++)
! 303: SLIST_INIT(&intr_handlers[i]);
! 304:
! 305: /*
! 306: * Configure the system.
! 307: */
! 308: if (boothowto & RB_CONFIG) {
! 309: #ifdef BOOT_CONFIG
! 310: user_config();
! 311: #else
! 312: printf("kernel does not support -c; continuing..\n");
! 313: #endif
! 314: }
! 315: }
! 316:
! 317: /*
! 318: * Allocate space for system data structures. We are given
! 319: * a starting virtual address and we return a final virtual
! 320: * address; along the way we set each data structure pointer.
! 321: *
! 322: * We call allocsys() with 0 to find out how much space we want,
! 323: * allocate that much and fill it with zeroes, and then call
! 324: * allocsys() again with the correct base virtual address.
! 325: */
! 326: caddr_t
! 327: allocsys(v)
! 328: caddr_t v;
! 329: {
! 330:
! 331: #define valloc(name, type, num) \
! 332: v = (caddr_t)(((name) = (type *)v) + (num))
! 333:
! 334: #ifdef SYSVMSG
! 335: valloc(msgpool, char, msginfo.msgmax);
! 336: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 337: valloc(msghdrs, struct msg, msginfo.msgtql);
! 338: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 339: #endif
! 340:
! 341: return v;
! 342: }
! 343:
! 344: __dead void
! 345: doboot()
! 346: {
! 347: printf("Rebooting system...\n\n");
! 348: cmmu_shutdown();
! 349: scm_reboot(NULL);
! 350: /*NOTREACHED*/
! 351: for (;;); /* appease gcc */
! 352: }
! 353:
! 354: __dead void
! 355: boot(howto)
! 356: int howto;
! 357: {
! 358: /* take a snapshot before clobbering any registers */
! 359: if (curproc && curproc->p_addr)
! 360: savectx(curpcb);
! 361:
! 362: /* If system is cold, just halt. */
! 363: if (cold) {
! 364: /* (Unless the user explicitly asked for reboot.) */
! 365: if ((howto & RB_USERREQ) == 0)
! 366: howto |= RB_HALT;
! 367: goto haltsys;
! 368: }
! 369:
! 370: boothowto = howto;
! 371: if ((howto & RB_NOSYNC) == 0) {
! 372: vfs_shutdown();
! 373: /*
! 374: * If we've been adjusting the clock, the todr
! 375: * will be out of synch; adjust it now unless
! 376: * the system was sitting in ddb.
! 377: */
! 378: if ((howto & RB_TIMEBAD) == 0)
! 379: resettodr();
! 380: else
! 381: printf("WARNING: not updating battery clock\n");
! 382: }
! 383:
! 384: /* Disable interrupts. */
! 385: splhigh();
! 386:
! 387: /* If rebooting and a dump is requested, do it. */
! 388: if (howto & RB_DUMP)
! 389: dumpsys();
! 390:
! 391: haltsys:
! 392: /* Run any shutdown hooks. */
! 393: doshutdownhooks();
! 394:
! 395: if (howto & RB_HALT) {
! 396: printf("System halted.\n\n");
! 397: cmmu_shutdown();
! 398: scm_halt();
! 399: }
! 400:
! 401: doboot();
! 402:
! 403: for (;;);
! 404: /*NOTREACHED*/
! 405: }
! 406:
! 407: unsigned dumpmag = 0x8fca0101; /* magic number for savecore */
! 408: int dumpsize = 0; /* also for savecore */
! 409: long dumplo = 0;
! 410: cpu_kcore_hdr_t cpu_kcore_hdr;
! 411:
! 412: /*
! 413: * This is called by configure to set dumplo and dumpsize.
! 414: * Dumps always skip the first PAGE_SIZE of disk space
! 415: * in case there might be a disk label stored there.
! 416: * If there is extra space, put dump at the end to
! 417: * reduce the chance that swapping trashes it.
! 418: */
! 419: void
! 420: dumpconf(void)
! 421: {
! 422: int nblks; /* size of dump area */
! 423:
! 424: if (dumpdev == NODEV ||
! 425: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
! 426: return;
! 427: if (nblks <= ctod(1))
! 428: return;
! 429:
! 430: dumpsize = physmem;
! 431:
! 432: /* aviion only uses a single segment. */
! 433: cpu_kcore_hdr.ram_segs[0].start = 0;
! 434: cpu_kcore_hdr.ram_segs[0].size = ctob(physmem);
! 435: cpu_kcore_hdr.cputype = cputyp;
! 436:
! 437: /*
! 438: * Don't dump on the first block
! 439: * in case the dump device includes a disk label.
! 440: */
! 441: if (dumplo < ctod(1))
! 442: dumplo = ctod(1);
! 443:
! 444: /* Put dump at end of partition, and make it fit. */
! 445: if (dumpsize + 1 > dtoc(nblks - dumplo))
! 446: dumpsize = dtoc(nblks - dumplo) - 1;
! 447: if (dumplo < nblks - ctod(dumpsize) - 1)
! 448: dumplo = nblks - ctod(dumpsize) - 1;
! 449: }
! 450:
! 451: /*
! 452: * Doadump comes here after turning off memory management and
! 453: * getting on the dump stack, either when called above, or by
! 454: * the auto-restart code.
! 455: */
! 456: void
! 457: dumpsys()
! 458: {
! 459: int maj;
! 460: int psize;
! 461: daddr64_t blkno; /* current block to write */
! 462: /* dump routine */
! 463: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 464: int pg; /* page being dumped */
! 465: paddr_t maddr; /* PA being dumped */
! 466: int error; /* error code from (*dump)() */
! 467: kcore_seg_t *kseg_p;
! 468: cpu_kcore_hdr_t *chdr_p;
! 469: char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
! 470:
! 471: extern int msgbufmapped;
! 472:
! 473: msgbufmapped = 0;
! 474:
! 475: /* Make sure dump device is valid. */
! 476: if (dumpdev == NODEV)
! 477: return;
! 478: if (dumpsize == 0) {
! 479: dumpconf();
! 480: if (dumpsize == 0)
! 481: return;
! 482: }
! 483: maj = major(dumpdev);
! 484: if (dumplo < 0) {
! 485: printf("\ndump to dev %u,%u not possible\n", maj,
! 486: minor(dumpdev));
! 487: return;
! 488: }
! 489: dump = bdevsw[maj].d_dump;
! 490: blkno = dumplo;
! 491:
! 492: printf("\ndumping to dev %u,%u offset %ld\n", maj,
! 493: minor(dumpdev), dumplo);
! 494:
! 495: /* Setup the dump header */
! 496: kseg_p = (kcore_seg_t *)dump_hdr;
! 497: chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
! 498: bzero(dump_hdr, sizeof(dump_hdr));
! 499:
! 500: CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
! 501: kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
! 502: *chdr_p = cpu_kcore_hdr;
! 503:
! 504: printf("dump ");
! 505: psize = (*bdevsw[maj].d_psize)(dumpdev);
! 506: if (psize == -1) {
! 507: printf("area unavailable\n");
! 508: return;
! 509: }
! 510:
! 511: /* Dump the header. */
! 512: error = (*dump)(dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
! 513: if (error != 0)
! 514: goto abort;
! 515:
! 516: maddr = (paddr_t)0;
! 517: for (pg = 0; pg < dumpsize; pg++) {
! 518: #define NPGMB (1024 * 1024 / PAGE_SIZE)
! 519: /* print out how many MBs we have dumped */
! 520: if (pg != 0 && (pg % NPGMB) == 0)
! 521: printf("%d ", pg / NPGMB);
! 522: #undef NPGMB
! 523: pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
! 524: VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
! 525:
! 526: error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
! 527: if (error == 0) {
! 528: maddr += PAGE_SIZE;
! 529: blkno += btodb(PAGE_SIZE);
! 530: } else
! 531: break;
! 532: }
! 533: abort:
! 534: switch (error) {
! 535: case 0:
! 536: printf("succeeded\n");
! 537: break;
! 538:
! 539: case ENXIO:
! 540: printf("device bad\n");
! 541: break;
! 542:
! 543: case EFAULT:
! 544: printf("device not ready\n");
! 545: break;
! 546:
! 547: case EINVAL:
! 548: printf("area improper\n");
! 549: break;
! 550:
! 551: case EIO:
! 552: printf("i/o error\n");
! 553: break;
! 554:
! 555: case EINTR:
! 556: printf("aborted from console\n");
! 557: break;
! 558:
! 559: default:
! 560: printf("error %d\n", error);
! 561: break;
! 562: }
! 563: }
! 564:
! 565: #ifdef MULTIPROCESSOR
! 566:
! 567: /*
! 568: * Secondary CPU early initialization routine.
! 569: * Determine CPU number and set it, then allocate the idle pcb (and stack).
! 570: *
! 571: * Running on a minimal stack here, with interrupts disabled; do nothing fancy.
! 572: */
! 573: void
! 574: secondary_pre_main()
! 575: {
! 576: struct cpu_info *ci;
! 577:
! 578: set_cpu_number(cmmu_cpu_number()); /* Determine cpu number by CMMU */
! 579: ci = curcpu();
! 580: ci->ci_curproc = &proc0;
! 581:
! 582: splhigh();
! 583:
! 584: /*
! 585: * Setup CMMUs and translation tables (shared with the master cpu).
! 586: */
! 587: pmap_bootstrap_cpu(ci->ci_cpuid);
! 588:
! 589: /*
! 590: * Allocate UPAGES contiguous pages for the idle PCB and stack.
! 591: */
! 592: ci->ci_idle_pcb = (struct pcb *)uvm_km_zalloc(kernel_map, USPACE);
! 593: if (ci->ci_idle_pcb == NULL) {
! 594: printf("cpu%d: unable to allocate idle stack\n", ci->ci_cpuid);
! 595: }
! 596: }
! 597:
! 598: /*
! 599: * Further secondary CPU initialization.
! 600: *
! 601: * We are now running on our idle stack, with proper page tables.
! 602: * There is nothing to do but display some details about the CPU and its CMMUs.
! 603: */
! 604: void
! 605: secondary_main()
! 606: {
! 607: struct cpu_info *ci = curcpu();
! 608:
! 609: cpu_configuration_print(0);
! 610: ncpus++;
! 611: __cpu_simple_unlock(&cpu_mutex);
! 612:
! 613: microuptime(&ci->ci_schedstate.spc_runtime);
! 614: ci->ci_curproc = NULL;
! 615:
! 616: /*
! 617: * Upon return, the secondary cpu bootstrap code in locore will
! 618: * enter the idle loop, waiting for some food to process on this
! 619: * processor.
! 620: */
! 621: }
! 622:
! 623: #endif /* MULTIPROCESSOR */
! 624:
! 625: /*
! 626: * Try to insert ihand in the list of handlers for vector vec.
! 627: */
! 628: int
! 629: intr_establish(int vec, struct intrhand *ihand, const char *name)
! 630: {
! 631: struct intrhand *intr;
! 632: intrhand_t *list;
! 633:
! 634: if (vec < 0 || vec >= NVMEINTR) {
! 635: #ifdef DIAGNOSTIC
! 636: printf("intr_establish: vec (0x%x) not between 0x00 and 0xff\n",
! 637: vec);
! 638: #endif /* DIAGNOSTIC */
! 639: return (EINVAL);
! 640: }
! 641:
! 642: list = &intr_handlers[vec];
! 643: if (!SLIST_EMPTY(list)) {
! 644: intr = SLIST_FIRST(list);
! 645: if (intr->ih_ipl != ihand->ih_ipl) {
! 646: #ifdef DIAGNOSTIC
! 647: printf("intr_establish: there are other handlers with "
! 648: "vec (0x%x) at ipl %x, but you want it at %x\n",
! 649: vec, intr->ih_ipl, ihand->ih_ipl);
! 650: #endif /* DIAGNOSTIC */
! 651: return (EINVAL);
! 652: }
! 653: }
! 654:
! 655: evcount_attach(&ihand->ih_count, name, (void *)&ihand->ih_ipl,
! 656: &evcount_intr);
! 657: SLIST_INSERT_HEAD(list, ihand, ih_link);
! 658: return (0);
! 659: }
! 660:
! 661: void
! 662: nmihand(void *frame)
! 663: {
! 664: #ifdef DDB
! 665: printf("Abort switch pressed\n");
! 666: if (db_console) {
! 667: /*
! 668: * We can't use Debugger() here, as we are coming from an
! 669: * exception, and can't assume anything on the state we are
! 670: * in. Invoke the post-trap ddb entry directly.
! 671: */
! 672: extern void m88k_db_trap(int, struct trapframe *);
! 673: m88k_db_trap(T_KDB_ENTRY, (struct trapframe *)frame);
! 674: }
! 675: #endif
! 676: }
! 677:
! 678: int
! 679: cpu_exec_aout_makecmds(p, epp)
! 680: struct proc *p;
! 681: struct exec_package *epp;
! 682: {
! 683:
! 684: return (ENOEXEC);
! 685: }
! 686:
! 687: int
! 688: sys_sysarch(p, v, retval)
! 689: struct proc *p;
! 690: void *v;
! 691: register_t *retval;
! 692: {
! 693: #if 0
! 694: struct sys_sysarch_args /* {
! 695: syscallarg(int) op;
! 696: syscallarg(char *) parm;
! 697: } */ *uap = v;
! 698: #endif
! 699:
! 700: return (ENOSYS);
! 701: }
! 702:
! 703: /*
! 704: * machine dependent system variables.
! 705: */
! 706:
! 707: int
! 708: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 709: int *name;
! 710: u_int namelen;
! 711: void *oldp;
! 712: size_t *oldlenp;
! 713: void *newp;
! 714: size_t newlen;
! 715: struct proc *p;
! 716: {
! 717: dev_t consdev;
! 718:
! 719: /* all sysctl names are this level are terminal */
! 720: if (namelen != 1)
! 721: return (ENOTDIR); /* overloaded */
! 722:
! 723: switch (name[0]) {
! 724: case CPU_CONSDEV:
! 725: if (cn_tab != NULL)
! 726: consdev = cn_tab->cn_dev;
! 727: else
! 728: consdev = NODEV;
! 729: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
! 730: sizeof consdev));
! 731: default:
! 732: return (EOPNOTSUPP);
! 733: }
! 734: /*NOTREACHED*/
! 735: }
! 736:
! 737: /*
! 738: * Called from locore.S during boot,
! 739: * this is the first C code that's run.
! 740: */
! 741: void
! 742: aviion_bootstrap()
! 743: {
! 744: extern int kernelstart;
! 745: extern char *end;
! 746: #ifndef MULTIPROCESSOR
! 747: cpuid_t master_cpu;
! 748: #endif
! 749:
! 750: /* Save a copy of our commandline before it gets overwritten. */
! 751: strlcpy(bootargs, prom_bootargs, sizeof bootargs);
! 752:
! 753: avtyp = aviion_identify();
! 754:
! 755: /* Set up interrupt and fp exception handlers based on the machine. */
! 756: switch (avtyp) {
! 757: #ifdef AV400
! 758: case AV_400:
! 759: platform = &board_av400;
! 760: break;
! 761: #endif
! 762: #ifdef AV530
! 763: case AV_530:
! 764: platform = &board_av530;
! 765: break;
! 766: #endif
! 767: #ifdef AV5000
! 768: case AV_5000:
! 769: platform = &board_av5000;
! 770: break;
! 771: #endif
! 772: #ifdef AV6280
! 773: case AV_6280:
! 774: platform = &board_av6280;
! 775: break;
! 776: #endif
! 777: default:
! 778: scm_printf("Sorry, OpenBSD/" MACHINE
! 779: " does not support this model.\n");
! 780: scm_halt();
! 781: break;
! 782: };
! 783:
! 784: cn_tab = &bootcons;
! 785: /* we can use printf() from here. */
! 786:
! 787: platform->bootstrap();
! 788:
! 789: /* Parse the commandline */
! 790: cmdline_parse();
! 791:
! 792: uvmexp.pagesize = PAGE_SIZE;
! 793: uvm_setpagesize();
! 794:
! 795: #if defined(DDB) || NKSYMS > 0
! 796: if (esym != 0)
! 797: first_addr = esym;
! 798: else
! 799: #endif
! 800: first_addr = (vaddr_t)&end;
! 801: first_addr = round_page(first_addr);
! 802:
! 803: last_addr = platform->memsize();
! 804: physmem = btoc(last_addr);
! 805:
! 806: setup_board_config();
! 807: master_cpu = cmmu_init();
! 808: set_cpu_number(master_cpu);
! 809:
! 810: /*
! 811: * Now that set_cpu_number() set us with a valid cpu_info pointer,
! 812: * we need to initialize p_addr and curpcb before autoconf, for the
! 813: * fault handler to behave properly [except for badaddr() faults,
! 814: * which can be taken care of without a valid curcpu()].
! 815: */
! 816: proc0.p_addr = proc0paddr;
! 817: curproc = &proc0;
! 818: curpcb = &proc0paddr->u_pcb;
! 819:
! 820: avail_start = round_page(first_addr);
! 821: avail_end = last_addr;
! 822:
! 823: /* Steal MSGBUFSIZE at the top of physical memory for msgbuf. */
! 824: avail_end -= round_page(MSGBUFSIZE);
! 825: pmap_bootstrap((vaddr_t)trunc_page((unsigned)&kernelstart));
! 826:
! 827: /*
! 828: * Tell the VM system about available physical memory.
! 829: * The aviion systems only have one contiguous area.
! 830: *
! 831: * XXX However, on series 5000, SRAM overlaps a low memory range,
! 832: * XXX so we will need to upload two ranges of pages on them.
! 833: */
! 834: uvm_page_physload(atop(avail_start), atop(avail_end),
! 835: atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
! 836:
! 837: /* Initialize the "u-area" pages. */
! 838: bzero((caddr_t)curpcb, USPACE);
! 839: }
! 840:
! 841: #ifdef MULTIPROCESSOR
! 842: void
! 843: cpu_boot_secondary_processors()
! 844: {
! 845: cpuid_t cpu;
! 846: int rc;
! 847: extern void secondary_start(void);
! 848:
! 849: for (cpu = 0; cpu < max_cpus; cpu++) {
! 850: if (cpu != curcpu()->ci_cpuid) {
! 851: rc = scm_spincpu(cpu, (vaddr_t)secondary_start);
! 852: if (rc != 0)
! 853: printf("cpu%d: spin_cpu error %d\n", cpu, rc);
! 854: }
! 855: }
! 856: }
! 857: #endif
! 858:
! 859: /*
! 860: * Boot console routines:
! 861: * Enables printing of boot messages before consinit().
! 862: */
! 863: void
! 864: bootcnprobe(cp)
! 865: struct consdev *cp;
! 866: {
! 867: cp->cn_dev = makedev(0, 0);
! 868: cp->cn_pri = CN_NORMAL;
! 869: }
! 870:
! 871: void
! 872: bootcninit(cp)
! 873: struct consdev *cp;
! 874: {
! 875: /* Nothing to do */
! 876: }
! 877:
! 878: int
! 879: bootcngetc(dev)
! 880: dev_t dev;
! 881: {
! 882: return (scm_getc());
! 883: }
! 884:
! 885: void
! 886: bootcnputc(dev, c)
! 887: dev_t dev;
! 888: int c;
! 889: {
! 890: if (c == '\n')
! 891: scm_putcrlf();
! 892: else
! 893: scm_putc(c);
! 894: }
! 895:
! 896: u_int
! 897: getipl(void)
! 898: {
! 899: u_int curspl, psr;
! 900:
! 901: disable_interrupt(psr);
! 902: curspl = platform->getipl();
! 903: set_psr(psr);
! 904: return curspl;
! 905: }
! 906:
! 907: u_int
! 908: setipl(u_int level)
! 909: {
! 910: u_int curspl, psr;
! 911:
! 912: disable_interrupt(psr);
! 913: curspl = platform->setipl(level);
! 914:
! 915: /*
! 916: * The flush pipeline is required to make sure the above change gets
! 917: * through the data pipe and to the hardware; otherwise, the next
! 918: * bunch of instructions could execute at the wrong spl protection.
! 919: */
! 920: flush_pipeline();
! 921:
! 922: set_psr(psr);
! 923: return curspl;
! 924: }
! 925:
! 926: u_int
! 927: raiseipl(u_int level)
! 928: {
! 929: u_int curspl, psr;
! 930:
! 931: disable_interrupt(psr);
! 932: curspl = platform->raiseipl(level);
! 933:
! 934: /*
! 935: * The flush pipeline is required to make sure the above change gets
! 936: * through the data pipe and to the hardware; otherwise, the next
! 937: * bunch of instructions could execute at the wrong spl protection.
! 938: */
! 939: flush_pipeline();
! 940:
! 941: set_psr(psr);
! 942: return curspl;
! 943: }
! 944:
! 945: u_char hostaddr[6];
! 946:
! 947: void
! 948: myetheraddr(u_char *cp)
! 949: {
! 950: bcopy(hostaddr, cp, 6);
! 951: }
! 952:
! 953: /*
! 954: * Attempt to identify which AViiON flavour we are running on.
! 955: * The only thing we can do at this point is peek at random addresses and
! 956: * see if they cause bus errors, or not.
! 957: *
! 958: * These heuristics are probably not the best; feel free to come with better
! 959: * ones...
! 960: */
! 961: int
! 962: aviion_identify()
! 963: {
! 964: /*
! 965: * We don't know anything about 88110-based models.
! 966: * Note that we can't use CPU_IS81x0 here since these are optimized
! 967: * if the kernel you're running is compiled for only one processor
! 968: * type, and we want to check against the real hardware.
! 969: */
! 970: if (cputyp == CPU_88110)
! 971: return (0);
! 972:
! 973: /*
! 974: * Series 100/200/300/400/3000/4000/4300 do not have the VIRQLV
! 975: * register at 0xfff85000.
! 976: */
! 977: if (badaddr(0xfff85000, 4) != 0)
! 978: return (AV_400);
! 979:
! 980: /*
! 981: * Series 5000 and 6000 do not have an RTC counter at 0xfff8f084.
! 982: */
! 983: if (badaddr(0xfff8f084, 4) != 0)
! 984: return (AV_5000);
! 985:
! 986: /*
! 987: * Series 4600/530 have IOFUSEs at 0xfffb0040 and 0xfffb00c0.
! 988: */
! 989: if (badaddr(0xfffb0040, 1) == 0 && badaddr(0xfffb00c0, 1) == 0)
! 990: return (AV_530);
! 991:
! 992: /*
! 993: * Series 6280/8000-8 fall here.
! 994: */
! 995: return (AV_6280);
! 996: }
CVSweb