1 /* SPDX-License-Identifier: GPL-2.0-or-later * 2 /* 3 * PowerPC version 4 * Copyright (C) 1995-1996 Gary Thomas (gdt 5 * 6 * Rewritten by Cort Dougan (cort@cs.nmt.edu) 7 * Copyright (C) 1996 Cort Dougan <cort@cs.n 8 * Adapted for Power Macintosh by Paul Macker 9 * Low-level exception handlers and MMU suppo 10 * rewritten by Paul Mackerras. 11 * Copyright (C) 1996 Paul Mackerras. 12 * MPC8xx modifications Copyright (C) 1997 Da 13 * 14 * This file contains the low-level support a 15 * PowerPC platform, including trap and inter 16 * (The PPC 8xx embedded CPUs use head_8xx.S 17 */ 18 19 #include <linux/init.h> 20 #include <linux/pgtable.h> 21 #include <linux/linkage.h> 22 23 #include <asm/reg.h> 24 #include <asm/page.h> 25 #include <asm/mmu.h> 26 #include <asm/cputable.h> 27 #include <asm/cache.h> 28 #include <asm/thread_info.h> 29 #include <asm/ppc_asm.h> 30 #include <asm/asm-offsets.h> 31 #include <asm/ptrace.h> 32 #include <asm/bug.h> 33 #include <asm/kvm_book3s_asm.h> 34 #include <asm/feature-fixups.h> 35 #include <asm/interrupt.h> 36 37 #include "head_32.h" 38 39 #define LOAD_BAT(n, reg, RA, RB) \ 40 /* see the comment for clear_bats() -- 41 li RA,0; \ 42 mtspr SPRN_IBAT##n##U,RA; \ 43 mtspr SPRN_DBAT##n##U,RA; \ 44 lwz RA,(n*16)+0(reg); \ 45 lwz RB,(n*16)+4(reg); \ 46 mtspr SPRN_IBAT##n##U,RA; \ 47 mtspr SPRN_IBAT##n##L,RB; \ 48 lwz RA,(n*16)+8(reg); \ 49 lwz RB,(n*16)+12(reg); \ 50 mtspr SPRN_DBAT##n##U,RA; \ 51 mtspr SPRN_DBAT##n##L,RB 52 53 __HEAD 54 _GLOBAL(_stext); 55 56 /* 57 * _start is defined this way because the XCOF 58 * on the powermac expects the entry point to 59 */ 60 _GLOBAL(_start); 61 /* 62 * These are here for legacy reasons, 63 * need to look like a coff function e 64 * but we're always started by some ki 65 * -- Cort 66 */ 67 nop /* used by __secondary_hold on 68 nop /* used by __secondary_hold on 69 nop 70 71 /* PMAC 72 * Enter here with the kernel text, data and b 73 * 0, running with virtual == physical mapping 74 * r5 points to the prom entry point (the clie 75 * address). Address translation is turned on 76 * managing the hash table. Interrupts are di 77 * pointer (r1) points to just below the end o 78 * from 0x380000 - 0x400000, which is mapped i 79 * 80 * If we are booted from MacOS via BootX, we e 81 * image loaded somewhere, and the following v 82 * r3: 'BooX' (0x426f6f58) 83 * r4: virtual address of boot_infos_t 84 * r5: 0 85 * 86 * PREP 87 * This is jumped to on prep systems right aft 88 * to its proper place in memory by the boot l 89 * of the regs is: 90 * r3: ptr to residual data 91 * r4: initrd_start or if no initrd then 0 92 * r5: initrd_end - unused if r4 is 0 93 * r6: Start of command line string 94 * r7: End of command line string 95 * 96 * This just gets a minimal mmu environment se 97 * start_here() to do the real work. 98 * -- Cort 99 */ 100 101 .globl __start 102 __start: 103 /* 104 * We have to do any OF calls before we map ou 105 * because OF may have I/O devices mapped into 106 * (particularly on CHRP). 107 */ 108 cmpwi 0,r5,0 109 beq 1f 110 111 #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE 112 /* find out where we are now */ 113 bcl 20,31,$+4 114 0: mflr r8 /* r8 115 addis r8,r8,(_stext - 0b)@ha 116 addi r8,r8,(_stext - 0b)@l /* cur 117 bl prom_init 118 #endif /* CONFIG_PPC_OF_BOOT_TRAMPOLINE */ 119 120 /* We never return. We also hit that t 121 * from OF while CONFIG_PPC_OF_BOOT_TR 122 trap 123 124 /* 125 * Check for BootX signature when supporting P 126 * appropriate trampoline if it's present 127 */ 128 #ifdef CONFIG_PPC_PMAC 129 1: lis r31,0x426f 130 ori r31,r31,0x6f58 131 cmpw 0,r3,r31 132 bne 1f 133 bl bootx_init 134 trap 135 #endif /* CONFIG_PPC_PMAC */ 136 137 1: mr r31,r3 /* sav 138 li r24,0 /* cpu 139 140 /* 141 * early_init() does the early machine identif 142 * the necessary low-level setup and clears th 143 * -- Cort <cort@fsmlabs.com> 144 */ 145 bl early_init 146 147 /* Switch MMU off, clear BATs and flush TLB. A 148 * the physical address we are running at, ret 149 */ 150 bl mmu_off 151 __after_mmu_off: 152 bl clear_bats 153 bl flush_tlbs 154 155 bl initial_bats 156 bl load_segment_registers 157 bl reloc_offset 158 bl early_hash_table 159 #if defined(CONFIG_BOOTX_TEXT) 160 bl setup_disp_bat 161 #endif 162 #ifdef CONFIG_PPC_EARLY_DEBUG_CPM 163 bl setup_cpm_bat 164 #endif 165 #ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO 166 bl setup_usbgecko_bat 167 #endif 168 169 /* 170 * Call setup_cpu for CPU 0 and initialize 6xx 171 */ 172 bl reloc_offset 173 li r24,0 /* cpu 174 bl call_setup_cpu /* Cal 175 bl reloc_offset 176 bl init_idle_6xx 177 178 179 /* 180 * We need to run with _start at physical addr 181 * On CHRP, we are loaded at 0x10000 since OF 182 * the exception vectors at 0 (and therefore t 183 * overwrites OF's exception vectors with our 184 * The MMU is off at this point. 185 */ 186 bl reloc_offset 187 mr r26,r3 188 addis r4,r3,KERNELBASE@h /* cur 189 lis r5,PHYSICAL_START@h 190 cmplw 0,r4,r5 /* alr 191 bne relocate_kernel 192 /* 193 * we now have the 1st 16M of ram mapped with 194 * prep needs the mmu to be turned on here, bu 195 * this shouldn't bother the pmac since it jus 196 * as we jump to our code at KERNELBASE. -- Co 197 * Actually no, pmac doesn't have it on any mo 198 * off, and in other cases, we now turn it off 199 */ 200 turn_on_mmu: 201 mfmsr r0 202 ori r0,r0,MSR_DR|MSR_IR|MSR_RI 203 mtspr SPRN_SRR1,r0 204 lis r0,start_here@h 205 ori r0,r0,start_here@l 206 mtspr SPRN_SRR0,r0 207 rfi /* ena 208 209 /* 210 * We need __secondary_hold as a place to hold 211 * an SMP machine, even when we are running a 212 */ 213 . = 0xc0 /* for 214 li r3,1 /* MTX 215 .globl __secondary_hold 216 __secondary_hold: 217 /* tell the master we're here */ 218 stw r3,__secondary_hold_acknowledg 219 #ifdef CONFIG_SMP 220 100: lwz r4,0(0) 221 /* wait until we're told to start */ 222 cmpw 0,r4,r3 223 bne 100b 224 /* our cpu # was at addr 0 - go */ 225 mr r24,r3 /* cpu 226 b __secondary_start 227 #else 228 b . 229 #endif /* CONFIG_SMP */ 230 231 .globl __secondary_hold_spinloop 232 __secondary_hold_spinloop: 233 .long 0 234 .globl __secondary_hold_acknowledge 235 __secondary_hold_acknowledge: 236 .long -1 237 238 /* System reset */ 239 /* core99 pmac starts the seconary here by cha 240 putting it back to what it was (unknown_asy 241 EXCEPTION(INTERRUPT_SYSTEM_RESET, Rese 242 243 /* Machine check */ 244 /* 245 * On CHRP, this is complicated by the fact th 246 * machine check inside RTAS, and we have no g 247 * critical registers will have the values we 248 * registers that might have bad values includ 249 * and all the BATs. We indicate that we are 250 * a non-zero value, the address of the except 251 * in thread.rtas_sp. The machine check handl 252 * and uses its value if it is non-zero. 253 * (Other exception handlers assume that r1 is 254 * pointer when we take an exception from supe 255 * -- paulus. 256 */ 257 START_EXCEPTION(INTERRUPT_MACHINE_CHEC 258 EXCEPTION_PROLOG_0 259 #ifdef CONFIG_PPC_CHRP 260 mtspr SPRN_SPRG_SCRATCH2,r1 261 mfspr r1, SPRN_SPRG_THREAD 262 lwz r1, RTAS_SP(r1) 263 cmpwi cr1, r1, 0 264 bne cr1, 7f 265 mfspr r1, SPRN_SPRG_SCRATCH2 266 #endif /* CONFIG_PPC_CHRP */ 267 EXCEPTION_PROLOG_1 268 7: EXCEPTION_PROLOG_2 0x200 MachineCheck 269 #ifdef CONFIG_PPC_CHRP 270 beq cr1, 1f 271 twi 31, 0, 0 272 #endif 273 1: prepare_transfer_to_handler 274 bl machine_check_exception 275 b interrupt_return 276 277 /* Data access exception. */ 278 START_EXCEPTION(INTERRUPT_DATA_STORAGE 279 #ifdef CONFIG_PPC_BOOK3S_604 280 BEGIN_MMU_FTR_SECTION 281 mtspr SPRN_SPRG_SCRATCH2,r10 282 mfspr r10, SPRN_SPRG_THREAD 283 stw r11, THR11(r10) 284 mfspr r10, SPRN_DSISR 285 mfcr r11 286 andis. r10, r10, (DSISR_BAD_FAULT_32S 287 mfspr r10, SPRN_SPRG_THREAD 288 beq hash_page_dsi 289 .Lhash_page_dsi_cont: 290 mtcr r11 291 lwz r11, THR11(r10) 292 mfspr r10, SPRN_SPRG_SCRATCH2 293 MMU_FTR_SECTION_ELSE 294 b 1f 295 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TAB 296 #endif 297 1: EXCEPTION_PROLOG_0 handle_dar_dsisr=1 298 EXCEPTION_PROLOG_1 299 EXCEPTION_PROLOG_2 INTERRUPT_DATA_STOR 300 prepare_transfer_to_handler 301 lwz r5, _DSISR(r1) 302 andis. r0, r5, DSISR_DABRMATCH@h 303 bne- 1f 304 bl do_page_fault 305 b interrupt_return 306 1: bl do_break 307 REST_NVGPRS(r1) 308 b interrupt_return 309 310 311 /* Instruction access exception. */ 312 START_EXCEPTION(INTERRUPT_INST_STORAGE 313 mtspr SPRN_SPRG_SCRATCH0,r10 314 mtspr SPRN_SPRG_SCRATCH1,r11 315 mfspr r10, SPRN_SPRG_THREAD 316 mfspr r11, SPRN_SRR0 317 stw r11, SRR0(r10) 318 mfspr r11, SPRN_SRR1 /* che 319 stw r11, SRR1(r10) 320 mfcr r10 321 #ifdef CONFIG_PPC_BOOK3S_604 322 BEGIN_MMU_FTR_SECTION 323 andis. r11, r11, SRR1_ISI_NOPT@h 324 bne hash_page_isi 325 .Lhash_page_isi_cont: 326 mfspr r11, SPRN_SRR1 /* che 327 END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE) 328 #endif 329 andi. r11, r11, MSR_PR 330 331 EXCEPTION_PROLOG_1 332 EXCEPTION_PROLOG_2 INTERRUPT_INST_STOR 333 andis. r5,r9,DSISR_SRR1_MATCH_32S@h / 334 stw r5, _DSISR(r11) 335 stw r12, _DAR(r11) 336 prepare_transfer_to_handler 337 bl do_page_fault 338 b interrupt_return 339 340 /* External interrupt */ 341 EXCEPTION(INTERRUPT_EXTERNAL, Hardware 342 343 /* Alignment exception */ 344 START_EXCEPTION(INTERRUPT_ALIGNMENT, A 345 EXCEPTION_PROLOG INTERRUPT_ALIGNMENT A 346 prepare_transfer_to_handler 347 bl alignment_exception 348 REST_NVGPRS(r1) 349 b interrupt_return 350 351 /* Program check exception */ 352 START_EXCEPTION(INTERRUPT_PROGRAM, Pro 353 EXCEPTION_PROLOG INTERRUPT_PROGRAM Pro 354 prepare_transfer_to_handler 355 bl program_check_exception 356 REST_NVGPRS(r1) 357 b interrupt_return 358 359 /* Floating-point unavailable */ 360 START_EXCEPTION(0x800, FPUnavailable) 361 #ifdef CONFIG_PPC_FPU 362 BEGIN_FTR_SECTION 363 /* 364 * Certain Freescale cores don't have a FPU an 365 * as a FP Unavailable exception. Redirect to 366 */ 367 b ProgramCheck 368 END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE) 369 EXCEPTION_PROLOG INTERRUPT_FP_UNAVAIL 370 beq 1f 371 bl load_up_fpu /* if 372 b fast_exception_return 373 1: prepare_transfer_to_handler 374 bl kernel_fp_unavailable_exceptio 375 b interrupt_return 376 #else 377 b ProgramCheck 378 #endif 379 380 /* Decrementer */ 381 EXCEPTION(INTERRUPT_DECREMENTER, Decre 382 383 EXCEPTION(0xa00, Trap_0a, unknown_exce 384 EXCEPTION(0xb00, Trap_0b, unknown_exce 385 386 /* System call */ 387 START_EXCEPTION(INTERRUPT_SYSCALL, Sys 388 SYSCALL_ENTRY INTERRUPT_SYSCALL 389 390 EXCEPTION(INTERRUPT_TRACE, SingleStep, 391 EXCEPTION(0xe00, Trap_0e, unknown_exce 392 393 /* 394 * The Altivec unavailable trap is at 0x0f20. 395 * We effectively remap it to 0x3000. 396 * We include an altivec unavailable exception 397 * not configured for Altivec, so that you can 398 * non-altivec kernel running on a machine wit 399 * by executing an altivec instruction. 400 */ 401 START_EXCEPTION(INTERRUPT_PERFMON, Per 402 b PerformanceMonitor 403 404 START_EXCEPTION(INTERRUPT_ALTIVEC_UNAV 405 b AltiVecUnavailable 406 407 __HEAD 408 /* 409 * Handle TLB miss for instruction on 603/603e 410 * Note: we get an alternate set of r0 - r3 to 411 */ 412 . = INTERRUPT_INST_TLB_MISS_603 413 InstructionTLBMiss: 414 /* Get PTE (linux-style) and check acc 415 mfspr r0,SPRN_IMISS 416 mfspr r2, SPRN_SDR1 417 li r1,_PAGE_PRESENT | _PAGE_ACCES 418 rlwinm r2, r2, 28, 0xfffff000 419 rlwimi r2,r0,12,20,29 /* ins 420 lwz r2,0(r2) /* get 421 #ifdef CONFIG_EXECMEM 422 rlwinm r3, r0, 4, 0xf 423 subi r3, r3, (TASK_SIZE >> 28) & 0x 424 #endif 425 rlwinm. r2,r2,0,0,19 /* ext 426 beq- InstructionAddressInvalid 427 rlwimi r2,r0,22,20,29 /* ins 428 lwz r2,0(r2) /* get 429 andc. r1,r1,r2 /* che 430 bne- InstructionAddressInvalid /* r 431 /* Convert linux-style PTE to low word 432 #ifdef CONFIG_EXECMEM 433 rlwimi r2, r3, 1, 31, 31 /* use 434 #endif 435 ori r1, r1, 0xe06 /* cle 436 andc r1, r2, r1 /* PP 437 BEGIN_FTR_SECTION 438 rlwinm r1,r1,0,~_PAGE_COHERENT /* cle 439 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) 440 mtspr SPRN_RPA,r1 441 tlbli r0 442 mfspr r3,SPRN_SRR1 /* Nee 443 mtcrf 0x80,r3 444 rfi 445 InstructionAddressInvalid: 446 mfspr r3,SPRN_SRR1 447 rlwinm r1,r3,9,6,6 /* Get load/st 448 449 addis r1,r1,0x2000 450 mtspr SPRN_DSISR,r1 /* (shouldn't 451 andi. r2,r3,0xFFFF /* Clear upper 452 or r2,r2,r1 453 mtspr SPRN_SRR1,r2 454 mfspr r1,SPRN_IMISS /* Get failing 455 rlwinm. r2,r2,0,31,31 /* Check for l 456 rlwimi r2,r2,1,30,30 /* change 1 -> 457 xor r1,r1,r2 458 mtspr SPRN_DAR,r1 /* Set fault a 459 mfmsr r0 /* Restore "no 460 xoris r0,r0,MSR_TGPR>>16 461 mtcrf 0x80,r3 /* Restore CR0 462 mtmsr r0 463 b InstructionAccess 464 465 /* 466 * Handle TLB miss for DATA Load operation on 467 */ 468 . = INTERRUPT_DATA_LOAD_TLB_MISS_603 469 DataLoadTLBMiss: 470 /* Get PTE (linux-style) and check acc 471 mfspr r0,SPRN_DMISS 472 mfspr r2, SPRN_SDR1 473 rlwinm r1, r2, 28, 0xfffff000 474 rlwimi r1,r0,12,20,29 /* ins 475 lwz r2,0(r1) /* get 476 rlwinm r3, r0, 4, 0xf 477 rlwinm. r2,r2,0,0,19 /* ext 478 subi r3, r3, (TASK_SIZE >> 28) & 0x 479 beq- 2f /* bai 480 1: rlwimi r2,r0,22,20,29 /* ins 481 lwz r2,0(r2) /* get 482 li r1, _PAGE_PRESENT | _PAGE_ACCE 483 andc. r1,r1,r2 /* che 484 bne- DataAddressInvalid /* ret 485 /* Convert linux-style PTE to low word 486 rlwinm r1,r2,32-9,30,30 /* _PA 487 rlwimi r2,r3,2,30,31 /* use 488 rlwimi r1,r2,32-3,24,24 /* _PA 489 xori r1,r1,_PAGE_DIRTY /* cle 490 ori r1,r1,0xe04 /* cle 491 andc r1,r2,r1 /* PP 492 BEGIN_FTR_SECTION 493 rlwinm r1,r1,0,~_PAGE_COHERENT /* cle 494 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) 495 mtspr SPRN_RPA,r1 496 BEGIN_MMU_FTR_SECTION 497 li r3,1 498 mfspr r1,SPRN_SPRG_603_LRU 499 rlwinm r2,r0,20,27,31 /* Get 500 slw r3,r3,r2 501 xor r1,r3,r1 502 srw r3,r1,r2 503 mtspr SPRN_SPRG_603_LRU,r1 504 mfspr r2,SPRN_SRR1 505 rlwimi r2,r3,31-14,14,14 506 mtspr SPRN_SRR1,r2 507 mtcrf 0x80,r2 508 tlbld r0 509 rfi 510 MMU_FTR_SECTION_ELSE 511 mfspr r2,SPRN_SRR1 /* Nee 512 mtcrf 0x80,r2 513 tlbld r0 514 rfi 515 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTL 516 517 2: lis r2, (swapper_pg_dir - PAGE_OFF 518 addi r2, r2, (swapper_pg_dir - PAGE 519 rlwimi r2,r0,12,20,29 /* ins 520 lwz r2,0(r2) /* get 521 cmpwi cr0,r2,0 522 beq- DataAddressInvalid /* ret 523 stw r2,0(r1) 524 rlwinm. r2,r2,0,0,19 /* ext 525 b 1b 526 DataAddressInvalid: 527 mfspr r3,SPRN_SRR1 528 rlwinm r1,r3,9,6,6 /* Get load/st 529 addis r1,r1,0x2000 530 mtspr SPRN_DSISR,r1 531 andi. r2,r3,0xFFFF /* Clear upper 532 mtspr SPRN_SRR1,r2 533 mfspr r1,SPRN_DMISS /* Get failing 534 rlwinm. r2,r2,0,31,31 /* Check for l 535 beq 20f /* Jump if big 536 xori r1,r1,3 537 20: mtspr SPRN_DAR,r1 /* Set fault a 538 mfmsr r0 /* Restore "no 539 xoris r0,r0,MSR_TGPR>>16 540 mtcrf 0x80,r3 /* Restore CR0 541 mtmsr r0 542 b DataAccess 543 544 /* 545 * Handle TLB miss for DATA Store on 603/603e 546 */ 547 . = INTERRUPT_DATA_STORE_TLB_MISS_603 548 DataStoreTLBMiss: 549 /* Get PTE (linux-style) and check acc 550 mfspr r0,SPRN_DMISS 551 mfspr r2, SPRN_SDR1 552 rlwinm r1, r2, 28, 0xfffff000 553 rlwimi r1,r0,12,20,29 /* ins 554 lwz r2,0(r1) /* get 555 rlwinm r3, r0, 4, 0xf 556 rlwinm. r2,r2,0,0,19 /* ext 557 subi r3, r3, (TASK_SIZE >> 28) & 0x 558 beq- 2f /* bai 559 1: 560 rlwimi r2,r0,22,20,29 /* ins 561 lwz r2,0(r2) /* get 562 li r1, _PAGE_RW | _PAGE_DIRTY | _ 563 andc. r1,r1,r2 /* che 564 bne- DataAddressInvalid /* ret 565 /* Convert linux-style PTE to low word 566 rlwimi r2,r3,1,31,31 /* use 567 li r1,0xe06 /* cle 568 andc r1,r2,r1 /* PP 569 BEGIN_FTR_SECTION 570 rlwinm r1,r1,0,~_PAGE_COHERENT /* cle 571 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) 572 mtspr SPRN_RPA,r1 573 mfspr r2,SPRN_SRR1 /* Nee 574 mtcrf 0x80,r2 575 BEGIN_MMU_FTR_SECTION 576 li r3,1 577 mfspr r1,SPRN_SPRG_603_LRU 578 rlwinm r2,r0,20,27,31 /* Get 579 slw r3,r3,r2 580 xor r1,r3,r1 581 srw r3,r1,r2 582 mtspr SPRN_SPRG_603_LRU,r1 583 mfspr r2,SPRN_SRR1 584 rlwimi r2,r3,31-14,14,14 585 mtspr SPRN_SRR1,r2 586 mtcrf 0x80,r2 587 tlbld r0 588 rfi 589 MMU_FTR_SECTION_ELSE 590 mfspr r2,SPRN_SRR1 /* Nee 591 mtcrf 0x80,r2 592 tlbld r0 593 rfi 594 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTL 595 596 2: lis r2, (swapper_pg_dir - PAGE_OFF 597 addi r2, r2, (swapper_pg_dir - PAGE 598 rlwimi r2,r0,12,20,29 /* ins 599 lwz r2,0(r2) /* get 600 cmpwi cr0,r2,0 601 beq- DataAddressInvalid /* ret 602 stw r2,0(r1) 603 rlwinm r2,r2,0,0,19 /* ext 604 b 1b 605 606 #ifndef CONFIG_ALTIVEC 607 #define altivec_assist_exception unknow 608 #endif 609 610 #ifndef CONFIG_TAU_INT 611 #define TAUException unknown_async_exceptio 612 #endif 613 614 EXCEPTION(0x1300, Trap_13, instruction 615 EXCEPTION(0x1400, SMI, SMIException) 616 EXCEPTION(0x1500, Trap_15, unknown_exc 617 EXCEPTION(0x1600, Trap_16, altivec_ass 618 EXCEPTION(0x1700, Trap_17, TAUExceptio 619 EXCEPTION(0x1800, Trap_18, unknown_exc 620 EXCEPTION(0x1900, Trap_19, unknown_exc 621 EXCEPTION(0x1a00, Trap_1a, unknown_exc 622 EXCEPTION(0x1b00, Trap_1b, unknown_exc 623 EXCEPTION(0x1c00, Trap_1c, unknown_exc 624 EXCEPTION(0x1d00, Trap_1d, unknown_exc 625 EXCEPTION(0x1e00, Trap_1e, unknown_exc 626 EXCEPTION(0x1f00, Trap_1f, unknown_exc 627 EXCEPTION(0x2000, RunMode, RunModeExce 628 EXCEPTION(0x2100, Trap_21, unknown_exc 629 EXCEPTION(0x2200, Trap_22, unknown_exc 630 EXCEPTION(0x2300, Trap_23, unknown_exc 631 EXCEPTION(0x2400, Trap_24, unknown_exc 632 EXCEPTION(0x2500, Trap_25, unknown_exc 633 EXCEPTION(0x2600, Trap_26, unknown_exc 634 EXCEPTION(0x2700, Trap_27, unknown_exc 635 EXCEPTION(0x2800, Trap_28, unknown_exc 636 EXCEPTION(0x2900, Trap_29, unknown_exc 637 EXCEPTION(0x2a00, Trap_2a, unknown_exc 638 EXCEPTION(0x2b00, Trap_2b, unknown_exc 639 EXCEPTION(0x2c00, Trap_2c, unknown_exc 640 EXCEPTION(0x2d00, Trap_2d, unknown_exc 641 EXCEPTION(0x2e00, Trap_2e, unknown_exc 642 EXCEPTION(0x2f00, Trap_2f, unknown_exc 643 644 __HEAD 645 . = 0x3000 646 647 #ifdef CONFIG_PPC_BOOK3S_604 648 .macro save_regs_thread thread 649 stw r0, THR0(\thread) 650 stw r3, THR3(\thread) 651 stw r4, THR4(\thread) 652 stw r5, THR5(\thread) 653 stw r6, THR6(\thread) 654 stw r8, THR8(\thread) 655 stw r9, THR9(\thread) 656 mflr r0 657 stw r0, THLR(\thread) 658 mfctr r0 659 stw r0, THCTR(\thread) 660 .endm 661 662 .macro restore_regs_thread thread 663 lwz r0, THLR(\thread) 664 mtlr r0 665 lwz r0, THCTR(\thread) 666 mtctr r0 667 lwz r0, THR0(\thread) 668 lwz r3, THR3(\thread) 669 lwz r4, THR4(\thread) 670 lwz r5, THR5(\thread) 671 lwz r6, THR6(\thread) 672 lwz r8, THR8(\thread) 673 lwz r9, THR9(\thread) 674 .endm 675 676 hash_page_dsi: 677 save_regs_thread r10 678 mfdsisr r3 679 mfdar r4 680 mfsrr0 r5 681 mfsrr1 r9 682 rlwinm r3, r3, 32 - 15, _PAGE_WRITE 683 ori r3, r3, _PAGE_PRESENT | _PAGE_ 684 bl hash_page 685 mfspr r10, SPRN_SPRG_THREAD 686 restore_regs_thread r10 687 b .Lhash_page_dsi_cont 688 689 hash_page_isi: 690 mr r11, r10 691 mfspr r10, SPRN_SPRG_THREAD 692 save_regs_thread r10 693 li r3, _PAGE_PRESENT | _PAGE_EXEC 694 lwz r4, SRR0(r10) 695 lwz r9, SRR1(r10) 696 bl hash_page 697 mfspr r10, SPRN_SPRG_THREAD 698 restore_regs_thread r10 699 mr r10, r11 700 b .Lhash_page_isi_cont 701 702 .globl fast_hash_page_return 703 fast_hash_page_return: 704 andis. r10, r9, SRR1_ISI_NOPT@h 705 mfspr r10, SPRN_SPRG_THREAD 706 restore_regs_thread r10 707 bne 1f 708 709 /* DSI */ 710 mtcr r11 711 lwz r11, THR11(r10) 712 mfspr r10, SPRN_SPRG_SCRATCH2 713 rfi 714 715 1: /* ISI */ 716 mtcr r11 717 mfspr r11, SPRN_SPRG_SCRATCH1 718 mfspr r10, SPRN_SPRG_SCRATCH0 719 rfi 720 #endif /* CONFIG_PPC_BOOK3S_604 */ 721 722 #ifdef CONFIG_VMAP_STACK 723 vmap_stack_overflow_exception 724 #endif 725 726 __HEAD 727 AltiVecUnavailable: 728 EXCEPTION_PROLOG 0xf20 AltiVecUnavaila 729 #ifdef CONFIG_ALTIVEC 730 beq 1f 731 bl load_up_altivec /* if 732 b fast_exception_return 733 #endif /* CONFIG_ALTIVEC */ 734 1: prepare_transfer_to_handler 735 bl altivec_unavailable_exception 736 b interrupt_return 737 738 __HEAD 739 PerformanceMonitor: 740 EXCEPTION_PROLOG 0xf00 PerformanceMoni 741 prepare_transfer_to_handler 742 bl performance_monitor_exception 743 b interrupt_return 744 745 746 __HEAD 747 /* 748 * This code is jumped to from the startup cod 749 * the kernel image to physical address PHYSIC 750 */ 751 relocate_kernel: 752 lis r3,PHYSICAL_START@h /* Des 753 li r6,0 /* Des 754 li r5,0x4000 /* # b 755 bl copy_and_flush /* cop 756 addi r0,r3,4f@l /* jum 757 mtctr r0 /* in 758 bctr /* jum 759 4: lis r5,_end-KERNELBASE@h 760 ori r5,r5,_end-KERNELBASE@l 761 bl copy_and_flush /* cop 762 b turn_on_mmu 763 764 /* 765 * Copy routine used to copy the kernel to sta 766 * and flush and invalidate the caches as need 767 * r3 = dest addr, r4 = source addr, r5 = copy 768 * on exit, r3, r4, r5 are unchanged, r6 is up 769 */ 770 _GLOBAL(copy_and_flush) 771 addi r5,r5,-4 772 addi r6,r6,-4 773 4: li r0,L1_CACHE_BYTES/4 774 mtctr r0 775 3: addi r6,r6,4 /* cop 776 lwzx r0,r6,r4 777 stwx r0,r6,r3 778 bdnz 3b 779 dcbst r6,r3 /* wri 780 sync 781 icbi r6,r3 /* flu 782 cmplw 0,r6,r5 783 blt 4b 784 sync /* add 785 isync 786 addi r5,r5,4 787 addi r6,r6,4 788 blr 789 790 #ifdef CONFIG_SMP 791 .globl __secondary_start_mpc86xx 792 __secondary_start_mpc86xx: 793 mfspr r3, SPRN_PIR 794 stw r3, __secondary_hold_acknowled 795 mr r24, r3 /* cpu 796 b __secondary_start 797 798 .globl __secondary_start_pmac_0 799 __secondary_start_pmac_0: 800 /* NB the entries for cpus 0, 1, 2 mus 801 li r24,0 802 b 1f 803 li r24,1 804 b 1f 805 li r24,2 806 b 1f 807 li r24,3 808 1: 809 /* on powersurge, we come in here with 810 set to map the 0xf0000000 - 0xfffff 811 mfmsr r0 812 rlwinm r0,r0,0,28,26 /* cle 813 mtmsr r0 814 isync 815 816 .globl __secondary_start 817 __secondary_start: 818 /* Copy some CPU settings from CPU 0 * 819 bl __restore_cpu_setup 820 821 lis r3,-KERNELBASE@h 822 mr r4,r24 823 bl call_setup_cpu /* Cal 824 lis r3,-KERNELBASE@h 825 bl init_idle_6xx 826 827 /* get current's stack and current */ 828 lis r2,secondary_current@ha 829 tophys(r2,r2) 830 lwz r2,secondary_current@l(r2) 831 tophys(r1,r2) 832 lwz r1,TASK_STACK(r1) 833 834 /* stack */ 835 addi r1,r1,THREAD_SIZE-STACK_FRAME_ 836 li r0,0 837 tophys(r3,r1) 838 stw r0,0(r3) 839 840 /* load up the MMU */ 841 bl load_segment_registers 842 bl load_up_mmu 843 844 /* ptr to phys current thread */ 845 tophys(r4,r2) 846 addi r4,r4,THREAD /* phys addres 847 mtspr SPRN_SPRG_THREAD,r4 848 BEGIN_MMU_FTR_SECTION 849 lis r4, (swapper_pg_dir - PAGE_OFF 850 ori r4, r4, (swapper_pg_dir - PAGE 851 rlwinm r4, r4, 4, 0xffff01ff 852 mtspr SPRN_SDR1, r4 853 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE) 854 855 /* enable MMU and jump to start_second 856 li r4,MSR_KERNEL 857 lis r3,start_secondary@h 858 ori r3,r3,start_secondary@l 859 mtspr SPRN_SRR0,r3 860 mtspr SPRN_SRR1,r4 861 rfi 862 #endif /* CONFIG_SMP */ 863 864 #ifdef CONFIG_KVM_BOOK3S_HANDLER 865 #include "../kvm/book3s_rmhandlers.S" 866 #endif 867 868 /* 869 * Load stuff into the MMU. Intended to be ca 870 * IR=0 and DR=0. 871 */ 872 SYM_FUNC_START_LOCAL(early_hash_table) 873 sync /* Force all P 874 isync 875 tlbia /* Clear all T 876 sync /* wait for tl 877 TLBSYNC /* ... on all 878 /* Load the SDR1 register (hash table 879 lis r6, early_hash - PAGE_OFFSET@h 880 ori r6, r6, 3 /* 256kB table 881 mtspr SPRN_SDR1, r6 882 blr 883 SYM_FUNC_END(early_hash_table) 884 885 SYM_FUNC_START_LOCAL(load_up_mmu) 886 sync /* Force all P 887 isync 888 tlbia /* Clear all T 889 sync /* wait for tl 890 TLBSYNC /* ... on all 891 BEGIN_MMU_FTR_SECTION 892 /* Load the SDR1 register (hash table 893 lis r6,_SDR1@ha 894 tophys(r6,r6) 895 lwz r6,_SDR1@l(r6) 896 mtspr SPRN_SDR1,r6 897 END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE) 898 899 /* Load the BAT registers with the values set 900 lis r3,BATS@ha 901 addi r3,r3,BATS@l 902 tophys(r3,r3) 903 LOAD_BAT(0,r3,r4,r5) 904 LOAD_BAT(1,r3,r4,r5) 905 LOAD_BAT(2,r3,r4,r5) 906 LOAD_BAT(3,r3,r4,r5) 907 BEGIN_MMU_FTR_SECTION 908 LOAD_BAT(4,r3,r4,r5) 909 LOAD_BAT(5,r3,r4,r5) 910 LOAD_BAT(6,r3,r4,r5) 911 LOAD_BAT(7,r3,r4,r5) 912 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BAT 913 blr 914 SYM_FUNC_END(load_up_mmu) 915 916 _GLOBAL(load_segment_registers) 917 li r0, NUM_USER_SEGMENTS /* load 918 mtctr r0 /* for context 919 #ifdef CONFIG_PPC_KUEP 920 lis r3, SR_NX@h /* Kp = 0, Ks 921 #else 922 li r3, 0 /* Kp = 0, Ks 923 #endif 924 li r4, 0 925 3: mtsrin r3, r4 926 addi r3, r3, 0x111 /* increment V 927 addis r4, r4, 0x1000 /* address of 928 bdnz 3b 929 li r0, 16 - NUM_USER_SEGMENTS /* 930 mtctr r0 /* for 931 rlwinm r3, r3, 0, ~SR_NX /* Nx 932 rlwinm r3, r3, 0, ~SR_KS /* Ks 933 oris r3, r3, SR_KP@h /* Kp 934 3: mtsrin r3, r4 935 addi r3, r3, 0x111 /* increment V 936 addis r4, r4, 0x1000 /* address of 937 bdnz 3b 938 blr 939 940 /* 941 * This is where the main kernel code starts. 942 */ 943 start_here: 944 /* ptr to current */ 945 lis r2,init_task@h 946 ori r2,r2,init_task@l 947 /* Set up for using our exception vect 948 /* ptr to phys current thread */ 949 tophys(r4,r2) 950 addi r4,r4,THREAD /* init task's 951 mtspr SPRN_SPRG_THREAD,r4 952 BEGIN_MMU_FTR_SECTION 953 lis r4, (swapper_pg_dir - PAGE_OFF 954 ori r4, r4, (swapper_pg_dir - PAGE 955 rlwinm r4, r4, 4, 0xffff01ff 956 mtspr SPRN_SDR1, r4 957 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE) 958 959 /* stack */ 960 lis r1,init_thread_union@ha 961 addi r1,r1,init_thread_union@l 962 li r0,0 963 stwu r0,THREAD_SIZE-STACK_FRAME_MIN 964 /* 965 * Do early platform-specific initialization, 966 * and set up the MMU. 967 */ 968 #ifdef CONFIG_KASAN 969 bl kasan_early_init 970 #endif 971 li r3,0 972 mr r4,r31 973 bl machine_init 974 bl __save_cpu_setup 975 bl MMU_init 976 bl MMU_init_hw_patch 977 978 /* 979 * Go back to running unmapped so we can load 980 * for SDR1 (hash table pointer) and the segme 981 * and change to using our exception vectors. 982 */ 983 lis r4,2f@h 984 ori r4,r4,2f@l 985 tophys(r4,r4) 986 li r3,MSR_KERNEL & ~(MSR_IR|MSR_D 987 988 .align 4 989 mtspr SPRN_SRR0,r4 990 mtspr SPRN_SRR1,r3 991 rfi 992 /* Load up the kernel context */ 993 2: bl load_up_mmu 994 995 #ifdef CONFIG_BDI_SWITCH 996 /* Add helper information for the Abat 997 * We do this here because we know the 998 * will be enabled for real in just a 999 */ 1000 lis r5, abatron_pteptrs@h 1001 ori r5, r5, abatron_pteptrs@l 1002 stw r5, 0xf0(0) /* This much 1003 lis r6, swapper_pg_dir@h 1004 ori r6, r6, swapper_pg_dir@l 1005 tophys(r5, r5) 1006 stw r6, 0(r5) 1007 #endif /* CONFIG_BDI_SWITCH */ 1008 1009 /* Now turn on the MMU for real! */ 1010 li r4,MSR_KERNEL 1011 lis r3,start_kernel@h 1012 ori r3,r3,start_kernel@l 1013 mtspr SPRN_SRR0,r3 1014 mtspr SPRN_SRR1,r4 1015 rfi 1016 1017 /* 1018 * An undocumented "feature" of 604e requires 1019 * be cleared before changing BAT values. 1020 * 1021 * Also, newer IBM firmware does not clear ba 1022 * this makes sure it's done. 1023 * -- Cort 1024 */ 1025 SYM_FUNC_START_LOCAL(clear_bats) 1026 li r10,0 1027 1028 mtspr SPRN_DBAT0U,r10 1029 mtspr SPRN_DBAT0L,r10 1030 mtspr SPRN_DBAT1U,r10 1031 mtspr SPRN_DBAT1L,r10 1032 mtspr SPRN_DBAT2U,r10 1033 mtspr SPRN_DBAT2L,r10 1034 mtspr SPRN_DBAT3U,r10 1035 mtspr SPRN_DBAT3L,r10 1036 mtspr SPRN_IBAT0U,r10 1037 mtspr SPRN_IBAT0L,r10 1038 mtspr SPRN_IBAT1U,r10 1039 mtspr SPRN_IBAT1L,r10 1040 mtspr SPRN_IBAT2U,r10 1041 mtspr SPRN_IBAT2L,r10 1042 mtspr SPRN_IBAT3U,r10 1043 mtspr SPRN_IBAT3L,r10 1044 BEGIN_MMU_FTR_SECTION 1045 /* Here's a tweak: at this point, CPU 1046 * not been called yet, so HIGH_BAT_E 1047 * set in HID0 for the 745x processor 1048 * seems that doesn't affect our abil 1049 * write to these SPRs. 1050 */ 1051 mtspr SPRN_DBAT4U,r10 1052 mtspr SPRN_DBAT4L,r10 1053 mtspr SPRN_DBAT5U,r10 1054 mtspr SPRN_DBAT5L,r10 1055 mtspr SPRN_DBAT6U,r10 1056 mtspr SPRN_DBAT6L,r10 1057 mtspr SPRN_DBAT7U,r10 1058 mtspr SPRN_DBAT7L,r10 1059 mtspr SPRN_IBAT4U,r10 1060 mtspr SPRN_IBAT4L,r10 1061 mtspr SPRN_IBAT5U,r10 1062 mtspr SPRN_IBAT5L,r10 1063 mtspr SPRN_IBAT6U,r10 1064 mtspr SPRN_IBAT6L,r10 1065 mtspr SPRN_IBAT7U,r10 1066 mtspr SPRN_IBAT7L,r10 1067 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BA 1068 blr 1069 SYM_FUNC_END(clear_bats) 1070 1071 _GLOBAL(update_bats) 1072 lis r4, 1f@h 1073 ori r4, r4, 1f@l 1074 tophys(r4, r4) 1075 mfmsr r6 1076 mflr r7 1077 li r3, MSR_KERNEL & ~(MSR_IR | M 1078 rlwinm r0, r6, 0, ~MSR_RI 1079 rlwinm r0, r0, 0, ~MSR_EE 1080 mtmsr r0 1081 1082 .align 4 1083 mtspr SPRN_SRR0, r4 1084 mtspr SPRN_SRR1, r3 1085 rfi 1086 1: bl clear_bats 1087 lis r3, BATS@ha 1088 addi r3, r3, BATS@l 1089 tophys(r3, r3) 1090 LOAD_BAT(0, r3, r4, r5) 1091 LOAD_BAT(1, r3, r4, r5) 1092 LOAD_BAT(2, r3, r4, r5) 1093 LOAD_BAT(3, r3, r4, r5) 1094 BEGIN_MMU_FTR_SECTION 1095 LOAD_BAT(4, r3, r4, r5) 1096 LOAD_BAT(5, r3, r4, r5) 1097 LOAD_BAT(6, r3, r4, r5) 1098 LOAD_BAT(7, r3, r4, r5) 1099 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BA 1100 li r3, MSR_KERNEL & ~(MSR_IR | M 1101 mtmsr r3 1102 mtspr SPRN_SRR0, r7 1103 mtspr SPRN_SRR1, r6 1104 rfi 1105 1106 SYM_FUNC_START_LOCAL(flush_tlbs) 1107 lis r10, 0x40 1108 1: addic. r10, r10, -0x1000 1109 tlbie r10 1110 bgt 1b 1111 sync 1112 blr 1113 SYM_FUNC_END(flush_tlbs) 1114 1115 SYM_FUNC_START_LOCAL(mmu_off) 1116 addi r4, r3, __after_mmu_off - _st 1117 mfmsr r3 1118 andi. r0,r3,MSR_DR|MSR_IR 1119 beqlr 1120 andc r3,r3,r0 1121 1122 .align 4 1123 mtspr SPRN_SRR0,r4 1124 mtspr SPRN_SRR1,r3 1125 sync 1126 rfi 1127 SYM_FUNC_END(mmu_off) 1128 1129 /* We use one BAT to map up to 256M of RAM at 1130 SYM_FUNC_START_LOCAL(initial_bats) 1131 lis r11,PAGE_OFFSET@h 1132 tophys(r8,r11) 1133 #ifdef CONFIG_SMP 1134 ori r8,r8,0x12 /* R/ 1135 #else 1136 ori r8,r8,2 /* R/ 1137 #endif /* CONFIG_SMP */ 1138 ori r11,r11,BL_256M<<2|0x2 /* se 1139 1140 mtspr SPRN_DBAT0L,r8 /* N. 1141 mtspr SPRN_DBAT0U,r11 /* bi 1142 mtspr SPRN_IBAT0L,r8 1143 mtspr SPRN_IBAT0U,r11 1144 isync 1145 blr 1146 SYM_FUNC_END(initial_bats) 1147 1148 #ifdef CONFIG_BOOTX_TEXT 1149 SYM_FUNC_START_LOCAL(setup_disp_bat) 1150 /* 1151 * setup the display bat prepared for 1152 */ 1153 mflr r8 1154 bl reloc_offset 1155 mtlr r8 1156 addis r8,r3,disp_BAT@ha 1157 addi r8,r8,disp_BAT@l 1158 cmpwi cr0,r8,0 1159 beqlr 1160 lwz r11,0(r8) 1161 lwz r8,4(r8) 1162 mtspr SPRN_DBAT3L,r8 1163 mtspr SPRN_DBAT3U,r11 1164 blr 1165 SYM_FUNC_END(setup_disp_bat) 1166 #endif /* CONFIG_BOOTX_TEXT */ 1167 1168 #ifdef CONFIG_PPC_EARLY_DEBUG_CPM 1169 SYM_FUNC_START_LOCAL(setup_cpm_bat) 1170 lis r8, 0xf000 1171 ori r8, r8, 0x002a 1172 mtspr SPRN_DBAT1L, r8 1173 1174 lis r11, 0xf000 1175 ori r11, r11, (BL_1M << 2) | 2 1176 mtspr SPRN_DBAT1U, r11 1177 1178 blr 1179 SYM_FUNC_END(setup_cpm_bat) 1180 #endif 1181 1182 #ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO 1183 SYM_FUNC_START_LOCAL(setup_usbgecko_bat) 1184 /* prepare a BAT for early io */ 1185 #if defined(CONFIG_GAMECUBE) 1186 lis r8, 0x0c00 1187 #elif defined(CONFIG_WII) 1188 lis r8, 0x0d00 1189 #else 1190 #error Invalid platform for USB Gecko based e 1191 #endif 1192 /* 1193 * The virtual address used must matc 1194 * associated to the fixmap entry FIX 1195 */ 1196 lis r11, 0xfffe /* top 128K * 1197 ori r8, r8, 0x002a /* uncached, 1198 ori r11, r11, 0x2 /* 128K, Vs=1 1199 mtspr SPRN_DBAT1L, r8 1200 mtspr SPRN_DBAT1U, r11 1201 blr 1202 SYM_FUNC_END(setup_usbgecko_bat) 1203 #endif 1204 1205 .data
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.