1 /* $NetBSD: oea_machdep.c,v 1.88 2026/03/30 10:27:45 jmcneill 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.88 2026/03/30 10:27:45 jmcneill Exp $"); 37 38 #ifdef _KERNEL_OPT 39 #include "opt_altivec.h" 40 #include "opt_ddb.h" 41 #include "opt_kgdb.h" 42 #include "opt_multiprocessor.h" 43 #include "opt_ppcarch.h" 44 #endif 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/mbuf.h> 52 #include <sys/mount.h> 53 #include <sys/msgbuf.h> 54 #include <sys/proc.h> 55 #include <sys/reboot.h> 56 #include <sys/syscallargs.h> 57 #include <sys/syslog.h> 58 #include <sys/systm.h> 59 #include <sys/cpu.h> 60 #include <sys/kcore.h> 61 #include <sys/conf.h> 62 #include <sys/core.h> 63 64 #include <uvm/uvm_extern.h> 65 #include <uvm/uvm_page.h> 66 67 #ifdef DDB 68 #include <powerpc/db_machdep.h> 69 #include <ddb/db_extern.h> 70 #endif 71 72 #ifdef KGDB 73 #include <sys/kgdb.h> 74 #endif 75 76 #include <machine/powerpc.h> 77 #include <machine/kcore.h> 78 79 #include <powerpc/trap.h> 80 #include <powerpc/spr.h> 81 #include <powerpc/pte.h> 82 #include <powerpc/altivec.h> 83 #include <powerpc/pcb.h> 84 85 #include <powerpc/oea/bat.h> 86 #include <powerpc/oea/cpufeat.h> 87 #include <powerpc/oea/spr.h> 88 #include <powerpc/oea/sr_601.h> 89 90 char machine[] = MACHINE; /* from <machine/param.h> */ 91 char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ 92 93 struct vm_map *phys_map = NULL; 94 95 vaddr_t memhook; 96 97 /* 98 * Global variables used here and there 99 */ 100 static void trap0(void *); 101 102 /* XXXSL: The battable is not initialized to non-zero for PPC_OEA64 and PPC_OEA64_BRIDGE */ 103 struct bat battable[BAT_VA2IDX(0xffffffff)+1]; 104 105 register_t iosrtable[16]; /* I/O segments, for kernel_pmap setup */ 106 #ifndef MSGBUFADDR 107 paddr_t msgbuf_paddr; 108 #endif 109 110 extern int dsitrap_fix_dbat4[]; 111 extern int dsitrap_fix_dbat5[]; 112 extern int dsitrap_fix_dbat6[]; 113 extern int dsitrap_fix_dbat7[]; 114 115 /* 116 * Load pointer with 0 behind GCC's back, otherwise it will 117 * emit a "trap" instead. 118 */ 119 static __inline__ uintptr_t 120 zero_value(void) 121 { 122 uintptr_t dont_tell_gcc; 123 124 __asm volatile ("li %0, 0" : "=r"(dont_tell_gcc) :); 125 return dont_tell_gcc; 126 } 127 128 void 129 oea_init(void (*handler)(void)) 130 { 131 extern int trapcode[], trapsize[]; 132 extern int sctrap[], scsize[]; 133 extern int alitrap[], alisize[]; 134 extern int dsitrap[], dsisize[]; 135 extern int trapstart[], trapend[]; 136 #ifdef PPC_OEA601 137 extern int dsi601trap[], dsi601size[]; 138 #endif 139 extern int decrint[], decrsize[]; 140 extern int tlbimiss[], tlbimsize[]; 141 extern int tlbdlmiss[], tlbdlmsize[]; 142 extern int tlbdsmiss[], tlbdsmsize[]; 143 #if defined(DDB) || defined(KGDB) 144 extern int ddblow[], ddbsize[]; 145 #endif 146 #ifdef ALTIVEC 147 register_t msr; 148 #endif 149 uintptr_t exc, exc_base; 150 #if defined(ALTIVEC) || defined(PPC_OEA) 151 register_t scratch; 152 #endif 153 unsigned int cpuvers; 154 size_t size; 155 struct cpu_info * const ci = &cpu_info[0]; 156 157 #ifdef PPC_HIGH_VEC 158 exc_base = EXC_HIGHVEC; 159 #else 160 exc_base = zero_value(); 161 #endif 162 KASSERT(mfspr(SPR_SPRG0) == (uintptr_t)ci); 163 164 #if defined (PPC_OEA64_BRIDGE) && defined (PPC_OEA) 165 if (oeacpufeat & OEACPU_64_BRIDGE) 166 pmap_setup64bridge(); 167 else 168 pmap_setup32(); 169 #endif 170 171 172 cpuvers = mfpvr() >> 16; 173 174 /* 175 * Initialize proc0 and current pcb and pmap pointers. 176 */ 177 (void) ci; 178 KASSERT(ci != NULL); 179 KASSERT(curcpu() == ci); 180 KASSERT(lwp0.l_cpu == ci); 181 182 curpcb = lwp_getpcb(&lwp0); 183 memset(curpcb, 0, sizeof(struct pcb)); 184 185 #ifdef ALTIVEC 186 /* 187 * Initialize the vectors with NaNs 188 */ 189 for (scratch = 0; scratch < 32; scratch++) { 190 curpcb->pcb_vr.vreg[scratch][0] = 0x7FFFDEAD; 191 curpcb->pcb_vr.vreg[scratch][1] = 0x7FFFDEAD; 192 curpcb->pcb_vr.vreg[scratch][2] = 0x7FFFDEAD; 193 curpcb->pcb_vr.vreg[scratch][3] = 0x7FFFDEAD; 194 } 195 #endif 196 curpm = curpcb->pcb_pm = pmap_kernel(); 197 198 /* 199 * Cause a PGM trap if we branch to 0. 200 * 201 * XXX GCC4.1 complains about memset on address zero, so 202 * don't use the builtin. 203 */ 204 #undef memset 205 memset(0, 0, 0x100); 206 207 /* 208 * Set up trap vectors. Don't assume vectors are on 0x100. 209 */ 210 for (exc = exc_base; exc <= exc_base + EXC_LAST; exc += 0x100) { 211 switch (exc - exc_base) { 212 default: 213 size = (size_t)trapsize; 214 memcpy((void *)exc, trapcode, size); 215 break; 216 #if 0 217 case EXC_EXI: 218 /* 219 * This one is (potentially) installed during autoconf 220 */ 221 break; 222 #endif 223 case EXC_SC: 224 size = (size_t)scsize; 225 memcpy((void *)exc, sctrap, size); 226 break; 227 case EXC_ALI: 228 size = (size_t)alisize; 229 memcpy((void *)exc, alitrap, size); 230 break; 231 case EXC_DSI: 232 #ifdef PPC_OEA601 233 if (cpuvers == MPC601) { 234 size = (size_t)dsi601size; 235 memcpy((void *)exc, dsi601trap, size); 236 break; 237 } else 238 #endif /* PPC_OEA601 */ 239 if (oeacpufeat & OEACPU_NOBAT) { 240 size = (size_t)alisize; 241 memcpy((void *)exc, alitrap, size); 242 } else { 243 size = (size_t)dsisize; 244 memcpy((void *)exc, dsitrap, size); 245 } 246 break; 247 case EXC_DECR: 248 size = (size_t)decrsize; 249 memcpy((void *)exc, decrint, size); 250 break; 251 case EXC_IMISS: 252 size = (size_t)tlbimsize; 253 memcpy((void *)exc, tlbimiss, size); 254 break; 255 case EXC_DLMISS: 256 size = (size_t)tlbdlmsize; 257 memcpy((void *)exc, tlbdlmiss, size); 258 break; 259 case EXC_DSMISS: 260 size = (size_t)tlbdsmsize; 261 memcpy((void *)exc, tlbdsmiss, size); 262 break; 263 case EXC_PERF: 264 size = (size_t)trapsize; 265 memcpy((void *)exc, trapcode, size); 266 memcpy((void *)(exc_base + EXC_VEC), trapcode, size); 267 break; 268 #if defined(DDB) || defined(KGDB) 269 case EXC_RUNMODETRC: 270 #ifdef PPC_OEA601 271 if (cpuvers != MPC601) 272 #endif 273 { 274 size = (size_t)trapsize; 275 memcpy((void *)exc, trapcode, size); 276 break; 277 } 278 /* FALLTHROUGH */ 279 case EXC_PGM: 280 case EXC_TRC: 281 case EXC_BPT: 282 size = (size_t)ddbsize; 283 memcpy((void *)exc, ddblow, size); 284 break; 285 #endif /* DDB || KGDB */ 286 } 287 #if 0 288 exc += roundup(size, 32); 289 #endif 290 } 291 292 /* 293 * Install a branch absolute to trap0 to force a panic. 294 */ 295 if ((uintptr_t)trap0 < 0x2000000) { 296 uint32_t *p = (uint32_t *)zero_value(); 297 298 p[0] = 0x7c6802a6; 299 p[1] = 0x48000002 | (uintptr_t) trap0; 300 } 301 302 /* 303 * Get the cache sizes because install_extint calls __syncicache. 304 */ 305 cpu_probe_cache(); 306 307 #define MxSPR_MASK 0x7c1fffff 308 #define MFSPR_MQ 0x7c0002a6 309 #define MTSPR_MQ 0x7c0003a6 310 #define MTSPR_IBAT0L 0x7c1183a6 311 #define MTSPR_IBAT1L 0x7c1383a6 312 #define NOP 0x60000000 313 #define B 0x48000000 314 #define TLBSYNC 0x7c00046c 315 #define SYNC 0x7c0004ac 316 #ifdef PPC_OEA64_BRIDGE 317 #define MFMSR_MASK 0xfc1fffff 318 #define MFMSR 0x7c0000a6 319 #define MTMSRD_MASK 0xfc1effff 320 #define MTMSRD 0x7c000164 321 #define RLDICL_MASK 0xfc00001c 322 #define RLDICL 0x78000000 323 #define RFID 0x4c000024 324 #define RFI 0x4c000064 325 #endif 326 327 #ifdef ALTIVEC 328 #define MFSPR_VRSAVE 0x7c0042a6 329 #define MTSPR_VRSAVE 0x7c0043a6 330 331 /* 332 * Try to set the VEC bit in the MSR. If it doesn't get set, we are 333 * not on a AltiVec capable processor. 334 */ 335 __asm volatile ( 336 "mfmsr %0; oris %1,%0,%2@h; mtmsr %1; isync; " 337 "mfmsr %1; mtmsr %0; isync" 338 : "=r"(msr), "=r"(scratch) 339 : "J"(PSL_VEC)); 340 341 /* 342 * If we aren't on an AltiVec capable processor, we need to zap any of 343 * the sequences we save/restore the VRSAVE SPR into NOPs. 344 */ 345 if (scratch & PSL_VEC) { 346 cpu_altivec = 1; 347 } else { 348 for (int *ip = trapstart; ip < trapend; ip++) { 349 if ((ip[0] & MxSPR_MASK) == MFSPR_VRSAVE) { 350 ip[0] = NOP; /* mfspr */ 351 ip[1] = NOP; /* stw */ 352 } else if ((ip[0] & MxSPR_MASK) == MTSPR_VRSAVE) { 353 ip[-1] = NOP; /* lwz */ 354 ip[0] = NOP; /* mtspr */ 355 } 356 } 357 } 358 #endif 359 360 /* XXX It would seem like this code could be elided ifndef 601, but 361 * doing so breaks my power3 machine. 362 */ 363 /* 364 * If we aren't on a MPC601 processor, we need to zap any of the 365 * sequences we save/restore the MQ SPR into NOPs, and skip over the 366 * sequences where we zap/restore BAT registers on kernel exit/entry. 367 */ 368 if (cpuvers != MPC601) { 369 for (int *ip = trapstart; ip < trapend; ip++) { 370 if ((ip[0] & MxSPR_MASK) == MFSPR_MQ) { 371 ip[0] = NOP; /* mfspr */ 372 ip[1] = NOP; /* stw */ 373 } else if ((ip[0] & MxSPR_MASK) == MTSPR_MQ) { 374 ip[-1] = NOP; /* lwz */ 375 ip[0] = NOP; /* mtspr */ 376 } else if ((ip[0] & MxSPR_MASK) == MTSPR_IBAT0L) { 377 if ((ip[1] & MxSPR_MASK) == MTSPR_IBAT1L) 378 ip[-1] = B | 0x14; /* li */ 379 else 380 ip[-4] = B | 0x24; /* lis */ 381 } 382 } 383 } 384 385 #ifdef PPC_OEA64_BRIDGE 386 if ((oeacpufeat & OEACPU_64_BRIDGE) == 0) { 387 for (int *ip = (int *)exc_base; 388 (uintptr_t)ip <= exc_base + EXC_LAST; 389 ip++) { 390 if ((ip[0] & MFMSR_MASK) == MFMSR 391 && (ip[1] & RLDICL_MASK) == RLDICL 392 && (ip[2] & MTMSRD_MASK) == MTMSRD) { 393 *ip++ = NOP; 394 *ip++ = NOP; 395 ip[0] = NOP; 396 } else if (*ip == RFID) { 397 *ip = RFI; 398 } 399 } 400 401 /* 402 * Now replace each rfid instruction with a rfi instruction. 403 */ 404 for (int *ip = trapstart; ip < trapend; ip++) { 405 if ((ip[0] & MFMSR_MASK) == MFMSR 406 && (ip[1] & RLDICL_MASK) == RLDICL 407 && (ip[2] & MTMSRD_MASK) == MTMSRD) { 408 *ip++ = NOP; 409 *ip++ = NOP; 410 ip[0] = NOP; 411 } else if (*ip == RFID) { 412 *ip = RFI; 413 } 414 } 415 } 416 #endif /* PPC_OEA64_BRIDGE */ 417 418 /* 419 * Sync the changed instructions. 420 */ 421 __syncicache((void *) trapstart, 422 (uintptr_t) trapend - (uintptr_t) trapstart); 423 __syncicache(dsitrap_fix_dbat4, 16); 424 __syncicache(dsitrap_fix_dbat7, 8); 425 #ifdef PPC_OEA601 426 427 /* 428 * If we are on a MPC601 processor, we need to zap any tlbsync 429 * instructions into sync. This differs from the above in 430 * examining all kernel text, as opposed to just the exception handling. 431 * We sync the icache on every instruction found since there are 432 * only very few of them. 433 */ 434 if (cpuvers == MPC601) { 435 extern int kernel_text[], etext[]; 436 int *ip; 437 438 for (ip = kernel_text; ip < etext; ip++) { 439 if (*ip == TLBSYNC) { 440 *ip = SYNC; 441 __syncicache(ip, sizeof(*ip)); 442 } 443 } 444 } 445 #endif /* PPC_OEA601 */ 446 447 /* 448 * Configure a PSL user mask matching this processor. 449 * Don't allow to set PSL_FP/PSL_VEC, since that will affect PCU. 450 */ 451 cpu_psluserset = PSL_EE | PSL_PR | PSL_ME | PSL_IR | PSL_DR | PSL_RI; 452 cpu_pslusermod = PSL_FE0 | PSL_FE1 | PSL_LE | PSL_SE | PSL_BE; 453 #ifdef PPC_OEA601 454 if (cpuvers == MPC601) { 455 cpu_psluserset &= PSL_601_MASK; 456 cpu_pslusermod &= PSL_601_MASK; 457 } 458 #endif 459 #ifdef PPC_HIGH_VEC 460 cpu_psluserset |= PSL_IP; /* XXX ok? */ 461 #endif 462 463 /* 464 * external interrupt handler install 465 */ 466 if (handler) 467 oea_install_extint(handler); 468 469 __syncicache((void *)exc_base, EXC_LAST + 0x100); 470 471 /* 472 * Now enable translation (and machine checks/recoverable interrupts). 473 */ 474 #ifdef PPC_OEA 475 __asm volatile ("sync; mfmsr %0; ori %0,%0,%1; mtmsr %0; isync" 476 : "=r"(scratch) 477 : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI)); 478 #endif 479 480 /* 481 * Let's take all the indirect calls via our stubs and patch 482 * them to be direct calls. 483 */ 484 cpu_fixup_stubs(); 485 486 KASSERT(curcpu() == ci); 487 } 488 489 #ifdef PPC_OEA601 490 static void 491 mpc601_ioseg_add(paddr_t pa, register_t len) 492 { 493 const u_int i = pa >> ADDR_SR_SHFT; 494 495 if (len != BAT_BL_256M) 496 panic("mpc601_ioseg_add: len != 256M"); 497 498 /* 499 * Translate into an I/O segment, load it, and stash away for use 500 * in pmap_bootstrap(). 501 */ 502 iosrtable[i] = SR601(SR601_Ks, SR601_BUID_MEMFORCED, 0, i); 503 504 /* 505 * XXX Setting segment register 0xf on my powermac 7200 506 * wedges machine so set later in pmap.c 507 */ 508 /* 509 __asm volatile ("mtsrin %0,%1" 510 :: "r"(iosrtable[i]), 511 "r"(pa)); 512 */ 513 } 514 #endif /* PPC_OEA601 */ 515 516 #if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE) 517 #define DBAT_SET(n, batl, batu) \ 518 do { \ 519 mtspr(SPR_DBAT##n##L, (batl)); \ 520 mtspr(SPR_DBAT##n##U, (batu)); \ 521 } while (/*CONSTCOND*/ 0) 522 #define DBAT_RESET(n) DBAT_SET(n, 0, 0) 523 #define DBATU_GET(n) mfspr(SPR_DBAT##n##U) 524 #define IBAT_SET(n, batl, batu) \ 525 do { \ 526 mtspr(SPR_IBAT##n##L, (batl)); \ 527 mtspr(SPR_IBAT##n##U, (batu)); \ 528 } while (/*CONSTCOND*/ 0) 529 #define IBAT_RESET(n) IBAT_SET(n, 0, 0) 530 531 void 532 oea_iobat_add(paddr_t pa, register_t len) 533 { 534 static int z = 1; 535 const u_int n = BAT_BL_TO_SIZE(len) / BAT_BL_TO_SIZE(BAT_BL_8M); 536 const u_int i = BAT_VA2IDX(pa) & -n; /* in case pa was in the middle */ 537 const int after_bat3 = (oeacpufeat & OEACPU_HIGHBAT) ? 4 : 8; 538 539 KASSERT(len >= BAT_BL_8M); 540 541 #ifdef PPC_OEA601 542 if (mfpvr() >> 16 == MPC601) { 543 /* Use I/O segments on the BAT-starved 601. */ 544 mpc601_ioseg_add(pa, len); 545 return; 546 } 547 #endif /* PPC_OEA601 */ 548 549 /* 550 * If the caller wanted a bigger BAT than the hardware supports, 551 * split it into smaller BATs. 552 */ 553 if (len > BAT_BL_256M && (oeacpufeat & OEACPU_XBSEN) == 0) { 554 u_int xn = BAT_BL_TO_SIZE(len) >> 28; 555 while (xn-- > 0) { 556 oea_iobat_add(pa, BAT_BL_256M); 557 pa += 0x10000000; 558 } 559 return; 560 } 561 562 const register_t batl = BATL(pa, BAT_I|BAT_G, BAT_PP_RW); 563 const register_t batu = BATU(pa, len, BAT_Vs); 564 565 for (u_int j = 0; j < n; j++) { 566 battable[i + j].batl = batl; 567 battable[i + j].batu = batu; 568 } 569 570 /* 571 * Let's start loading the BAT registers. 572 */ 573 switch (z) { 574 case 1: 575 DBAT_SET(1, batl, batu); 576 z = 2; 577 break; 578 case 2: 579 DBAT_SET(2, batl, batu); 580 z = 3; 581 break; 582 case 3: 583 DBAT_SET(3, batl, batu); 584 z = after_bat3; /* no highbat, skip to end */ 585 break; 586 case 4: 587 DBAT_SET(4, batl, batu); 588 z = 5; 589 break; 590 case 5: 591 DBAT_SET(5, batl, batu); 592 z = 6; 593 break; 594 case 6: 595 DBAT_SET(6, batl, batu); 596 z = 7; 597 break; 598 case 7: 599 DBAT_SET(7, batl, batu); 600 z = 8; 601 break; 602 default: 603 break; 604 } 605 } 606 607 void 608 oea_iobat_remove(paddr_t pa) 609 { 610 const u_int i = BAT_VA2IDX(pa); 611 612 if (!BAT_VA_MATCH_P(battable[i].batu, pa) || 613 !BAT_VALID_P(battable[i].batu, PSL_PR)) 614 return; 615 const int n = 616 __SHIFTOUT(battable[i].batu, (BAT_XBL|BAT_BL) & ~BAT_BL_8M) + 1; 617 KASSERT((n & (n-1)) == 0); /* power of 2 */ 618 KASSERT((i & (n-1)) == 0); /* multiple of n */ 619 620 memset(&battable[i], 0, n*sizeof(battable[0])); 621 622 const int maxbat = oeacpufeat & OEACPU_HIGHBAT ? 8 : 4; 623 for (u_int k = 1 ; k < maxbat; k++) { 624 register_t batu; 625 switch (k) { 626 case 1: 627 batu = DBATU_GET(1); 628 if (BAT_VA_MATCH_P(batu, pa) && 629 BAT_VALID_P(batu, PSL_PR)) 630 DBAT_RESET(1); 631 break; 632 case 2: 633 batu = DBATU_GET(2); 634 if (BAT_VA_MATCH_P(batu, pa) && 635 BAT_VALID_P(batu, PSL_PR)) 636 DBAT_RESET(2); 637 break; 638 case 3: 639 batu = DBATU_GET(3); 640 if (BAT_VA_MATCH_P(batu, pa) && 641 BAT_VALID_P(batu, PSL_PR)) 642 DBAT_RESET(3); 643 break; 644 case 4: 645 batu = DBATU_GET(4); 646 if (BAT_VA_MATCH_P(batu, pa) && 647 BAT_VALID_P(batu, PSL_PR)) 648 DBAT_RESET(4); 649 break; 650 case 5: 651 batu = DBATU_GET(5); 652 if (BAT_VA_MATCH_P(batu, pa) && 653 BAT_VALID_P(batu, PSL_PR)) 654 DBAT_RESET(5); 655 break; 656 case 6: 657 batu = DBATU_GET(6); 658 if (BAT_VA_MATCH_P(batu, pa) && 659 BAT_VALID_P(batu, PSL_PR)) 660 DBAT_RESET(6); 661 break; 662 case 7: 663 batu = DBATU_GET(7); 664 if (BAT_VA_MATCH_P(batu, pa) && 665 BAT_VALID_P(batu, PSL_PR)) 666 DBAT_RESET(7); 667 break; 668 default: 669 break; 670 } 671 } 672 } 673 674 void 675 oea_batinit(paddr_t pa, ...) 676 { 677 struct mem_region *allmem, *availmem, *mp; 678 register_t msr = mfmsr(); 679 va_list ap; 680 #ifdef PPC_OEA601 681 unsigned int cpuvers; 682 683 cpuvers = mfpvr() >> 16; 684 #endif /* PPC_OEA601 */ 685 686 /* 687 * we need to call this before zapping BATs so OF calls work 688 */ 689 mem_regions(&allmem, &availmem); 690 691 /* 692 * Initialize BAT registers to unmapped to not generate 693 * overlapping mappings below. 694 * 695 * The 601's implementation differs in the Valid bit being situated 696 * in the lower BAT register, and in being a unified BAT only whose 697 * four entries are accessed through the IBAT[0-3] SPRs. 698 * 699 * Also, while the 601 does distinguish between supervisor/user 700 * protection keys, it does _not_ distinguish between validity in 701 * supervisor/user mode. 702 */ 703 if ((msr & (PSL_IR|PSL_DR)) == 0) { 704 #ifdef PPC_OEA601 705 if (cpuvers == MPC601) { 706 __asm volatile ("mtibatl 0,%0" :: "r"(0)); 707 __asm volatile ("mtibatl 1,%0" :: "r"(0)); 708 __asm volatile ("mtibatl 2,%0" :: "r"(0)); 709 __asm volatile ("mtibatl 3,%0" :: "r"(0)); 710 } else 711 #endif /* PPC_OEA601 */ 712 { 713 DBAT_RESET(0); IBAT_RESET(0); 714 DBAT_RESET(1); IBAT_RESET(1); 715 DBAT_RESET(2); IBAT_RESET(2); 716 DBAT_RESET(3); IBAT_RESET(3); 717 if (oeacpufeat & OEACPU_HIGHBAT) { 718 DBAT_RESET(4); IBAT_RESET(4); 719 DBAT_RESET(5); IBAT_RESET(5); 720 DBAT_RESET(6); IBAT_RESET(6); 721 DBAT_RESET(7); IBAT_RESET(7); 722 723 /* 724 * Change the first instruction to branch to 725 * dsitrap_fix_dbat6 726 */ 727 dsitrap_fix_dbat4[0] &= ~0xfffc; 728 dsitrap_fix_dbat4[0] 729 += (uintptr_t)dsitrap_fix_dbat6 730 - (uintptr_t)&dsitrap_fix_dbat4[0]; 731 732 /* 733 * Change the second instruction to branch to 734 * dsitrap_fix_dbat5 if bit 30 (aka bit 1) is 735 * true. 736 */ 737 dsitrap_fix_dbat4[1] = 0x419e0000 738 + (uintptr_t)dsitrap_fix_dbat5 739 - (uintptr_t)&dsitrap_fix_dbat4[1]; 740 741 /* 742 * Change it to load dbat4 instead of dbat2 743 */ 744 dsitrap_fix_dbat4[2] = 0x7fd88ba6; 745 dsitrap_fix_dbat4[3] = 0x7ff98ba6; 746 747 /* 748 * Change it to load dbat7 instead of dbat3 749 */ 750 dsitrap_fix_dbat7[0] = 0x7fde8ba6; 751 dsitrap_fix_dbat7[1] = 0x7fff8ba6; 752 } 753 } 754 } 755 756 /* 757 * Set up BAT to map physical memory 758 */ 759 #ifdef PPC_OEA601 760 if (cpuvers == MPC601) { 761 int i; 762 763 /* 764 * Set up battable to map the lowest 256 MB area. 765 * Map the lowest 32 MB area via BAT[0-3]; 766 * BAT[01] are fixed, BAT[23] are floating. 767 */ 768 for (i = 0; i < 32; i++) { 769 battable[i].batl = BATL601(i << 23, 770 BAT601_BSM_8M, BAT601_V); 771 battable[i].batu = BATU601(i << 23, 772 BAT601_M, BAT601_Ku, BAT601_PP_NONE); 773 } 774 __asm volatile ("mtibatu 0,%1; mtibatl 0,%0" 775 :: "r"(battable[0x00000000 >> 23].batl), 776 "r"(battable[0x00000000 >> 23].batu)); 777 __asm volatile ("mtibatu 1,%1; mtibatl 1,%0" 778 :: "r"(battable[0x00800000 >> 23].batl), 779 "r"(battable[0x00800000 >> 23].batu)); 780 __asm volatile ("mtibatu 2,%1; mtibatl 2,%0" 781 :: "r"(battable[0x01000000 >> 23].batl), 782 "r"(battable[0x01000000 >> 23].batu)); 783 __asm volatile ("mtibatu 3,%1; mtibatl 3,%0" 784 :: "r"(battable[0x01800000 >> 23].batl), 785 "r"(battable[0x01800000 >> 23].batu)); 786 } 787 #endif /* PPC_OEA601 */ 788 789 /* 790 * Now setup other fixed bat registers 791 * 792 * Note that we still run in real mode, and the BAT 793 * registers were cleared above. 794 */ 795 796 /* 797 * Add any I/O BATs specified; 798 */ 799 va_start(ap, pa); 800 while (pa != 0) { 801 register_t len = va_arg(ap, register_t); 802 oea_iobat_add(pa, len); 803 pa = va_arg(ap, paddr_t); 804 } 805 va_end(ap); 806 807 /* 808 * Set up battable to map all RAM regions. 809 */ 810 #ifdef PPC_OEA601 811 if (cpuvers == MPC601) { 812 for (mp = allmem; mp->size; mp++) { 813 paddr_t paddr = mp->start & 0xff800000; 814 paddr_t end = mp->start + mp->size; 815 816 do { 817 u_int ix = paddr >> 23; 818 819 battable[ix].batl = 820 BATL601(paddr, BAT601_BSM_8M, BAT601_V); 821 battable[ix].batu = 822 BATU601(paddr, BAT601_M, BAT601_Ku, BAT601_PP_NONE); 823 paddr += (1 << 23); 824 } while (paddr < end); 825 } 826 } else 827 #endif 828 { 829 const register_t bat_inc = BAT_IDX2VA(1); 830 for (mp = allmem; mp->size; mp++) { 831 paddr_t paddr = mp->start & -bat_inc; 832 paddr_t end = roundup2(mp->start + mp->size, bat_inc); 833 834 /* 835 * If the next entries are adjacent, merge them 836 * into this one 837 */ 838 while (mp[1].size && end == (mp[1].start & -bat_inc)) { 839 mp++; 840 end = roundup2(mp->start + mp->size, bat_inc); 841 } 842 843 while (paddr < end) { 844 register_t bl = (oeacpufeat & OEACPU_XBSEN 845 ? BAT_BL_2G 846 : BAT_BL_256M); 847 psize_t size = BAT_BL_TO_SIZE(bl); 848 u_int n = BAT_VA2IDX(size); 849 u_int i = BAT_VA2IDX(paddr); 850 851 while ((paddr & (size - 1)) 852 || paddr + size > end) { 853 size >>= 1; 854 bl = (bl >> 1) & (BAT_XBL|BAT_BL); 855 n >>= 1; 856 } 857 858 KASSERT(size >= bat_inc); 859 KASSERT(n >= 1); 860 KASSERT(bl >= BAT_BL_8M); 861 862 register_t batl = BATL(paddr, BAT_M, BAT_PP_RW); 863 register_t batu = BATU(paddr, bl, BAT_Vs); 864 865 for (; n-- > 0; i++) { 866 battable[i].batl = batl; 867 battable[i].batu = batu; 868 } 869 paddr += size; 870 } 871 } 872 /* 873 * Set up BAT0 to only map the lowest area. 874 */ 875 __asm volatile ("mtibatl 0,%0; mtibatu 0,%1;" 876 "mtdbatl 0,%0; mtdbatu 0,%1;" 877 :: "r"(battable[0].batl), "r"(battable[0].batu)); 878 } 879 } 880 #endif /* PPC_OEA || PPC_OEA64_BRIDGE */ 881 882 void 883 oea_install_extint_vec(void (*handler)(void), u_int vector) 884 { 885 extern int extint[], extsize[]; 886 extern int extint_call[]; 887 uintptr_t offset = (uintptr_t)handler - (uintptr_t)extint_call; 888 #ifdef PPC_HIGH_VEC 889 const uintptr_t exc_exi_base = EXC_HIGHVEC + vector; 890 #else 891 const uintptr_t exc_exi_base = vector; 892 #endif 893 int omsr, msr; 894 895 #ifdef DIAGNOSTIC 896 if (offset > 0x1ffffff) 897 panic("install_extint: %p too far away (%#lx)", handler, 898 (unsigned long) offset); 899 #endif 900 __asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1" 901 : "=r" (omsr), "=r" (msr) 902 : "K" ((u_short)~PSL_EE)); 903 extint_call[0] = (extint_call[0] & 0xfc000003) | offset; 904 __syncicache((void *)extint_call, sizeof extint_call[0]); 905 memcpy((void *)exc_exi_base, extint, (size_t)extsize); 906 #ifdef PPC_OEA64_BRIDGE 907 if ((oeacpufeat & OEACPU_64_BRIDGE) == 0) { 908 for (int *ip = (int *)exc_exi_base; 909 (uintptr_t)ip <= exc_exi_base + (size_t)extsize; 910 ip++) { 911 if ((ip[0] & MFMSR_MASK) == MFMSR 912 && (ip[1] & RLDICL_MASK) == RLDICL 913 && (ip[2] & MTMSRD_MASK) == MTMSRD) { 914 *ip++ = NOP; 915 *ip++ = NOP; 916 ip[0] = NOP; 917 } else if (*ip == RFID) { 918 *ip = RFI; 919 } 920 } 921 } 922 #endif 923 __syncicache((void *)exc_exi_base, (size_t)extsize); 924 925 __asm volatile ("mtmsr %0" :: "r"(omsr)); 926 } 927 928 void 929 oea_install_extint(void (*handler)(void)) 930 { 931 oea_install_extint_vec(handler, EXC_EXI); 932 } 933 934 /* 935 * Machine dependent startup code. 936 */ 937 void 938 oea_startup(const char *model) 939 { 940 uintptr_t sz; 941 void *v; 942 vaddr_t minaddr, maxaddr; 943 char pbuf[9], mstr[128]; 944 945 KASSERT(curcpu() != NULL); 946 KASSERT(lwp0.l_cpu != NULL); 947 KASSERT(curcpu()->ci_idepth == -1); 948 949 sz = round_page(MSGBUFSIZE); 950 #ifdef MSGBUFADDR 951 v = (void *) MSGBUFADDR; 952 #else 953 /* 954 * If the msgbuf is not in segment 0, allocate KVA for it and access 955 * it via mapped pages. [This prevents unneeded BAT switches.] 956 */ 957 v = (void *) msgbuf_paddr; 958 if (msgbuf_paddr + sz > SEGMENT_LENGTH) { 959 u_int i; 960 961 minaddr = 0; 962 if (uvm_map(kernel_map, &minaddr, sz, 963 NULL, UVM_UNKNOWN_OFFSET, 0, 964 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, 965 UVM_INH_NONE, UVM_ADV_NORMAL, 0)) != 0) 966 panic("startup: cannot allocate VM for msgbuf"); 967 v = (void *)minaddr; 968 for (i = 0; i < sz; i += PAGE_SIZE) { 969 pmap_kenter_pa(minaddr + i, msgbuf_paddr + i, 970 VM_PROT_READ|VM_PROT_WRITE, 0); 971 } 972 pmap_update(pmap_kernel()); 973 } 974 #endif 975 initmsgbuf(v, sz); 976 977 printf("%s%s", copyright, version); 978 if (model != NULL) 979 printf("Model: %s\n", model); 980 cpu_identify(mstr, sizeof(mstr)); 981 cpu_setmodel("%s", mstr); 982 983 format_bytes(pbuf, sizeof(pbuf), ctob((u_int)physmem)); 984 printf("total memory = %s\n", pbuf); 985 986 /* 987 * Allocate away the pages that map to 0xDEA[CDE]xxxx. Do this after 988 * the bufpages are allocated in case they overlap since it's not 989 * fatal if we can't allocate these. 990 */ 991 if (KERNEL_SR == 13 || KERNEL2_SR == 14) { 992 int error; 993 minaddr = 0xDEAC0000; 994 error = uvm_map(kernel_map, &minaddr, 0x30000, 995 NULL, UVM_UNKNOWN_OFFSET, 0, 996 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 997 UVM_ADV_NORMAL, UVM_FLAG_FIXED)); 998 if (error != 0 || minaddr != 0xDEAC0000) 999 printf("oea_startup: failed to allocate DEAD " 1000 "ZONE: error=%d\n", error); 1001 } 1002 1003 minaddr = 0; 1004 1005 /* 1006 * Allocate a submap for physio 1007 */ 1008 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 1009 VM_PHYS_SIZE, 0, false, NULL); 1010 1011 /* 1012 * Steal a page for crash dumps 1013 */ 1014 memhook = uvm_km_alloc(kernel_map, PAGE_SIZE, PAGE_SIZE, 1015 UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 1016 1017 format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 1018 printf("avail memory = %s\n", pbuf); 1019 1020 #ifdef MULTIPROCESSOR 1021 kcpuset_create(&cpuset_info.cpus_running, true); 1022 kcpuset_create(&cpuset_info.cpus_hatched, true); 1023 kcpuset_create(&cpuset_info.cpus_paused, true); 1024 kcpuset_create(&cpuset_info.cpus_resumed, true); 1025 kcpuset_create(&cpuset_info.cpus_halted, true); 1026 1027 kcpuset_set(cpuset_info.cpus_running, cpu_number()); 1028 #endif 1029 } 1030 1031 /* 1032 * Crash dump handling. 1033 */ 1034 1035 static int 1036 cpu_dump(void) 1037 { 1038 #if defined(PPC_OEA) && !defined(PPC_OEA64) && !defined(PPC_OEA64_BRIDGE) 1039 int (*dump)(dev_t, daddr_t, void *, size_t); 1040 char bf[dbtob(1)]; 1041 kcore_seg_t *segp; 1042 cpu_kcore_hdr_t *cpuhdrp; 1043 phys_ram_seg_t *memsegp; 1044 struct mem_region *mem, *avail; 1045 const struct bdevsw *bdev; 1046 vaddr_t addr; 1047 int i; 1048 1049 bdev = bdevsw_lookup(dumpdev); 1050 if (bdev == NULL) { 1051 return ENXIO; 1052 } 1053 dump = bdev->d_dump; 1054 1055 memset(bf, 0, sizeof(bf)); 1056 segp = (kcore_seg_t *)bf; 1057 cpuhdrp = (cpu_kcore_hdr_t *)&bf[ALIGN(sizeof(*segp))]; 1058 memsegp = (phys_ram_seg_t *)&bf[ALIGN(sizeof(*segp)) + 1059 ALIGN(sizeof(*cpuhdrp))]; 1060 1061 /* Generate a segment header. */ 1062 CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 1063 segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); 1064 1065 /* Add the machine-dependent header info. */ 1066 cpuhdrp->pad = 0; 1067 cpuhdrp->pvr = mfpvr(); 1068 asm volatile ("mfsdr1 %0" : "=r" (cpuhdrp->sdr1)); 1069 addr = 0; 1070 for (i = 0; i < 16; i++) { 1071 asm volatile ("mfsrin %0, %1" 1072 : "=r" (cpuhdrp->sr[i]) 1073 : "r" (addr)); 1074 addr += 1 << ADDR_SR_SHFT; 1075 } 1076 asm volatile ("mfibatu %0,0" : "=r"(cpuhdrp->ibatu[0])); 1077 asm volatile ("mfibatl %0,0" : "=r"(cpuhdrp->ibatl[0])); 1078 asm volatile ("mfibatu %0,1" : "=r"(cpuhdrp->ibatu[1])); 1079 asm volatile ("mfibatl %0,1" : "=r"(cpuhdrp->ibatl[1])); 1080 asm volatile ("mfibatu %0,2" : "=r"(cpuhdrp->ibatu[2])); 1081 asm volatile ("mfibatl %0,2" : "=r"(cpuhdrp->ibatl[2])); 1082 asm volatile ("mfibatu %0,3" : "=r"(cpuhdrp->ibatu[3])); 1083 asm volatile ("mfibatl %0,3" : "=r"(cpuhdrp->ibatl[3])); 1084 if ((cpuhdrp->pvr >> 16) != MPC601) { 1085 asm volatile ("mfdbatu %0,0" : "=r"(cpuhdrp->dbatu[0])); 1086 asm volatile ("mfdbatl %0,0" : "=r"(cpuhdrp->dbatl[0])); 1087 asm volatile ("mfdbatu %0,1" : "=r"(cpuhdrp->dbatu[1])); 1088 asm volatile ("mfdbatl %0,1" : "=r"(cpuhdrp->dbatl[1])); 1089 asm volatile ("mfdbatu %0,2" : "=r"(cpuhdrp->dbatu[2])); 1090 asm volatile ("mfdbatl %0,2" : "=r"(cpuhdrp->dbatl[2])); 1091 asm volatile ("mfdbatu %0,3" : "=r"(cpuhdrp->dbatu[3])); 1092 asm volatile ("mfdbatl %0,3" : "=r"(cpuhdrp->dbatl[3])); 1093 } else { 1094 memset(cpuhdrp->dbatl, 0, sizeof(cpuhdrp->dbatl)); 1095 memset(cpuhdrp->dbatu, 0, sizeof(cpuhdrp->dbatu)); 1096 memset(cpuhdrp->ibatl, 0, sizeof(cpuhdrp->ibatl)); 1097 memset(cpuhdrp->ibatu, 0, sizeof(cpuhdrp->ibatu)); 1098 } 1099 cpuhdrp->pad_reg = 0; 1100 1101 /* Fill in the memory segment descriptors. */ 1102 mem_regions(&mem, &avail); 1103 while (mem->size != 0) { 1104 memsegp->start = mem->start; 1105 memsegp->size = mem->size; 1106 memsegp++; 1107 mem++; 1108 } 1109 1110 return dump(dumpdev, dumplo, bf, dbtob(1)); 1111 #else 1112 return ENOSYS; 1113 #endif 1114 } 1115 1116 void 1117 oea_dumpsys(void) 1118 { 1119 const struct bdevsw *bdev; 1120 daddr_t blkno; 1121 unsigned long long len; 1122 int psize, error, addr; 1123 struct mem_region *mem, *avail; 1124 vaddr_t dumpspace; 1125 1126 if (dumpdev == NODEV) { 1127 return; 1128 } 1129 if (dumpsize == 0) { 1130 cpu_dumpconf(); 1131 } 1132 if (dumplo <= 0 || dumpsize == 0) { 1133 printf("\ndump to dev %u,%u not possible\n", 1134 major(dumpdev), minor(dumpdev)); 1135 delay(5000000); 1136 return; 1137 } 1138 printf("\ndumping to dev %u,%u offset %ld\n", 1139 major(dumpdev), minor(dumpdev), dumplo); 1140 1141 bdev = bdevsw_lookup(dumpdev); 1142 if (bdev == NULL || bdev->d_psize == NULL) { 1143 return; 1144 } 1145 psize = bdev_size(dumpdev); 1146 printf("dump "); 1147 if (psize == -1) { 1148 printf("area unavailable\n"); 1149 return; 1150 } 1151 1152 #ifdef MULTIPROCESSOR 1153 cpu_pause_others(); 1154 #endif 1155 1156 if ((error = cpu_dump()) != 0) { 1157 goto done; 1158 } 1159 1160 blkno = dumplo + cpu_dumpsize(); 1161 dumpspace = memhook; 1162 error = 0; 1163 len = 0; 1164 1165 mem_regions(&mem, &avail); 1166 while (mem->size != 0) { 1167 for (addr = mem->start; 1168 addr < mem->start + mem->size; 1169 addr += PAGE_SIZE) { 1170 if ((len % (1024 * 1024)) == 0) { 1171 printf("%lld ", len / (1024 * 1024)); 1172 } 1173 pmap_kenter_pa(dumpspace, addr, VM_PROT_READ, 0); 1174 pmap_update(pmap_kernel()); 1175 error = bdev->d_dump(dumpdev, blkno, 1176 (void *)dumpspace, PAGE_SIZE); 1177 if (error != 0) { 1178 goto done; 1179 } 1180 blkno += btodb(PAGE_SIZE); 1181 len += PAGE_SIZE; 1182 } 1183 mem++; 1184 } 1185 1186 done: 1187 switch (error) { 1188 case ENXIO: 1189 printf("device bad\n"); 1190 break; 1191 case EFAULT: 1192 printf("device not ready\n"); 1193 break; 1194 case EINVAL: 1195 printf("area improper\n"); 1196 break; 1197 case EIO: 1198 printf("i/o error\n"); 1199 break; 1200 case EINTR: 1201 printf("aborted from console\n"); 1202 break; 1203 case ENOSYS: 1204 printf("not implemented\n"); 1205 break; 1206 case 0: 1207 printf("succeeded\n"); 1208 break; 1209 default: 1210 printf("error %d\n", error); 1211 break; 1212 } 1213 printf("\n\n"); 1214 delay(5000000); 1215 1216 #ifdef MULTIPROCESSOR 1217 cpu_resume_others(); 1218 #endif 1219 } 1220 1221 /* 1222 * Convert kernel VA to physical address 1223 */ 1224 paddr_t 1225 kvtop(void *addr) 1226 { 1227 vaddr_t va; 1228 paddr_t pa; 1229 uintptr_t off; 1230 extern char end[]; 1231 1232 if (addr < (void *)end) 1233 return (paddr_t)addr; 1234 1235 va = trunc_page((vaddr_t)addr); 1236 off = (uintptr_t)addr - va; 1237 1238 if (pmap_extract(pmap_kernel(), va, &pa) == false) { 1239 /*printf("kvtop: zero page frame (va=0x%x)\n", addr);*/ 1240 return (paddr_t)addr; 1241 } 1242 1243 return(pa + off); 1244 } 1245 1246 /* 1247 * Allocate vm space and mapin the I/O address 1248 */ 1249 void * 1250 mapiodev(paddr_t pa, psize_t len, bool prefetchable) 1251 { 1252 paddr_t faddr; 1253 vaddr_t taddr, va; 1254 int off; 1255 1256 faddr = trunc_page(pa); 1257 off = pa - faddr; 1258 len = round_page(off + len); 1259 va = taddr = uvm_km_alloc(kernel_map, len, 0, UVM_KMF_VAONLY); 1260 1261 if (va == 0) 1262 return NULL; 1263 1264 for (; len > 0; len -= PAGE_SIZE) { 1265 pmap_kenter_pa(taddr, faddr, VM_PROT_READ | VM_PROT_WRITE, 1266 PMAP_NOCACHE | (prefetchable ? PMAP_MD_PREFETCHABLE : 0)); 1267 faddr += PAGE_SIZE; 1268 taddr += PAGE_SIZE; 1269 } 1270 pmap_update(pmap_kernel()); 1271 return (void *)(va + off); 1272 } 1273 1274 void 1275 unmapiodev(vaddr_t va, vsize_t len) 1276 { 1277 paddr_t faddr; 1278 1279 if (! va) 1280 return; 1281 1282 faddr = trunc_page(va); 1283 len = round_page(va - faddr + len); 1284 1285 pmap_kremove(faddr, len); 1286 pmap_update(pmap_kernel()); 1287 uvm_km_free(kernel_map, faddr, len, UVM_KMF_VAONLY); 1288 } 1289 1290 void 1291 trap0(void *lr) 1292 { 1293 panic("call to null-ptr from %p", lr); 1294 } 1295