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 <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 <machine/sigframe.h> 113 114 int physmem = 0; 115 int cold = 1; 116 117 struct mtx sched_lock; 118 struct mtx Giant; 119 120 struct user *proc0uarea; 121 vm_offset_t proc0kstack; 122 123 char machine[] = "powerpc"; 124 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 125 126 static char model[128]; 127 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); 128 129 char bootpath[256]; 130 131 #ifdef DDB 132 /* start and end of kernel symbol table */ 133 void *ksym_start, *ksym_end; 134 #endif /* DDB */ 135 136 static void cpu_startup(void *); 137 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 138 139 void powerpc_init(u_int, u_int, u_int, char *); 140 141 int save_ofw_mapping(void); 142 int restore_ofw_mapping(void); 143 144 void install_extint(void (*)(void)); 145 146 #ifdef COMPAT_43 147 void osendsig(sig_t, int, sigset_t *, u_long); 148 #endif 149 150 static int 151 sysctl_hw_physmem(SYSCTL_HANDLER_ARGS) 152 { 153 int error = sysctl_handle_int(oidp, 0, ctob(physmem), req); 154 return (error); 155 } 156 157 SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD, 158 0, 0, sysctl_hw_physmem, "IU", ""); 159 160 struct msgbuf *msgbufp = 0; 161 162 int bootverbose = 0, Maxmem = 0; 163 long dumplo; 164 165 vm_offset_t phys_avail[10]; 166 167 static int chosen; 168 169 static struct trapframe proc0_tf; 170 171 struct pmap ofw_pmap; 172 extern int ofmsr; 173 174 struct bat battable[16]; 175 176 static void identifycpu(void); 177 178 struct kva_md_info kmi; 179 180 static void 181 powerpc_ofw_shutdown(void *junk, int howto) 182 { 183 if (howto & RB_HALT) { 184 OF_exit(); 185 } 186 } 187 188 static void 189 cpu_startup(void *dummy) 190 { 191 192 /* 193 * Good {morning,afternoon,evening,night}. 194 */ 195 identifycpu(); 196 197 /* startrtclock(); */ 198 #ifdef PERFMON 199 perfmon_init(); 200 #endif 201 printf("real memory = %ld (%ldK bytes)\n", ptoa(Maxmem), 202 ptoa(Maxmem) / 1024); 203 204 /* 205 * Display any holes after the first chunk of extended memory. 206 */ 207 if (bootverbose) { 208 int indx; 209 210 printf("Physical memory chunk(s):\n"); 211 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 212 int size1 = phys_avail[indx + 1] - phys_avail[indx]; 213 214 printf("0x%08x - 0x%08x, %d bytes (%d pages)\n", 215 phys_avail[indx], phys_avail[indx + 1] - 1, size1, 216 size1 / PAGE_SIZE); 217 } 218 } 219 220 vm_ksubmap_init(&kmi); 221 222 #if defined(USERCONFIG) 223 #if defined(USERCONFIG_BOOT) 224 if (1) 225 #else 226 if (boothowto & RB_CONFIG) 227 #endif 228 { 229 userconfig(); 230 cninit(); /* the preferred console may have changed */ 231 } 232 #endif 233 234 printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count), 235 ptoa(cnt.v_free_count) / 1024); 236 237 /* 238 * Set up buffers, so they can be used to read disk labels. 239 */ 240 bufinit(); 241 vm_pager_bufferinit(); 242 EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0, 243 SHUTDOWN_PRI_LAST); 244 245 #ifdef SMP 246 /* 247 * OK, enough kmem_alloc/malloc state should be up, lets get on with it! 248 */ 249 mp_start(); /* fire up the secondaries */ 250 mp_announce(); 251 #endif /* SMP */ 252 } 253 254 void 255 identifycpu() 256 { 257 unsigned int pvr, version, revision; 258 259 /* 260 * Find cpu type (Do it by OpenFirmware?) 261 */ 262 __asm ("mfpvr %0" : "=r"(pvr)); 263 version = pvr >> 16; 264 revision = pvr & 0xffff; 265 switch (version) { 266 case 0x0001: 267 sprintf(model, "601"); 268 break; 269 case 0x0003: 270 sprintf(model, "603 (Wart)"); 271 break; 272 case 0x0004: 273 sprintf(model, "604 (Zephyr)"); 274 break; 275 case 0x0005: 276 sprintf(model, "602 (Galahad)"); 277 break; 278 case 0x0006: 279 sprintf(model, "603e (Stretch)"); 280 break; 281 case 0x0007: 282 if ((revision && 0xf000) == 0x0000) 283 sprintf(model, "603ev (Valiant)"); 284 else 285 sprintf(model, "603r (Goldeneye)"); 286 break; 287 case 0x0008: 288 if ((revision && 0xf000) == 0x0000) 289 sprintf(model, "G3 / 750 (Arthur)"); 290 else 291 sprintf(model, "G3 / 755 (Goldfinger)"); 292 break; 293 case 0x0009: 294 if ((revision && 0xf000) == 0x0000) 295 sprintf(model, "604e (Sirocco)"); 296 else 297 sprintf(model, "604r (Mach V)"); 298 break; 299 case 0x000a: 300 sprintf(model, "604r (Mach V)"); 301 break; 302 case 0x000c: 303 sprintf(model, "G4 / 7400 (Max)"); 304 break; 305 case 0x0014: 306 sprintf(model, "620 (Red October)"); 307 break; 308 case 0x0081: 309 sprintf(model, "8240 (Kahlua)"); 310 break; 311 case 0x8000: 312 sprintf(model, "G4 / 7450 (V'ger)"); 313 break; 314 case 0x800c: 315 sprintf(model, "G4 / 7410 (Nitro)"); 316 break; 317 case 0x8081: 318 sprintf(model, "8245 (Kahlua II)"); 319 break; 320 default: 321 sprintf(model, "Version %x", version); 322 break; 323 } 324 sprintf(model + strlen(model), " (Revision %x)", revision); 325 printf("CPU: PowerPC %s\n", model); 326 } 327 328 extern char kernel_text[], _end[]; 329 330 extern void *trapcode, *trapsize; 331 extern void *alitrap, *alisize; 332 extern void *dsitrap, *dsisize; 333 extern void *isitrap, *isisize; 334 extern void *decrint, *decrsize; 335 extern void *tlbimiss, *tlbimsize; 336 extern void *tlbdlmiss, *tlbdlmsize; 337 extern void *tlbdsmiss, *tlbdsmsize; 338 339 #if 0 /* XXX: interrupt handler. We'll get to this later */ 340 extern void ext_intr(void); 341 #endif 342 343 #ifdef DDB 344 extern ddblow, ddbsize; 345 #endif 346 #ifdef IPKDB 347 extern ipkdblow, ipkdbsize; 348 #endif 349 350 void 351 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args) 352 { 353 unsigned int exc, scratch; 354 struct mem_region *allmem, *availmem, *mp; 355 struct globaldata *globalp; 356 357 /* 358 * Set up BAT0 to only map the lowest 256 MB area 359 */ 360 battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); 361 battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); 362 363 /* 364 * Map PCI memory space. 365 */ 366 battable[0x8].batl = BATL(0x80000000, BAT_I, BAT_PP_RW); 367 battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); 368 369 battable[0x9].batl = BATL(0x90000000, BAT_I, BAT_PP_RW); 370 battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs); 371 372 battable[0xa].batl = BATL(0xa0000000, BAT_I, BAT_PP_RW); 373 battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs); 374 375 /* 376 * Map obio devices. 377 */ 378 battable[0xf].batl = BATL(0xf0000000, BAT_I, BAT_PP_RW); 379 battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs); 380 381 /* 382 * Now setup fixed bat registers 383 * 384 * Note that we still run in real mode, and the BAT 385 * registers were cleared above. 386 */ 387 /* BAT0 used for initial 256 MB segment */ 388 __asm __volatile ("mtibatl 0,%0; mtibatu 0,%1;" 389 "mtdbatl 0,%0; mtdbatu 0,%1;" 390 :: "r"(battable[0].batl), "r"(battable[0].batu)); 391 /* 392 * Set up battable to map all RAM regions. 393 * This is here because mem_regions() call needs bat0 set up. 394 */ 395 mem_regions(&allmem, &availmem); 396 397 /* Calculate the physical memory in the machine */ 398 for (mp = allmem; mp->size; mp++) 399 physmem += btoc(mp->size); 400 401 for (mp = allmem; mp->size; mp++) { 402 vm_offset_t pa = mp->start & 0xf0000000; 403 vm_offset_t end = mp->start + mp->size; 404 405 do { 406 u_int n = pa >> 28; 407 408 battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW); 409 battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs); 410 pa += 0x10000000; 411 } while (pa < end); 412 } 413 414 chosen = OF_finddevice("/chosen"); 415 save_ofw_mapping(); 416 417 pmap_setavailmem(startkernel, endkernel); 418 419 proc_linkup(&proc0); 420 421 proc0uarea = (struct user *)pmap_steal_memory(UAREA_PAGES * PAGE_SIZE); 422 proc0kstack = pmap_steal_memory(KSTACK_PAGES * PAGE_SIZE); 423 proc0.p_uarea = proc0uarea; 424 thread0 = &proc0.p_thread; 425 thread0->td_kstack = proc0kstack; 426 thread0->td_pcb = (struct pcb *) 427 (thread0->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 428 429 globalp = pmap_steal_memory(round_page(sizeof(struct globaldata))); 430 431 /* 432 * XXX: Pass 0 as CPU id. This is bad. We need to work out 433 * XXX: which CPU we are somehow. 434 */ 435 globaldata_init(globalp, 0, sizeof(struct globaldata)); 436 __asm ("mtsprg 0, %0" :: "r"(globalp)); 437 438 /* Init basic tunables, hz etc */ 439 init_param(); 440 441 /* setup curproc so the mutexes work */ 442 443 PCPU_SET(curthread, thread0); 444 PCPU_SET(spinlocks, NULL); 445 446 LIST_INIT(&thread0->td_contested); 447 448 /* XXX: NetBSDism I _think_. Not sure yet. */ 449 #if 0 450 curpm = PCPU_GET(curpcb)->pcb_pmreal = PCPU_GET(curpcb)->pcb_pm = kernel_pmap; 451 #endif 452 453 /* 454 * Initialise some mutexes. 455 */ 456 mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE); 457 mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE); 458 mtx_init(&proc0.p_mtx, "process lock", MTX_DEF); 459 460 /* 461 * Initialise console. 462 */ 463 cninit(); 464 465 mtx_lock(&Giant); 466 467 #ifdef __notyet__ /* Needs some rethinking regarding real/virtual OFW */ 468 OF_set_callback(callback); 469 #endif 470 471 /* 472 * Set up trap vectors 473 */ 474 for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) { 475 switch (exc) { 476 default: 477 bcopy(&trapcode, (void *)exc, (size_t)&trapsize); 478 break; 479 case EXC_DECR: 480 bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize); 481 break; 482 #if 0 /* XXX: Not enabling these traps yet. */ 483 case EXC_EXI: 484 /* 485 * This one is (potentially) installed during autoconf 486 */ 487 break; 488 case EXC_ALI: 489 bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize); 490 break; 491 case EXC_DSI: 492 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); 493 break; 494 case EXC_ISI: 495 bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); 496 break; 497 case EXC_IMISS: 498 bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize); 499 break; 500 case EXC_DLMISS: 501 bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize); 502 break; 503 case EXC_DSMISS: 504 bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize); 505 break; 506 #if defined(DDB) || defined(IPKDB) 507 case EXC_TRC: 508 case EXC_PGM: 509 case EXC_BPT: 510 #if defined(DDB) 511 bcopy(&ddblow, (void *)exc, (size_t)&ddbsize); 512 #else 513 bcopy(&ipkdblow, (void *)exc, (size_t)&ipkdbsize); 514 #endif 515 break; 516 #endif /* DDB || IPKDB */ 517 #endif 518 } 519 } 520 521 #if 0 /* XXX: coming soon... */ 522 /* 523 * external interrupt handler install 524 */ 525 install_extint(ext_intr); 526 #endif 527 528 __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); 529 530 /* 531 * Now enable translation (and machine checks/recoverable interrupts). 532 */ 533 __asm ("mfmsr %0" : "=r"(scratch)); 534 scratch |= PSL_IR | PSL_DR | PSL_ME | PSL_RI; 535 __asm ("mtmsr %0" :: "r"(scratch)); 536 537 ofmsr &= ~PSL_IP; 538 539 /* 540 * Parse arg string. 541 */ 542 #ifdef DDB 543 bcopy(args + strlen(args) + 1, &startsym, sizeof(startsym)); 544 bcopy(args + strlen(args) + 5, &endsym, sizeof(endsym)); 545 if (startsym == NULL || endsym == NULL) 546 startsym = endsym = NULL; 547 #endif 548 549 strcpy(bootpath, args); 550 args = bootpath; 551 while (*++args && *args != ' '); 552 if (*args) { 553 *args++ = 0; 554 while (*args) { 555 switch (*args++) { 556 case 'a': 557 boothowto |= RB_ASKNAME; 558 break; 559 case 's': 560 boothowto |= RB_SINGLE; 561 break; 562 case 'd': 563 boothowto |= RB_KDB; 564 break; 565 case 'v': 566 boothowto |= RB_VERBOSE; 567 break; 568 } 569 } 570 } 571 572 #ifdef DDB 573 ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 574 #endif 575 #ifdef IPKDB 576 /* 577 * Now trap to IPKDB 578 */ 579 ipkdb_init(); 580 if (boothowto & RB_KDB) 581 ipkdb_connect(0); 582 #endif 583 584 /* 585 * Set the page size. 586 */ 587 #if 0 588 vm_set_page_size(); 589 #endif 590 591 /* 592 * Initialize pmap module. 593 */ 594 pmap_bootstrap(); 595 596 restore_ofw_mapping(); 597 598 PCPU_GET(next_asn) = 1; /* 0 used for proc0 pmap */ 599 600 /* setup proc 0's pcb */ 601 thread0->td_pcb->pcb_flags = 0; /* XXXKSE */ 602 thread0->td_frame = &proc0_tf; 603 } 604 605 static int N_mapping; 606 static struct { 607 vm_offset_t va; 608 int len; 609 vm_offset_t pa; 610 int mode; 611 } ofw_mapping[256]; 612 613 int 614 save_ofw_mapping() 615 { 616 int mmui, mmu; 617 618 OF_getprop(chosen, "mmu", &mmui, 4); 619 mmu = OF_instance_to_package(mmui); 620 621 bzero(ofw_mapping, sizeof(ofw_mapping)); 622 623 N_mapping = 624 OF_getprop(mmu, "translations", ofw_mapping, sizeof(ofw_mapping)); 625 N_mapping /= sizeof(ofw_mapping[0]); 626 627 return 0; 628 } 629 630 int 631 restore_ofw_mapping() 632 { 633 int i; 634 struct vm_page pg; 635 636 pmap_pinit(&ofw_pmap); 637 638 ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT; 639 640 for (i = 0; i < N_mapping; i++) { 641 vm_offset_t pa = ofw_mapping[i].pa; 642 vm_offset_t va = ofw_mapping[i].va; 643 int size = ofw_mapping[i].len; 644 645 if (va < 0x80000000) /* XXX */ 646 continue; 647 648 while (size > 0) { 649 pg.phys_addr = pa; 650 pmap_enter(&ofw_pmap, va, &pg, VM_PROT_ALL, 651 VM_PROT_ALL); 652 pa += PAGE_SIZE; 653 va += PAGE_SIZE; 654 size -= PAGE_SIZE; 655 } 656 } 657 658 return 0; 659 } 660 661 void 662 bzero(void *buf, size_t len) 663 { 664 caddr_t p; 665 666 p = buf; 667 668 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { 669 *p++ = 0; 670 len--; 671 } 672 673 while (len >= sizeof(u_long) * 8) { 674 *(u_long*) p = 0; 675 *((u_long*) p + 1) = 0; 676 *((u_long*) p + 2) = 0; 677 *((u_long*) p + 3) = 0; 678 len -= sizeof(u_long) * 8; 679 *((u_long*) p + 4) = 0; 680 *((u_long*) p + 5) = 0; 681 *((u_long*) p + 6) = 0; 682 *((u_long*) p + 7) = 0; 683 p += sizeof(u_long) * 8; 684 } 685 686 while (len >= sizeof(u_long)) { 687 *(u_long*) p = 0; 688 len -= sizeof(u_long); 689 p += sizeof(u_long); 690 } 691 692 while (len) { 693 *p++ = 0; 694 len--; 695 } 696 } 697 698 #if 0 699 void 700 delay(unsigned n) 701 { 702 u_long tb; 703 704 do { 705 __asm __volatile("mftb %0" : "=r" (tb)); 706 } while (n > (int)(tb & 0xffffffff)); 707 } 708 #endif 709 710 #ifdef COMPAT_43 711 void 712 osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 713 { 714 715 /* XXX: To be done */ 716 return; 717 } 718 #endif 719 720 void 721 sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 722 { 723 724 /* XXX: To be done */ 725 return; 726 } 727 728 #ifdef COMPAT_43 729 int 730 osigreturn(struct thread *td, struct osigreturn_args *uap) 731 { 732 733 /* XXX: To be done */ 734 return(ENOSYS); 735 } 736 #endif 737 738 int 739 sigreturn(struct thread *td, struct sigreturn_args *uap) 740 { 741 742 /* XXX: To be done */ 743 return(ENOSYS); 744 } 745 746 void 747 cpu_boot(int howto) 748 { 749 } 750 751 /* 752 * Shutdown the CPU as much as possible. 753 */ 754 void 755 cpu_halt(void) 756 { 757 758 OF_exit(); 759 } 760 761 /* 762 * Set set up registers on exec. 763 */ 764 void 765 setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 766 { 767 struct trapframe *tf; 768 struct ps_strings arginfo; 769 770 tf = trapframe(td); 771 bzero(tf, sizeof *tf); 772 tf->fixreg[1] = -roundup(-stack + 8, 16); 773 774 /* 775 * XXX Machine-independent code has already copied arguments and 776 * XXX environment to userland. Get them back here. 777 */ 778 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo)); 779 780 /* 781 * Set up arguments for _start(): 782 * _start(argc, argv, envp, obj, cleanup, ps_strings); 783 * 784 * Notes: 785 * - obj and cleanup are the auxilliary and termination 786 * vectors. They are fixed up by ld.elf_so. 787 * - ps_strings is a NetBSD extention, and will be 788 * ignored by executables which are strictly 789 * compliant with the SVR4 ABI. 790 * 791 * XXX We have to set both regs and retval here due to different 792 * XXX calling convention in trap.c and init_main.c. 793 */ 794 tf->fixreg[3] = arginfo.ps_nargvstr; 795 tf->fixreg[4] = (register_t)arginfo.ps_argvstr; 796 tf->fixreg[5] = (register_t)arginfo.ps_envstr; 797 tf->fixreg[6] = 0; /* auxillary vector */ 798 tf->fixreg[7] = 0; /* termination vector */ 799 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ 800 801 tf->srr0 = entry; 802 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 803 td->td_pcb->pcb_flags = 0; 804 } 805 806 extern void *extint, *extsize; 807 extern u_long extint_call; 808 809 void 810 install_extint(void (*handler)(void)) 811 { 812 u_long offset; 813 int omsr, msr; 814 815 offset = (u_long)handler - (u_long)&extint_call; 816 817 #ifdef DIAGNOSTIC 818 if (offset > 0x1ffffff) 819 panic("install_extint: too far away"); 820 #endif 821 822 msr = mfmsr(); 823 mtmsr(msr & ~PSL_EE); 824 825 extint_call = (extint_call & 0xfc000003) | offset; 826 bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize); 827 __syncicache((void *)&extint_call, sizeof extint_call); 828 __syncicache((void *)EXC_EXI, (int)&extsize); 829 830 mtmsr(msr); 831 } 832 833 #if !defined(DDB) 834 void 835 Debugger(const char *msg) 836 { 837 838 printf("Debugger(\"%s\") called.\n", msg); 839 } 840 #endif /* !defined(DDB) */ 841 842 /* XXX: dummy {fill,set}_[fp]regs */ 843 int 844 fill_regs(struct thread *td, struct reg *regs) 845 { 846 847 return (ENOSYS); 848 } 849 850 int 851 fill_dbregs(struct thread *td, struct dbreg *dbregs) 852 { 853 854 return (ENOSYS); 855 } 856 857 int 858 fill_fpregs(struct thread *td, struct fpreg *fpregs) 859 { 860 861 return (ENOSYS); 862 } 863 864 int 865 set_regs(struct thread *td, struct reg *regs) 866 { 867 868 return (ENOSYS); 869 } 870 871 int 872 set_dbregs(struct thread *td, struct dbreg *dbregs) 873 { 874 875 return (ENOSYS); 876 } 877 878 int 879 set_fpregs(struct thread *td, struct fpreg *fpregs) 880 { 881 882 return (ENOSYS); 883 } 884 885 int 886 ptrace_set_pc(struct thread *td, unsigned long addr) 887 { 888 889 /* XXX: coming soon... */ 890 return (ENOSYS); 891 } 892 893 int 894 ptrace_single_step(struct thread *td) 895 { 896 897 /* XXX: coming soon... */ 898 return (ENOSYS); 899 } 900 901 int 902 ptrace_clear_single_step(struct thread *td) 903 { 904 905 /* XXX: coming soon... */ 906 return (ENOSYS); 907 } 908 909 /* 910 * Initialise a struct globaldata. 911 */ 912 void 913 globaldata_init(struct globaldata *globaldata, int cpuid, size_t sz) 914 { 915 916 bzero(globaldata, sz); 917 globaldata->gd_cpuid = cpuid; 918 globaldata->gd_next_asn = 0; 919 globaldata->gd_current_asngen = 1; 920 } 921 922 void 923 enable_fpu(pcb) 924 struct pcb *pcb; 925 { 926 int msr, scratch; 927 928 if (!(pcb->pcb_flags & PCB_FPU)) { 929 bzero(&pcb->pcb_fpu, sizeof pcb->pcb_fpu); 930 pcb->pcb_flags |= PCB_FPU; 931 } 932 __asm volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync" 933 : "=r"(msr), "=r"(scratch) : "K"(PSL_FP)); 934 __asm volatile ("lfd 0,0(%0); mtfsf 0xff,0" :: "b"(&pcb->pcb_fpu.fpscr)); 935 __asm ("lfd 0,0(%0);" 936 "lfd 1,8(%0);" 937 "lfd 2,16(%0);" 938 "lfd 3,24(%0);" 939 "lfd 4,32(%0);" 940 "lfd 5,40(%0);" 941 "lfd 6,48(%0);" 942 "lfd 7,56(%0);" 943 "lfd 8,64(%0);" 944 "lfd 9,72(%0);" 945 "lfd 10,80(%0);" 946 "lfd 11,88(%0);" 947 "lfd 12,96(%0);" 948 "lfd 13,104(%0);" 949 "lfd 14,112(%0);" 950 "lfd 15,120(%0);" 951 "lfd 16,128(%0);" 952 "lfd 17,136(%0);" 953 "lfd 18,144(%0);" 954 "lfd 19,152(%0);" 955 "lfd 20,160(%0);" 956 "lfd 21,168(%0);" 957 "lfd 22,176(%0);" 958 "lfd 23,184(%0);" 959 "lfd 24,192(%0);" 960 "lfd 25,200(%0);" 961 "lfd 26,208(%0);" 962 "lfd 27,216(%0);" 963 "lfd 28,224(%0);" 964 "lfd 29,232(%0);" 965 "lfd 30,240(%0);" 966 "lfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0])); 967 __asm volatile ("mtmsr %0; isync" :: "r"(msr)); 968 } 969 970 void 971 save_fpu(pcb) 972 struct pcb *pcb; 973 { 974 int msr, scratch; 975 976 __asm volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync" 977 : "=r"(msr), "=r"(scratch) : "K"(PSL_FP)); 978 __asm ("stfd 0,0(%0);" 979 "stfd 1,8(%0);" 980 "stfd 2,16(%0);" 981 "stfd 3,24(%0);" 982 "stfd 4,32(%0);" 983 "stfd 5,40(%0);" 984 "stfd 6,48(%0);" 985 "stfd 7,56(%0);" 986 "stfd 8,64(%0);" 987 "stfd 9,72(%0);" 988 "stfd 10,80(%0);" 989 "stfd 11,88(%0);" 990 "stfd 12,96(%0);" 991 "stfd 13,104(%0);" 992 "stfd 14,112(%0);" 993 "stfd 15,120(%0);" 994 "stfd 16,128(%0);" 995 "stfd 17,136(%0);" 996 "stfd 18,144(%0);" 997 "stfd 19,152(%0);" 998 "stfd 20,160(%0);" 999 "stfd 21,168(%0);" 1000 "stfd 22,176(%0);" 1001 "stfd 23,184(%0);" 1002 "stfd 24,192(%0);" 1003 "stfd 25,200(%0);" 1004 "stfd 26,208(%0);" 1005 "stfd 27,216(%0);" 1006 "stfd 28,224(%0);" 1007 "stfd 29,232(%0);" 1008 "stfd 30,240(%0);" 1009 "stfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0])); 1010 __asm volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); 1011 __asm volatile ("mtmsr %0; isync" :: "r"(msr)); 1012 } 1013