1 /* 2 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3 * Copyright (C) 1995, 1996 TooLs GmbH. 4 * All rights reserved. 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 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by TooLs GmbH. 17 * 4. The name of TooLs GmbH may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /* 32 * Copyright (C) 2001 Benno Rice 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 44 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 47 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 49 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 50 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 51 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 52 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 53 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $ 55 */ 56 57 #ifndef lint 58 static const char rcsid[] = 59 "$FreeBSD$"; 60 #endif /* not lint */ 61 62 #include "opt_ddb.h" 63 #include "opt_compat.h" 64 #include "opt_msgbuf.h" 65 66 #include <sys/param.h> 67 #include <sys/systm.h> 68 #include <sys/eventhandler.h> 69 #include <sys/sysproto.h> 70 #include <sys/mutex.h> 71 #include <sys/ktr.h> 72 #include <sys/signalvar.h> 73 #include <sys/kernel.h> 74 #include <sys/proc.h> 75 #include <sys/lock.h> 76 #include <sys/malloc.h> 77 #include <sys/reboot.h> 78 #include <sys/bio.h> 79 #include <sys/buf.h> 80 #include <sys/bus.h> 81 #include <sys/mbuf.h> 82 #include <sys/vmmeter.h> 83 #include <sys/msgbuf.h> 84 #include <sys/exec.h> 85 #include <sys/sysctl.h> 86 #include <sys/uio.h> 87 #include <sys/linker.h> 88 #include <sys/cons.h> 89 #include <net/netisr.h> 90 #include <vm/vm.h> 91 #include <vm/vm_kern.h> 92 #include <vm/vm_page.h> 93 #include <vm/vm_map.h> 94 #include <vm/vm_extern.h> 95 #include <vm/vm_object.h> 96 #include <vm/vm_pager.h> 97 #include <sys/user.h> 98 #include <sys/ptrace.h> 99 #include <machine/bat.h> 100 #include <machine/clock.h> 101 #include <machine/md_var.h> 102 #include <machine/reg.h> 103 #include <machine/fpu.h> 104 #include <machine/globaldata.h> 105 #include <machine/vmparam.h> 106 #include <machine/elf.h> 107 #include <machine/trap.h> 108 #include <machine/powerpc.h> 109 #include <dev/ofw/openfirm.h> 110 #include <ddb/ddb.h> 111 #include <sys/vnode.h> 112 #include <fs/procfs/procfs.h> 113 #include <machine/sigframe.h> 114 115 int cold = 1; 116 117 struct mtx sched_lock; 118 struct mtx Giant; 119 120 struct user *proc0paddr; 121 122 char machine[] = "powerpc"; 123 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 124 125 static char model[128]; 126 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); 127 128 char bootpath[256]; 129 130 #ifdef DDB 131 /* start and end of kernel symbol table */ 132 void *ksym_start, *ksym_end; 133 #endif /* DDB */ 134 135 static void cpu_startup(void *); 136 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 137 138 void powerpc_init(u_int, u_int, u_int, char *); 139 140 int save_ofw_mapping(void); 141 int restore_ofw_mapping(void); 142 143 void install_extint(void (*)(void)); 144 145 void osendsig(sig_t, int, sigset_t *, u_long); 146 147 struct msgbuf *msgbufp = 0; 148 149 int bootverbose = 0, Maxmem = 0; 150 long dumplo; 151 152 vm_offset_t phys_avail[10]; 153 154 static int chosen; 155 156 struct pmap ofw_pmap; 157 extern int ofmsr; 158 159 struct bat battable[16]; 160 161 static void identifycpu(void); 162 163 static vm_offset_t buffer_sva, buffer_eva; 164 vm_offset_t clean_sva, clean_eva; 165 static vm_offset_t pager_sva, pager_eva; 166 167 static void 168 powerpc_ofw_shutdown(void *junk, int howto) 169 { 170 if (howto & RB_HALT) { 171 OF_exit(); 172 } 173 } 174 175 static void 176 cpu_startup(void *dummy) 177 { 178 unsigned int i; 179 caddr_t v; 180 vm_offset_t maxaddr; 181 vm_size_t size; 182 vm_offset_t firstaddr; 183 vm_offset_t minaddr; 184 185 size = 0; 186 187 /* 188 * Good {morning,afternoon,evening,night}. 189 */ 190 identifycpu(); 191 192 /* startrtclock(); */ 193 #ifdef PERFMON 194 perfmon_init(); 195 #endif 196 printf("real memory = %ld (%ldK bytes)\n", ptoa(Maxmem), 197 ptoa(Maxmem) / 1024); 198 199 /* 200 * Display any holes after the first chunk of extended memory. 201 */ 202 if (bootverbose) { 203 int indx; 204 205 printf("Physical memory chunk(s):\n"); 206 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 207 int size1 = phys_avail[indx + 1] - phys_avail[indx]; 208 209 printf("0x%08x - 0x%08x, %d bytes (%d pages)\n", 210 phys_avail[indx], phys_avail[indx + 1] - 1, size1, 211 size1 / PAGE_SIZE); 212 } 213 } 214 215 /* 216 * Calculate callout wheel size 217 */ 218 for (callwheelsize = 1, callwheelbits = 0; 219 callwheelsize < ncallout; 220 callwheelsize <<= 1, ++callwheelbits) 221 ; 222 callwheelmask = callwheelsize - 1; 223 224 /* 225 * Allocate space for system data structures. 226 * The first available kernel virtual address is in "v". 227 * As pages of kernel virtual memory are allocated, "v" is incremented. 228 * As pages of memory are allocated and cleared, 229 * "firstaddr" is incremented. 230 * An index into the kernel page table corresponding to the 231 * virtual memory address maintained in "v" is kept in "mapaddr". 232 */ 233 234 /* 235 * Make two passes. The first pass calculates how much memory is 236 * needed and allocates it. The second pass assigns virtual 237 * addresses to the various data structures. 238 */ 239 firstaddr = 0; 240 again: 241 v = (caddr_t)firstaddr; 242 243 #define valloc(name, type, num) \ 244 (name) = (type *)v; v = (caddr_t)((name)+(num)) 245 #define valloclim(name, type, num, lim) \ 246 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 247 248 valloc(callout, struct callout, ncallout); 249 valloc(callwheel, struct callout_tailq, callwheelsize); 250 251 /* 252 * The nominal buffer size (and minimum KVA allocation) is BKVASIZE. 253 * For the first 64MB of ram nominally allocate sufficient buffers to 254 * cover 1/4 of our ram. Beyond the first 64MB allocate additional 255 * buffers to cover 1/20 of our ram over 64MB. 256 */ 257 258 if (nbuf == 0) { 259 int factor; 260 261 factor = 4 * BKVASIZE / PAGE_SIZE; 262 nbuf = 50; 263 if (Maxmem > 1024) 264 nbuf += min((Maxmem - 1024) / factor, 16384 / factor); 265 if (Maxmem > 16384) 266 nbuf += (Maxmem - 16384) * 2 / (factor * 5); 267 } 268 nswbuf = max(min(nbuf/4, 64), 16); 269 270 valloc(swbuf, struct buf, nswbuf); 271 valloc(buf, struct buf, nbuf); 272 v = bufhashinit(v); 273 274 /* 275 * End of first pass, size has been calculated so allocate memory 276 */ 277 if (firstaddr == 0) { 278 size = (vm_size_t)(v - firstaddr); 279 firstaddr = (vm_offset_t)kmem_alloc(kernel_map, 280 round_page(size)); 281 if (firstaddr == 0) 282 panic("startup: no room for tables"); 283 goto again; 284 } 285 286 /* 287 * End of second pass, addresses have been assigned 288 */ 289 if ((vm_size_t)(v - firstaddr) != size) 290 panic("startup: table size inconsistency"); 291 292 clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, 293 (nbuf*BKVASIZE) + (nswbuf*MAXPHYS) + pager_map_size); 294 buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva, 295 (nbuf*BKVASIZE)); 296 pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva, 297 (nswbuf*MAXPHYS) + pager_map_size); 298 pager_map->system_map = 1; 299 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 300 (16*(ARG_MAX+(PAGE_SIZE*3)))); 301 302 /* 303 * XXX: Mbuf system machine-specific initializations should 304 * go here, if anywhere. 305 */ 306 307 /* 308 * Initialize callouts 309 */ 310 SLIST_INIT(&callfree); 311 for (i = 0; i < ncallout; i++) { 312 callout_init(&callout[i], 0); 313 callout[i].c_flags = CALLOUT_LOCAL_ALLOC; 314 SLIST_INSERT_HEAD(&callfree, &callout[i], c_links.sle); 315 } 316 317 for (i = 0; i < callwheelsize; i++) { 318 TAILQ_INIT(&callwheel[i]); 319 } 320 321 mtx_init(&callout_lock, "callout", MTX_SPIN); 322 323 #if defined(USERCONFIG) 324 #if defined(USERCONFIG_BOOT) 325 if (1) 326 #else 327 if (boothowto & RB_CONFIG) 328 #endif 329 { 330 userconfig(); 331 cninit(); /* the preferred console may have changed */ 332 } 333 #endif 334 335 printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count), 336 ptoa(cnt.v_free_count) / 1024); 337 338 /* 339 * Set up buffers, so they can be used to read disk labels. 340 */ 341 bufinit(); 342 vm_pager_bufferinit(); 343 EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0, 344 SHUTDOWN_PRI_LAST); 345 346 #ifdef SMP 347 /* 348 * OK, enough kmem_alloc/malloc state should be up, lets get on with it! 349 */ 350 mp_start(); /* fire up the secondaries */ 351 mp_announce(); 352 #endif /* SMP */ 353 } 354 355 void 356 identifycpu() 357 { 358 unsigned int pvr, version, revision; 359 360 /* 361 * Find cpu type (Do it by OpenFirmware?) 362 */ 363 __asm ("mfpvr %0" : "=r"(pvr)); 364 version = pvr >> 16; 365 revision = pvr & 0xffff; 366 switch (version) { 367 case 0x0001: 368 sprintf(model, "601"); 369 break; 370 case 0x0003: 371 sprintf(model, "603 (Wart)"); 372 break; 373 case 0x0004: 374 sprintf(model, "604 (Zephyr)"); 375 break; 376 case 0x0005: 377 sprintf(model, "602 (Galahad)"); 378 break; 379 case 0x0006: 380 sprintf(model, "603e (Stretch)"); 381 break; 382 case 0x0007: 383 if ((revision && 0xf000) == 0x0000) 384 sprintf(model, "603ev (Valiant)"); 385 else 386 sprintf(model, "603r (Goldeneye)"); 387 break; 388 case 0x0008: 389 if ((revision && 0xf000) == 0x0000) 390 sprintf(model, "G3 / 750 (Arthur)"); 391 else 392 sprintf(model, "G3 / 755 (Goldfinger)"); 393 break; 394 case 0x0009: 395 if ((revision && 0xf000) == 0x0000) 396 sprintf(model, "604e (Sirocco)"); 397 else 398 sprintf(model, "604r (Mach V)"); 399 break; 400 case 0x000a: 401 sprintf(model, "604r (Mach V)"); 402 break; 403 case 0x000c: 404 sprintf(model, "G4 / 7400 (Max)"); 405 break; 406 case 0x0014: 407 sprintf(model, "620 (Red October)"); 408 break; 409 case 0x0081: 410 sprintf(model, "8240 (Kahlua)"); 411 break; 412 case 0x8000: 413 sprintf(model, "G4 / 7450 (V'ger)"); 414 break; 415 case 0x800c: 416 sprintf(model, "G4 / 7410 (Nitro)"); 417 break; 418 case 0x8081: 419 sprintf(model, "8245 (Kahlua II)"); 420 break; 421 default: 422 sprintf(model, "Version %x", version); 423 break; 424 } 425 sprintf(model + strlen(model), " (Revision %x)", revision); 426 printf("CPU: PowerPC %s\n", model); 427 } 428 429 extern char kernel_text[], _end[]; 430 431 extern void *trapcode, *trapsize; 432 extern void *alitrap, *alisize; 433 extern void *dsitrap, *dsisize; 434 extern void *isitrap, *isisize; 435 extern void *decrint, *decrsize; 436 extern void *tlbimiss, *tlbimsize; 437 extern void *tlbdlmiss, *tlbdlmsize; 438 extern void *tlbdsmiss, *tlbdsmsize; 439 440 #if 0 /* XXX: interrupt handler. We'll get to this later */ 441 extern void ext_intr(void); 442 #endif 443 444 #ifdef DDB 445 extern ddblow, ddbsize; 446 #endif 447 #ifdef IPKDB 448 extern ipkdblow, ipkdbsize; 449 #endif 450 451 static struct globaldata tmpglobal; 452 453 void 454 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args) 455 { 456 unsigned int exc, scratch; 457 struct mem_region *allmem, *availmem, *mp; 458 struct globaldata *globalp; 459 460 /* 461 * Set up BAT0 to only map the lowest 256 MB area 462 */ 463 battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); 464 battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); 465 466 /* 467 * Map PCI memory space. 468 */ 469 battable[0x8].batl = BATL(0x80000000, BAT_I, BAT_PP_RW); 470 battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); 471 472 battable[0x9].batl = BATL(0x90000000, BAT_I, BAT_PP_RW); 473 battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs); 474 475 battable[0xa].batl = BATL(0xa0000000, BAT_I, BAT_PP_RW); 476 battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs); 477 478 /* 479 * Map obio devices. 480 */ 481 battable[0xf].batl = BATL(0xf0000000, BAT_I, BAT_PP_RW); 482 battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs); 483 484 /* 485 * Now setup fixed bat registers 486 * 487 * Note that we still run in real mode, and the BAT 488 * registers were cleared above. 489 */ 490 /* BAT0 used for initial 256 MB segment */ 491 __asm __volatile ("mtibatl 0,%0; mtibatu 0,%1;" 492 "mtdbatl 0,%0; mtdbatu 0,%1;" 493 :: "r"(battable[0].batl), "r"(battable[0].batu)); 494 /* 495 * Set up battable to map all RAM regions. 496 * This is here because mem_regions() call needs bat0 set up. 497 */ 498 mem_regions(&allmem, &availmem); 499 for (mp = allmem; mp->size; mp++) { 500 vm_offset_t pa = mp->start & 0xf0000000; 501 vm_offset_t end = mp->start + mp->size; 502 503 do { 504 u_int n = pa >> 28; 505 506 battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW); 507 battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs); 508 pa += 0x10000000; 509 } while (pa < end); 510 } 511 512 chosen = OF_finddevice("/chosen"); 513 save_ofw_mapping(); 514 515 proc0.p_addr = proc0paddr; 516 bzero(proc0.p_addr, sizeof *proc0.p_addr); 517 518 LIST_INIT(&proc0.p_contested); 519 520 /* XXX: NetBSDism I _think_. Not sure yet. */ 521 #if 0 522 curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = kernel_pmap; 523 #endif 524 525 /* 526 * Initialise some mutexes. 527 */ 528 mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE); 529 mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE); 530 mtx_init(&proc0.p_mtx, "process lock", MTX_DEF); 531 532 /* 533 * Initialise console. 534 */ 535 cninit(); 536 537 mtx_lock(&Giant); 538 539 #ifdef __notyet__ /* Needs some rethinking regarding real/virtual OFW */ 540 OF_set_callback(callback); 541 #endif 542 543 /* 544 * Set up trap vectors 545 */ 546 for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) { 547 switch (exc) { 548 default: 549 bcopy(&trapcode, (void *)exc, (size_t)&trapsize); 550 break; 551 case EXC_DECR: 552 bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize); 553 break; 554 #if 0 /* XXX: Not enabling these traps yet. */ 555 case EXC_EXI: 556 /* 557 * This one is (potentially) installed during autoconf 558 */ 559 break; 560 case EXC_ALI: 561 bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize); 562 break; 563 case EXC_DSI: 564 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); 565 break; 566 case EXC_ISI: 567 bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); 568 break; 569 case EXC_IMISS: 570 bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize); 571 break; 572 case EXC_DLMISS: 573 bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize); 574 break; 575 case EXC_DSMISS: 576 bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize); 577 break; 578 #if defined(DDB) || defined(IPKDB) 579 case EXC_TRC: 580 case EXC_PGM: 581 case EXC_BPT: 582 #if defined(DDB) 583 bcopy(&ddblow, (void *)exc, (size_t)&ddbsize); 584 #else 585 bcopy(&ipkdblow, (void *)exc, (size_t)&ipkdbsize); 586 #endif 587 break; 588 #endif /* DDB || IPKDB */ 589 #endif 590 } 591 } 592 593 #if 0 /* XXX: coming soon... */ 594 /* 595 * external interrupt handler install 596 */ 597 install_extint(ext_intr); 598 #endif 599 600 __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); 601 602 /* 603 * Now enable translation (and machine checks/recoverable interrupts). 604 */ 605 __asm ("mfmsr %0" : "=r"(scratch)); 606 scratch |= PSL_IR | PSL_DR | PSL_ME | PSL_RI; 607 __asm ("mtmsr %0" :: "r"(scratch)); 608 609 ofmsr &= ~PSL_IP; 610 611 /* 612 * Parse arg string. 613 */ 614 #ifdef DDB 615 bcopy(args + strlen(args) + 1, &startsym, sizeof(startsym)); 616 bcopy(args + strlen(args) + 5, &endsym, sizeof(endsym)); 617 if (startsym == NULL || endsym == NULL) 618 startsym = endsym = NULL; 619 #endif 620 621 strcpy(bootpath, args); 622 args = bootpath; 623 while (*++args && *args != ' '); 624 if (*args) { 625 *args++ = 0; 626 while (*args) { 627 switch (*args++) { 628 case 'a': 629 boothowto |= RB_ASKNAME; 630 break; 631 case 's': 632 boothowto |= RB_SINGLE; 633 break; 634 case 'd': 635 boothowto |= RB_KDB; 636 break; 637 case 'v': 638 boothowto |= RB_VERBOSE; 639 break; 640 } 641 } 642 } 643 644 #ifdef DDB 645 ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 646 #endif 647 #ifdef IPKDB 648 /* 649 * Now trap to IPKDB 650 */ 651 ipkdb_init(); 652 if (boothowto & RB_KDB) 653 ipkdb_connect(0); 654 #endif 655 656 /* 657 * Set the page size. 658 */ 659 #if 0 660 vm_set_page_size(); 661 #endif 662 663 /* 664 * Initialize pmap module. 665 */ 666 pmap_bootstrap(startkernel, endkernel); 667 668 restore_ofw_mapping(); 669 670 /* 671 * Setup the global data for the bootstrap cpu. 672 */ 673 globalp = (struct globaldata *) &tmpglobal; 674 675 /* 676 * XXX: Pass 0 as CPU id. This is bad. We need to work out 677 * XXX: which CPU we are somehow. 678 */ 679 globaldata_init(globalp, 0, sizeof(struct globaldata)); 680 __asm ("mtsprg 0, %0" :: "r"(globalp)); 681 682 PCPU_GET(next_asn) = 1; /* 0 used for proc0 pmap */ 683 PCPU_SET(curproc, &proc0); 684 PCPU_SET(spinlocks, NULL); 685 } 686 687 static int N_mapping; 688 static struct { 689 vm_offset_t va; 690 int len; 691 vm_offset_t pa; 692 int mode; 693 } ofw_mapping[256]; 694 695 int 696 save_ofw_mapping() 697 { 698 int mmui, mmu; 699 700 OF_getprop(chosen, "mmu", &mmui, 4); 701 mmu = OF_instance_to_package(mmui); 702 703 bzero(ofw_mapping, sizeof(ofw_mapping)); 704 705 N_mapping = 706 OF_getprop(mmu, "translations", ofw_mapping, sizeof(ofw_mapping)); 707 N_mapping /= sizeof(ofw_mapping[0]); 708 709 return 0; 710 } 711 712 int 713 restore_ofw_mapping() 714 { 715 int i; 716 struct vm_page pg; 717 718 pmap_pinit(&ofw_pmap); 719 720 ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT; 721 722 for (i = 0; i < N_mapping; i++) { 723 vm_offset_t pa = ofw_mapping[i].pa; 724 vm_offset_t va = ofw_mapping[i].va; 725 int size = ofw_mapping[i].len; 726 727 if (va < 0x90000000) /* XXX */ 728 continue; 729 730 while (size > 0) { 731 pg.phys_addr = pa; 732 pmap_enter(&ofw_pmap, va, &pg, VM_PROT_ALL, 733 VM_PROT_ALL); 734 pa += PAGE_SIZE; 735 va += PAGE_SIZE; 736 size -= PAGE_SIZE; 737 } 738 } 739 740 return 0; 741 } 742 743 void 744 bzero(void *buf, size_t len) 745 { 746 caddr_t p; 747 748 p = buf; 749 750 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { 751 *p++ = 0; 752 len--; 753 } 754 755 while (len >= sizeof(u_long) * 8) { 756 *(u_long*) p = 0; 757 *((u_long*) p + 1) = 0; 758 *((u_long*) p + 2) = 0; 759 *((u_long*) p + 3) = 0; 760 len -= sizeof(u_long) * 8; 761 *((u_long*) p + 4) = 0; 762 *((u_long*) p + 5) = 0; 763 *((u_long*) p + 6) = 0; 764 *((u_long*) p + 7) = 0; 765 p += sizeof(u_long) * 8; 766 } 767 768 while (len >= sizeof(u_long)) { 769 *(u_long*) p = 0; 770 len -= sizeof(u_long); 771 p += sizeof(u_long); 772 } 773 774 while (len) { 775 *p++ = 0; 776 len--; 777 } 778 } 779 780 #if 0 781 void 782 delay(unsigned n) 783 { 784 u_long tb; 785 786 do { 787 __asm __volatile("mftb %0" : "=r" (tb)); 788 } while (n > (int)(tb & 0xffffffff)); 789 } 790 #endif 791 792 void 793 osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 794 { 795 796 /* XXX: To be done */ 797 return; 798 } 799 800 void 801 sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 802 { 803 804 /* XXX: To be done */ 805 return; 806 } 807 808 int 809 osigreturn(struct proc *p, struct osigreturn_args *uap) 810 { 811 812 /* XXX: To be done */ 813 return(ENOSYS); 814 } 815 816 int 817 sigreturn(struct proc *p, struct sigreturn_args *uap) 818 { 819 820 /* XXX: To be done */ 821 return(ENOSYS); 822 } 823 824 void 825 cpu_boot(int howto) 826 { 827 } 828 829 /* 830 * Shutdown the CPU as much as possible. 831 */ 832 void 833 cpu_halt(void) 834 { 835 836 OF_exit(); 837 } 838 839 /* 840 * Set set up registers on exec. 841 */ 842 void 843 setregs(struct proc *p, u_long entry, u_long stack, u_long ps_strings) 844 { 845 struct trapframe *tf; 846 struct ps_strings arginfo; 847 848 tf = trapframe(p); 849 850 bzero(tf, sizeof *tf); 851 tf->fixreg[1] = -roundup(-stack + 8, 16); 852 853 /* 854 * XXX Machine-independent code has already copied arguments and 855 * XXX environment to userland. Get them back here. 856 */ 857 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo)); 858 859 /* 860 * Set up arguments for _start(): 861 * _start(argc, argv, envp, obj, cleanup, ps_strings); 862 * 863 * Notes: 864 * - obj and cleanup are the auxilliary and termination 865 * vectors. They are fixed up by ld.elf_so. 866 * - ps_strings is a NetBSD extention, and will be 867 * ignored by executables which are strictly 868 * compliant with the SVR4 ABI. 869 * 870 * XXX We have to set both regs and retval here due to different 871 * XXX calling convention in trap.c and init_main.c. 872 */ 873 tf->fixreg[3] = arginfo.ps_nargvstr; 874 tf->fixreg[4] = (register_t)arginfo.ps_argvstr; 875 tf->fixreg[5] = (register_t)arginfo.ps_envstr; 876 tf->fixreg[6] = 0; /* auxillary vector */ 877 tf->fixreg[7] = 0; /* termination vector */ 878 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ 879 880 tf->srr0 = entry; 881 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 882 p->p_addr->u_pcb.pcb_flags = 0; 883 } 884 885 extern void *extint, *extsize; 886 extern u_long extint_call; 887 888 void 889 install_extint(void (*handler)(void)) 890 { 891 u_long offset; 892 int omsr, msr; 893 894 offset = (u_long)handler - (u_long)&extint_call; 895 896 #ifdef DIAGNOSTIC 897 if (offset > 0x1ffffff) 898 panic("install_extint: too far away"); 899 #endif 900 901 msr = mfmsr(); 902 mtmsr(msr & ~PSL_EE); 903 904 extint_call = (extint_call & 0xfc000003) | offset; 905 bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize); 906 __syncicache((void *)&extint_call, sizeof extint_call); 907 __syncicache((void *)EXC_EXI, (int)&extsize); 908 909 mtmsr(msr); 910 } 911 912 #if !defined(DDB) 913 void 914 Debugger(const char *msg) 915 { 916 917 printf("Debugger(\"%s\") called.\n", msg); 918 } 919 #endif /* !defined(DDB) */ 920 921 /* XXX: dummy {fill,set}_[fp]regs */ 922 int 923 fill_regs(struct proc *p, struct reg *regs) 924 { 925 926 return (ENOSYS); 927 } 928 929 int 930 fill_fpregs(struct proc *p, struct fpreg *fpregs) 931 { 932 933 return (ENOSYS); 934 } 935 936 int 937 set_regs(struct proc *p, struct reg *regs) 938 { 939 940 return (ENOSYS); 941 } 942 943 int 944 set_fpregs(struct proc *p, struct fpreg *fpregs) 945 { 946 947 return (ENOSYS); 948 } 949 950 int 951 ptrace_set_pc(struct proc *p, unsigned long addr) 952 { 953 954 /* XXX: coming soon... */ 955 return (ENOSYS); 956 } 957 958 int 959 ptrace_single_step(struct proc *p) 960 { 961 962 /* XXX: coming soon... */ 963 return (ENOSYS); 964 } 965 966 int 967 ptrace_write_u(struct proc *p, vm_offset_t off, long data) 968 { 969 970 /* XXX: coming soon... */ 971 return (ENOSYS); 972 } 973 974 int 975 ptrace_read_u_check(struct proc *p, vm_offset_t addr, size_t len) 976 { 977 978 /* XXX: coming soon... */ 979 return (ENOSYS); 980 } 981 982 int 983 ptrace_clear_single_step(struct proc *p) 984 { 985 986 /* XXX: coming soon... */ 987 return (ENOSYS); 988 } 989 990 /* 991 * Initialise a struct globaldata. 992 */ 993 void 994 globaldata_init(struct globaldata *globaldata, int cpuid, size_t sz) 995 { 996 997 bzero(globaldata, sz); 998 globaldata->gd_cpuid = cpuid; 999 globaldata->gd_next_asn = 0; 1000 globaldata->gd_current_asngen = 1; 1001 } 1002