Annotation of sys/arch/sgi/sgi/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.47 2007/07/18 20:05:25 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
! 16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
! 19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 25: * SUCH DAMAGE.
! 26: *
! 27: */
! 28: #include <sys/param.h>
! 29: #include <sys/systm.h>
! 30: #include <sys/signalvar.h>
! 31: #include <sys/kernel.h>
! 32: #include <sys/proc.h>
! 33: #include <sys/buf.h>
! 34: #include <sys/reboot.h>
! 35: #include <sys/conf.h>
! 36: #include <sys/file.h>
! 37: #include <sys/malloc.h>
! 38: #include <sys/mbuf.h>
! 39: #include <sys/msgbuf.h>
! 40: #include <sys/ioctl.h>
! 41: #include <sys/tty.h>
! 42: #include <sys/user.h>
! 43: #include <sys/exec.h>
! 44: #include <sys/sysctl.h>
! 45: #include <sys/mount.h>
! 46: #include <sys/syscallargs.h>
! 47: #include <sys/exec_elf.h>
! 48: #include <sys/extent.h>
! 49: #ifdef SYSVSHM
! 50: #include <sys/shm.h>
! 51: #endif
! 52: #ifdef SYSVSEM
! 53: #include <sys/sem.h>
! 54: #endif
! 55: #ifdef SYSVMSG
! 56: #include <sys/msg.h>
! 57: #endif
! 58:
! 59: #include <uvm/uvm_extern.h>
! 60:
! 61: #include <machine/db_machdep.h>
! 62: #include <ddb/db_interface.h>
! 63:
! 64: #include <machine/pte.h>
! 65: #include <machine/cpu.h>
! 66: #include <machine/frame.h>
! 67: #include <machine/pio.h>
! 68: #include <machine/psl.h>
! 69: #include <machine/autoconf.h>
! 70: #include <machine/memconf.h>
! 71: #include <machine/regnum.h>
! 72: #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
! 73: #include <machine/mnode.h>
! 74: #endif
! 75:
! 76: #include <mips64/rm7000.h>
! 77:
! 78: #include <dev/cons.h>
! 79:
! 80: #include <mips64/arcbios.h>
! 81: #include <mips64/archtype.h>
! 82: #include <machine/bus.h>
! 83:
! 84: #include <sgi/localbus/crimebus.h>
! 85: #include <sgi/localbus/macebus.h>
! 86: #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
! 87: #include <sgi/localbus/xbowmux.h>
! 88: #endif
! 89:
! 90: extern struct consdev *cn_tab;
! 91: extern char kernel_text[];
! 92: extern int makebootdev(const char *, int);
! 93: extern void stacktrace(void);
! 94:
! 95: #ifdef DEBUG
! 96: void dump_tlb(void);
! 97: #endif
! 98:
! 99: /* the following is used externally (sysctl_hw) */
! 100: char machine[] = MACHINE; /* machine "architecture" */
! 101: char cpu_model[30];
! 102:
! 103: /*
! 104: * Declare these as initialized data so we can patch them.
! 105: */
! 106: #ifndef BUFCACHEPERCENT
! 107: #define BUFCACHEPERCENT 5 /* Can be changed in config */
! 108: #endif
! 109: #ifndef BUFPAGES
! 110: #define BUFPAGES 0 /* Can be changed in config */
! 111: #endif
! 112:
! 113: int bufpages = BUFPAGES;
! 114: int bufcachepercent = BUFCACHEPERCENT;
! 115:
! 116: vm_map_t exec_map;
! 117: vm_map_t phys_map;
! 118:
! 119: int extent_malloc_flags = 0;
! 120:
! 121: caddr_t msgbufbase;
! 122:
! 123: int physmem; /* max supported memory, changes to actual */
! 124: int rsvdmem; /* reserved memory not usable */
! 125: int ncpu = 1; /* At least one cpu in the system */
! 126: struct user *proc0paddr;
! 127: struct user *curprocpaddr;
! 128: int console_ok; /* set when console initialized */
! 129: int bootdriveoffs = 0;
! 130:
! 131: int32_t *environment;
! 132: struct sys_rec sys_config;
! 133:
! 134:
! 135: /* ddb symbol init stuff */
! 136: caddr_t ssym;
! 137: caddr_t esym;
! 138: caddr_t ekern;
! 139:
! 140: struct phys_mem_desc mem_layout[MAXMEMSEGS];
! 141:
! 142: void crime_configure_memory(void);
! 143:
! 144: caddr_t mips_init(int, void *);
! 145: void initcpu(void);
! 146: void dumpsys(void);
! 147: void dumpconf(void);
! 148: caddr_t allocsys(caddr_t);
! 149:
! 150: void db_command_loop(void);
! 151:
! 152: static void dobootopts(int, void *);
! 153: static int atoi(const char *, int, const char **);
! 154:
! 155: #if BYTE_ORDER == BIG_ENDIAN
! 156: int my_endian = 1;
! 157: #else
! 158: int my_endian = 0;
! 159: #endif
! 160:
! 161: #if defined(TGT_O2)
! 162: void
! 163: crime_configure_memory(void)
! 164: {
! 165: struct phys_mem_desc *m;
! 166: volatile u_int64_t *bank_ctrl;
! 167: paddr_t addr;
! 168: psize_t size;
! 169: u_int32_t first_page, last_page;
! 170: int bank, i;
! 171:
! 172: bank_ctrl = (void *)PHYS_TO_KSEG1(CRIMEBUS_BASE + CRIME_MEM_BANK0_CONTROL);
! 173: for (bank = 0; bank < CRIME_MAX_BANKS; bank++) {
! 174: addr = (bank_ctrl[bank] & CRIME_MEM_BANK_ADDR) << 25;
! 175: size = (bank_ctrl[bank] & CRIME_MEM_BANK_128MB) ? 128 : 32;
! 176: #ifdef DEBUG
! 177: bios_printf("crime: bank %d contains %ld MB at 0x%lx\n",
! 178: bank, size, addr);
! 179: #endif
! 180:
! 181: /*
! 182: * Do not report memory regions below 256MB, since
! 183: * arcbios will do. Moreover, empty banks are reported
! 184: * at address zero.
! 185: */
! 186: if (addr < 256 * 1024 * 1024)
! 187: continue;
! 188:
! 189: addr += 1024 * 1024 * 1024;
! 190: size *= 1024 * 1024;
! 191: first_page = atop(addr);
! 192: last_page = atop(addr + size);
! 193:
! 194: /*
! 195: * Try to coalesce with other memory segments if banks
! 196: * are contiguous.
! 197: */
! 198: m = NULL;
! 199: for (i = 0; i < MAXMEMSEGS; i++) {
! 200: if (mem_layout[i].mem_last_page == 0) {
! 201: if (m == NULL)
! 202: m = &mem_layout[i];
! 203: } else if (last_page == mem_layout[i].mem_first_page) {
! 204: m = &mem_layout[i];
! 205: m->mem_first_page = first_page;
! 206: } else if (mem_layout[i].mem_last_page == first_page) {
! 207: m = &mem_layout[i];
! 208: m->mem_last_page = last_page;
! 209: }
! 210: }
! 211: if (m != NULL && m->mem_last_page == 0) {
! 212: m->mem_first_page = first_page;
! 213: m->mem_last_page = last_page;
! 214: }
! 215: if (m != NULL)
! 216: physmem += atop(size);
! 217: }
! 218:
! 219: #ifdef DEBUG
! 220: for (i = 0; i < MAXMEMSEGS; i++)
! 221: if (mem_layout[i].mem_first_page)
! 222: bios_printf("MEM %d, 0x%x to 0x%x\n",i,
! 223: ptoa(mem_layout[i].mem_first_page),
! 224: ptoa(mem_layout[i].mem_last_page));
! 225: #endif
! 226: }
! 227: #endif
! 228:
! 229: /*
! 230: * Do all the stuff that locore normally does before calling main().
! 231: * Reset mapping and set up mapping to hardware and init "wired" reg.
! 232: */
! 233:
! 234: caddr_t
! 235: mips_init(int argc, void *argv)
! 236: {
! 237: char *cp;
! 238: int i;
! 239: caddr_t sd;
! 240: extern char start[], edata[], end[];
! 241: extern char tlb_miss_tramp[], e_tlb_miss_tramp[];
! 242: extern char xtlb_miss_tramp[], e_xtlb_miss_tramp[];
! 243: extern char exception[], e_exception[];
! 244:
! 245: /*
! 246: * Make sure we can access the extended address space.
! 247: * Note that r10k and later do not allow XUSEG accesses
! 248: * from kernel mode unless SR_UX is set.
! 249: */
! 250: setsr(getsr() | SR_KX | SR_UX);
! 251:
! 252: /*
! 253: * Clear the compiled BSS segment in OpenBSD code
! 254: */
! 255: bzero(edata, end - edata);
! 256:
! 257: /*
! 258: * Reserve symbol table space. If invalid pointers no table.
! 259: */
! 260: ssym = (char *)*(u_int64_t *)end;
! 261: esym = (char *)*((u_int64_t *)end + 1);
! 262: ekern = esym;
! 263: if (((long)ssym - (long)end) < 0 ||
! 264: ((long)ssym - (long)end) > 0x1000 ||
! 265: ssym[0] != ELFMAG0 || ssym[1] != ELFMAG1 ||
! 266: ssym[2] != ELFMAG2 || ssym[3] != ELFMAG3 ) {
! 267: ssym = NULL;
! 268: esym = NULL;
! 269: ekern = end;
! 270: }
! 271:
! 272: /*
! 273: * Initialize the system type and set up memory layout
! 274: * Note that some systems have more complex memory setup.
! 275: */
! 276: bios_ident();
! 277:
! 278: bios_printf("SR=%08x\n", getsr()); /* leave this in for now. need to see sr */
! 279:
! 280: /*
! 281: * Determine system type and set up configuration record data.
! 282: */
! 283: switch (sys_config.system_type) {
! 284: #if defined(TGT_O2)
! 285: case SGI_O2:
! 286: bios_printf("Found SGI-IP32, setting up.\n");
! 287: strlcpy(cpu_model, "SGI-O2 (IP32)", sizeof(cpu_model));
! 288: sys_config.cons_ioaddr[0] = MACE_ISA_SER1_OFFS;
! 289: sys_config.cons_ioaddr[1] = MACE_ISA_SER2_OFFS;
! 290: sys_config.cons_baudclk = 1843200; /*XXX*/
! 291: sys_config.cons_iot = &macebus_tag;
! 292: sys_config.local.bus_base = 0x0; /*XXX*/
! 293: sys_config.pci_io[0].bus_base = 0xffffffff00000000;/*XXX*/
! 294: sys_config.pci_mem[0].bus_base = 0xffffffff00000000;/*XXX*/
! 295: sys_config.pci_mem[0].bus_base_dma = 0x00000000;/*XXX*/
! 296: sys_config.pci_mem[0].bus_reverse = my_endian;
! 297: sys_config.cpu[0].tlbwired = 2;
! 298:
! 299: crime_configure_memory();
! 300:
! 301: sys_config.cpu[0].clock = 180000000; /* Reasonable default */
! 302: cp = Bios_GetEnvironmentVariable("cpufreq");
! 303: if (cp && atoi(cp, 10, NULL) > 100)
! 304: sys_config.cpu[0].clock = atoi(cp, 10, NULL) * 1000000;
! 305:
! 306: /* R1xK O2's are one disk slot machines. Offset slotno */
! 307: switch ((cp0_get_prid() >> 8) & 0xff) {
! 308: case MIPS_R10000:
! 309: case MIPS_R12000:
! 310: bootdriveoffs = -1;
! 311: break;
! 312: }
! 313: /* R12K O2's must run with DSD on */
! 314: switch ((cp0_get_prid() >> 8) & 0xff) {
! 315: case MIPS_R12000:
! 316: setsr(getsr() | SR_DSD);
! 317: break;
! 318: }
! 319: break;
! 320: #endif
! 321:
! 322: #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
! 323: case SGI_O200:
! 324: bios_printf("Found SGI-IP27, setting up.\n");
! 325: strlcpy(cpu_model, "SGI- Origin200 (IP27)", sizeof(cpu_model));
! 326:
! 327: kl_scan_config(0);
! 328:
! 329: sys_config.cons_ioaddr[0] = kl_get_console_base();
! 330: sys_config.cons_ioaddr[1] = kl_get_console_base() - 8;
! 331: sys_config.cons_baudclk = 22000000 / 3; /*XXX*/
! 332: sys_config.cons_iot = &xbowmux_tag;
! 333: sys_config.local.bus_base = 0x0; /*XXX*/
! 334: sys_config.pci_io[0].bus_base = 0xffffffff00000000;/*XXX*/
! 335: sys_config.pci_mem[0].bus_base = 0xffffffff00000000;/*XXX*/
! 336: sys_config.pci_mem[0].bus_base_dma = 0x00000000;/*XXX*/
! 337: sys_config.pci_mem[0].bus_reverse = my_endian;
! 338: sys_config.cpu[0].tlbwired = 2;
! 339: break;
! 340: #endif
! 341:
! 342: default:
! 343: bios_printf("Kernel doesn't support this system type!\n");
! 344: bios_printf("Halting system.\n");
! 345: Bios_Halt();
! 346: while(1);
! 347: }
! 348:
! 349: /*
! 350: * Look at arguments passed to us and compute boothowto.
! 351: * Default to SINGLE and ASKNAME if no args or
! 352: * SINGLE and DFLTROOT if this is a ramdisk kernel.
! 353: */
! 354: #ifdef RAMDISK_HOOKS
! 355: boothowto = RB_SINGLE | RB_DFLTROOT;
! 356: #else
! 357: boothowto = RB_SINGLE | RB_ASKNAME;
! 358: #endif /* RAMDISK_HOOKS */
! 359:
! 360: dobootopts(argc, argv);
! 361:
! 362: /*
! 363: * Figure out where we was booted from.
! 364: */
! 365: cp = Bios_GetEnvironmentVariable("OSLoadPartition");
! 366: if (cp == NULL)
! 367: cp = "unknown";
! 368: if (makebootdev(cp, bootdriveoffs))
! 369: bios_printf("Boot device unrecognized: '%s'\n", cp);
! 370:
! 371: /*
! 372: * Read platform-specific environment variables.
! 373: */
! 374: switch (sys_config.system_type) {
! 375: #if defined(TGT_O2)
! 376: case SGI_O2:
! 377: /* get ethernet address from ARCBIOS */
! 378: cp = Bios_GetEnvironmentVariable("eaddr");
! 379: if (cp != NULL && strlen(cp) > 0)
! 380: strlcpy(bios_enaddr, cp, sizeof bios_enaddr);
! 381: break;
! 382: #endif
! 383: default:
! 384: break;
! 385: }
! 386:
! 387: /*
! 388: * Set pagesize to enable use of page macros and functions.
! 389: * Commit available memory to UVM system
! 390: */
! 391: uvmexp.pagesize = PAGE_SIZE;
! 392: uvm_setpagesize();
! 393:
! 394: for (i = 0; i < MAXMEMSEGS && mem_layout[i].mem_first_page != 0; i++) {
! 395: u_int32_t fp, lp;
! 396: u_int32_t firstkernpage, lastkernpage;
! 397: paddr_t firstkernpa, lastkernpa;
! 398:
! 399: if (IS_XKPHYS((vaddr_t)start))
! 400: firstkernpa = XKPHYS_TO_PHYS((vaddr_t)start);
! 401: else
! 402: firstkernpa = KSEG0_TO_PHYS((vaddr_t)start);
! 403: if (IS_XKPHYS((vaddr_t)ekern))
! 404: lastkernpa = XKPHYS_TO_PHYS((vaddr_t)ekern);
! 405: else
! 406: lastkernpa = KSEG0_TO_PHYS((vaddr_t)ekern);
! 407:
! 408: firstkernpage = atop(trunc_page(firstkernpa));
! 409: lastkernpage = atop(round_page(lastkernpa));
! 410:
! 411: fp = mem_layout[i].mem_first_page;
! 412: lp = mem_layout[i].mem_last_page;
! 413:
! 414: /* Account for kernel and kernel symbol table */
! 415: if (fp >= firstkernpage && lp < lastkernpage)
! 416: continue; /* In kernel */
! 417:
! 418: if (lp < firstkernpage || fp > lastkernpage) {
! 419: uvm_page_physload(fp, lp, fp, lp, VM_FREELIST_DEFAULT);
! 420: continue; /* Outside kernel */
! 421: }
! 422:
! 423: if (fp >= firstkernpage)
! 424: fp = lastkernpage;
! 425: else if (lp < lastkernpage)
! 426: lp = firstkernpage;
! 427: else { /* Need to split! */
! 428: u_int32_t xp = firstkernpage;
! 429: uvm_page_physload(fp, xp, fp, xp, VM_FREELIST_DEFAULT);
! 430: fp = lastkernpage;
! 431: }
! 432: if (lp >= fp)
! 433: uvm_page_physload(fp, lp, fp, lp, VM_FREELIST_DEFAULT);
! 434: }
! 435:
! 436:
! 437: switch (sys_config.system_type) {
! 438: #if defined(TGT_O2)
! 439: case SGI_O2:
! 440: sys_config.cpu[0].type = (cp0_get_prid() >> 8) & 0xff;
! 441: sys_config.cpu[0].vers_maj = (cp0_get_prid() >> 4) & 0x0f;
! 442: sys_config.cpu[0].vers_min = cp0_get_prid() & 0x0f;
! 443: sys_config.cpu[0].fptype = (cp1_get_prid() >> 8) & 0xff;
! 444: sys_config.cpu[0].fpvers_maj = (cp1_get_prid() >> 4) & 0x0f;
! 445: sys_config.cpu[0].fpvers_min = cp1_get_prid() & 0x0f;
! 446:
! 447: /*
! 448: * Configure TLB.
! 449: */
! 450: switch(sys_config.cpu[0].type) {
! 451: case MIPS_RM7000:
! 452: /* Rev A (version >= 2) CPU's have 64 TLB entries. */
! 453: if (sys_config.cpu[0].vers_maj < 2) {
! 454: sys_config.cpu[0].tlbsize = 48;
! 455: } else {
! 456: sys_config.cpu[0].tlbsize = 64;
! 457: }
! 458: break;
! 459:
! 460: case MIPS_R10000:
! 461: case MIPS_R12000:
! 462: sys_config.cpu[0].tlbsize = 64;
! 463: break;
! 464:
! 465: default:
! 466: sys_config.cpu[0].tlbsize = 48;
! 467: break;
! 468: }
! 469: break;
! 470: #endif
! 471: default:
! 472: break;
! 473: }
! 474:
! 475: /*
! 476: * Configure Cache.
! 477: */
! 478: switch(sys_config.cpu[0].type) {
! 479: case MIPS_R10000:
! 480: case MIPS_R12000:
! 481: case MIPS_R14000:
! 482: sys_config.cpu[0].cfg_reg = Mips10k_ConfigCache();
! 483: sys_config._SyncCache = Mips10k_SyncCache;
! 484: sys_config._InvalidateICache = Mips10k_InvalidateICache;
! 485: sys_config._InvalidateICachePage = Mips10k_InvalidateICachePage;
! 486: sys_config._SyncDCachePage = Mips10k_SyncDCachePage;
! 487: sys_config._HitSyncDCache = Mips10k_HitSyncDCache;
! 488: sys_config._IOSyncDCache = Mips10k_IOSyncDCache;
! 489: sys_config._HitInvalidateDCache = Mips10k_HitInvalidateDCache;
! 490: break;
! 491:
! 492: default:
! 493: sys_config.cpu[0].cfg_reg = Mips5k_ConfigCache();
! 494: sys_config._SyncCache = Mips5k_SyncCache;
! 495: sys_config._InvalidateICache = Mips5k_InvalidateICache;
! 496: sys_config._InvalidateICachePage = Mips5k_InvalidateICachePage;
! 497: sys_config._SyncDCachePage = Mips5k_SyncDCachePage;
! 498: sys_config._HitSyncDCache = Mips5k_HitSyncDCache;
! 499: sys_config._IOSyncDCache = Mips5k_IOSyncDCache;
! 500: sys_config._HitInvalidateDCache = Mips5k_HitInvalidateDCache;
! 501: break;
! 502: }
! 503:
! 504: /*
! 505: * Last chance to call the bios. Wiping the TLB means
! 506: * bios data areas are demapped on most systems.
! 507: * O2's are OK. Does not have mapped bios text or data.
! 508: */
! 509: delay(20*1000); /* Let any uart fifo drain... */
! 510: tlb_set_wired(0);
! 511: tlb_flush(sys_config.cpu[0].tlbsize);
! 512: tlb_set_wired(sys_config.cpu[0].tlbwired);
! 513:
! 514: #if 0
! 515: /* XXX Save the following as an example on how to optimize I/O mapping */
! 516:
! 517: /*
! 518: * Set up some fixed mappings. These are so frequently
! 519: * used so faulting them in will waste to many cycles.
! 520: */
! 521: if (sys_config.system_type == MOMENTUM_CP7000G ||
! 522: sys_config.system_type == MOMENTUM_CP7000 ||
! 523: sys_config.system_type == GALILEO_EV64240) {
! 524: struct tlb tlb;
! 525:
! 526: tlb.tlb_mask = PG_SIZE_16M;
! 527: #if defined(LP64)
! 528: tlb.tlb_hi = vad_to_vpn(0xfffffffffc000000) | 1;
! 529: tlb.tlb_lo0 = vad_to_pfn(0xfffffffff4000000) | PG_IOPAGE;
! 530: #else
! 531: tlb.tlb_hi = vad_to_vpn(0xfc000000) | 1;
! 532: tlb.tlb_lo0 = vad_to_pfn(0xf4000000) | PG_IOPAGE;
! 533: #endif
! 534: tlb.tlb_lo1 = vad_to_pfn(sys_config.cons_ioaddr[0]) | PG_IOPAGE;
! 535: tlb_write_indexed(2, &tlb);
! 536:
! 537: if (sys_config.system_type == GALILEO_EV64240) {
! 538: tlb.tlb_mask = PG_SIZE_16M;
! 539: tlb.tlb_hi = vad_to_vpn(0xf8000000) | 1;
! 540: tlb.tlb_lo0 = vad_to_pfn(sys_config.pci_io[0].bus_base) | PG_IOPAGE;
! 541: tlb.tlb_lo1 = vad_to_pfn(sys_config.pci_mem[0].bus_base) | PG_IOPAGE;
! 542: tlb_write_indexed(3, &tlb);
! 543: }
! 544: }
! 545: /* XXX */
! 546: #endif
! 547:
! 548: #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
! 549: /*
! 550: * If an IP27 system set up Node 0's HUB.
! 551: */
! 552: if (sys_config.system_type == SGI_O200) {
! 553: IP27_LHUB_S(PI_REGION_PRESENT, 1);
! 554: IP27_LHUB_S(PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
! 555: }
! 556: #endif
! 557:
! 558: /*
! 559: * Get a console, very early but after initial mapping setup.
! 560: */
! 561: consinit();
! 562: printf("Initial setup done, switching console.\n");
! 563:
! 564: /*
! 565: * Init message buffer.
! 566: */
! 567: msgbufbase = (caddr_t)pmap_steal_memory(MSGBUFSIZE, NULL,NULL);
! 568: initmsgbuf(msgbufbase, MSGBUFSIZE);
! 569:
! 570: /*
! 571: * Allocate U page(s) for proc[0], pm_tlbpid 1.
! 572: */
! 573: proc0.p_addr = proc0paddr = curprocpaddr =
! 574: (struct user *)pmap_steal_memory(USPACE, NULL, NULL);
! 575: proc0.p_md.md_regs = (struct trap_frame *)&proc0paddr->u_pcb.pcb_regs;
! 576: tlb_set_pid(1);
! 577:
! 578: /*
! 579: * Allocate system data structures.
! 580: */
! 581: i = (vsize_t)allocsys(NULL);
! 582: sd = (caddr_t)pmap_steal_memory(i, NULL, NULL);
! 583: allocsys(sd);
! 584:
! 585: /*
! 586: * Bootstrap VM system.
! 587: */
! 588: pmap_bootstrap();
! 589:
! 590:
! 591: /*
! 592: * Copy down exception vector code.
! 593: */
! 594: bcopy(tlb_miss_tramp, (char *)TLB_MISS_EXC_VEC,
! 595: e_tlb_miss_tramp - tlb_miss_tramp);
! 596: bcopy(xtlb_miss_tramp, (char *)XTLB_MISS_EXC_VEC,
! 597: e_xtlb_miss_tramp - xtlb_miss_tramp);
! 598: bcopy(exception, (char *)CACHE_ERR_EXC_VEC, e_exception - exception);
! 599: bcopy(exception, (char *)GEN_EXC_VEC, e_exception - exception);
! 600:
! 601: /*
! 602: * Turn off bootstrap exception vectors.
! 603: */
! 604: setsr(getsr() & ~SR_BOOT_EXC_VEC);
! 605: proc0.p_md.md_regs->sr = getsr();
! 606:
! 607: /*
! 608: * Clear out the I and D caches.
! 609: */
! 610: Mips_SyncCache();
! 611:
! 612: #ifdef DDB
! 613: db_machine_init();
! 614: if (boothowto & RB_KDB)
! 615: Debugger();
! 616: #endif
! 617:
! 618: /*
! 619: * Return new stack pointer.
! 620: */
! 621: return ((caddr_t)proc0paddr + USPACE - 64);
! 622: }
! 623:
! 624: /*
! 625: * Allocate space for system data structures. Doesn't need to be mapped.
! 626: */
! 627: caddr_t
! 628: allocsys(caddr_t v)
! 629: {
! 630: caddr_t start;
! 631:
! 632: start = v;
! 633:
! 634: #define valloc(name, type, num) \
! 635: (name) = (type *)v; v = (caddr_t)((name)+(num))
! 636: #ifdef SYSVMSG
! 637: valloc(msgpool, char, msginfo.msgmax);
! 638: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 639: valloc(msghdrs, struct msg, msginfo.msgtql);
! 640: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 641: #endif
! 642:
! 643: return(v);
! 644: }
! 645:
! 646:
! 647: /*
! 648: * Decode boot options.
! 649: */
! 650: static void
! 651: dobootopts(int argc, void *argv)
! 652: {
! 653: char *cp;
! 654: int i;
! 655:
! 656: /* XXX Should this be done differently, eg env vs. args? */
! 657: for (i = 1; i < argc; i++) {
! 658: if (bios_is_32bit)
! 659: cp = (char *)(long)((int32_t *)argv)[i];
! 660: else
! 661: cp = ((char **)argv)[i];
! 662: if (cp != NULL && strncmp(cp, "OSLoadOptions=", 14) == 0) {
! 663: if (strcmp(&cp[14], "auto") == 0)
! 664: boothowto &= ~(RB_SINGLE|RB_ASKNAME);
! 665: else if (strcmp(&cp[14], "single") == 0)
! 666: boothowto |= RB_SINGLE;
! 667: else if (strcmp(&cp[14], "debug") == 0)
! 668: boothowto |= RB_KDB;
! 669: }
! 670: }
! 671:
! 672: /* Catch serial consoles on O2's */
! 673: cp = Bios_GetEnvironmentVariable("ConsoleOut");
! 674: if (cp != NULL && strncmp(cp, "serial", 6) == 0)
! 675: boothowto |= RB_SERCONS;
! 676: }
! 677:
! 678:
! 679: /*
! 680: * Console initialization: called early on from main,
! 681: * before vm init or startup. Do enough configuration
! 682: * to choose and initialize a console.
! 683: */
! 684: void
! 685: consinit()
! 686: {
! 687: if (console_ok) {
! 688: return;
! 689: }
! 690: cninit();
! 691: console_ok = 1;
! 692: }
! 693:
! 694: /*
! 695: * cpu_startup: allocate memory for variable-sized tables,
! 696: * initialize cpu, and do autoconfiguration.
! 697: */
! 698: void
! 699: cpu_startup()
! 700: {
! 701: vaddr_t minaddr, maxaddr;
! 702: #ifdef PMAPDEBUG
! 703: extern int pmapdebug;
! 704: int opmapdebug = pmapdebug;
! 705:
! 706: pmapdebug = 0; /* Shut up pmap debug during bootstrap */
! 707: #endif
! 708:
! 709: /*
! 710: * Good {morning,afternoon,evening,night}.
! 711: */
! 712: printf(version);
! 713: printf("real mem = %u (%uMB)\n", ptoa(physmem),
! 714: ptoa(physmem)/1024/1024);
! 715: printf("rsvd mem = %u (%uMB)\n", ptoa(rsvdmem),
! 716: ptoa(rsvdmem)/1024/1024);
! 717:
! 718: /*
! 719: * Determine how many buffers to allocate.
! 720: * We allocate bufcachepercent% of memory for buffer space.
! 721: */
! 722: if (bufpages == 0)
! 723: bufpages = physmem * bufcachepercent / 100;
! 724:
! 725: /* Restrict to at most 25% filled kvm */
! 726: if (bufpages >
! 727: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 728: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 729: PAGE_SIZE / 4;
! 730:
! 731: /*
! 732: * Allocate a submap for exec arguments. This map effectively
! 733: * limits the number of processes exec'ing at any time.
! 734: */
! 735: minaddr = vm_map_min(kernel_map);
! 736: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 737: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 738: /* Allocate a submap for physio */
! 739: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 740: VM_PHYS_SIZE, 0, FALSE, NULL);
! 741:
! 742: #ifdef PMAPDEBUG
! 743: pmapdebug = opmapdebug;
! 744: #endif
! 745: printf("avail mem = %u (%uMB)\n", ptoa(uvmexp.free),
! 746: ptoa(uvmexp.free)/1024/1024);
! 747:
! 748: extent_malloc_flags = EX_MALLOCOK;
! 749:
! 750: /*
! 751: * Set up CPU-specific registers, cache, etc.
! 752: */
! 753: initcpu();
! 754:
! 755: /*
! 756: * Set up buffers, so they can be used to read disk labels.
! 757: */
! 758: bufinit();
! 759:
! 760: /*
! 761: * Configure the system.
! 762: */
! 763: if (boothowto & RB_CONFIG) {
! 764: #ifdef BOOT_CONFIG
! 765: user_config();
! 766: #else
! 767: printf("kernel does not support -c; continuing..\n");
! 768: #endif
! 769: }
! 770: }
! 771:
! 772: /*
! 773: * machine dependent system variables.
! 774: */
! 775: int
! 776: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 777: int *name;
! 778: u_int namelen;
! 779: void *oldp;
! 780: size_t *oldlenp;
! 781: void *newp;
! 782: size_t newlen;
! 783: struct proc *p;
! 784: {
! 785: /* all sysctl names at this level are terminal */
! 786: if (namelen != 1)
! 787: return ENOTDIR; /* overloaded */
! 788:
! 789: switch (name[0]) {
! 790: default:
! 791: return EOPNOTSUPP;
! 792: }
! 793: }
! 794:
! 795: /*
! 796: * Set registers on exec for native exec format. For o64/64.
! 797: */
! 798: void
! 799: setregs(p, pack, stack, retval)
! 800: struct proc *p;
! 801: struct exec_package *pack;
! 802: u_long stack;
! 803: register_t *retval;
! 804: {
! 805: extern struct proc *machFPCurProcPtr;
! 806: #if 0
! 807: /* XXX should check validity of header and perhaps be 32/64 indep. */
! 808: Elf64_Ehdr *eh = pack->ep_hdr;
! 809:
! 810: if ((((eh->e_flags & EF_MIPS_ABI) != E_MIPS_ABI_NONE) &&
! 811: ((eh->e_flags & EF_MIPS_ABI) != E_MIPS_ABI_O32)) ||
! 812: ((eh->e_flags & EF_MIPS_ARCH) >= E_MIPS_ARCH_3) ||
! 813: (eh->e_ident[EI_CLASS] != ELFCLASS32)) {
! 814: p->p_md.md_flags |= MDP_O32;
! 815: }
! 816: #endif
! 817:
! 818: #if !defined(__LP64__)
! 819: p->p_md.md_flags |= MDP_O32;
! 820: #else
! 821: p->p_md.md_flags &= ~MDP_O32;
! 822: #endif
! 823:
! 824: bzero((caddr_t)p->p_md.md_regs, sizeof(struct trap_frame));
! 825: p->p_md.md_regs->sp = stack;
! 826: p->p_md.md_regs->pc = pack->ep_entry & ~3;
! 827: p->p_md.md_regs->t9 = pack->ep_entry & ~3; /* abicall req */
! 828: #if defined(__LP64__)
! 829: p->p_md.md_regs->sr = SR_FR_32 | SR_XX | SR_KSU_USER | SR_KX | SR_UX |
! 830: SR_EXL | SR_INT_ENAB;
! 831: if (sys_config.cpu[0].type == MIPS_R12000 &&
! 832: sys_config.system_type == SGI_O2)
! 833: p->p_md.md_regs->sr |= SR_DSD;
! 834: #else
! 835: p->p_md.md_regs->sr = SR_KSU_USER|SR_XX|SR_EXL|SR_INT_ENAB;
! 836: #endif
! 837: p->p_md.md_regs->sr |= idle_mask & SR_INT_MASK;
! 838: p->p_md.md_regs->ic = (idle_mask << 8) & IC_INT_MASK;
! 839: p->p_md.md_flags &= ~MDP_FPUSED;
! 840: if (machFPCurProcPtr == p)
! 841: machFPCurProcPtr = (struct proc *)0;
! 842: p->p_md.md_ss_addr = 0;
! 843: p->p_md.md_pc_ctrl = 0;
! 844: p->p_md.md_watch_1 = 0;
! 845: p->p_md.md_watch_2 = 0;
! 846:
! 847: retval[1] = 0;
! 848: }
! 849:
! 850:
! 851: int waittime = -1;
! 852:
! 853: void
! 854: boot(int howto)
! 855: {
! 856:
! 857: /* take a snap shot before clobbering any registers */
! 858: if (curproc)
! 859: savectx(curproc->p_addr, 0);
! 860:
! 861: #ifdef DEBUG
! 862: if (panicstr)
! 863: stacktrace();
! 864: #endif
! 865:
! 866: if (cold) {
! 867: /*
! 868: * If the system is cold, just halt, unless the user
! 869: * explicitely asked for reboot.
! 870: */
! 871: if ((howto & RB_USERREQ) == 0)
! 872: howto |= RB_HALT;
! 873: goto haltsys;
! 874: }
! 875:
! 876: boothowto = howto;
! 877: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
! 878: extern struct proc proc0;
! 879: /* fill curproc with live object */
! 880: if (curproc == NULL)
! 881: curproc = &proc0;
! 882: /*
! 883: * Synchronize the disks....
! 884: */
! 885: waittime = 0;
! 886: vfs_shutdown();
! 887:
! 888: /*
! 889: * If we've been adjusting the clock, the todr
! 890: * will be out of synch; adjust it now.
! 891: */
! 892: if ((howto & RB_TIMEBAD) == 0) {
! 893: resettodr();
! 894: } else {
! 895: printf("WARNING: not updating battery clock\n");
! 896: }
! 897: }
! 898:
! 899: (void) splhigh(); /* extreme priority */
! 900:
! 901: if (howto & RB_DUMP)
! 902: dumpsys();
! 903:
! 904: haltsys:
! 905: doshutdownhooks();
! 906:
! 907: if (howto & RB_HALT) {
! 908: if (howto & RB_POWERDOWN) {
! 909: printf("System Power Down.\n");
! 910: delay(1000000);
! 911: Bios_PowerDown();
! 912: } else {
! 913: printf("System Halt.\n");
! 914: delay(1000000);
! 915: Bios_EnterInteractiveMode();
! 916: }
! 917: printf("Didn't want to die!!! Reset manually.\n");
! 918: } else {
! 919: printf("System restart.\n");
! 920: delay(1000000);
! 921: Bios_Reboot();
! 922: printf("Restart failed!!! Reset manually.\n");
! 923: }
! 924: for (;;) ;
! 925: /*NOTREACHED*/
! 926: }
! 927:
! 928: int dumpmag = (int)0x8fca0101; /* magic number for savecore */
! 929: int dumpsize = 0; /* also for savecore */
! 930: long dumplo = 0;
! 931:
! 932: void
! 933: dumpconf(void)
! 934: {
! 935: int nblks;
! 936:
! 937: if (dumpdev == NODEV ||
! 938: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
! 939: return;
! 940: if (nblks <= ctod(1))
! 941: return;
! 942:
! 943: dumpsize = ptoa(physmem);
! 944: if (dumpsize > btoc(dbtob(nblks - dumplo)))
! 945: dumpsize = btoc(dbtob(nblks - dumplo));
! 946: else if (dumplo == 0)
! 947: dumplo = nblks - btodb(ctob(physmem));
! 948:
! 949: /*
! 950: * Don't dump on the first page
! 951: * in case the dump device includes a disk label.
! 952: */
! 953: if (dumplo < btodb(PAGE_SIZE))
! 954: dumplo = btodb(PAGE_SIZE);
! 955: }
! 956:
! 957: /*
! 958: * Doadump comes here after turning off memory management and
! 959: * getting on the dump stack, either when called above, or by
! 960: * the auto-restart code.
! 961: */
! 962: void
! 963: dumpsys()
! 964: {
! 965: extern int msgbufmapped;
! 966:
! 967: msgbufmapped = 0;
! 968: if (dumpdev == NODEV)
! 969: return;
! 970: /*
! 971: * For dumps during autoconfiguration,
! 972: * if dump device has already configured...
! 973: */
! 974: if (dumpsize == 0)
! 975: dumpconf();
! 976: if (dumplo < 0)
! 977: return;
! 978: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
! 979: printf("dump not yet implemented");
! 980: #if 0 /* XXX HAVE TO FIX XXX */
! 981: switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev, dumplo,)) {
! 982:
! 983: case ENXIO:
! 984: printf("device bad\n");
! 985: break;
! 986:
! 987: case EFAULT:
! 988: printf("device not ready\n");
! 989: break;
! 990:
! 991: case EINVAL:
! 992: printf("area improper\n");
! 993: break;
! 994:
! 995: case EIO:
! 996: printf("i/o error\n");
! 997: break;
! 998:
! 999: default:
! 1000: printf("error %d\n", error);
! 1001: break;
! 1002:
! 1003: case 0:
! 1004: printf("succeeded\n");
! 1005: }
! 1006: #endif
! 1007: }
! 1008:
! 1009: void
! 1010: initcpu()
! 1011: {
! 1012: }
! 1013:
! 1014: /*
! 1015: * Convert "xx:xx:xx:xx:xx:xx" string to ethernet hardware address.
! 1016: */
! 1017: void
! 1018: enaddr_aton(const char *s, u_int8_t *a)
! 1019: {
! 1020: int i;
! 1021:
! 1022: if (s != NULL) {
! 1023: for(i = 0; i < 6; i++) {
! 1024: a[i] = atoi(s, 16, &s);
! 1025: if (*s == ':')
! 1026: s++;
! 1027: }
! 1028: }
! 1029: }
! 1030:
! 1031: /*
! 1032: * Convert an ASCII string into an integer.
! 1033: */
! 1034: static int
! 1035: atoi(const char *s, int b, const char **o)
! 1036: {
! 1037: int c;
! 1038: unsigned base = b, d;
! 1039: int neg = 0, val = 0;
! 1040:
! 1041: if (s == NULL || *s == 0) {
! 1042: if (o != NULL)
! 1043: *o = s;
! 1044: return 0;
! 1045: }
! 1046:
! 1047: /* skip spaces if any */
! 1048: do {
! 1049: c = *s++;
! 1050: } while (c == ' ' || c == '\t');
! 1051:
! 1052: /* parse sign, allow more than one (compat) */
! 1053: while (c == '-') {
! 1054: neg = !neg;
! 1055: c = *s++;
! 1056: }
! 1057:
! 1058: /* parse base specification, if any */
! 1059: if (c == '0') {
! 1060: c = *s++;
! 1061: switch (c) {
! 1062: case 'X':
! 1063: case 'x':
! 1064: base = 16;
! 1065: c = *s++;
! 1066: break;
! 1067: case 'B':
! 1068: case 'b':
! 1069: base = 2;
! 1070: c = *s++;
! 1071: break;
! 1072: default:
! 1073: base = 8;
! 1074: }
! 1075: }
! 1076:
! 1077: /* parse number proper */
! 1078: for (;;) {
! 1079: if (c >= '0' && c <= '9')
! 1080: d = c - '0';
! 1081: else if (c >= 'a' && c <= 'z')
! 1082: d = c - 'a' + 10;
! 1083: else if (c >= 'A' && c <= 'Z')
! 1084: d = c - 'A' + 10;
! 1085: else
! 1086: break;
! 1087: val *= base;
! 1088: val += d;
! 1089: c = *s++;
! 1090: }
! 1091: if (neg)
! 1092: val = -val;
! 1093: if (o != NULL)
! 1094: *o = s - 1;
! 1095: return val;
! 1096: }
! 1097:
! 1098: /*
! 1099: * RM7000 Performance counter support.
! 1100: */
! 1101:
! 1102: int
! 1103: rm7k_perfcntr(cmd, arg1, arg2, arg3)
! 1104: int cmd;
! 1105: long arg1, arg2, arg3;
! 1106: {
! 1107: int result;
! 1108: quad_t cntval;
! 1109: struct proc *p = curproc;
! 1110:
! 1111:
! 1112: switch(cmd) {
! 1113: case PCNT_FNC_SELECT:
! 1114: if ((arg1 & 0xff) > PCNT_SRC_MAX ||
! 1115: (arg1 & ~(PCNT_CE|PCNT_UM|PCNT_KM|0xff)) != 0) {
! 1116: result = EINVAL;
! 1117: break;
! 1118: }
! 1119: #ifdef DEBUG
! 1120: printf("perfcnt select %x, proc %p\n", arg1, p);
! 1121: #endif
! 1122: p->p_md.md_pc_count = 0;
! 1123: p->p_md.md_pc_spill = 0;
! 1124: p->p_md.md_pc_ctrl = arg1;
! 1125: result = 0;
! 1126: break;
! 1127:
! 1128: case PCNT_FNC_READ:
! 1129: cntval = p->p_md.md_pc_count;
! 1130: cntval += (quad_t)p->p_md.md_pc_spill << 31;
! 1131: result = copyout(&cntval, (void *)arg1, sizeof(cntval));
! 1132: break;
! 1133:
! 1134: default:
! 1135: #ifdef DEBUG
! 1136: printf("perfcnt error %d\n", cmd);
! 1137: #endif
! 1138: result = -1;
! 1139: break;
! 1140: }
! 1141: return(result);
! 1142: }
! 1143:
! 1144: /*
! 1145: * Called when the performance counter d31 gets set.
! 1146: * Increase spill value and reset d31.
! 1147: */
! 1148: void
! 1149: rm7k_perfintr(trapframe)
! 1150: struct trap_frame *trapframe;
! 1151: {
! 1152: struct proc *p = curproc;
! 1153:
! 1154: printf("perfintr proc %p!\n", p);
! 1155: cp0_setperfcount(cp0_getperfcount() & 0x7fffffff);
! 1156: if (p != NULL) {
! 1157: p->p_md.md_pc_spill++;
! 1158: }
! 1159: }
! 1160:
! 1161: int
! 1162: rm7k_watchintr(trapframe)
! 1163: struct trap_frame *trapframe;
! 1164: {
! 1165: return(0);
! 1166: }
! 1167:
! 1168: #ifdef DEBUG
! 1169: /*
! 1170: * Dump TLB contents.
! 1171: */
! 1172: void
! 1173: dump_tlb()
! 1174: {
! 1175: char *attr[] = {
! 1176: "CWTNA", "CWTA ", "UCBL ", "CWB ", "RES ", "RES ", "UCNB ", "BPASS"
! 1177: };
! 1178:
! 1179: int tlbno, last;
! 1180: struct tlb_entry tlb;
! 1181:
! 1182: last = 64;
! 1183:
! 1184: for (tlbno = 0; tlbno < last; tlbno++) {
! 1185: tlb_read(tlbno, &tlb);
! 1186:
! 1187: if (tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V) {
! 1188: bios_printf("%2d v=%p", tlbno, tlb.tlb_hi & 0xffffffffffffff00);
! 1189: bios_printf("/%02x ", tlb.tlb_hi & 0xff);
! 1190:
! 1191: if (tlb.tlb_lo0 & PG_V) {
! 1192: bios_printf("0x%09x ", pfn_to_pad(tlb.tlb_lo0));
! 1193: bios_printf("%c", tlb.tlb_lo0 & PG_M ? 'M' : ' ');
! 1194: bios_printf("%c", tlb.tlb_lo0 & PG_G ? 'G' : ' ');
! 1195: bios_printf(" %s ", attr[(tlb.tlb_lo0 >> 3) & 7]);
! 1196: } else {
! 1197: bios_printf("invalid ");
! 1198: }
! 1199:
! 1200: if (tlb.tlb_lo1 & PG_V) {
! 1201: bios_printf("0x%08x ", pfn_to_pad(tlb.tlb_lo1));
! 1202: bios_printf("%c", tlb.tlb_lo1 & PG_M ? 'M' : ' ');
! 1203: bios_printf("%c", tlb.tlb_lo1 & PG_G ? 'G' : ' ');
! 1204: bios_printf(" %s ", attr[(tlb.tlb_lo1 >> 3) & 7]);
! 1205: } else {
! 1206: bios_printf("invalid ");
! 1207: }
! 1208: bios_printf(" sz=%x", tlb.tlb_mask);
! 1209: }
! 1210: else {
! 1211: bios_printf("%2d v=invalid ", tlbno);
! 1212: }
! 1213: bios_printf("\n");
! 1214: }
! 1215: }
! 1216: #endif
CVSweb