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