Annotation of sys/arch/luna88k/luna88k/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.44 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: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 46: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
! 47: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 48: *
! 49: * Carnegie Mellon requests users of this software to return to
! 50: *
! 51: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 52: * School of Computer Science
! 53: * Carnegie Mellon University
! 54: * Pittsburgh PA 15213-3890
! 55: *
! 56: * any improvements or extensions that they make and grant Carnegie the
! 57: * rights to redistribute these changes.
! 58: */
! 59:
! 60: #include <sys/param.h>
! 61: #include <sys/systm.h>
! 62: #include <sys/kernel.h>
! 63: #include <sys/proc.h>
! 64: #include <sys/user.h>
! 65: #include <sys/buf.h>
! 66: #include <sys/reboot.h>
! 67: #include <sys/conf.h>
! 68: #include <sys/malloc.h>
! 69: #include <sys/mount.h>
! 70: #include <sys/msgbuf.h>
! 71: #include <sys/syscallargs.h>
! 72: #ifdef SYSVMSG
! 73: #include <sys/msg.h>
! 74: #endif
! 75: #include <sys/exec.h>
! 76: #include <sys/sysctl.h>
! 77: #include <sys/errno.h>
! 78: #include <sys/extent.h>
! 79: #include <sys/core.h>
! 80: #include <sys/kcore.h>
! 81:
! 82: #include <machine/asm.h>
! 83: #include <machine/asm_macro.h>
! 84: #include <machine/board.h>
! 85: #include <machine/cmmu.h>
! 86: #include <machine/cpu.h>
! 87: #include <machine/kcore.h>
! 88: #include <machine/reg.h>
! 89: #include <machine/trap.h>
! 90: #include <machine/m88100.h>
! 91:
! 92: #include <luna88k/luna88k/isr.h>
! 93:
! 94: #include <dev/cons.h>
! 95:
! 96: #include <uvm/uvm_extern.h>
! 97:
! 98: #include "ksyms.h"
! 99: #if DDB
! 100: #include <machine/db_machdep.h>
! 101: #include <ddb/db_extern.h>
! 102: #include <ddb/db_interface.h>
! 103: #include <ddb/db_output.h> /* db_printf() */
! 104: #endif /* DDB */
! 105:
! 106: caddr_t allocsys(caddr_t);
! 107: void consinit(void);
! 108: void dumpconf(void);
! 109: void dumpsys(void);
! 110: int getcpuspeed(void);
! 111: u_int getipl(void);
! 112: void identifycpu(void);
! 113: void luna88k_bootstrap(void);
! 114: void savectx(struct pcb *);
! 115: void secondary_main(void);
! 116: void secondary_pre_main(void);
! 117: void setlevel(unsigned int);
! 118:
! 119: vaddr_t size_memory(void);
! 120: void powerdown(void);
! 121: void get_fuse_rom_data(void);
! 122: void get_nvram_data(void);
! 123: char *nvram_by_symbol(char *);
! 124: void get_autoboot_device(void); /* in disksubr.c */
! 125: int clockintr(void *); /* in clock.c */
! 126:
! 127: /*
! 128: * *int_mask_reg[CPU]
! 129: * Points to the hardware interrupt status register for each CPU.
! 130: */
! 131: unsigned int *volatile int_mask_reg[] = {
! 132: (unsigned int *)INT_ST_MASK0,
! 133: (unsigned int *)INT_ST_MASK1,
! 134: (unsigned int *)INT_ST_MASK2,
! 135: (unsigned int *)INT_ST_MASK3
! 136: };
! 137:
! 138: unsigned int luna88k_curspl[] = {0, 0, 0, 0};
! 139:
! 140: unsigned int int_set_val[INT_LEVEL] = {
! 141: INT_SET_LV0,
! 142: INT_SET_LV1,
! 143: INT_SET_LV2,
! 144: INT_SET_LV3,
! 145: INT_SET_LV4,
! 146: INT_SET_LV5,
! 147: INT_SET_LV6,
! 148: INT_SET_LV7
! 149: };
! 150:
! 151: /*
! 152: * *clock_reg[CPU]
! 153: */
! 154: unsigned int *volatile clock_reg[] = {
! 155: (unsigned int *)OBIO_CLOCK0,
! 156: (unsigned int *)OBIO_CLOCK1,
! 157: (unsigned int *)OBIO_CLOCK2,
! 158: (unsigned int *)OBIO_CLOCK3
! 159: };
! 160:
! 161: /*
! 162: * FUSE ROM and NVRAM data
! 163: */
! 164: struct fuse_rom_byte {
! 165: u_int32_t h;
! 166: u_int32_t l;
! 167: };
! 168: #define FUSE_ROM_BYTES (FUSE_ROM_SPACE / sizeof(struct fuse_rom_byte))
! 169: char fuse_rom_data[FUSE_ROM_BYTES];
! 170:
! 171: #define NNVSYM 8
! 172: #define NVSYMLEN 16
! 173: #define NVVALLEN 16
! 174: struct nvram_t {
! 175: char symbol[NVSYMLEN];
! 176: char value[NVVALLEN];
! 177: } nvram[NNVSYM];
! 178:
! 179: vaddr_t obiova;
! 180:
! 181: int physmem; /* available physical memory, in pages */
! 182:
! 183: struct vm_map *exec_map = NULL;
! 184: struct vm_map *phys_map = NULL;
! 185:
! 186: /*
! 187: * Declare these as initialized data so we can patch them.
! 188: */
! 189: #ifndef BUFCACHEPERCENT
! 190: #define BUFCACHEPERCENT 5
! 191: #endif
! 192:
! 193: #ifdef BUFPAGES
! 194: int bufpages = BUFPAGES;
! 195: #else
! 196: int bufpages = 0;
! 197: #endif
! 198: int bufcachepercent = BUFCACHEPERCENT;
! 199:
! 200: /*
! 201: * Info for CTL_HW
! 202: */
! 203: char machine[] = MACHINE; /* cpu "architecture" */
! 204: char cpu_model[120];
! 205:
! 206: #if defined(DDB) || NKSYMS > 0
! 207: extern char *esym;
! 208: #endif
! 209:
! 210: int machtype = LUNA_88K; /* may be overwritten in cpu_startup() */
! 211: int cputyp = CPU_88100; /* XXX: aoyama */
! 212: int boothowto; /* XXX: should be set in boot loader and locore.S */
! 213: int bootdev; /* XXX: should be set in boot loader and locore.S */
! 214: int cpuspeed = 33; /* safe guess */
! 215: int sysconsole = 1; /* 0 = ttya, 1 = keyboard/mouse, used in dev/sio.c */
! 216: u_int16_t dipswitch = 0; /* set in locore.S */
! 217: int hwplanebits; /* set in locore.S */
! 218:
! 219: extern struct consdev syscons; /* in dev/siotty.c */
! 220:
! 221: extern void syscnattach(int); /* in dev/siotty.c */
! 222: extern int omfb_cnattach(void); /* in dev/lunafb.c */
! 223: extern void ws_cnattach(void); /* in dev/lunaws.c */
! 224:
! 225: vaddr_t first_addr;
! 226: vaddr_t last_addr;
! 227:
! 228: vaddr_t avail_start, avail_end;
! 229: vaddr_t virtual_avail, virtual_end;
! 230:
! 231: extern struct user *proc0paddr;
! 232:
! 233: /*
! 234: * This is to fake out the console routines, while booting.
! 235: * We could use directly the romtty console, but we want to be able to
! 236: * configure a kernel without romtty since we do not necessarily need a
! 237: * full-blown console driver.
! 238: */
! 239: cons_decl(romtty);
! 240: extern void nullcnpollc(dev_t, int);
! 241:
! 242: struct consdev romttycons = {
! 243: NULL,
! 244: NULL,
! 245: romttycngetc,
! 246: romttycnputc,
! 247: nullcnpollc,
! 248: NULL,
! 249: makedev(14, 0),
! 250: CN_NORMAL,
! 251: };
! 252:
! 253: /*
! 254: * Early console initialization: called early on from main, before vm init.
! 255: */
! 256: void
! 257: consinit()
! 258: {
! 259: /*
! 260: * Initialize the console before we print anything out.
! 261: */
! 262: if (sysconsole == 0) {
! 263: syscnattach(0);
! 264: } else {
! 265: omfb_cnattach();
! 266: ws_cnattach();
! 267: }
! 268:
! 269: #if defined(DDB)
! 270: db_machine_init();
! 271: ddb_init();
! 272: if (boothowto & RB_KDB)
! 273: Debugger();
! 274: #endif
! 275: }
! 276:
! 277: /*
! 278: * Figure out how much real memory is available.
! 279: * Start looking from the megabyte after the end of the kernel data,
! 280: * until we find non-memory.
! 281: */
! 282: vaddr_t
! 283: size_memory()
! 284: {
! 285: unsigned int *volatile look;
! 286: unsigned int *max;
! 287: #if 0
! 288: extern char *end;
! 289: #endif
! 290: #define PATTERN 0x5a5a5a5a
! 291: #define STRIDE (4*1024) /* 4k at a time */
! 292: #define Roundup(value, stride) (((unsigned)(value) + (stride) - 1) & ~((stride)-1))
! 293: /*
! 294: * count it up.
! 295: */
! 296: max = (void *)MAXPHYSMEM;
! 297: #if 0
! 298: for (look = (void *)Roundup(end, STRIDE); look < max;
! 299: #else
! 300: for (look = (void *)first_addr; look < max;
! 301: #endif
! 302: look = (int *)((unsigned)look + STRIDE)) {
! 303: unsigned save;
! 304:
! 305: /* if can't access, we've reached the end */
! 306: if (badaddr((vaddr_t)look, 4)) {
! 307: #if defined(DEBUG)
! 308: printf("%x\n", look);
! 309: #endif
! 310: look = (int *)((int)look - STRIDE);
! 311: break;
! 312: }
! 313:
! 314: /*
! 315: * If we write a value, we expect to read the same value back.
! 316: * We'll do this twice, the 2nd time with the opposite bit
! 317: * pattern from the first, to make sure we check all bits.
! 318: */
! 319: save = *look;
! 320: if (*look = PATTERN, *look != PATTERN)
! 321: break;
! 322: if (*look = ~PATTERN, *look != ~PATTERN)
! 323: break;
! 324: *look = save;
! 325: }
! 326:
! 327: return (trunc_page((unsigned)look));
! 328: }
! 329:
! 330: int
! 331: getcpuspeed()
! 332: {
! 333: switch(machtype) {
! 334: case LUNA_88K:
! 335: return 25;
! 336: case LUNA_88K2:
! 337: return 33;
! 338: default:
! 339: panic("getcpuspeed: can not determine CPU speed");
! 340: }
! 341: }
! 342:
! 343: void
! 344: identifycpu()
! 345: {
! 346: cpuspeed = getcpuspeed();
! 347: snprintf(cpu_model, sizeof cpu_model,
! 348: "OMRON LUNA-88K%s, %dMHz",
! 349: machtype == LUNA_88K2 ? "2" : "", cpuspeed);
! 350: }
! 351:
! 352: void
! 353: cpu_startup()
! 354: {
! 355: caddr_t v;
! 356: int sz, i;
! 357: vaddr_t minaddr, maxaddr;
! 358:
! 359: /*
! 360: * Initialize error message buffer (at end of core).
! 361: * avail_end was pre-decremented in luna88k_bootstrap() to compensate.
! 362: */
! 363: for (i = 0; i < btoc(MSGBUFSIZE); i++)
! 364: pmap_kenter_pa((paddr_t)msgbufp + i * PAGE_SIZE,
! 365: avail_end + i * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE);
! 366: pmap_update(pmap_kernel());
! 367: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
! 368:
! 369: /* Determine the machine type from FUSE ROM data. */
! 370: get_fuse_rom_data();
! 371: if (strncmp(fuse_rom_data, "MNAME=LUNA88K+", 14) == 0) {
! 372: machtype = LUNA_88K2;
! 373: }
! 374:
! 375: /* Determine the 'auto-boot' device from NVRAM data */
! 376: get_nvram_data();
! 377: get_autoboot_device();
! 378:
! 379: /*
! 380: * Good {morning,afternoon,evening,night}.
! 381: */
! 382: printf(version);
! 383: identifycpu();
! 384: printf("real mem = %d\n", ctob(physmem));
! 385:
! 386: /*
! 387: * Check front DIP switch setting
! 388: */
! 389: #ifdef DEBUG
! 390: printf("dipsw = 0x%x\n", dipswitch);
! 391: #endif
! 392:
! 393: /* Check DIP switch 1 - 1 */
! 394: if ((0x8000 & dipswitch) == 0) {
! 395: boothowto |= RB_SINGLE;
! 396: }
! 397:
! 398: /* Check DIP switch 1 - 3 */
! 399: if ((0x2000 & dipswitch) == 0) {
! 400: boothowto |= RB_ASKNAME;
! 401: }
! 402:
! 403: /* Check DIP switch 1 - 4 */
! 404: if ((0x1000 & dipswitch) == 0) {
! 405: boothowto |= RB_CONFIG;
! 406: }
! 407:
! 408: /*
! 409: * Check frame buffer depth.
! 410: */
! 411: switch (hwplanebits) {
! 412: case 0: /* No frame buffer */
! 413: case 1:
! 414: case 4:
! 415: case 8:
! 416: break;
! 417: default:
! 418: printf("unexpected frame buffer depth = %d\n", hwplanebits);
! 419: hwplanebits = 0;
! 420: break;
! 421: }
! 422:
! 423: #if 0 /* just for test */
! 424: /*
! 425: * Get boot arguments
! 426: */
! 427: {
! 428: char buf[256];
! 429: char **p = (volatile char **)0x00001120;
! 430:
! 431: strncpy(buf, *p, 256);
! 432: if (buf[255] != '\0')
! 433: buf[255] = '\0';
! 434:
! 435: printf("boot arg: (0x%x) %s\n", *p, buf);
! 436: }
! 437: #endif
! 438:
! 439: /*
! 440: * Find out how much space we need, allocate it,
! 441: * and then give everything true virtual addresses.
! 442: */
! 443: sz = (int)allocsys((caddr_t)0);
! 444:
! 445: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
! 446: panic("startup: no room for tables");
! 447: if (allocsys(v) - v != sz)
! 448: panic("startup: table size inconsistency");
! 449:
! 450: /*
! 451: * Grab the OBIO space that we hardwired in pmap_bootstrap
! 452: */
! 453: obiova = OBIO_START;
! 454: uvm_map(kernel_map, (vaddr_t *)&obiova, OBIO_SIZE,
! 455: NULL, UVM_UNKNOWN_OFFSET, 0,
! 456: UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
! 457: UVM_ADV_NORMAL, 0));
! 458: if (obiova != OBIO_START)
! 459: panic("obiova %lx: OBIO not free", obiova);
! 460:
! 461: /*
! 462: * Determine how many buffers to allocate.
! 463: * We allocate bufcachepercent% of memory for buffer space.
! 464: */
! 465: if (bufpages == 0)
! 466: bufpages = physmem * bufcachepercent / 100;
! 467:
! 468: /* Restrict to at most 25% filled kvm */
! 469: if (bufpages >
! 470: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 471: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 472: PAGE_SIZE / 4;
! 473:
! 474: /*
! 475: * Allocate a submap for exec arguments. This map effectively
! 476: * limits the number of processes exec'ing at any time.
! 477: */
! 478: minaddr = vm_map_min(kernel_map);
! 479: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 480: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 481:
! 482: /*
! 483: * Allocate map for physio.
! 484: */
! 485: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 486: VM_PHYS_SIZE, 0, FALSE, NULL);
! 487:
! 488: printf("avail mem = %ld (%d pages)\n", ptoa(uvmexp.free), uvmexp.free);
! 489:
! 490: /*
! 491: * Set up buffers, so they can be used to read disk labels.
! 492: */
! 493: bufinit();
! 494:
! 495: /*
! 496: * Initialize the autovectored interrupt list.
! 497: */
! 498: isrinit();
! 499:
! 500: /*
! 501: * Configure the system.
! 502: */
! 503: if (boothowto & RB_CONFIG) {
! 504: #ifdef BOOT_CONFIG
! 505: user_config();
! 506: #else
! 507: printf("kernel does not support -c; continuing..\n");
! 508: #endif
! 509: }
! 510: }
! 511:
! 512: /*
! 513: * Allocate space for system data structures. We are given
! 514: * a starting virtual address and we return a final virtual
! 515: * address; along the way we set each data structure pointer.
! 516: *
! 517: * We call allocsys() with 0 to find out how much space we want,
! 518: * allocate that much and fill it with zeroes, and then call
! 519: * allocsys() again with the correct base virtual address.
! 520: */
! 521: caddr_t
! 522: allocsys(v)
! 523: caddr_t v;
! 524: {
! 525:
! 526: #define valloc(name, type, num) \
! 527: v = (caddr_t)(((name) = (type *)v) + (num))
! 528:
! 529: #ifdef SYSVMSG
! 530: valloc(msgpool, char, msginfo.msgmax);
! 531: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 532: valloc(msghdrs, struct msg, msginfo.msgtql);
! 533: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 534: #endif
! 535:
! 536: return v;
! 537: }
! 538:
! 539: __dead void
! 540: boot(howto)
! 541: int howto;
! 542: {
! 543: /* take a snapshot before clobbering any registers */
! 544: if (curproc && curproc->p_addr)
! 545: savectx(curpcb);
! 546:
! 547: /* If system is cold, just halt. */
! 548: if (cold) {
! 549: /* (Unless the user explicitly asked for reboot.) */
! 550: if ((howto & RB_USERREQ) == 0)
! 551: howto |= RB_HALT;
! 552: goto haltsys;
! 553: }
! 554:
! 555: boothowto = howto;
! 556: if ((howto & RB_NOSYNC) == 0) {
! 557: vfs_shutdown();
! 558: /*
! 559: * If we've been adjusting the clock, the todr
! 560: * will be out of synch; adjust it now unless
! 561: * the system was sitting in ddb.
! 562: */
! 563: if ((howto & RB_TIMEBAD) == 0)
! 564: resettodr();
! 565: else
! 566: printf("WARNING: not updating battery clock\n");
! 567: }
! 568:
! 569: /* Disable interrupts. */
! 570: splhigh();
! 571:
! 572: /* If rebooting and a dump is requested, do it. */
! 573: if (howto & RB_DUMP)
! 574: dumpsys();
! 575:
! 576: haltsys:
! 577: /* Run any shutdown hooks. */
! 578: doshutdownhooks();
! 579:
! 580: /* Luna88k supports automatic powerdown */
! 581: if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
! 582: printf("attempting to power down...\n");
! 583: powerdown();
! 584: /* if failed, fall through. */
! 585: }
! 586:
! 587: if (howto & RB_HALT) {
! 588: printf("halted\n\n");
! 589: } else {
! 590: /* Reset all cpus, which causes reboot */
! 591: *((volatile unsigned *)0x6d000010) = 0;
! 592: }
! 593:
! 594: for (;;); /* to keep compiler happy, and me from going crazy */
! 595: /*NOTREACHED*/
! 596: }
! 597:
! 598: unsigned dumpmag = 0x8fca0101; /* magic number for savecore */
! 599: int dumpsize = 0; /* also for savecore */
! 600: long dumplo = 0;
! 601: cpu_kcore_hdr_t cpu_kcore_hdr;
! 602:
! 603: /*
! 604: * This is called by configure to set dumplo and dumpsize.
! 605: * Dumps always skip the first PAGE_SIZE of disk space
! 606: * in case there might be a disk label stored there.
! 607: * If there is extra space, put dump at the end to
! 608: * reduce the chance that swapping trashes it.
! 609: */
! 610: void
! 611: dumpconf(void)
! 612: {
! 613: int nblks; /* size of dump area */
! 614:
! 615: if (dumpdev == NODEV ||
! 616: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
! 617: return;
! 618: if (nblks <= ctod(1))
! 619: return;
! 620:
! 621: dumpsize = physmem;
! 622:
! 623: /* luna88k only uses a single segment. */
! 624: cpu_kcore_hdr.ram_segs[0].start = 0;
! 625: cpu_kcore_hdr.ram_segs[0].size = ctob(physmem);
! 626: cpu_kcore_hdr.cputype = cputyp;
! 627:
! 628: /*
! 629: * Don't dump on the first block
! 630: * in case the dump device includes a disk label.
! 631: */
! 632: if (dumplo < ctod(1))
! 633: dumplo = ctod(1);
! 634:
! 635: /* Put dump at end of partition, and make it fit. */
! 636: if (dumpsize + 1 > dtoc(nblks - dumplo))
! 637: dumpsize = dtoc(nblks - dumplo) - 1;
! 638: if (dumplo < nblks - ctod(dumpsize) - 1)
! 639: dumplo = nblks - ctod(dumpsize) - 1;
! 640: }
! 641:
! 642: /*
! 643: * Doadump comes here after turning off memory management and
! 644: * getting on the dump stack, either when called above, or by
! 645: * the auto-restart code.
! 646: */
! 647: void
! 648: dumpsys()
! 649: {
! 650: int maj;
! 651: int psize;
! 652: daddr64_t blkno; /* current block to write */
! 653: /* dump routine */
! 654: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 655: int pg; /* page being dumped */
! 656: paddr_t maddr; /* PA being dumped */
! 657: int error; /* error code from (*dump)() */
! 658: kcore_seg_t *kseg_p;
! 659: cpu_kcore_hdr_t *chdr_p;
! 660: char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
! 661:
! 662: extern int msgbufmapped;
! 663:
! 664: msgbufmapped = 0;
! 665:
! 666: /* Make sure dump device is valid. */
! 667: if (dumpdev == NODEV)
! 668: return;
! 669: if (dumpsize == 0) {
! 670: dumpconf();
! 671: if (dumpsize == 0)
! 672: return;
! 673: }
! 674: maj = major(dumpdev);
! 675: if (dumplo < 0) {
! 676: printf("\ndump to dev %u,%u not possible\n", maj,
! 677: minor(dumpdev));
! 678: return;
! 679: }
! 680: dump = bdevsw[maj].d_dump;
! 681: blkno = dumplo;
! 682:
! 683: printf("\ndumping to dev %u,%u offset %ld\n", maj,
! 684: minor(dumpdev), dumplo);
! 685:
! 686: /* Setup the dump header */
! 687: kseg_p = (kcore_seg_t *)dump_hdr;
! 688: chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
! 689: bzero(dump_hdr, sizeof(dump_hdr));
! 690:
! 691: CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
! 692: kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
! 693: *chdr_p = cpu_kcore_hdr;
! 694:
! 695: printf("dump ");
! 696: psize = (*bdevsw[maj].d_psize)(dumpdev);
! 697: if (psize == -1) {
! 698: printf("area unavailable\n");
! 699: return;
! 700: }
! 701:
! 702: /* Dump the header. */
! 703: error = (*dump)(dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
! 704: if (error != 0)
! 705: goto abort;
! 706:
! 707: maddr = (paddr_t)0;
! 708: for (pg = 0; pg < dumpsize; pg++) {
! 709: #define NPGMB (1024 * 1024 / PAGE_SIZE)
! 710: /* print out how many MBs we have dumped */
! 711: if (pg != 0 && (pg % NPGMB) == 0)
! 712: printf("%d ", pg / NPGMB);
! 713: #undef NPGMB
! 714: pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
! 715: VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
! 716:
! 717: error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
! 718: if (error == 0) {
! 719: maddr += PAGE_SIZE;
! 720: blkno += btodb(PAGE_SIZE);
! 721: } else
! 722: break;
! 723: }
! 724: abort:
! 725: switch (error) {
! 726: case 0:
! 727: printf("succeeded\n");
! 728: break;
! 729:
! 730: case ENXIO:
! 731: printf("device bad\n");
! 732: break;
! 733:
! 734: case EFAULT:
! 735: printf("device not ready\n");
! 736: break;
! 737:
! 738: case EINVAL:
! 739: printf("area improper\n");
! 740: break;
! 741:
! 742: case EIO:
! 743: printf("i/o error\n");
! 744: break;
! 745:
! 746: case EINTR:
! 747: printf("aborted from console\n");
! 748: break;
! 749:
! 750: default:
! 751: printf("error %d\n", error);
! 752: break;
! 753: }
! 754: }
! 755:
! 756: #ifdef MULTIPROCESSOR
! 757:
! 758: /*
! 759: * Secondary CPU early initialization routine.
! 760: * Determine CPU number and set it, then allocate the idle pcb (and stack).
! 761: *
! 762: * Running on a minimal stack here, with interrupts disabled; do nothing fancy.
! 763: */
! 764: void
! 765: secondary_pre_main()
! 766: {
! 767: struct cpu_info *ci;
! 768:
! 769: set_cpu_number(cmmu_cpu_number());
! 770: ci = curcpu();
! 771:
! 772: /*
! 773: * Setup CMMUs and translation tables (shared with the master cpu).
! 774: */
! 775: pmap_bootstrap_cpu(ci->ci_cpuid);
! 776:
! 777: /*
! 778: * Allocate UPAGES contiguous pages for the idle PCB and stack.
! 779: */
! 780: ci->ci_idle_pcb = (struct pcb *)uvm_km_zalloc(kernel_map, USPACE);
! 781: if (ci->ci_idle_pcb == NULL) {
! 782: printf("cpu%d: unable to allocate idle stack\n", ci->ci_cpuid);
! 783: }
! 784: }
! 785:
! 786: /*
! 787: * Further secondary CPU initialization.
! 788: *
! 789: * We are now running on our idle stack, with proper page tables.
! 790: * There is nothing to do but display some details about the CPU and its CMMUs.
! 791: */
! 792: void
! 793: secondary_main()
! 794: {
! 795: struct cpu_info *ci = curcpu();
! 796:
! 797: cpu_configuration_print(0);
! 798: ncpus++;
! 799:
! 800: microuptime(&ci->ci_schedstate.spc_runtime);
! 801:
! 802: /*
! 803: * Upon return, the secondary cpu bootstrap code in locore will
! 804: * enter the idle loop, waiting for some food to process on this
! 805: * processor.
! 806: */
! 807: }
! 808:
! 809: #endif /* MULTIPROCESSOR */
! 810:
! 811: /*
! 812: * Device interrupt handler for LUNA88K
! 813: */
! 814:
! 815: void
! 816: luna88k_ext_int(u_int v, struct trapframe *eframe)
! 817: {
! 818: int cpu = cpu_number();
! 819: unsigned int cur_mask, cur_int;
! 820: unsigned int level, old_spl;
! 821:
! 822: cur_mask = *int_mask_reg[cpu];
! 823: old_spl = luna88k_curspl[cpu];
! 824: eframe->tf_mask = old_spl;
! 825:
! 826: cur_int = cur_mask >> 29;
! 827:
! 828: if (cur_int == 0) {
! 829: /*
! 830: * Spurious interrupts - may be caused by debug output clearing
! 831: * serial port interrupts.
! 832: */
! 833: #ifdef DEBUG
! 834: printf("luna88k_ext_int(): Spurious interrupts?\n");
! 835: #endif
! 836: flush_pipeline();
! 837: goto out;
! 838: }
! 839:
! 840: uvmexp.intrs++;
! 841:
! 842: /*
! 843: * We want to service all interrupts marked in the IST register
! 844: * They are all valid because the mask would have prevented them
! 845: * from being generated otherwise. We will service them in order of
! 846: * priority.
! 847: */
! 848:
! 849: /* XXX: This is very rough. Should be considered more. (aoyama) */
! 850: do {
! 851: level = (cur_int > old_spl ? cur_int : old_spl);
! 852:
! 853: #ifdef DEBUG
! 854: if (level > 7 || (char)level < 0) {
! 855: panic("int level (%x) is not between 0 and 7", level);
! 856: }
! 857: #endif
! 858:
! 859: setipl(level);
! 860:
! 861: set_psr(get_psr() & ~PSR_IND);
! 862:
! 863: switch(cur_int) {
! 864: case CLOCK_INT_LEVEL:
! 865: clockintr((void *)eframe);
! 866: break;
! 867: case 5:
! 868: case 4:
! 869: case 3:
! 870: isrdispatch_autovec(cur_int);
! 871: break;
! 872: default:
! 873: printf("luna88k_ext_int(): level %d interrupt.\n", cur_int);
! 874: break;
! 875: }
! 876: } while ((cur_int = (*int_mask_reg[cpu]) >> 29) != 0);
! 877:
! 878: out:
! 879: /*
! 880: * process any remaining data access exceptions before
! 881: * returning to assembler
! 882: */
! 883: if (eframe->tf_dmt0 & DMT_VALID)
! 884: m88100_trap(T_DATAFLT, eframe);
! 885:
! 886: /*
! 887: * Disable interrupts before returning to assembler, the spl will
! 888: * be restored later.
! 889: */
! 890: set_psr(get_psr() | PSR_IND);
! 891: }
! 892:
! 893: int
! 894: cpu_exec_aout_makecmds(p, epp)
! 895: struct proc *p;
! 896: struct exec_package *epp;
! 897: {
! 898:
! 899: return (ENOEXEC);
! 900: }
! 901:
! 902: int
! 903: sys_sysarch(p, v, retval)
! 904: struct proc *p;
! 905: void *v;
! 906: register_t *retval;
! 907: {
! 908: #if 0
! 909: struct sys_sysarch_args /* {
! 910: syscallarg(int) op;
! 911: syscallarg(char *) parm;
! 912: } */ *uap = v;
! 913: #endif
! 914:
! 915: return (ENOSYS);
! 916: }
! 917:
! 918: /*
! 919: * machine dependent system variables.
! 920: */
! 921:
! 922: int
! 923: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 924: int *name;
! 925: u_int namelen;
! 926: void *oldp;
! 927: size_t *oldlenp;
! 928: void *newp;
! 929: size_t newlen;
! 930: struct proc *p;
! 931: {
! 932: dev_t consdev;
! 933:
! 934: /* all sysctl names are this level are terminal */
! 935: if (namelen != 1)
! 936: return (ENOTDIR); /* overloaded */
! 937:
! 938: switch (name[0]) {
! 939: case CPU_CONSDEV:
! 940: if (cn_tab != NULL)
! 941: consdev = cn_tab->cn_dev;
! 942: else
! 943: consdev = NODEV;
! 944: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
! 945: sizeof consdev));
! 946: default:
! 947: return (EOPNOTSUPP);
! 948: }
! 949: /*NOTREACHED*/
! 950: }
! 951:
! 952: /*
! 953: * Called from locore.S during boot,
! 954: * this is the first C code that's run.
! 955: */
! 956: void
! 957: luna88k_bootstrap()
! 958: {
! 959: extern int kernelstart;
! 960: extern struct consdev *cn_tab;
! 961: extern struct cmmu_p cmmu8820x;
! 962: extern char *end;
! 963: #ifndef MULTIPROCESSOR
! 964: cpuid_t master_cpu;
! 965: #endif
! 966: cpuid_t cpu;
! 967: extern void m8820x_initialize_cpu(cpuid_t);
! 968: extern void m8820x_set_sapr(cpuid_t, apr_t);
! 969: extern void cpu_boot_secondary_processors(void);
! 970:
! 971: cmmu = &cmmu8820x;
! 972:
! 973: /* clear and disable all interrupts */
! 974: *int_mask_reg[0] = 0;
! 975: *int_mask_reg[1] = 0;
! 976: *int_mask_reg[2] = 0;
! 977: *int_mask_reg[3] = 0;
! 978:
! 979: /* startup fake console driver. It will be replaced by consinit() */
! 980: cn_tab = &romttycons;
! 981:
! 982: uvmexp.pagesize = PAGE_SIZE;
! 983: uvm_setpagesize();
! 984:
! 985: first_addr = round_page((vaddr_t)&end); /* XXX temp until symbols */
! 986: last_addr = size_memory();
! 987: physmem = btoc(last_addr);
! 988:
! 989: setup_board_config();
! 990: master_cpu = cmmu_init();
! 991: set_cpu_number(master_cpu);
! 992:
! 993: m88100_apply_patches();
! 994:
! 995: /*
! 996: * Now that set_cpu_number() set us with a valid cpu_info pointer,
! 997: * we need to initialize p_addr and curpcb before autoconf, for the
! 998: * fault handler to behave properly [except for badaddr() faults,
! 999: * which can be taken care of without a valid curcpu()].
! 1000: */
! 1001: proc0.p_addr = proc0paddr;
! 1002: curproc = &proc0;
! 1003: curpcb = &proc0paddr->u_pcb;
! 1004:
! 1005: avail_start = first_addr;
! 1006: avail_end = last_addr;
! 1007:
! 1008: /*
! 1009: * Steal MSGBUFSIZE at the top of physical memory for msgbuf
! 1010: */
! 1011: avail_end -= round_page(MSGBUFSIZE);
! 1012:
! 1013: #ifdef DEBUG
! 1014: printf("LUNA88K boot: memory from 0x%x to 0x%x\n",
! 1015: avail_start, avail_end);
! 1016: #endif
! 1017: pmap_bootstrap((vaddr_t)trunc_page((unsigned)&kernelstart));
! 1018:
! 1019: /*
! 1020: * Tell the VM system about available physical memory.
! 1021: * luna88k only has one segment.
! 1022: */
! 1023: uvm_page_physload(atop(avail_start), atop(avail_end),
! 1024: atop(avail_start), atop(avail_end),VM_FREELIST_DEFAULT);
! 1025:
! 1026: /* Initialize the "u-area" pages. */
! 1027: bzero((caddr_t)curpcb, USPACE);
! 1028:
! 1029: /*
! 1030: * On the luna88k, secondary processors are not disabled while the
! 1031: * kernel is initializing. We just initialized the CMMUs tied to the
! 1032: * currently-running CPU; initialize the others with similar settings
! 1033: * as well, after calling pmap_bootstrap() above.
! 1034: */
! 1035: for (cpu = 0; cpu < max_cpus; cpu++) {
! 1036: if (cpu == master_cpu)
! 1037: continue;
! 1038: if (m88k_cpus[cpu].ci_alive == 0)
! 1039: continue;
! 1040: m8820x_initialize_cpu(cpu);
! 1041: cmmu_set_sapr(cpu, kernel_pmap->pm_apr);
! 1042: }
! 1043: /* Release the cpu_mutex */
! 1044: cpu_boot_secondary_processors();
! 1045:
! 1046: #ifdef DEBUG
! 1047: printf("leaving luna88k_bootstrap()\n");
! 1048: #endif
! 1049: }
! 1050:
! 1051: /*
! 1052: * Rom console routines:
! 1053: * Enables printing of boot messages before consinit().
! 1054: */
! 1055:
! 1056: #define __ROM_FUNC_TABLE ((int **)0x00001100)
! 1057: #define ROMGETC() (*(int (*)(void))__ROM_FUNC_TABLE[3])()
! 1058: #define ROMPUTC(x) (*(void (*)(int))__ROM_FUNC_TABLE[4])(x)
! 1059:
! 1060: void
! 1061: romttycnprobe(cp)
! 1062: struct consdev *cp;
! 1063: {
! 1064: cp->cn_dev = makedev(14, 0);
! 1065: cp->cn_pri = CN_NORMAL;
! 1066: }
! 1067:
! 1068: void
! 1069: romttycninit(cp)
! 1070: struct consdev *cp;
! 1071: {
! 1072: /* Nothing to do */
! 1073: }
! 1074:
! 1075: int
! 1076: romttycngetc(dev)
! 1077: dev_t dev;
! 1078: {
! 1079: int s, c;
! 1080:
! 1081: do {
! 1082: s = splhigh();
! 1083: c = ROMGETC();
! 1084: splx(s);
! 1085: } while (c == -1);
! 1086: return c;
! 1087: }
! 1088:
! 1089: void
! 1090: romttycnputc(dev, c)
! 1091: dev_t dev;
! 1092: int c;
! 1093: {
! 1094: int s;
! 1095:
! 1096: #if 0
! 1097: if ((char)c == '\n')
! 1098: ROMPUTC('\r');
! 1099: #endif
! 1100: s = splhigh();
! 1101: ROMPUTC(c);
! 1102: splx(s);
! 1103: }
! 1104:
! 1105: /* taken from NetBSD/luna68k */
! 1106: void
! 1107: microtime(tvp)
! 1108: register struct timeval *tvp;
! 1109: {
! 1110: int s = splclock();
! 1111: static struct timeval lasttime;
! 1112:
! 1113: *tvp = time;
! 1114: #ifdef notdef
! 1115: tvp->tv_usec += clkread();
! 1116: while (tvp->tv_usec >= 1000000) {
! 1117: tvp->tv_sec++;
! 1118: tvp->tv_usec -= 1000000;
! 1119: }
! 1120: #endif
! 1121: if (tvp->tv_sec == lasttime.tv_sec &&
! 1122: tvp->tv_usec <= lasttime.tv_usec &&
! 1123: (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
! 1124: tvp->tv_sec++;
! 1125: tvp->tv_usec -= 1000000;
! 1126: }
! 1127: lasttime = *tvp;
! 1128: splx(s);
! 1129: }
! 1130:
! 1131: /* powerdown */
! 1132:
! 1133: struct pio {
! 1134: volatile u_int8_t portA;
! 1135: volatile unsigned : 24;
! 1136: volatile u_int8_t portB;
! 1137: volatile unsigned : 24;
! 1138: volatile u_int8_t portC;
! 1139: volatile unsigned : 24;
! 1140: volatile u_int8_t cntrl;
! 1141: volatile unsigned : 24;
! 1142: };
! 1143:
! 1144: #define PIO1_POWER 0x04
! 1145:
! 1146: #define PIO1_ENABLE 0x01
! 1147: #define PIO1_DISABLE 0x00
! 1148:
! 1149: void
! 1150: powerdown(void)
! 1151: {
! 1152: struct pio *p1 = (struct pio *)OBIO_PIO1_BASE;
! 1153:
! 1154: DELAY(100000);
! 1155: p1->cntrl = (PIO1_POWER << 1) | PIO1_DISABLE;
! 1156: *(volatile u_int8_t *)&p1->portC;
! 1157: }
! 1158:
! 1159: /* Get data from FUSE ROM */
! 1160:
! 1161: void
! 1162: get_fuse_rom_data(void)
! 1163: {
! 1164: int i;
! 1165: struct fuse_rom_byte *p = (struct fuse_rom_byte *)FUSE_ROM_ADDR;
! 1166:
! 1167: for (i = 0; i < FUSE_ROM_BYTES; i++) {
! 1168: fuse_rom_data[i] =
! 1169: (char)((((p->h) >> 24) & 0x000000f0) |
! 1170: (((p->l) >> 28) & 0x0000000f));
! 1171: p++;
! 1172: }
! 1173: }
! 1174:
! 1175: /* Get data from NVRAM */
! 1176:
! 1177: void
! 1178: get_nvram_data(void)
! 1179: {
! 1180: int i, j;
! 1181: u_int8_t *page;
! 1182: char buf[NVSYMLEN], *data;
! 1183:
! 1184: if (machtype == LUNA_88K) {
! 1185: data = (char *)(NVRAM_ADDR + 0x80);
! 1186:
! 1187: for (i = 0; i < NNVSYM; i++) {
! 1188: for (j = 0; j < NVSYMLEN; j++) {
! 1189: buf[j] = *data;
! 1190: data += 4;
! 1191: }
! 1192: strlcpy(nvram[i].symbol, buf, sizeof(nvram[i].symbol));
! 1193:
! 1194: for (j = 0; j < NVVALLEN; j++) {
! 1195: buf[j] = *data;
! 1196: data += 4;
! 1197: }
! 1198: strlcpy(nvram[i].value, buf, sizeof(nvram[i].value));
! 1199: }
! 1200: } else if (machtype == LUNA_88K2) {
! 1201: page = (u_int8_t *)(NVRAM_ADDR_88K2 + 0x20);
! 1202:
! 1203: for (i = 0; i < NNVSYM; i++) {
! 1204: *page = (u_int8_t)i;
! 1205:
! 1206: data = (char *)NVRAM_ADDR_88K2;
! 1207: strlcpy(nvram[i].symbol, data, sizeof(nvram[i].symbol));
! 1208:
! 1209: data = (char *)(NVRAM_ADDR_88K2 + 0x10);
! 1210: strlcpy(nvram[i].value, data, sizeof(nvram[i].value));
! 1211: }
! 1212: }
! 1213: }
! 1214:
! 1215: char *
! 1216: nvram_by_symbol(symbol)
! 1217: char *symbol;
! 1218: {
! 1219: char *value;
! 1220: int i;
! 1221:
! 1222: value = NULL;
! 1223:
! 1224: for (i = 0; i < NNVSYM; i++) {
! 1225: if (strncmp(nvram[i].symbol, symbol, NVSYMLEN) == 0) {
! 1226: value = nvram[i].value;
! 1227: break;
! 1228: }
! 1229: }
! 1230:
! 1231: return value;
! 1232: }
! 1233:
! 1234: void
! 1235: setlevel(unsigned int level)
! 1236: {
! 1237: unsigned int set_value;
! 1238: int cpu = cpu_number();
! 1239:
! 1240: set_value = int_set_val[level];
! 1241:
! 1242: #ifdef MULTIPROCESSOR
! 1243: if (cpu != master_cpu)
! 1244: set_value &= INT_SLAVE_MASK;
! 1245: #endif
! 1246:
! 1247: *int_mask_reg[cpu] = set_value;
! 1248: luna88k_curspl[cpu] = level;
! 1249: }
! 1250:
! 1251: u_int
! 1252: getipl(void)
! 1253: {
! 1254: u_int curspl, psr;
! 1255:
! 1256: disable_interrupt(psr);
! 1257: curspl = luna88k_curspl[cpu_number()];
! 1258: set_psr(psr);
! 1259: return curspl;
! 1260: }
! 1261:
! 1262: unsigned
! 1263: setipl(unsigned level)
! 1264: {
! 1265: unsigned int curspl, psr;
! 1266:
! 1267: disable_interrupt(psr);
! 1268: curspl = luna88k_curspl[cpu_number()];
! 1269: setlevel(level);
! 1270:
! 1271: /*
! 1272: * The flush pipeline is required to make sure the above write gets
! 1273: * through the data pipe and to the hardware; otherwise, the next
! 1274: * bunch of instructions could execute at the wrong spl protection.
! 1275: */
! 1276: flush_pipeline();
! 1277:
! 1278: set_psr(psr);
! 1279: return curspl;
! 1280: }
! 1281:
! 1282: unsigned
! 1283: raiseipl(unsigned level)
! 1284: {
! 1285: unsigned int curspl, psr;
! 1286:
! 1287: disable_interrupt(psr);
! 1288: curspl = luna88k_curspl[cpu_number()];
! 1289: if (curspl < level)
! 1290: setlevel(level);
! 1291:
! 1292: /*
! 1293: * The flush pipeline is required to make sure the above write gets
! 1294: * through the data pipe and to the hardware; otherwise, the next
! 1295: * bunch of instructions could execute at the wrong spl protection.
! 1296: */
! 1297: flush_pipeline();
! 1298:
! 1299: set_psr(psr);
! 1300: return curspl;
! 1301: }
CVSweb