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/lock.h> 71 #include <sys/mutex.h> 72 #include <sys/ktr.h> 73 #include <sys/signalvar.h> 74 #include <sys/kernel.h> 75 #include <sys/proc.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 <sys/ucontext.h> 90 #include <net/netisr.h> 91 #include <vm/vm.h> 92 #include <vm/vm_kern.h> 93 #include <vm/vm_page.h> 94 #include <vm/vm_map.h> 95 #include <vm/vm_extern.h> 96 #include <vm/vm_object.h> 97 #include <vm/vm_pager.h> 98 #include <sys/user.h> 99 #include <sys/ptrace.h> 100 #include <machine/bat.h> 101 #include <machine/clock.h> 102 #include <machine/md_var.h> 103 #include <machine/metadata.h> 104 #include <machine/reg.h> 105 #include <machine/fpu.h> 106 #include <machine/vmparam.h> 107 #include <machine/elf.h> 108 #include <machine/trap.h> 109 #include <machine/powerpc.h> 110 #include <dev/ofw/openfirm.h> 111 #include <ddb/ddb.h> 112 #include <sys/vnode.h> 113 #include <machine/sigframe.h> 114 115 int physmem = 0; 116 int cold = 1; 117 118 char pcpu0[PAGE_SIZE]; 119 char uarea0[UAREA_PAGES * PAGE_SIZE]; 120 struct trapframe frame0; 121 122 vm_offset_t kstack0; 123 vm_offset_t kstack0_phys; 124 125 char machine[] = "powerpc"; 126 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 127 128 static char model[128]; 129 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); 130 131 char bootpath[256]; 132 133 #ifdef DDB 134 /* start and end of kernel symbol table */ 135 void *ksym_start, *ksym_end; 136 #endif /* DDB */ 137 138 static void cpu_startup(void *); 139 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 140 141 void powerpc_init(u_int, u_int, u_int, void *); 142 143 int save_ofw_mapping(void); 144 int restore_ofw_mapping(void); 145 146 void install_extint(void (*)(void)); 147 148 #ifdef COMPAT_43 149 void osendsig(sig_t, int, sigset_t *, u_long); 150 #endif 151 152 static int 153 sysctl_hw_physmem(SYSCTL_HANDLER_ARGS) 154 { 155 int error = sysctl_handle_int(oidp, 0, ctob(physmem), req); 156 return (error); 157 } 158 159 SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD, 160 0, 0, sysctl_hw_physmem, "IU", ""); 161 162 int Maxmem = 0; 163 164 static int chosen; 165 166 struct pmap ofw_pmap; 167 extern int ofmsr; 168 169 struct bat battable[16]; 170 171 static void identifycpu(void); 172 173 struct kva_md_info kmi; 174 175 static void 176 powerpc_ofw_shutdown(void *junk, int howto) 177 { 178 if (howto & RB_HALT) { 179 OF_exit(); 180 } 181 } 182 183 static void 184 cpu_startup(void *dummy) 185 { 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 vm_ksubmap_init(&kmi); 216 217 printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count), 218 ptoa(cnt.v_free_count) / 1024); 219 220 /* 221 * Set up buffers, so they can be used to read disk labels. 222 */ 223 bufinit(); 224 vm_pager_bufferinit(); 225 226 EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0, 227 SHUTDOWN_PRI_LAST); 228 229 #ifdef SMP 230 /* 231 * OK, enough kmem_alloc/malloc state should be up, lets get on with it! 232 */ 233 mp_start(); /* fire up the secondaries */ 234 mp_announce(); 235 #endif /* SMP */ 236 } 237 238 void 239 identifycpu() 240 { 241 unsigned int pvr, version, revision; 242 243 /* 244 * Find cpu type (Do it by OpenFirmware?) 245 */ 246 __asm ("mfpvr %0" : "=r"(pvr)); 247 version = pvr >> 16; 248 revision = pvr & 0xffff; 249 switch (version) { 250 case 0x0000: 251 sprintf(model, "Simulator (psim)"); 252 break; 253 case 0x0001: 254 sprintf(model, "601"); 255 break; 256 case 0x0003: 257 sprintf(model, "603 (Wart)"); 258 break; 259 case 0x0004: 260 sprintf(model, "604 (Zephyr)"); 261 break; 262 case 0x0005: 263 sprintf(model, "602 (Galahad)"); 264 break; 265 case 0x0006: 266 sprintf(model, "603e (Stretch)"); 267 break; 268 case 0x0007: 269 if ((revision && 0xf000) == 0x0000) 270 sprintf(model, "603ev (Valiant)"); 271 else 272 sprintf(model, "603r (Goldeneye)"); 273 break; 274 case 0x0008: 275 if ((revision && 0xf000) == 0x0000) 276 sprintf(model, "G3 / 750 (Arthur)"); 277 else 278 sprintf(model, "G3 / 755 (Goldfinger)"); 279 break; 280 case 0x0009: 281 if ((revision && 0xf000) == 0x0000) 282 sprintf(model, "604e (Sirocco)"); 283 else 284 sprintf(model, "604r (Mach V)"); 285 break; 286 case 0x000a: 287 sprintf(model, "604r (Mach V)"); 288 break; 289 case 0x000c: 290 sprintf(model, "G4 / 7400 (Max)"); 291 break; 292 case 0x0014: 293 sprintf(model, "620 (Red October)"); 294 break; 295 case 0x0081: 296 sprintf(model, "8240 (Kahlua)"); 297 break; 298 case 0x8000: 299 sprintf(model, "G4 / 7450 (V'ger)"); 300 break; 301 case 0x800c: 302 sprintf(model, "G4 / 7410 (Nitro)"); 303 break; 304 case 0x8081: 305 sprintf(model, "8245 (Kahlua II)"); 306 break; 307 default: 308 sprintf(model, "Version %x", version); 309 break; 310 } 311 sprintf(model + strlen(model), " (Revision %x)", revision); 312 printf("CPU: PowerPC %s\n", model); 313 } 314 315 extern char kernel_text[], _end[]; 316 317 extern void *trapcode, *trapsize; 318 extern void *alitrap, *alisize; 319 extern void *dsitrap, *dsisize; 320 extern void *isitrap, *isisize; 321 extern void *decrint, *decrsize; 322 extern void *tlbimiss, *tlbimsize; 323 extern void *tlbdlmiss, *tlbdlmsize; 324 extern void *tlbdsmiss, *tlbdsmsize; 325 extern void *extint, *extsize; 326 327 #if 0 /* XXX: interrupt handler. We'll get to this later */ 328 extern void ext_intr(void); 329 #endif 330 331 #ifdef DDB 332 extern ddblow, ddbsize; 333 #endif 334 #ifdef IPKDB 335 extern ipkdblow, ipkdbsize; 336 #endif 337 338 void 339 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) 340 { 341 struct pcpu *pc; 342 vm_offset_t end, off; 343 void *kmdp; 344 345 end = 0; 346 kmdp = NULL; 347 348 /* 349 * Parse metadata if present and fetch parameters. Must be done 350 * before console is inited so cninit gets the right value of 351 * boothowto. 352 */ 353 if (mdp != NULL) { 354 preload_metadata = mdp; 355 kmdp = preload_search_by_type("elf kernel"); 356 if (kmdp != NULL) { 357 boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 358 kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 359 end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 360 } 361 } 362 363 /* 364 * Initialize the console before printing anything. 365 */ 366 cninit(); 367 368 /* 369 * Complain if there is no metadata. 370 */ 371 if (mdp == NULL || kmdp == NULL) { 372 printf("powerpc_init: no loader metadata.\n"); 373 } 374 375 #ifdef DDB 376 kdb_init(); 377 #endif 378 379 /* 380 * XXX: Initialize the interrupt tables. 381 */ 382 bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize); 383 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); 384 bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); 385 bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); 386 bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize); 387 bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize); 388 389 /* 390 * Start initializing proc0 and thread0. 391 */ 392 proc_linkup(&proc0, &proc0.p_ksegrp, &proc0.p_kse, &thread0); 393 proc0.p_uarea = (struct user *)uarea0; 394 proc0.p_stats = &proc0.p_uarea->u_stats; 395 thread0.td_frame = &frame0; 396 397 /* 398 * Set up per-cpu data. 399 */ 400 pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1; 401 pcpu_init(pc, 0, sizeof(struct pcpu)); 402 pc->pc_curthread = &thread0; 403 pc->pc_curpcb = thread0.td_pcb; 404 pc->pc_cpuid = 0; 405 /* pc->pc_mid = mid; */ 406 407 __asm __volatile("mtsprg 0, %0" :: "r"(pc)); 408 409 mutex_init(); 410 411 /* 412 * Initialise virtual memory. 413 */ 414 pmap_bootstrap(startkernel, endkernel); 415 416 /* 417 * Initialize tunables. 418 */ 419 init_param1(); 420 init_param2(physmem); 421 422 /* 423 * Finish setting up thread0. 424 */ 425 thread0.td_kstack = kstack0; 426 thread0.td_pcb = (struct pcb *) 427 (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 428 429 /* 430 * Map and initialise the message buffer. 431 */ 432 for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE) 433 pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off); 434 msgbufinit(msgbufp, MSGBUF_SIZE); 435 } 436 437 #if 0 /* XXX: Old powerpc_init */ 438 void 439 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args) 440 { 441 unsigned int exc, scratch; 442 struct mem_region *allmem, *availmem, *mp; 443 struct pcpu *pcpup; 444 445 /* 446 * Set up BAT0 to only map the lowest 256 MB area 447 */ 448 battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); 449 battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); 450 451 /* 452 * Map PCI memory space. 453 */ 454 battable[0x8].batl = BATL(0x80000000, BAT_I, BAT_PP_RW); 455 battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); 456 457 battable[0x9].batl = BATL(0x90000000, BAT_I, BAT_PP_RW); 458 battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs); 459 460 battable[0xa].batl = BATL(0xa0000000, BAT_I, BAT_PP_RW); 461 battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs); 462 463 /* 464 * Map obio devices. 465 */ 466 battable[0xf].batl = BATL(0xf0000000, BAT_I, BAT_PP_RW); 467 battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs); 468 469 /* 470 * Now setup fixed bat registers 471 * 472 * Note that we still run in real mode, and the BAT 473 * registers were cleared above. 474 */ 475 /* BAT0 used for initial 256 MB segment */ 476 __asm __volatile ("mtibatl 0,%0; mtibatu 0,%1;" 477 "mtdbatl 0,%0; mtdbatu 0,%1;" 478 :: "r"(battable[0].batl), "r"(battable[0].batu)); 479 /* 480 * Set up battable to map all RAM regions. 481 * This is here because mem_regions() call needs bat0 set up. 482 */ 483 mem_regions(&allmem, &availmem); 484 485 /* Calculate the physical memory in the machine */ 486 for (mp = allmem; mp->size; mp++) 487 physmem += btoc(mp->size); 488 489 for (mp = allmem; mp->size; mp++) { 490 vm_offset_t pa = mp->start & 0xf0000000; 491 vm_offset_t end = mp->start + mp->size; 492 493 do { 494 u_int n = pa >> 28; 495 496 battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW); 497 battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs); 498 pa += 0x10000000; 499 } while (pa < end); 500 } 501 502 chosen = OF_finddevice("/chosen"); 503 save_ofw_mapping(); 504 505 pmap_setavailmem(startkernel, endkernel); 506 507 proc_linkup(&proc0, &proc0.p_ksegrp, &proc0.p_kse, &thread0); 508 509 proc0uarea = (struct user *)pmap_steal_memory(UAREA_PAGES * PAGE_SIZE); 510 proc0kstack = pmap_steal_memory(KSTACK_PAGES * PAGE_SIZE); 511 proc0.p_uarea = proc0uarea; 512 thread0.td_kstack = proc0kstack; 513 thread0.td_pcb = (struct pcb *) 514 (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 515 516 pcpup = pmap_steal_memory(round_page(sizeof(struct pcpu))); 517 518 /* 519 * XXX: Pass 0 as CPU id. This is bad. We need to work out 520 * XXX: which CPU we are somehow. 521 */ 522 pcpu_init(pcpup, 0, sizeof(struct pcpu)); 523 __asm ("mtsprg 0, %0" :: "r"(pcpup)); 524 525 /* Init basic tunables, hz etc */ 526 init_param1(); 527 init_param2(physmem); 528 529 PCPU_SET(curthread, &thread0); 530 531 /* XXX: NetBSDism I _think_. Not sure yet. */ 532 #if 0 533 curpm = PCPU_GET(curpcb)->pcb_pmreal = PCPU_GET(curpcb)->pcb_pm = kernel_pmap; 534 #endif 535 536 mutex_init(); 537 538 /* 539 * Initialise console. 540 */ 541 cninit(); 542 543 #ifdef __notyet__ /* Needs some rethinking regarding real/virtual OFW */ 544 OF_set_callback(callback); 545 #endif 546 547 /* 548 * Set up trap vectors 549 */ 550 for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) { 551 switch (exc) { 552 default: 553 bcopy(&trapcode, (void *)exc, (size_t)&trapsize); 554 break; 555 case EXC_DECR: 556 bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize); 557 break; 558 #if 0 /* XXX: Not enabling these traps yet. */ 559 case EXC_EXI: 560 /* 561 * This one is (potentially) installed during autoconf 562 */ 563 break; 564 case EXC_ALI: 565 bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize); 566 break; 567 case EXC_DSI: 568 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); 569 break; 570 case EXC_ISI: 571 bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); 572 break; 573 case EXC_IMISS: 574 bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize); 575 break; 576 case EXC_DLMISS: 577 bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize); 578 break; 579 case EXC_DSMISS: 580 bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize); 581 break; 582 #if defined(DDB) || defined(IPKDB) 583 case EXC_TRC: 584 case EXC_PGM: 585 case EXC_BPT: 586 #if defined(DDB) 587 bcopy(&ddblow, (void *)exc, (size_t)&ddbsize); 588 #else 589 bcopy(&ipkdblow, (void *)exc, (size_t)&ipkdbsize); 590 #endif 591 break; 592 #endif /* DDB || IPKDB */ 593 #endif 594 } 595 } 596 597 #if 0 /* XXX: coming soon... */ 598 /* 599 * external interrupt handler install 600 */ 601 install_extint(ext_intr); 602 #endif 603 604 __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); 605 606 /* 607 * Now enable translation (and machine checks/recoverable interrupts). 608 */ 609 __asm ("mfmsr %0" : "=r"(scratch)); 610 scratch |= PSL_IR | PSL_DR | PSL_ME | PSL_RI; 611 __asm ("mtmsr %0" :: "r"(scratch)); 612 613 ofmsr &= ~PSL_IP; 614 615 /* 616 * Parse arg string. 617 */ 618 #ifdef DDB 619 bcopy(args + strlen(args) + 1, &startsym, sizeof(startsym)); 620 bcopy(args + strlen(args) + 5, &endsym, sizeof(endsym)); 621 if (startsym == NULL || endsym == NULL) 622 startsym = endsym = NULL; 623 #endif 624 625 strcpy(bootpath, args); 626 args = bootpath; 627 while (*++args && *args != ' '); 628 if (*args) { 629 *args++ = 0; 630 while (*args) { 631 switch (*args++) { 632 case 'a': 633 boothowto |= RB_ASKNAME; 634 break; 635 case 's': 636 boothowto |= RB_SINGLE; 637 break; 638 case 'd': 639 boothowto |= RB_KDB; 640 break; 641 case 'v': 642 boothowto |= RB_VERBOSE; 643 break; 644 } 645 } 646 } 647 648 #ifdef DDB 649 ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 650 #endif 651 #ifdef IPKDB 652 /* 653 * Now trap to IPKDB 654 */ 655 ipkdb_init(); 656 if (boothowto & RB_KDB) 657 ipkdb_connect(0); 658 #endif 659 660 /* 661 * Set the page size. 662 */ 663 #if 0 664 vm_set_page_size(); 665 #endif 666 667 /* 668 * Initialize pmap module. 669 */ 670 pmap_bootstrap(); 671 672 restore_ofw_mapping(); 673 674 PCPU_GET(next_asn) = 1; /* 0 used for proc0 pmap */ 675 676 /* setup proc 0's pcb */ 677 thread0.td_pcb->pcb_flags = 0; /* XXXKSE */ 678 thread0.td_frame = &proc0_tf; 679 } 680 #endif 681 682 static int N_mapping; 683 static struct { 684 vm_offset_t va; 685 int len; 686 vm_offset_t pa; 687 int mode; 688 } ofw_mapping[256]; 689 690 int 691 save_ofw_mapping() 692 { 693 int mmui, mmu; 694 695 OF_getprop(chosen, "mmu", &mmui, 4); 696 mmu = OF_instance_to_package(mmui); 697 698 bzero(ofw_mapping, sizeof(ofw_mapping)); 699 700 N_mapping = 701 OF_getprop(mmu, "translations", ofw_mapping, sizeof(ofw_mapping)); 702 N_mapping /= sizeof(ofw_mapping[0]); 703 704 return 0; 705 } 706 707 int 708 restore_ofw_mapping() 709 { 710 int i; 711 struct vm_page pg; 712 713 pmap_pinit(&ofw_pmap); 714 715 ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT; 716 717 for (i = 0; i < N_mapping; i++) { 718 vm_offset_t pa = ofw_mapping[i].pa; 719 vm_offset_t va = ofw_mapping[i].va; 720 int size = ofw_mapping[i].len; 721 722 if (va < 0x80000000) /* XXX */ 723 continue; 724 725 while (size > 0) { 726 pg.phys_addr = pa; 727 pmap_enter(&ofw_pmap, va, &pg, VM_PROT_ALL, 728 VM_PROT_ALL); 729 pa += PAGE_SIZE; 730 va += PAGE_SIZE; 731 size -= PAGE_SIZE; 732 } 733 } 734 735 return 0; 736 } 737 738 void 739 bzero(void *buf, size_t len) 740 { 741 caddr_t p; 742 743 p = buf; 744 745 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { 746 *p++ = 0; 747 len--; 748 } 749 750 while (len >= sizeof(u_long) * 8) { 751 *(u_long*) p = 0; 752 *((u_long*) p + 1) = 0; 753 *((u_long*) p + 2) = 0; 754 *((u_long*) p + 3) = 0; 755 len -= sizeof(u_long) * 8; 756 *((u_long*) p + 4) = 0; 757 *((u_long*) p + 5) = 0; 758 *((u_long*) p + 6) = 0; 759 *((u_long*) p + 7) = 0; 760 p += sizeof(u_long) * 8; 761 } 762 763 while (len >= sizeof(u_long)) { 764 *(u_long*) p = 0; 765 len -= sizeof(u_long); 766 p += sizeof(u_long); 767 } 768 769 while (len) { 770 *p++ = 0; 771 len--; 772 } 773 } 774 775 #if 0 776 void 777 delay(unsigned n) 778 { 779 u_long tb; 780 781 do { 782 __asm __volatile("mftb %0" : "=r" (tb)); 783 } while (n > (int)(tb & 0xffffffff)); 784 } 785 #endif 786 787 #ifdef COMPAT_43 788 void 789 osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 790 { 791 792 /* XXX: To be done */ 793 return; 794 } 795 #endif 796 797 void 798 sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 799 { 800 801 /* XXX: To be done */ 802 return; 803 } 804 805 /* 806 * Stub to satisfy the reference to osigreturn in the syscall table. This 807 * is needed even for newer arches that don't support old signals because 808 * the syscall table is machine-independent. 809 */ 810 int 811 osigreturn(struct thread *td, struct osigreturn_args *uap) 812 { 813 814 return (nosys(td, (struct nosys_args *)uap)); 815 } 816 817 int 818 sigreturn(struct thread *td, struct sigreturn_args *uap) 819 { 820 821 /* XXX: To be done */ 822 return(ENOSYS); 823 } 824 825 void 826 cpu_boot(int howto) 827 { 828 } 829 830 /* 831 * Shutdown the CPU as much as possible. 832 */ 833 void 834 cpu_halt(void) 835 { 836 837 OF_exit(); 838 } 839 840 /* 841 * Set set up registers on exec. 842 */ 843 void 844 setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 845 { 846 struct trapframe *tf; 847 struct ps_strings arginfo; 848 849 tf = trapframe(td); 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 td->td_pcb->pcb_flags = 0; 883 } 884 885 #if !defined(DDB) 886 void 887 Debugger(const char *msg) 888 { 889 890 printf("Debugger(\"%s\") called.\n", msg); 891 } 892 #endif /* !defined(DDB) */ 893 894 /* XXX: dummy {fill,set}_[fp]regs */ 895 int 896 fill_regs(struct thread *td, struct reg *regs) 897 { 898 899 return (ENOSYS); 900 } 901 902 int 903 fill_dbregs(struct thread *td, struct dbreg *dbregs) 904 { 905 906 return (ENOSYS); 907 } 908 909 int 910 fill_fpregs(struct thread *td, struct fpreg *fpregs) 911 { 912 913 return (ENOSYS); 914 } 915 916 int 917 set_regs(struct thread *td, struct reg *regs) 918 { 919 920 return (ENOSYS); 921 } 922 923 int 924 set_dbregs(struct thread *td, struct dbreg *dbregs) 925 { 926 927 return (ENOSYS); 928 } 929 930 int 931 set_fpregs(struct thread *td, struct fpreg *fpregs) 932 { 933 934 return (ENOSYS); 935 } 936 937 int 938 ptrace_set_pc(struct thread *td, unsigned long addr) 939 { 940 941 /* XXX: coming soon... */ 942 return (ENOSYS); 943 } 944 945 int 946 ptrace_single_step(struct thread *td) 947 { 948 949 /* XXX: coming soon... */ 950 return (ENOSYS); 951 } 952 953 int 954 ptrace_clear_single_step(struct thread *td) 955 { 956 957 /* XXX: coming soon... */ 958 return (ENOSYS); 959 } 960 961 /* 962 * Initialise a struct pcpu. 963 */ 964 void 965 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) 966 { 967 968 pcpu->pc_current_asngen = 1; 969 } 970 971 /* 972 * kcopy(const void *src, void *dst, size_t len); 973 * 974 * Copy len bytes from src to dst, aborting if we encounter a fatal 975 * page fault. 976 * 977 * kcopy() _must_ save and restore the old fault handler since it is 978 * called by uiomove(), which may be in the path of servicing a non-fatal 979 * page fault. 980 */ 981 int 982 kcopy(const void *src, void *dst, size_t len) 983 { 984 struct thread *td; 985 faultbuf env, *oldfault; 986 int rv; 987 988 td = PCPU_GET(curthread); 989 oldfault = td->td_pcb->pcb_onfault; 990 if ((rv = setfault(env)) != 0) { 991 td->td_pcb->pcb_onfault = oldfault; 992 return rv; 993 } 994 995 memcpy(dst, src, len); 996 997 td->td_pcb->pcb_onfault = oldfault; 998 return (0); 999 } 1000