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