1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * PowerPC version 4 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 5 * 6 * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP 7 * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> 8 * Adapted for Power Macintosh by Paul Mackerras. 9 * Low-level exception handlers and MMU support 10 * rewritten by Paul Mackerras. 11 * Copyright (C) 1996 Paul Mackerras. 12 * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). 13 * 14 * This file contains the low-level support and setup for the 15 * PowerPC platform, including trap and interrupt dispatch. 16 * (The PPC 8xx embedded CPUs use head_8xx.S instead.) 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() -- Cort */ \ 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 XCOFF loader in the OpenFirmware 58 * on the powermac expects the entry point to be a procedure descriptor. 59 */ 60 _GLOBAL(_start); 61 /* 62 * These are here for legacy reasons, the kernel used to 63 * need to look like a coff function entry for the pmac 64 * but we're always started by some kind of bootloader now. 65 * -- Cort 66 */ 67 nop /* used by __secondary_hold on prep (mtx) and chrp smp */ 68 nop /* used by __secondary_hold on prep (mtx) and chrp smp */ 69 nop 70 71 /* PMAC 72 * Enter here with the kernel text, data and bss loaded starting at 73 * 0, running with virtual == physical mapping. 74 * r5 points to the prom entry point (the client interface handler 75 * address). Address translation is turned on, with the prom 76 * managing the hash table. Interrupts are disabled. The stack 77 * pointer (r1) points to just below the end of the half-meg region 78 * from 0x380000 - 0x400000, which is mapped in already. 79 * 80 * If we are booted from MacOS via BootX, we enter with the kernel 81 * image loaded somewhere, and the following values in registers: 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 after the kernel is relocated 88 * to its proper place in memory by the boot loader. The expected layout 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 setup so we can call 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 ourselves to KERNELBASE, 105 * because OF may have I/O devices mapped into that area 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 = runtime addr here */ 115 addis r8,r8,(_stext - 0b)@ha 116 addi r8,r8,(_stext - 0b)@l /* current runtime base addr */ 117 bl prom_init 118 #endif /* CONFIG_PPC_OF_BOOT_TRAMPOLINE */ 119 120 /* We never return. We also hit that trap if trying to boot 121 * from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */ 122 trap 123 124 /* 125 * Check for BootX signature when supporting PowerMac and branch to 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 /* save device tree ptr */ 138 li r24,0 /* cpu # */ 139 140 /* 141 * early_init() does the early machine identification and does 142 * the necessary low-level setup and clears the BSS 143 * -- Cort <cort@fsmlabs.com> 144 */ 145 bl early_init 146 147 /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains 148 * the physical address we are running at, returned by early_init() 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 Idle 171 */ 172 bl reloc_offset 173 li r24,0 /* cpu# */ 174 bl call_setup_cpu /* Call setup_cpu for this CPU */ 175 bl reloc_offset 176 bl init_idle_6xx 177 178 179 /* 180 * We need to run with _start at physical address 0. 181 * On CHRP, we are loaded at 0x10000 since OF on CHRP uses 182 * the exception vectors at 0 (and therefore this copy 183 * overwrites OF's exception vectors with our own). 184 * The MMU is off at this point. 185 */ 186 bl reloc_offset 187 mr r26,r3 188 addis r4,r3,KERNELBASE@h /* current address of _start */ 189 lis r5,PHYSICAL_START@h 190 cmplw 0,r4,r5 /* already running at PHYSICAL_START? */ 191 bne relocate_kernel 192 /* 193 * we now have the 1st 16M of ram mapped with the bats. 194 * prep needs the mmu to be turned on here, but pmac already has it on. 195 * this shouldn't bother the pmac since it just gets turned on again 196 * as we jump to our code at KERNELBASE. -- Cort 197 * Actually no, pmac doesn't have it on any more. BootX enters with MMU 198 * off, and in other cases, we now turn it off before changing BATs above. 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 /* enables MMU */ 208 209 /* 210 * We need __secondary_hold as a place to hold the other cpus on 211 * an SMP machine, even when we are running a UP kernel. 212 */ 213 . = 0xc0 /* for prep bootloader */ 214 li r3,1 /* MTX only has 1 cpu */ 215 .globl __secondary_hold 216 __secondary_hold: 217 /* tell the master we're here */ 218 stw r3,__secondary_hold_acknowledge@l(0) 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 changing the vector, and 240 putting it back to what it was (unknown_async_exception) when done. */ 241 EXCEPTION(INTERRUPT_SYSTEM_RESET, Reset, unknown_async_exception) 242 243 /* Machine check */ 244 /* 245 * On CHRP, this is complicated by the fact that we could get a 246 * machine check inside RTAS, and we have no guarantee that certain 247 * critical registers will have the values we expect. The set of 248 * registers that might have bad values includes all the GPRs 249 * and all the BATs. We indicate that we are in RTAS by putting 250 * a non-zero value, the address of the exception frame to use, 251 * in thread.rtas_sp. The machine check handler checks thread.rtas_sp 252 * and uses its value if it is non-zero. 253 * (Other exception handlers assume that r1 is a valid kernel stack 254 * pointer when we take an exception from supervisor mode.) 255 * -- paulus. 256 */ 257 START_EXCEPTION(INTERRUPT_MACHINE_CHECK, MachineCheck) 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, DataAccess) 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 | DSISR_DABRMATCH)@h 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_TABLE) 296 #endif 297 1: EXCEPTION_PROLOG_0 handle_dar_dsisr=1 298 EXCEPTION_PROLOG_1 299 EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataAccess handle_dar_dsisr=1 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, InstructionAccess) 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 /* check whether user or kernel */ 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 /* no pte found? */ 324 bne hash_page_isi 325 .Lhash_page_isi_cont: 326 mfspr r11, SPRN_SRR1 /* check whether user or kernel */ 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_STORAGE InstructionAccess 333 andis. r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */ 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, HardwareInterrupt, do_IRQ) 342 343 /* Alignment exception */ 344 START_EXCEPTION(INTERRUPT_ALIGNMENT, Alignment) 345 EXCEPTION_PROLOG INTERRUPT_ALIGNMENT Alignment handle_dar_dsisr=1 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, ProgramCheck) 353 EXCEPTION_PROLOG INTERRUPT_PROGRAM ProgramCheck 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 and treat fp instructions 365 * as a FP Unavailable exception. Redirect to illegal/emulation handling. 366 */ 367 b ProgramCheck 368 END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE) 369 EXCEPTION_PROLOG INTERRUPT_FP_UNAVAIL FPUnavailable 370 beq 1f 371 bl load_up_fpu /* if from user, just load it up */ 372 b fast_exception_return 373 1: prepare_transfer_to_handler 374 bl kernel_fp_unavailable_exception 375 b interrupt_return 376 #else 377 b ProgramCheck 378 #endif 379 380 /* Decrementer */ 381 EXCEPTION(INTERRUPT_DECREMENTER, Decrementer, timer_interrupt) 382 383 EXCEPTION(0xa00, Trap_0a, unknown_exception) 384 EXCEPTION(0xb00, Trap_0b, unknown_exception) 385 386 /* System call */ 387 START_EXCEPTION(INTERRUPT_SYSCALL, SystemCall) 388 SYSCALL_ENTRY INTERRUPT_SYSCALL 389 390 EXCEPTION(INTERRUPT_TRACE, SingleStep, single_step_exception) 391 EXCEPTION(0xe00, Trap_0e, unknown_exception) 392 393 /* 394 * The Altivec unavailable trap is at 0x0f20. Foo. 395 * We effectively remap it to 0x3000. 396 * We include an altivec unavailable exception vector even if 397 * not configured for Altivec, so that you can't panic a 398 * non-altivec kernel running on a machine with altivec just 399 * by executing an altivec instruction. 400 */ 401 START_EXCEPTION(INTERRUPT_PERFMON, PerformanceMonitorTrap) 402 b PerformanceMonitor 403 404 START_EXCEPTION(INTERRUPT_ALTIVEC_UNAVAIL, AltiVecUnavailableTrap) 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 use automatically. 411 */ 412 . = INTERRUPT_INST_TLB_MISS_603 413 InstructionTLBMiss: 414 /* Get PTE (linux-style) and check access */ 415 mfspr r0,SPRN_IMISS 416 mfspr r2, SPRN_SDR1 417 li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC 418 rlwinm r2, r2, 28, 0xfffff000 419 rlwimi r2,r0,12,20,29 /* insert top 10 bits of address */ 420 lwz r2,0(r2) /* get pmd entry */ 421 #ifdef CONFIG_EXECMEM 422 rlwinm r3, r0, 4, 0xf 423 subi r3, r3, (TASK_SIZE >> 28) & 0xf 424 #endif 425 rlwinm. r2,r2,0,0,19 /* extract address of pte page */ 426 beq- InstructionAddressInvalid /* return if no mapping */ 427 rlwimi r2,r0,22,20,29 /* insert next 10 bits of address */ 428 lwz r2,0(r2) /* get linux-style pte */ 429 andc. r1,r1,r2 /* check access & ~permission */ 430 bne- InstructionAddressInvalid /* return if access not permitted */ 431 /* Convert linux-style PTE to low word of PPC-style PTE */ 432 #ifdef CONFIG_EXECMEM 433 rlwimi r2, r3, 1, 31, 31 /* userspace ? -> PP lsb */ 434 #endif 435 ori r1, r1, 0xe06 /* clear out reserved bits */ 436 andc r1, r2, r1 /* PP = user? 1 : 0 */ 437 BEGIN_FTR_SECTION 438 rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ 439 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) 440 mtspr SPRN_RPA,r1 441 tlbli r0 442 mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ 443 mtcrf 0x80,r3 444 rfi 445 InstructionAddressInvalid: 446 mfspr r3,SPRN_SRR1 447 rlwinm r1,r3,9,6,6 /* Get load/store bit */ 448 449 addis r1,r1,0x2000 450 mtspr SPRN_DSISR,r1 /* (shouldn't be needed) */ 451 andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */ 452 or r2,r2,r1 453 mtspr SPRN_SRR1,r2 454 mfspr r1,SPRN_IMISS /* Get failing address */ 455 rlwinm. r2,r2,0,31,31 /* Check for little endian access */ 456 rlwimi r2,r2,1,30,30 /* change 1 -> 3 */ 457 xor r1,r1,r2 458 mtspr SPRN_DAR,r1 /* Set fault address */ 459 mfmsr r0 /* Restore "normal" registers */ 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 603/603e 467 */ 468 . = INTERRUPT_DATA_LOAD_TLB_MISS_603 469 DataLoadTLBMiss: 470 /* Get PTE (linux-style) and check access */ 471 mfspr r0,SPRN_DMISS 472 mfspr r2, SPRN_SDR1 473 rlwinm r1, r2, 28, 0xfffff000 474 rlwimi r1,r0,12,20,29 /* insert top 10 bits of address */ 475 lwz r2,0(r1) /* get pmd entry */ 476 rlwinm r3, r0, 4, 0xf 477 rlwinm. r2,r2,0,0,19 /* extract address of pte page */ 478 subi r3, r3, (TASK_SIZE >> 28) & 0xf 479 beq- 2f /* bail if no mapping */ 480 1: rlwimi r2,r0,22,20,29 /* insert next 10 bits of address */ 481 lwz r2,0(r2) /* get linux-style pte */ 482 li r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_READ 483 andc. r1,r1,r2 /* check access & ~permission */ 484 bne- DataAddressInvalid /* return if access not permitted */ 485 /* Convert linux-style PTE to low word of PPC-style PTE */ 486 rlwinm r1,r2,32-9,30,30 /* _PAGE_WRITE -> PP msb */ 487 rlwimi r2,r3,2,30,31 /* userspace ? -> PP */ 488 rlwimi r1,r2,32-3,24,24 /* _PAGE_WRITE -> _PAGE_DIRTY */ 489 xori r1,r1,_PAGE_DIRTY /* clear dirty when not rw */ 490 ori r1,r1,0xe04 /* clear out reserved bits */ 491 andc r1,r2,r1 /* PP = user? rw? 1: 3: 0 */ 492 BEGIN_FTR_SECTION 493 rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ 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 Address bits 15:19 */ 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 /* Need to restore CR0 */ 512 mtcrf 0x80,r2 513 tlbld r0 514 rfi 515 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) 516 517 2: lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha 518 addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ 519 rlwimi r2,r0,12,20,29 /* insert top 10 bits of address */ 520 lwz r2,0(r2) /* get pmd entry */ 521 cmpwi cr0,r2,0 522 beq- DataAddressInvalid /* return if no mapping */ 523 stw r2,0(r1) 524 rlwinm. r2,r2,0,0,19 /* extract address of pte page */ 525 b 1b 526 DataAddressInvalid: 527 mfspr r3,SPRN_SRR1 528 rlwinm r1,r3,9,6,6 /* Get load/store bit */ 529 addis r1,r1,0x2000 530 mtspr SPRN_DSISR,r1 531 andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */ 532 mtspr SPRN_SRR1,r2 533 mfspr r1,SPRN_DMISS /* Get failing address */ 534 rlwinm. r2,r2,0,31,31 /* Check for little endian access */ 535 beq 20f /* Jump if big endian */ 536 xori r1,r1,3 537 20: mtspr SPRN_DAR,r1 /* Set fault address */ 538 mfmsr r0 /* Restore "normal" registers */ 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 access */ 550 mfspr r0,SPRN_DMISS 551 mfspr r2, SPRN_SDR1 552 rlwinm r1, r2, 28, 0xfffff000 553 rlwimi r1,r0,12,20,29 /* insert top 10 bits of address */ 554 lwz r2,0(r1) /* get pmd entry */ 555 rlwinm r3, r0, 4, 0xf 556 rlwinm. r2,r2,0,0,19 /* extract address of pte page */ 557 subi r3, r3, (TASK_SIZE >> 28) & 0xf 558 beq- 2f /* bail if no mapping */ 559 1: 560 rlwimi r2,r0,22,20,29 /* insert next 10 bits of address */ 561 lwz r2,0(r2) /* get linux-style pte */ 562 li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED 563 andc. r1,r1,r2 /* check access & ~permission */ 564 bne- DataAddressInvalid /* return if access not permitted */ 565 /* Convert linux-style PTE to low word of PPC-style PTE */ 566 rlwimi r2,r3,1,31,31 /* userspace ? -> PP lsb */ 567 li r1,0xe06 /* clear out reserved bits & PP msb */ 568 andc r1,r2,r1 /* PP = user? 1: 0 */ 569 BEGIN_FTR_SECTION 570 rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ 571 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) 572 mtspr SPRN_RPA,r1 573 mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ 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 Address bits 15:19 */ 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 /* Need to restore CR0 */ 591 mtcrf 0x80,r2 592 tlbld r0 593 rfi 594 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) 595 596 2: lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha 597 addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ 598 rlwimi r2,r0,12,20,29 /* insert top 10 bits of address */ 599 lwz r2,0(r2) /* get pmd entry */ 600 cmpwi cr0,r2,0 601 beq- DataAddressInvalid /* return if no mapping */ 602 stw r2,0(r1) 603 rlwinm r2,r2,0,0,19 /* extract address of pte page */ 604 b 1b 605 606 #ifndef CONFIG_ALTIVEC 607 #define altivec_assist_exception unknown_exception 608 #endif 609 610 #ifndef CONFIG_TAU_INT 611 #define TAUException unknown_async_exception 612 #endif 613 614 EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception) 615 EXCEPTION(0x1400, SMI, SMIException) 616 EXCEPTION(0x1500, Trap_15, unknown_exception) 617 EXCEPTION(0x1600, Trap_16, altivec_assist_exception) 618 EXCEPTION(0x1700, Trap_17, TAUException) 619 EXCEPTION(0x1800, Trap_18, unknown_exception) 620 EXCEPTION(0x1900, Trap_19, unknown_exception) 621 EXCEPTION(0x1a00, Trap_1a, unknown_exception) 622 EXCEPTION(0x1b00, Trap_1b, unknown_exception) 623 EXCEPTION(0x1c00, Trap_1c, unknown_exception) 624 EXCEPTION(0x1d00, Trap_1d, unknown_exception) 625 EXCEPTION(0x1e00, Trap_1e, unknown_exception) 626 EXCEPTION(0x1f00, Trap_1f, unknown_exception) 627 EXCEPTION(0x2000, RunMode, RunModeException) 628 EXCEPTION(0x2100, Trap_21, unknown_exception) 629 EXCEPTION(0x2200, Trap_22, unknown_exception) 630 EXCEPTION(0x2300, Trap_23, unknown_exception) 631 EXCEPTION(0x2400, Trap_24, unknown_exception) 632 EXCEPTION(0x2500, Trap_25, unknown_exception) 633 EXCEPTION(0x2600, Trap_26, unknown_exception) 634 EXCEPTION(0x2700, Trap_27, unknown_exception) 635 EXCEPTION(0x2800, Trap_28, unknown_exception) 636 EXCEPTION(0x2900, Trap_29, unknown_exception) 637 EXCEPTION(0x2a00, Trap_2a, unknown_exception) 638 EXCEPTION(0x2b00, Trap_2b, unknown_exception) 639 EXCEPTION(0x2c00, Trap_2c, unknown_exception) 640 EXCEPTION(0x2d00, Trap_2d, unknown_exception) 641 EXCEPTION(0x2e00, Trap_2e, unknown_exception) 642 EXCEPTION(0x2f00, Trap_2f, unknown_exception) 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 /* DSISR_STORE -> _PAGE_WRITE */ 683 ori r3, r3, _PAGE_PRESENT | _PAGE_READ 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 /* Set on ISI, cleared on DSI */ 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 AltiVecUnavailable 729 #ifdef CONFIG_ALTIVEC 730 beq 1f 731 bl load_up_altivec /* if from user, just load it up */ 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 PerformanceMonitor 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 code to copy 749 * the kernel image to physical address PHYSICAL_START. 750 */ 751 relocate_kernel: 752 lis r3,PHYSICAL_START@h /* Destination base address */ 753 li r6,0 /* Destination offset */ 754 li r5,0x4000 /* # bytes of memory to copy */ 755 bl copy_and_flush /* copy the first 0x4000 bytes */ 756 addi r0,r3,4f@l /* jump to the address of 4f */ 757 mtctr r0 /* in copy and do the rest. */ 758 bctr /* jump to the copy */ 759 4: lis r5,_end-KERNELBASE@h 760 ori r5,r5,_end-KERNELBASE@l 761 bl copy_and_flush /* copy the rest */ 762 b turn_on_mmu 763 764 /* 765 * Copy routine used to copy the kernel to start at physical address 0 766 * and flush and invalidate the caches as needed. 767 * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset 768 * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. 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 /* copy a cache line */ 776 lwzx r0,r6,r4 777 stwx r0,r6,r3 778 bdnz 3b 779 dcbst r6,r3 /* write it to memory */ 780 sync 781 icbi r6,r3 /* flush the icache line */ 782 cmplw 0,r6,r5 783 blt 4b 784 sync /* additional sync needed on g4 */ 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_acknowledge@l(0) 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 must each occupy 8 bytes. */ 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 IR=0 and DR=1, and DBAT 0 810 set to map the 0xf0000000 - 0xffffffff region */ 811 mfmsr r0 812 rlwinm r0,r0,0,28,26 /* clear DR (0x10) */ 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 /* Call setup_cpu for this CPU */ 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_MIN_SIZE 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 address of our thread_struct */ 847 mtspr SPRN_SPRG_THREAD,r4 848 BEGIN_MMU_FTR_SECTION 849 lis r4, (swapper_pg_dir - PAGE_OFFSET)@h 850 ori r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l 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_secondary */ 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 called with 870 * IR=0 and DR=0. 871 */ 872 SYM_FUNC_START_LOCAL(early_hash_table) 873 sync /* Force all PTE updates to finish */ 874 isync 875 tlbia /* Clear all TLB entries */ 876 sync /* wait for tlbia/tlbie to finish */ 877 TLBSYNC /* ... on all CPUs */ 878 /* Load the SDR1 register (hash table base & size) */ 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 PTE updates to finish */ 887 isync 888 tlbia /* Clear all TLB entries */ 889 sync /* wait for tlbia/tlbie to finish */ 890 TLBSYNC /* ... on all CPUs */ 891 BEGIN_MMU_FTR_SECTION 892 /* Load the SDR1 register (hash table base & size) */ 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 up by MMU_init. */ 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_BATS) 913 blr 914 SYM_FUNC_END(load_up_mmu) 915 916 _GLOBAL(load_segment_registers) 917 li r0, NUM_USER_SEGMENTS /* load up user segment register values */ 918 mtctr r0 /* for context 0 */ 919 #ifdef CONFIG_PPC_KUEP 920 lis r3, SR_NX@h /* Kp = 0, Ks = 0, VSID = 0 */ 921 #else 922 li r3, 0 /* Kp = 0, Ks = 0, VSID = 0 */ 923 #endif 924 li r4, 0 925 3: mtsrin r3, r4 926 addi r3, r3, 0x111 /* increment VSID */ 927 addis r4, r4, 0x1000 /* address of next segment */ 928 bdnz 3b 929 li r0, 16 - NUM_USER_SEGMENTS /* load up kernel segment registers */ 930 mtctr r0 /* for context 0 */ 931 rlwinm r3, r3, 0, ~SR_NX /* Nx = 0 */ 932 rlwinm r3, r3, 0, ~SR_KS /* Ks = 0 */ 933 oris r3, r3, SR_KP@h /* Kp = 1 */ 934 3: mtsrin r3, r4 935 addi r3, r3, 0x111 /* increment VSID */ 936 addis r4, r4, 0x1000 /* address of next segment */ 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 vectors */ 948 /* ptr to phys current thread */ 949 tophys(r4,r2) 950 addi r4,r4,THREAD /* init task's THREAD */ 951 mtspr SPRN_SPRG_THREAD,r4 952 BEGIN_MMU_FTR_SECTION 953 lis r4, (swapper_pg_dir - PAGE_OFFSET)@h 954 ori r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l 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_SIZE(r1) 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 up new values 980 * for SDR1 (hash table pointer) and the segment registers 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_DR) 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 Abatron bdiGDB debugger. 997 * We do this here because we know the mmu is disabled, and 998 * will be enabled for real in just a few instructions. 999 */ 1000 lis r5, abatron_pteptrs@h 1001 ori r5, r5, abatron_pteptrs@l 1002 stw r5, 0xf0(0) /* This much match your Abatron config */ 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 that the v bit 1019 * be cleared before changing BAT values. 1020 * 1021 * Also, newer IBM firmware does not clear bat3 and 4 so 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 setup have 1046 * not been called yet, so HIGH_BAT_EN may not be 1047 * set in HID0 for the 745x processors. However, it 1048 * seems that doesn't affect our ability to actually 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_BATS) 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 | MSR_DR) 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_BATS) 1100 li r3, MSR_KERNEL & ~(MSR_IR | MSR_DR | MSR_RI) 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 - _start 1117 mfmsr r3 1118 andi. r0,r3,MSR_DR|MSR_IR /* MMU enabled? */ 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 _PAGE_OFFSET */ 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/W access, M=1 */ 1135 #else 1136 ori r8,r8,2 /* R/W access */ 1137 #endif /* CONFIG_SMP */ 1138 ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */ 1139 1140 mtspr SPRN_DBAT0L,r8 /* N.B. 6xx have valid */ 1141 mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */ 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 us in prom.c 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 early debugging. 1191 #endif 1192 /* 1193 * The virtual address used must match the virtual address 1194 * associated to the fixmap entry FIX_EARLY_DEBUG_BASE. 1195 */ 1196 lis r11, 0xfffe /* top 128K */ 1197 ori r8, r8, 0x002a /* uncached, guarded ,rw */ 1198 ori r11, r11, 0x2 /* 128K, Vs=1, Vp=0 */ 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.