1 /* $NetBSD: oea_machdep.c,v 1.60 2011/07/17 20:54:46 joerg Exp $ */ 2 3 /* 4 * Copyright (C) 2002 Matt Thomas 5 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 6 * Copyright (C) 1995, 1996 TooLs GmbH. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by TooLs GmbH. 20 * 4. The name of TooLs GmbH may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: oea_machdep.c,v 1.60 2011/07/17 20:54:46 joerg Exp $"); 37 38 #include "opt_ppcarch.h" 39 #include "opt_compat_netbsd.h" 40 #include "opt_ddb.h" 41 #include "opt_kgdb.h" 42 #include "opt_ipkdb.h" 43 #include "opt_multiprocessor.h" 44 #include "opt_altivec.h" 45 46 #include <sys/param.h> 47 #include <sys/buf.h> 48 #include <sys/boot_flag.h> 49 #include <sys/exec.h> 50 #include <sys/kernel.h> 51 #include <sys/malloc.h> 52 #include <sys/mbuf.h> 53 #include <sys/mount.h> 54 #include <sys/msgbuf.h> 55 #include <sys/proc.h> 56 #include <sys/reboot.h> 57 #include <sys/syscallargs.h> 58 #include <sys/syslog.h> 59 #include <sys/systm.h> 60 61 #include <uvm/uvm_extern.h> 62 63 #ifdef DDB 64 #include <powerpc/db_machdep.h> 65 #include <ddb/db_extern.h> 66 #endif 67 68 #ifdef KGDB 69 #include <sys/kgdb.h> 70 #endif 71 72 #ifdef IPKDB 73 #include <ipkdb/ipkdb.h> 74 #endif 75 76 #include <machine/powerpc.h> 77 78 #include <powerpc/trap.h> 79 #include <powerpc/spr.h> 80 #include <powerpc/pte.h> 81 #include <powerpc/altivec.h> 82 #include <powerpc/pcb.h> 83 84 #include <powerpc/oea/spr.h> 85 #include <powerpc/oea/bat.h> 86 #include <powerpc/oea/sr_601.h> 87 #include <powerpc/oea/cpufeat.h> 88 89 char machine[] = MACHINE; /* from <machine/param.h> */ 90 char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ 91 92 struct vm_map *phys_map = NULL; 93 94 /* 95 * Global variables used here and there 96 */ 97 static void trap0(void *); 98 99 /* XXXSL: The battable is not initialized to non-zero for PPC_OEA64 and PPC_OEA64_BRIDGE */ 100 struct bat battable[512]; 101 102 register_t iosrtable[16]; /* I/O segments, for kernel_pmap setup */ 103 #ifndef MSGBUFADDR 104 paddr_t msgbuf_paddr; 105 #endif 106 107 void 108 oea_init(void (*handler)(void)) 109 { 110 extern int trapcode[], trapsize[]; 111 extern int sctrap[], scsize[]; 112 extern int alitrap[], alisize[]; 113 extern int dsitrap[], dsisize[]; 114 extern int trapstart[], trapend[]; 115 #ifdef PPC_OEA601 116 extern int dsi601trap[], dsi601size[]; 117 #endif 118 extern int decrint[], decrsize[]; 119 extern int tlbimiss[], tlbimsize[]; 120 extern int tlbdlmiss[], tlbdlmsize[]; 121 extern int tlbdsmiss[], tlbdsmsize[]; 122 #if defined(DDB) || defined(KGDB) 123 extern int ddblow[], ddbsize[]; 124 #endif 125 #ifdef IPKDB 126 extern int ipkdblow[], ipkdbsize[]; 127 #endif 128 #ifdef ALTIVEC 129 register_t msr; 130 #endif 131 uintptr_t exc, exc_base; 132 #if defined(ALTIVEC) || defined(PPC_OEA) 133 register_t scratch; 134 #endif 135 unsigned int cpuvers; 136 size_t size; 137 struct cpu_info * const ci = &cpu_info[0]; 138 139 #ifdef PPC_HIGH_VEC 140 exc_base = EXC_HIGHVEC; 141 #else 142 exc_base = 0; 143 #endif 144 KASSERT(mfspr(SPR_SPRG0) == (uintptr_t)ci); 145 146 cpuvers = mfpvr() >> 16; 147 148 /* 149 * Initialize proc0 and current pcb and pmap pointers. 150 */ 151 (void) ci; 152 KASSERT(ci != NULL); 153 KASSERT(curcpu() == ci); 154 KASSERT(lwp0.l_cpu == ci); 155 156 curpcb = lwp_getpcb(&lwp0); 157 memset(curpcb, 0, sizeof(struct pcb)); 158 159 #ifdef ALTIVEC 160 /* 161 * Initialize the vectors with NaNs 162 */ 163 for (scratch = 0; scratch < 32; scratch++) { 164 curpcb->pcb_vr.vreg[scratch][0] = 0x7FFFDEAD; 165 curpcb->pcb_vr.vreg[scratch][1] = 0x7FFFDEAD; 166 curpcb->pcb_vr.vreg[scratch][2] = 0x7FFFDEAD; 167 curpcb->pcb_vr.vreg[scratch][3] = 0x7FFFDEAD; 168 } 169 #endif 170 curpm = curpcb->pcb_pm = pmap_kernel(); 171 172 /* 173 * Cause a PGM trap if we branch to 0. 174 * 175 * XXX GCC4.1 complains about memset on address zero, so 176 * don't use the builtin. 177 */ 178 #undef memset 179 memset(0, 0, 0x100); 180 181 /* 182 * Set up trap vectors. Don't assume vectors are on 0x100. 183 */ 184 for (exc = exc_base; exc <= exc_base + EXC_LAST; exc += 0x100) { 185 switch (exc - exc_base) { 186 default: 187 size = (size_t)trapsize; 188 memcpy((void *)exc, trapcode, size); 189 break; 190 #if 0 191 case EXC_EXI: 192 /* 193 * This one is (potentially) installed during autoconf 194 */ 195 break; 196 #endif 197 case EXC_SC: 198 size = (size_t)scsize; 199 memcpy((void *)exc, sctrap, size); 200 break; 201 case EXC_ALI: 202 size = (size_t)alisize; 203 memcpy((void *)exc, alitrap, size); 204 break; 205 case EXC_DSI: 206 #ifdef PPC_OEA601 207 if (cpuvers == MPC601) { 208 size = (size_t)dsi601size; 209 memcpy((void *)exc, dsi601trap, size); 210 break; 211 } else 212 #endif /* PPC_OEA601 */ 213 if (oeacpufeat & OEACPU_NOBAT) { 214 size = (size_t)alisize; 215 memcpy((void *)exc, alitrap, size); 216 } else { 217 size = (size_t)dsisize; 218 memcpy((void *)exc, dsitrap, size); 219 } 220 break; 221 case EXC_DECR: 222 size = (size_t)decrsize; 223 memcpy((void *)exc, decrint, size); 224 break; 225 case EXC_IMISS: 226 size = (size_t)tlbimsize; 227 memcpy((void *)exc, tlbimiss, size); 228 break; 229 case EXC_DLMISS: 230 size = (size_t)tlbdlmsize; 231 memcpy((void *)exc, tlbdlmiss, size); 232 break; 233 case EXC_DSMISS: 234 size = (size_t)tlbdsmsize; 235 memcpy((void *)exc, tlbdsmiss, size); 236 break; 237 case EXC_PERF: 238 size = (size_t)trapsize; 239 memcpy((void *)exc, trapcode, size); 240 memcpy((void *)(exc_base + EXC_VEC), trapcode, size); 241 break; 242 #if defined(DDB) || defined(IPKDB) || defined(KGDB) 243 case EXC_RUNMODETRC: 244 #ifdef PPC_OEA601 245 if (cpuvers != MPC601) { 246 #endif 247 size = (size_t)trapsize; 248 memcpy((void *)exc, trapcode, size); 249 break; 250 #ifdef PPC_OEA601 251 } 252 /* FALLTHROUGH */ 253 #endif 254 case EXC_PGM: 255 case EXC_TRC: 256 case EXC_BPT: 257 #if defined(DDB) || defined(KGDB) 258 size = (size_t)ddbsize; 259 memcpy((void *)exc, ddblow, size); 260 #if defined(IPKDB) 261 #error "cannot enable IPKDB with DDB or KGDB" 262 #endif 263 #else 264 size = (size_t)ipkdbsize; 265 memcpy((void *)exc, ipkdblow, size); 266 #endif 267 break; 268 #endif /* DDB || IPKDB || KGDB */ 269 } 270 #if 0 271 exc += roundup(size, 32); 272 #endif 273 } 274 275 /* 276 * Install a branch absolute to trap0 to force a panic. 277 */ 278 if ((uintptr_t)trap0 < 0x2000000) { 279 *(uint32_t *) 0 = 0x7c6802a6; 280 *(uint32_t *) 4 = 0x48000002 | (uintptr_t) trap0; 281 } 282 283 /* 284 * Get the cache sizes because install_extint calls __syncicache. 285 */ 286 cpu_probe_cache(); 287 288 #define MxSPR_MASK 0x7c1fffff 289 #define MFSPR_MQ 0x7c0002a6 290 #define MTSPR_MQ 0x7c0003a6 291 #define MTSPR_IBAT0L 0x7c1183a6 292 #define MTSPR_IBAT1L 0x7c1383a6 293 #define NOP 0x60000000 294 #define B 0x48000000 295 #define TLBSYNC 0x7c00046c 296 #define SYNC 0x7c0004ac 297 298 #ifdef ALTIVEC 299 #define MFSPR_VRSAVE 0x7c0042a6 300 #define MTSPR_VRSAVE 0x7c0043a6 301 302 /* 303 * Try to set the VEC bit in the MSR. If it doesn't get set, we are 304 * not on a AltiVec capable processor. 305 */ 306 __asm volatile ( 307 "mfmsr %0; oris %1,%0,%2@h; mtmsr %1; isync; " 308 "mfmsr %1; mtmsr %0; isync" 309 : "=r"(msr), "=r"(scratch) 310 : "J"(PSL_VEC)); 311 312 /* 313 * If we aren't on an AltiVec capable processor, we need to zap any of 314 * the sequences we save/restore the VRSAVE SPR into NOPs. 315 */ 316 if (scratch & PSL_VEC) { 317 cpu_altivec = 1; 318 } else { 319 int *ip = trapstart; 320 321 for (; ip < trapend; ip++) { 322 if ((ip[0] & MxSPR_MASK) == MFSPR_VRSAVE) { 323 ip[0] = NOP; /* mfspr */ 324 ip[1] = NOP; /* stw */ 325 } else if ((ip[0] & MxSPR_MASK) == MTSPR_VRSAVE) { 326 ip[-1] = NOP; /* lwz */ 327 ip[0] = NOP; /* mtspr */ 328 } 329 } 330 } 331 #endif 332 333 /* XXX It would seem like this code could be elided ifndef 601, but 334 * doing so breaks my power3 machine. 335 */ 336 /* 337 * If we aren't on a MPC601 processor, we need to zap any of the 338 * sequences we save/restore the MQ SPR into NOPs, and skip over the 339 * sequences where we zap/restore BAT registers on kernel exit/entry. 340 */ 341 if (cpuvers != MPC601) { 342 int *ip = trapstart; 343 344 for (; ip < trapend; ip++) { 345 if ((ip[0] & MxSPR_MASK) == MFSPR_MQ) { 346 ip[0] = NOP; /* mfspr */ 347 ip[1] = NOP; /* stw */ 348 } else if ((ip[0] & MxSPR_MASK) == MTSPR_MQ) { 349 ip[-1] = NOP; /* lwz */ 350 ip[0] = NOP; /* mtspr */ 351 } else if ((ip[0] & MxSPR_MASK) == MTSPR_IBAT0L) { 352 if ((ip[1] & MxSPR_MASK) == MTSPR_IBAT1L) 353 ip[-1] = B | 0x14; /* li */ 354 else 355 ip[-4] = B | 0x24; /* lis */ 356 } 357 } 358 } 359 360 /* 361 * Sync the changed instructions. 362 */ 363 __syncicache((void *) trapstart, 364 (uintptr_t) trapend - (uintptr_t) trapstart); 365 #ifdef PPC_OEA601 366 367 /* 368 * If we are on a MPC601 processor, we need to zap any tlbsync 369 * instructions into sync. This differs from the above in 370 * examing all kernel text, as opposed to just the exception handling. 371 * We sync the icache on every instruction found since there are 372 * only very few of them. 373 */ 374 if (cpuvers == MPC601) { 375 extern int kernel_text[], etext[]; 376 int *ip; 377 378 for (ip = kernel_text; ip < etext; ip++) 379 if (*ip == TLBSYNC) { 380 *ip = SYNC; 381 __syncicache(ip, sizeof(*ip)); 382 } 383 } 384 #endif /* PPC_OEA601 */ 385 386 /* 387 * Configure a PSL user mask matching this processor. 388 */ 389 cpu_psluserset = PSL_EE | PSL_PR | PSL_ME | PSL_IR | PSL_DR | PSL_RI; 390 cpu_pslusermod = PSL_FP | PSL_FE0 | PSL_FE1 | PSL_LE | PSL_SE | PSL_BE; 391 #ifdef PPC_OEA601 392 if (cpuvers == MPC601) { 393 cpu_psluserset &= PSL_601_MASK; 394 cpu_pslusermod &= PSL_601_MASK; 395 } 396 #endif 397 #ifdef ALTIVEC 398 if (cpu_altivec) 399 cpu_pslusermod |= PSL_VEC; 400 #endif 401 #ifdef PPC_HIGH_VEC 402 cpu_psluserset |= PSL_IP; /* XXX ok? */ 403 #endif 404 405 /* 406 * external interrupt handler install 407 */ 408 if (handler) 409 oea_install_extint(handler); 410 411 __syncicache((void *)exc_base, EXC_LAST + 0x100); 412 413 /* 414 * Now enable translation (and machine checks/recoverable interrupts). 415 */ 416 #ifdef PPC_OEA 417 __asm volatile ("sync; mfmsr %0; ori %0,%0,%1; mtmsr %0; isync" 418 : "=r"(scratch) 419 : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI)); 420 #endif 421 422 /* 423 * Let's take all the indirect calls via our stubs and patch 424 * them to be direct calls. 425 */ 426 cpu_fixup_stubs(); 427 428 KASSERT(curcpu() == ci); 429 } 430 431 #ifdef PPC_OEA601 432 void 433 mpc601_ioseg_add(paddr_t pa, register_t len) 434 { 435 const u_int i = pa >> ADDR_SR_SHFT; 436 437 if (len != BAT_BL_256M) 438 panic("mpc601_ioseg_add: len != 256M"); 439 440 /* 441 * Translate into an I/O segment, load it, and stash away for use 442 * in pmap_bootstrap(). 443 */ 444 iosrtable[i] = SR601(SR601_Ks, SR601_BUID_MEMFORCED, 0, i); 445 __asm volatile ("mtsrin %0,%1" 446 :: "r"(iosrtable[i]), 447 "r"(pa)); 448 } 449 #endif /* PPC_OEA601 */ 450 451 #if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE) 452 void 453 oea_iobat_add(paddr_t pa, register_t len) 454 { 455 static int n = 1; 456 const u_int i = pa >> 28; 457 battable[i].batl = BATL(pa, BAT_I|BAT_G, BAT_PP_RW); 458 battable[i].batu = BATU(pa, len, BAT_Vs); 459 460 /* 461 * Let's start loading the BAT registers. 462 */ 463 switch (n) { 464 case 1: 465 __asm volatile ("mtdbatl 1,%0; mtdbatu 1,%1;" 466 :: "r"(battable[i].batl), 467 "r"(battable[i].batu)); 468 n = 2; 469 break; 470 case 2: 471 __asm volatile ("mtdbatl 2,%0; mtdbatu 2,%1;" 472 :: "r"(battable[i].batl), 473 "r"(battable[i].batu)); 474 n = 3; 475 break; 476 case 3: 477 __asm volatile ("mtdbatl 3,%0; mtdbatu 3,%1;" 478 :: "r"(battable[i].batl), 479 "r"(battable[i].batu)); 480 n = 4; 481 break; 482 default: 483 break; 484 } 485 } 486 487 void 488 oea_iobat_remove(paddr_t pa) 489 { 490 register_t batu; 491 int i, n; 492 493 n = pa >> ADDR_SR_SHFT; 494 if (!BAT_VA_MATCH_P(battable[n].batu, pa) || 495 !BAT_VALID_P(battable[n].batu, PSL_PR)) 496 return; 497 battable[n].batl = 0; 498 battable[n].batu = 0; 499 #define BAT_RESET(n) \ 500 __asm volatile("mtdbatu %0,%1; mtdbatl %0,%1" :: "n"(n), "r"(0)) 501 #define BATU_GET(n, r) __asm volatile("mfdbatu %0,%1" : "=r"(r) : "n"(n)) 502 503 for (i=1 ; i<4 ; i++) { 504 switch (i) { 505 case 1: 506 BATU_GET(1, batu); 507 if (BAT_VA_MATCH_P(batu, pa) && 508 BAT_VALID_P(batu, PSL_PR)) 509 BAT_RESET(1); 510 break; 511 case 2: 512 BATU_GET(2, batu); 513 if (BAT_VA_MATCH_P(batu, pa) && 514 BAT_VALID_P(batu, PSL_PR)) 515 BAT_RESET(2); 516 break; 517 case 3: 518 BATU_GET(3, batu); 519 if (BAT_VA_MATCH_P(batu, pa) && 520 BAT_VALID_P(batu, PSL_PR)) 521 BAT_RESET(3); 522 break; 523 default: 524 break; 525 } 526 } 527 } 528 529 void 530 oea_batinit(paddr_t pa, ...) 531 { 532 struct mem_region *allmem, *availmem, *mp; 533 unsigned int cpuvers; 534 register_t msr = mfmsr(); 535 va_list ap; 536 537 cpuvers = mfpvr() >> 16; 538 539 /* 540 * Initialize BAT registers to unmapped to not generate 541 * overlapping mappings below. 542 * 543 * The 601's implementation differs in the Valid bit being situated 544 * in the lower BAT register, and in being a unified BAT only whose 545 * four entries are accessed through the IBAT[0-3] SPRs. 546 * 547 * Also, while the 601 does distinguish between supervisor/user 548 * protection keys, it does _not_ distinguish between validity in 549 * supervisor/user mode. 550 */ 551 if ((msr & (PSL_IR|PSL_DR)) == 0) { 552 #ifdef PPC_OEA601 553 if (cpuvers == MPC601) { 554 __asm volatile ("mtibatl 0,%0" :: "r"(0)); 555 __asm volatile ("mtibatl 1,%0" :: "r"(0)); 556 __asm volatile ("mtibatl 2,%0" :: "r"(0)); 557 __asm volatile ("mtibatl 3,%0" :: "r"(0)); 558 } else 559 #endif /* PPC_OEA601 */ 560 { 561 __asm volatile ("mtibatu 0,%0" :: "r"(0)); 562 __asm volatile ("mtibatu 1,%0" :: "r"(0)); 563 __asm volatile ("mtibatu 2,%0" :: "r"(0)); 564 __asm volatile ("mtibatu 3,%0" :: "r"(0)); 565 __asm volatile ("mtdbatu 0,%0" :: "r"(0)); 566 __asm volatile ("mtdbatu 1,%0" :: "r"(0)); 567 __asm volatile ("mtdbatu 2,%0" :: "r"(0)); 568 __asm volatile ("mtdbatu 3,%0" :: "r"(0)); 569 } 570 } 571 572 /* 573 * Set up BAT to map physical memory 574 */ 575 #ifdef PPC_OEA601 576 if (cpuvers == MPC601) { 577 int i; 578 579 /* 580 * Set up battable to map the lowest 256 MB area. 581 * Map the lowest 32 MB area via BAT[0-3]; 582 * BAT[01] are fixed, BAT[23] are floating. 583 */ 584 for (i = 0; i < 32; i++) { 585 battable[i].batl = BATL601(i << 23, 586 BAT601_BSM_8M, BAT601_V); 587 battable[i].batu = BATU601(i << 23, 588 BAT601_M, BAT601_Ku, BAT601_PP_NONE); 589 } 590 __asm volatile ("mtibatu 0,%1; mtibatl 0,%0" 591 :: "r"(battable[0x00000000 >> 23].batl), 592 "r"(battable[0x00000000 >> 23].batu)); 593 __asm volatile ("mtibatu 1,%1; mtibatl 1,%0" 594 :: "r"(battable[0x00800000 >> 23].batl), 595 "r"(battable[0x00800000 >> 23].batu)); 596 __asm volatile ("mtibatu 2,%1; mtibatl 2,%0" 597 :: "r"(battable[0x01000000 >> 23].batl), 598 "r"(battable[0x01000000 >> 23].batu)); 599 __asm volatile ("mtibatu 3,%1; mtibatl 3,%0" 600 :: "r"(battable[0x01800000 >> 23].batl), 601 "r"(battable[0x01800000 >> 23].batu)); 602 } else 603 #endif /* PPC_OEA601 */ 604 { 605 /* 606 * Set up BAT0 to only map the lowest 256 MB area 607 */ 608 battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); 609 battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); 610 611 __asm volatile ("mtibatl 0,%0; mtibatu 0,%1;" 612 "mtdbatl 0,%0; mtdbatu 0,%1;" 613 :: "r"(battable[0].batl), "r"(battable[0].batu)); 614 } 615 616 /* 617 * Now setup other fixed bat registers 618 * 619 * Note that we still run in real mode, and the BAT 620 * registers were cleared above. 621 */ 622 623 va_start(ap, pa); 624 625 /* 626 * Add any I/O BATs specificed; 627 * use I/O segments on the BAT-starved 601. 628 */ 629 #ifdef PPC_OEA601 630 if (cpuvers == MPC601) { 631 while (pa != 0) { 632 register_t len = va_arg(ap, register_t); 633 mpc601_ioseg_add(pa, len); 634 pa = va_arg(ap, paddr_t); 635 } 636 } else 637 #endif 638 { 639 while (pa != 0) { 640 register_t len = va_arg(ap, register_t); 641 oea_iobat_add(pa, len); 642 pa = va_arg(ap, paddr_t); 643 } 644 } 645 646 va_end(ap); 647 648 /* 649 * Set up battable to map all RAM regions. 650 * This is here because mem_regions() call needs bat0 set up. 651 */ 652 mem_regions(&allmem, &availmem); 653 #ifdef PPC_OEA601 654 if (cpuvers == MPC601) { 655 for (mp = allmem; mp->size; mp++) { 656 paddr_t paddr = mp->start & 0xff800000; 657 paddr_t end = mp->start + mp->size; 658 659 do { 660 u_int ix = paddr >> 23; 661 662 battable[ix].batl = 663 BATL601(paddr, BAT601_BSM_8M, BAT601_V); 664 battable[ix].batu = 665 BATU601(paddr, BAT601_M, BAT601_Ku, BAT601_PP_NONE); 666 paddr += (1 << 23); 667 } while (paddr < end); 668 } 669 } else 670 #endif 671 { 672 for (mp = allmem; mp->size; mp++) { 673 paddr_t paddr = mp->start & 0xf0000000; 674 paddr_t end = mp->start + mp->size; 675 676 do { 677 u_int ix = paddr >> 28; 678 679 battable[ix].batl = 680 BATL(paddr, BAT_M, BAT_PP_RW); 681 battable[ix].batu = 682 BATU(paddr, BAT_BL_256M, BAT_Vs); 683 paddr += SEGMENT_LENGTH; 684 } while (paddr < end); 685 } 686 } 687 } 688 #endif /* PPC_OEA || PPC_OEA64_BRIDGE */ 689 690 void 691 oea_install_extint(void (*handler)(void)) 692 { 693 extern int extint[], extsize[]; 694 extern int extint_call[]; 695 uintptr_t offset = (uintptr_t)handler - (uintptr_t)extint_call; 696 int omsr, msr; 697 698 #ifdef DIAGNOSTIC 699 if (offset > 0x1ffffff) 700 panic("install_extint: %p too far away (%#lx)", handler, 701 (unsigned long) offset); 702 #endif 703 __asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1" 704 : "=r" (omsr), "=r" (msr) 705 : "K" ((u_short)~PSL_EE)); 706 extint_call[0] = (extint_call[0] & 0xfc000003) | offset; 707 __syncicache((void *)extint_call, sizeof extint_call[0]); 708 #ifdef PPC_HIGH_VEC 709 memcpy((void *)(EXC_HIGHVEC + EXC_EXI), extint, (size_t)extsize); 710 __syncicache((void *)(EXC_HIGHVEC + EXC_EXI), (int)extsize); 711 #else 712 memcpy((void *)EXC_EXI, extint, (size_t)extsize); 713 __syncicache((void *)EXC_EXI, (int)extsize); 714 #endif 715 __asm volatile ("mtmsr %0" :: "r"(omsr)); 716 } 717 718 /* 719 * Machine dependent startup code. 720 */ 721 void 722 oea_startup(const char *model) 723 { 724 uintptr_t sz; 725 void *v; 726 vaddr_t minaddr, maxaddr; 727 char pbuf[9]; 728 729 KASSERT(curcpu() != NULL); 730 KASSERT(lwp0.l_cpu != NULL); 731 KASSERT(curcpu()->ci_idepth == -1); 732 733 sz = round_page(MSGBUFSIZE); 734 #ifdef MSGBUFADDR 735 v = (void *) MSGBUFADDR; 736 #else 737 /* 738 * If the msgbuf is not in segment 0, allocate KVA for it and access 739 * it via mapped pages. [This prevents unneeded BAT switches.] 740 */ 741 v = (void *) msgbuf_paddr; 742 if (msgbuf_paddr + sz > SEGMENT_LENGTH) { 743 u_int i; 744 745 minaddr = 0; 746 if (uvm_map(kernel_map, &minaddr, sz, 747 NULL, UVM_UNKNOWN_OFFSET, 0, 748 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, 749 UVM_INH_NONE, UVM_ADV_NORMAL, 0)) != 0) 750 panic("startup: cannot allocate VM for msgbuf"); 751 v = (void *)minaddr; 752 for (i = 0; i < sz; i += PAGE_SIZE) { 753 pmap_kenter_pa(minaddr + i, msgbuf_paddr + i, 754 VM_PROT_READ|VM_PROT_WRITE, 0); 755 } 756 pmap_update(pmap_kernel()); 757 } 758 #endif 759 initmsgbuf(v, sz); 760 761 printf("%s%s", copyright, version); 762 if (model != NULL) 763 printf("Model: %s\n", model); 764 cpu_identify(NULL, 0); 765 766 format_bytes(pbuf, sizeof(pbuf), ctob((u_int)physmem)); 767 printf("total memory = %s\n", pbuf); 768 769 /* 770 * Allocate away the pages that map to 0xDEA[CDE]xxxx. Do this after 771 * the bufpages are allocated in case they overlap since it's not 772 * fatal if we can't allocate these. 773 */ 774 if (KERNEL_SR == 13 || KERNEL2_SR == 14) { 775 int error; 776 minaddr = 0xDEAC0000; 777 error = uvm_map(kernel_map, &minaddr, 0x30000, 778 NULL, UVM_UNKNOWN_OFFSET, 0, 779 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 780 UVM_ADV_NORMAL, UVM_FLAG_FIXED)); 781 if (error != 0 || minaddr != 0xDEAC0000) 782 printf("oea_startup: failed to allocate DEAD " 783 "ZONE: error=%d\n", error); 784 } 785 786 minaddr = 0; 787 788 /* 789 * Allocate a submap for physio 790 */ 791 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 792 VM_PHYS_SIZE, 0, false, NULL); 793 794 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 795 printf("avail memory = %s\n", pbuf); 796 } 797 798 /* 799 * Crash dump handling. 800 */ 801 802 void 803 oea_dumpsys(void) 804 { 805 printf("dumpsys: TBD\n"); 806 } 807 808 /* 809 * Convert kernel VA to physical address 810 */ 811 paddr_t 812 kvtop(void *addr) 813 { 814 vaddr_t va; 815 paddr_t pa; 816 uintptr_t off; 817 extern char end[]; 818 819 if (addr < (void *)end) 820 return (paddr_t)addr; 821 822 va = trunc_page((vaddr_t)addr); 823 off = (uintptr_t)addr - va; 824 825 if (pmap_extract(pmap_kernel(), va, &pa) == false) { 826 /*printf("kvtop: zero page frame (va=0x%x)\n", addr);*/ 827 return (paddr_t)addr; 828 } 829 830 return(pa + off); 831 } 832 833 /* 834 * Allocate vm space and mapin the I/O address 835 */ 836 void * 837 mapiodev(paddr_t pa, psize_t len, bool prefetchable) 838 { 839 paddr_t faddr; 840 vaddr_t taddr, va; 841 int off; 842 843 faddr = trunc_page(pa); 844 off = pa - faddr; 845 len = round_page(off + len); 846 va = taddr = uvm_km_alloc(kernel_map, len, 0, UVM_KMF_VAONLY); 847 848 if (va == 0) 849 return NULL; 850 851 for (; len > 0; len -= PAGE_SIZE) { 852 pmap_kenter_pa(taddr, faddr, VM_PROT_READ | VM_PROT_WRITE, 853 (prefetchable ? PMAP_MD_PREFETCHABLE : PMAP_NOCACHE)); 854 faddr += PAGE_SIZE; 855 taddr += PAGE_SIZE; 856 } 857 pmap_update(pmap_kernel()); 858 return (void *)(va + off); 859 } 860 861 void 862 unmapiodev(vaddr_t va, vsize_t len) 863 { 864 paddr_t faddr; 865 866 if (! va) 867 return; 868 869 faddr = trunc_page(va); 870 len = round_page(va - faddr + len); 871 872 pmap_kremove(faddr, len); 873 pmap_update(pmap_kernel()); 874 uvm_km_free(kernel_map, faddr, len, UVM_KMF_VAONLY); 875 } 876 877 void 878 trap0(void *lr) 879 { 880 panic("call to null-ptr from %p", lr); 881 } 882