machdep.c revision 77957
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 77957 2001-06-10 02:39:37Z benno $"; 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 115int cold = 1; 116 117struct mtx sched_lock; 118struct mtx Giant; 119 120struct user *proc0paddr; 121 122char machine[] = "powerpc"; 123SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 124 125static char model[128]; 126SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); 127 128char bootpath[256]; 129 130#ifdef DDB 131/* start and end of kernel symbol table */ 132void *ksym_start, *ksym_end; 133#endif /* DDB */ 134 135static void cpu_startup(void *); 136SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 137 138void powerpc_init(u_int, u_int, u_int, char *); 139 140int save_ofw_mapping(void); 141int restore_ofw_mapping(void); 142 143void install_extint(void (*)(void)); 144 145void osendsig(sig_t, int, sigset_t *, u_long); 146 147struct msgbuf *msgbufp = 0; 148 149int bootverbose = 0, Maxmem = 0; 150long dumplo; 151 152vm_offset_t phys_avail[10]; 153 154static int chosen; 155 156struct pmap ofw_pmap; 157extern int ofmsr; 158 159struct bat battable[16]; 160 161static void identifycpu(void); 162 163static vm_offset_t buffer_sva, buffer_eva; 164vm_offset_t clean_sva, clean_eva; 165static vm_offset_t pager_sva, pager_eva; 166 167static void 168powerpc_ofw_shutdown(void *junk, int howto) 169{ 170 if (howto & RB_HALT) { 171 OF_exit(); 172 } 173} 174 175static void 176cpu_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; 240again: 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 355void 356identifycpu() 357{ 358 int pvr, cpu; 359 360 /* 361 * Find cpu type (Do it by OpenFirmware?) 362 */ 363 __asm ("mfpvr %0" : "=r"(pvr)); 364 cpu = pvr >> 16; 365 switch (cpu) { 366 case 1: 367 sprintf(model, "601"); 368 break; 369 case 3: 370 sprintf(model, "603"); 371 break; 372 case 4: 373 sprintf(model, "604"); 374 break; 375 case 5: 376 sprintf(model, "602"); 377 break; 378 case 6: 379 sprintf(model, "603e"); 380 break; 381 case 7: 382 sprintf(model, "603ev"); 383 break; 384 case 8: 385 sprintf(model, "750 (G3)"); 386 break; 387 case 9: 388 sprintf(model, "604ev"); 389 break; 390 case 12: 391 sprintf(model, "7400 (G4)"); 392 break; 393 case 20: 394 sprintf(model, "620"); 395 break; 396 default: 397 sprintf(model, "Version %x", cpu); 398 break; 399 } 400 sprintf(model + strlen(model), " (Revision %x)", pvr & 0xffff); 401 printf("CPU: PowerPC %s\n", model); 402} 403 404extern char kernel_text[], _end[]; 405 406extern void *trapcode, *trapsize; 407extern void *alitrap, *alisize; 408extern void *dsitrap, *dsisize; 409extern void *isitrap, *isisize; 410extern void *decrint, *decrsize; 411extern void *tlbimiss, *tlbimsize; 412extern void *tlbdlmiss, *tlbdlmsize; 413extern void *tlbdsmiss, *tlbdsmsize; 414 415#if 0 /* XXX: interrupt handler. We'll get to this later */ 416extern void ext_intr(void); 417#endif 418 419#ifdef DDB 420extern ddblow, ddbsize; 421#endif 422#ifdef IPKDB 423extern ipkdblow, ipkdbsize; 424#endif 425 426static struct globaldata tmpglobal; 427 428void 429powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args) 430{ 431 int exc, scratch; 432 struct mem_region *allmem, *availmem, *mp; 433 struct globaldata *globalp; 434 435 /* 436 * Set up BAT0 to only map the lowest 256 MB area 437 */ 438 battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); 439 battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); 440 441 /* 442 * Map PCI memory space. 443 */ 444 battable[0x8].batl = BATL(0x80000000, BAT_I, BAT_PP_RW); 445 battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); 446 447 battable[0x9].batl = BATL(0x90000000, BAT_I, BAT_PP_RW); 448 battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs); 449 450 battable[0xa].batl = BATL(0xa0000000, BAT_I, BAT_PP_RW); 451 battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs); 452 453 /* 454 * Map obio devices. 455 */ 456 battable[0xf].batl = BATL(0xf0000000, BAT_I, BAT_PP_RW); 457 battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs); 458 459 /* 460 * Now setup fixed bat registers 461 * 462 * Note that we still run in real mode, and the BAT 463 * registers were cleared above. 464 */ 465 /* BAT0 used for initial 256 MB segment */ 466 __asm __volatile ("mtibatl 0,%0; mtibatu 0,%1;" 467 "mtdbatl 0,%0; mtdbatu 0,%1;" 468 :: "r"(battable[0].batl), "r"(battable[0].batu)); 469 /* 470 * Set up battable to map all RAM regions. 471 * This is here because mem_regions() call needs bat0 set up. 472 */ 473 mem_regions(&allmem, &availmem); 474 for (mp = allmem; mp->size; mp++) { 475 vm_offset_t pa = mp->start & 0xf0000000; 476 vm_offset_t end = mp->start + mp->size; 477 478 do { 479 u_int n = pa >> 28; 480 481 battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW); 482 battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs); 483 pa += 0x10000000; 484 } while (pa < end); 485 } 486 487 chosen = OF_finddevice("/chosen"); 488 save_ofw_mapping(); 489 490 proc0.p_addr = proc0paddr; 491 bzero(proc0.p_addr, sizeof *proc0.p_addr); 492 493 LIST_INIT(&proc0.p_contested); 494 495/* XXX: NetBSDism I _think_. Not sure yet. */ 496#if 0 497 curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = kernel_pmap; 498#endif 499 500 /* 501 * Initialise some mutexes. 502 */ 503 mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE); 504 mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE); 505 mtx_init(&proc0.p_mtx, "process lock", MTX_DEF); 506 mtx_lock(&Giant); 507 508 /* 509 * Initialise console. 510 */ 511 cninit(); 512 513#ifdef __notyet__ /* Needs some rethinking regarding real/virtual OFW */ 514 OF_set_callback(callback); 515#endif 516 517 /* 518 * Set up trap vectors 519 */ 520 for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) { 521 switch (exc) { 522 default: 523 bcopy(&trapcode, (void *)exc, (size_t)&trapsize); 524 break; 525 case EXC_EXI: 526 /* 527 * This one is (potentially) installed during autoconf 528 */ 529 break; 530 case EXC_ALI: 531 bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize); 532 break; 533 case EXC_DSI: 534 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); 535 break; 536 case EXC_ISI: 537 bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); 538 break; 539 case EXC_DECR: 540 bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize); 541 break; 542 case EXC_IMISS: 543 bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize); 544 break; 545 case EXC_DLMISS: 546 bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize); 547 break; 548 case EXC_DSMISS: 549 bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize); 550 break; 551#if defined(DDB) || defined(IPKDB) 552 case EXC_TRC: 553 case EXC_PGM: 554 case EXC_BPT: 555#if defined(DDB) 556 bcopy(&ddblow, (void *)exc, (size_t)&ddbsize); 557#else 558 bcopy(&ipkdblow, (void *)exc, (size_t)&ipkdbsize); 559#endif 560 break; 561#endif /* DDB || IPKDB */ 562 } 563 } 564 565#if 0 /* XXX: coming soon... */ 566 /* 567 * external interrupt handler install 568 */ 569 install_extint(ext_intr); 570 571 __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); 572#endif 573 574 /* 575 * Now enable translation (and machine checks/recoverable interrupts). 576 */ 577 __asm __volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync" 578 : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI)); 579 580 581 ofmsr &= ~PSL_IP; 582 583 /* 584 * Parse arg string. 585 */ 586#ifdef DDB 587 bcopy(args + strlen(args) + 1, &startsym, sizeof(startsym)); 588 bcopy(args + strlen(args) + 5, &endsym, sizeof(endsym)); 589 if (startsym == NULL || endsym == NULL) 590 startsym = endsym = NULL; 591#endif 592 593 strcpy(bootpath, args); 594 args = bootpath; 595 while (*++args && *args != ' '); 596 if (*args) { 597 *args++ = 0; 598 while (*args) { 599 switch (*args++) { 600 case 'a': 601 boothowto |= RB_ASKNAME; 602 break; 603 case 's': 604 boothowto |= RB_SINGLE; 605 break; 606 case 'd': 607 boothowto |= RB_KDB; 608 break; 609 case 'v': 610 boothowto |= RB_VERBOSE; 611 break; 612 } 613 } 614 } 615 616#ifdef DDB 617 ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 618#endif 619#ifdef IPKDB 620 /* 621 * Now trap to IPKDB 622 */ 623 ipkdb_init(); 624 if (boothowto & RB_KDB) 625 ipkdb_connect(0); 626#endif 627 628 /* 629 * Set the page size. 630 */ 631#if 0 632 vm_set_page_size(); 633#endif 634 635 /* 636 * Initialize pmap module. 637 */ 638 pmap_bootstrap(startkernel, endkernel); 639 640 restore_ofw_mapping(); 641 642 /* 643 * Setup the global data for the bootstrap cpu. 644 */ 645 globalp = (struct globaldata *) &tmpglobal; 646 647 /* 648 * XXX: Pass 0 as CPU id. This is bad. We need to work out 649 * XXX: which CPU we are somehow. 650 */ 651 globaldata_init(globalp, 0, sizeof(struct globaldata)); 652 __asm("mtsprg 0,%0\n" :: "r" (globalp)); 653 654 PCPU_GET(next_asn) = 1; /* 0 used for proc0 pmap */ 655 PCPU_SET(curproc, &proc0); 656 PCPU_SET(spinlocks, NULL); 657} 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 < 0x90000000) /* 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 764void 765osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 766{ 767 768 /* XXX: To be done */ 769 return; 770} 771 772void 773sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 774{ 775 776 /* XXX: To be done */ 777 return; 778} 779 780int 781osigreturn(struct proc *p, struct osigreturn_args *uap) 782{ 783 784 /* XXX: To be done */ 785 return(ENOSYS); 786} 787 788int 789sigreturn(struct proc *p, struct sigreturn_args *uap) 790{ 791 792 /* XXX: To be done */ 793 return(ENOSYS); 794} 795 796void 797cpu_boot(int howto) 798{ 799} 800 801/* 802 * Shutdown the CPU as much as possible. 803 */ 804void 805cpu_halt(void) 806{ 807 808 OF_exit(); 809} 810 811/* 812 * Set set up registers on exec. 813 */ 814void 815setregs(struct proc *p, u_long entry, u_long stack, u_long ps_strings) 816{ 817 struct trapframe *tf; 818 struct ps_strings arginfo; 819 820 tf = trapframe(p); 821 822 bzero(tf, sizeof *tf); 823 tf->fixreg[1] = -roundup(-stack + 8, 16); 824 825 /* 826 * XXX Machine-independent code has already copied arguments and 827 * XXX environment to userland. Get them back here. 828 */ 829 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo)); 830 831 /* 832 * Set up arguments for _start(): 833 * _start(argc, argv, envp, obj, cleanup, ps_strings); 834 * 835 * Notes: 836 * - obj and cleanup are the auxilliary and termination 837 * vectors. They are fixed up by ld.elf_so. 838 * - ps_strings is a NetBSD extention, and will be 839 * ignored by executables which are strictly 840 * compliant with the SVR4 ABI. 841 * 842 * XXX We have to set both regs and retval here due to different 843 * XXX calling convention in trap.c and init_main.c. 844 */ 845 tf->fixreg[3] = arginfo.ps_nargvstr; 846 tf->fixreg[4] = (register_t)arginfo.ps_argvstr; 847 tf->fixreg[5] = (register_t)arginfo.ps_envstr; 848 tf->fixreg[6] = 0; /* auxillary vector */ 849 tf->fixreg[7] = 0; /* termination vector */ 850 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ 851 852 tf->srr0 = entry; 853 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 854 p->p_addr->u_pcb.pcb_flags = 0; 855} 856 857extern void *extint, *extsize; 858extern u_long extint_call; 859 860#if 0 861void 862install_extint(void (*handler)(void)) 863{ 864 u_long offset; 865 int omsr, msr; 866 867 offset = (u_long)handler - (u_long)&extint_call; 868 869#ifdef DIAGNOSTIC 870 if (offset > 0x1ffffff) 871 panic("install_extint: too far away"); 872#endif 873 __asm __volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1" 874 : "=r"(omsr), "=r"(msr) : "K"((u_short)~PSL_EE)); 875 extint_call = (extint_call & 0xfc000003) | offset; 876 bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize); 877 __syncicache((void *)&extint_call, sizeof extint_call); 878 __syncicache((void *)EXC_EXI, (int)&extsize); 879 __asm __volatile ("mtmsr %0" :: "r"(omsr)); 880} 881#endif 882 883#if !defined(DDB) 884void 885Debugger(const char *msg) 886{ 887 888 printf("Debugger(\"%s\") called.\n", msg); 889} 890#endif /* !defined(DDB) */ 891 892/* XXX: dummy {fill,set}_[fp]regs */ 893int 894fill_regs(struct proc *p, struct reg *regs) 895{ 896 897 return (ENOSYS); 898} 899 900int 901fill_fpregs(struct proc *p, struct fpreg *fpregs) 902{ 903 904 return (ENOSYS); 905} 906 907int 908set_regs(struct proc *p, struct reg *regs) 909{ 910 911 return (ENOSYS); 912} 913 914int 915set_fpregs(struct proc *p, struct fpreg *fpregs) 916{ 917 918 return (ENOSYS); 919} 920 921int 922ptrace_set_pc(struct proc *p, unsigned long addr) 923{ 924 925 /* XXX: coming soon... */ 926 return (ENOSYS); 927} 928 929int 930ptrace_single_step(struct proc *p) 931{ 932 933 /* XXX: coming soon... */ 934 return (ENOSYS); 935} 936 937int 938ptrace_write_u(struct proc *p, vm_offset_t off, long data) 939{ 940 941 /* XXX: coming soon... */ 942 return (ENOSYS); 943} 944 945int 946ptrace_read_u_check(struct proc *p, vm_offset_t addr, size_t len) 947{ 948 949 /* XXX: coming soon... */ 950 return (ENOSYS); 951} 952 953int 954ptrace_clear_single_step(struct proc *p) 955{ 956 957 /* XXX: coming soon... */ 958 return (ENOSYS); 959} 960 961/* 962 * Initialise a struct globaldata. 963 */ 964void 965globaldata_init(struct globaldata *globaldata, int cpuid, size_t sz) 966{ 967 968 bzero(globaldata, sz); 969 globaldata->gd_cpuid = cpuid; 970 globaldata->gd_next_asn = 0; 971 globaldata->gd_current_asngen = 1; 972} 973