Merge tag 'signal-for-v5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/ebieder...
[linux-block.git] / arch / powerpc / kernel / head_book3s_32.S
CommitLineData
2874c5fd 1/* SPDX-License-Identifier: GPL-2.0-or-later */
14cf11af
PM
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).
14cf11af
PM
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.)
14cf11af
PM
17 */
18
e7039845 19#include <linux/init.h>
65fddcfc 20#include <linux/pgtable.h>
b3b8dc6c 21#include <asm/reg.h>
14cf11af
PM
22#include <asm/page.h>
23#include <asm/mmu.h>
14cf11af
PM
24#include <asm/cputable.h>
25#include <asm/cache.h>
26#include <asm/thread_info.h>
27#include <asm/ppc_asm.h>
28#include <asm/asm-offsets.h>
ec2b36b9 29#include <asm/ptrace.h>
5e696617 30#include <asm/bug.h>
dd84c217 31#include <asm/kvm_book3s_asm.h>
9445aa1a 32#include <asm/export.h>
2c86cd18 33#include <asm/feature-fixups.h>
7fab6397 34#include <asm/interrupt.h>
14cf11af 35
8a23fdec
CL
36#include "head_32.h"
37
14cf11af
PM
38#define LOAD_BAT(n, reg, RA, RB) \
39 /* see the comment for clear_bats() -- Cort */ \
40 li RA,0; \
41 mtspr SPRN_IBAT##n##U,RA; \
42 mtspr SPRN_DBAT##n##U,RA; \
43 lwz RA,(n*16)+0(reg); \
44 lwz RB,(n*16)+4(reg); \
45 mtspr SPRN_IBAT##n##U,RA; \
46 mtspr SPRN_IBAT##n##L,RB; \
14cf11af
PM
47 lwz RA,(n*16)+8(reg); \
48 lwz RB,(n*16)+12(reg); \
49 mtspr SPRN_DBAT##n##U,RA; \
39097b9c 50 mtspr SPRN_DBAT##n##L,RB
14cf11af 51
e7039845 52 __HEAD
27e21e8f 53_GLOBAL(_stext);
14cf11af
PM
54
55/*
56 * _start is defined this way because the XCOFF loader in the OpenFirmware
57 * on the powermac expects the entry point to be a procedure descriptor.
58 */
27e21e8f 59_GLOBAL(_start);
14cf11af
PM
60 /*
61 * These are here for legacy reasons, the kernel used to
62 * need to look like a coff function entry for the pmac
63 * but we're always started by some kind of bootloader now.
64 * -- Cort
65 */
66 nop /* used by __secondary_hold on prep (mtx) and chrp smp */
67 nop /* used by __secondary_hold on prep (mtx) and chrp smp */
68 nop
69
70/* PMAC
71 * Enter here with the kernel text, data and bss loaded starting at
72 * 0, running with virtual == physical mapping.
73 * r5 points to the prom entry point (the client interface handler
74 * address). Address translation is turned on, with the prom
75 * managing the hash table. Interrupts are disabled. The stack
76 * pointer (r1) points to just below the end of the half-meg region
77 * from 0x380000 - 0x400000, which is mapped in already.
78 *
79 * If we are booted from MacOS via BootX, we enter with the kernel
80 * image loaded somewhere, and the following values in registers:
81 * r3: 'BooX' (0x426f6f58)
82 * r4: virtual address of boot_infos_t
83 * r5: 0
84 *
14cf11af
PM
85 * PREP
86 * This is jumped to on prep systems right after the kernel is relocated
87 * to its proper place in memory by the boot loader. The expected layout
88 * of the regs is:
89 * r3: ptr to residual data
90 * r4: initrd_start or if no initrd then 0
91 * r5: initrd_end - unused if r4 is 0
92 * r6: Start of command line string
93 * r7: End of command line string
94 *
95 * This just gets a minimal mmu environment setup so we can call
96 * start_here() to do the real work.
97 * -- Cort
98 */
99
100 .globl __start
101__start:
102/*
103 * We have to do any OF calls before we map ourselves to KERNELBASE,
104 * because OF may have I/O devices mapped into that area
105 * (particularly on CHRP).
106 */
9b6b563c
PM
107 cmpwi 0,r5,0
108 beq 1f
2bda347b 109
28794d34 110#ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE
2bda347b
BH
111 /* find out where we are now */
112 bcl 20,31,$+4
1130: mflr r8 /* r8 = runtime addr here */
114 addis r8,r8,(_stext - 0b)@ha
115 addi r8,r8,(_stext - 0b)@l /* current runtime base addr */
9b6b563c 116 bl prom_init
28794d34
BH
117#endif /* CONFIG_PPC_OF_BOOT_TRAMPOLINE */
118
119 /* We never return. We also hit that trap if trying to boot
120 * from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */
9b6b563c
PM
121 trap
122
d7f39454
BH
123/*
124 * Check for BootX signature when supporting PowerMac and branch to
125 * appropriate trampoline if it's present
126 */
127#ifdef CONFIG_PPC_PMAC
1281: lis r31,0x426f
129 ori r31,r31,0x6f58
130 cmpw 0,r3,r31
131 bne 1f
132 bl bootx_init
133 trap
134#endif /* CONFIG_PPC_PMAC */
135
6dece0eb 1361: mr r31,r3 /* save device tree ptr */
14cf11af
PM
137 li r24,0 /* cpu # */
138
139/*
140 * early_init() does the early machine identification and does
141 * the necessary low-level setup and clears the BSS
142 * -- Cort <cort@fsmlabs.com>
143 */
144 bl early_init
145
14cf11af
PM
146/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
147 * the physical address we are running at, returned by early_init()
148 */
149 bl mmu_off
150__after_mmu_off:
14cf11af
PM
151 bl clear_bats
152 bl flush_tlbs
153
154 bl initial_bats
215b8237 155 bl load_segment_registers
01776f07 156 bl reloc_offset
215b8237 157 bl early_hash_table
f21f49ea 158#if defined(CONFIG_BOOTX_TEXT)
51d3082f
BH
159 bl setup_disp_bat
160#endif
c374e00e
SW
161#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
162 bl setup_cpm_bat
163#endif
d1d56f8c
AH
164#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
165 bl setup_usbgecko_bat
166#endif
14cf11af
PM
167
168/*
169 * Call setup_cpu for CPU 0 and initialize 6xx Idle
170 */
171 bl reloc_offset
172 li r24,0 /* cpu# */
173 bl call_setup_cpu /* Call setup_cpu for this CPU */
14cf11af
PM
174 bl reloc_offset
175 bl init_idle_6xx
14cf11af
PM
176
177
14cf11af
PM
178/*
179 * We need to run with _start at physical address 0.
180 * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
181 * the exception vectors at 0 (and therefore this copy
182 * overwrites OF's exception vectors with our own).
9b6b563c 183 * The MMU is off at this point.
14cf11af
PM
184 */
185 bl reloc_offset
186 mr r26,r3
187 addis r4,r3,KERNELBASE@h /* current address of _start */
ccdcef72
DF
188 lis r5,PHYSICAL_START@h
189 cmplw 0,r4,r5 /* already running at PHYSICAL_START? */
14cf11af 190 bne relocate_kernel
14cf11af
PM
191/*
192 * we now have the 1st 16M of ram mapped with the bats.
193 * prep needs the mmu to be turned on here, but pmac already has it on.
194 * this shouldn't bother the pmac since it just gets turned on again
195 * as we jump to our code at KERNELBASE. -- Cort
196 * Actually no, pmac doesn't have it on any more. BootX enters with MMU
197 * off, and in other cases, we now turn it off before changing BATs above.
198 */
199turn_on_mmu:
200 mfmsr r0
215b8237 201 ori r0,r0,MSR_DR|MSR_IR|MSR_RI
14cf11af
PM
202 mtspr SPRN_SRR1,r0
203 lis r0,start_here@h
204 ori r0,r0,start_here@l
205 mtspr SPRN_SRR0,r0
120c0518 206 rfi /* enables MMU */
14cf11af
PM
207
208/*
209 * We need __secondary_hold as a place to hold the other cpus on
210 * an SMP machine, even when we are running a UP kernel.
211 */
212 . = 0xc0 /* for prep bootloader */
213 li r3,1 /* MTX only has 1 cpu */
214 .globl __secondary_hold
215__secondary_hold:
216 /* tell the master we're here */
bbd0abda 217 stw r3,__secondary_hold_acknowledge@l(0)
14cf11af
PM
218#ifdef CONFIG_SMP
219100: lwz r4,0(0)
220 /* wait until we're told to start */
221 cmpw 0,r4,r3
222 bne 100b
223 /* our cpu # was at addr 0 - go */
224 mr r24,r3 /* cpu # */
225 b __secondary_start
226#else
227 b .
228#endif /* CONFIG_SMP */
229
bbd0abda
PM
230 .globl __secondary_hold_spinloop
231__secondary_hold_spinloop:
232 .long 0
233 .globl __secondary_hold_acknowledge
234__secondary_hold_acknowledge:
235 .long -1
236
14cf11af
PM
237/* System reset */
238/* core99 pmac starts the seconary here by changing the vector, and
6c6aee00 239 putting it back to what it was (unknown_async_exception) when done. */
7fab6397 240 EXCEPTION(INTERRUPT_SYSTEM_RESET, Reset, unknown_async_exception)
14cf11af
PM
241
242/* Machine check */
243/*
244 * On CHRP, this is complicated by the fact that we could get a
245 * machine check inside RTAS, and we have no guarantee that certain
246 * critical registers will have the values we expect. The set of
247 * registers that might have bad values includes all the GPRs
248 * and all the BATs. We indicate that we are in RTAS by putting
249 * a non-zero value, the address of the exception frame to use,
0df977ea
CL
250 * in thread.rtas_sp. The machine check handler checks thread.rtas_sp
251 * and uses its value if it is non-zero.
14cf11af
PM
252 * (Other exception handlers assume that r1 is a valid kernel stack
253 * pointer when we take an exception from supervisor mode.)
254 * -- paulus.
255 */
7fab6397 256 START_EXCEPTION(INTERRUPT_MACHINE_CHECK, MachineCheck)
1f1c4d01 257 EXCEPTION_PROLOG_0
14cf11af 258#ifdef CONFIG_PPC_CHRP
98bf2d3f
CL
259 mtspr SPRN_SPRG_SCRATCH2,r1
260 mfspr r1, SPRN_SPRG_THREAD
261 lwz r1, RTAS_SP(r1)
262 cmpwi cr1, r1, 0
263 bne cr1, 7f
264 mfspr r1, SPRN_SPRG_SCRATCH2
14cf11af 265#endif /* CONFIG_PPC_CHRP */
7aa8dd67 266 EXCEPTION_PROLOG_1
719e7e21 2677: EXCEPTION_PROLOG_2 0x200 MachineCheck
14cf11af 268#ifdef CONFIG_PPC_CHRP
dc13b889 269 beq cr1, 1f
32746dfe 270 twi 31, 0, 0
14cf11af 271#endif
4c0104a8
CL
2721: prepare_transfer_to_handler
273 bl machine_check_exception
274 b interrupt_return
14cf11af
PM
275
276/* Data access exception. */
7fab6397 277 START_EXCEPTION(INTERRUPT_DATA_STORAGE, DataAccess)
259149cf 278#ifdef CONFIG_PPC_BOOK3S_604
232ca1ee 279BEGIN_MMU_FTR_SECTION
de1cd079
CL
280 mtspr SPRN_SPRG_SCRATCH2,r10
281 mfspr r10, SPRN_SPRG_THREAD
232ca1ee
CL
282 stw r11, THR11(r10)
283 mfspr r10, SPRN_DSISR
284 mfcr r11
232ca1ee 285 andis. r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH)@h
232ca1ee
CL
286 mfspr r10, SPRN_SPRG_THREAD
287 beq hash_page_dsi
288.Lhash_page_dsi_cont:
289 mtcr r11
290 lwz r11, THR11(r10)
de1cd079
CL
291 mfspr r10, SPRN_SPRG_SCRATCH2
292MMU_FTR_SECTION_ELSE
293 b 1f
294ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
259149cf 295#endif
de1cd079 2961: EXCEPTION_PROLOG_0 handle_dar_dsisr=1
232ca1ee 297 EXCEPTION_PROLOG_1
7fab6397 298 EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataAccess handle_dar_dsisr=1
4c0104a8 299 prepare_transfer_to_handler
62376365 300 lwz r5, _DSISR(r1)
dc13b889
CL
301 andis. r0, r5, DSISR_DABRMATCH@h
302 bne- 1f
4c0104a8
CL
303 bl do_page_fault
304 b interrupt_return
3051: bl do_break
8f6ff5bd
CL
306 REST_NVGPRS(r1)
307 b interrupt_return
dc13b889 308
14cf11af
PM
309
310/* Instruction access exception. */
7fab6397 311 START_EXCEPTION(INTERRUPT_INST_STORAGE, InstructionAccess)
232ca1ee
CL
312 mtspr SPRN_SPRG_SCRATCH0,r10
313 mtspr SPRN_SPRG_SCRATCH1,r11
314 mfspr r10, SPRN_SPRG_THREAD
315 mfspr r11, SPRN_SRR0
316 stw r11, SRR0(r10)
317 mfspr r11, SPRN_SRR1 /* check whether user or kernel */
318 stw r11, SRR1(r10)
319 mfcr r10
259149cf 320#ifdef CONFIG_PPC_BOOK3S_604
232ca1ee
CL
321BEGIN_MMU_FTR_SECTION
322 andis. r11, r11, SRR1_ISI_NOPT@h /* no pte found? */
323 bne hash_page_isi
324.Lhash_page_isi_cont:
325 mfspr r11, SPRN_SRR1 /* check whether user or kernel */
326END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
259149cf 327#endif
232ca1ee
CL
328 andi. r11, r11, MSR_PR
329
330 EXCEPTION_PROLOG_1
7fab6397 331 EXCEPTION_PROLOG_2 INTERRUPT_INST_STORAGE InstructionAccess
b4c001dc 332 andis. r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */
a01a3f2d
NP
333 stw r5, _DSISR(r11)
334 stw r12, _DAR(r11)
4c0104a8
CL
335 prepare_transfer_to_handler
336 bl do_page_fault
337 b interrupt_return
14cf11af 338
14cf11af 339/* External interrupt */
7fab6397 340 EXCEPTION(INTERRUPT_EXTERNAL, HardwareInterrupt, do_IRQ)
14cf11af
PM
341
342/* Alignment exception */
7fab6397
CL
343 START_EXCEPTION(INTERRUPT_ALIGNMENT, Alignment)
344 EXCEPTION_PROLOG INTERRUPT_ALIGNMENT Alignment handle_dar_dsisr=1
8f6ff5bd
CL
345 prepare_transfer_to_handler
346 bl alignment_exception
347 REST_NVGPRS(r1)
348 b interrupt_return
14cf11af
PM
349
350/* Program check exception */
7fab6397
CL
351 START_EXCEPTION(INTERRUPT_PROGRAM, ProgramCheck)
352 EXCEPTION_PROLOG INTERRUPT_PROGRAM ProgramCheck
8f6ff5bd
CL
353 prepare_transfer_to_handler
354 bl program_check_exception
355 REST_NVGPRS(r1)
356 b interrupt_return
14cf11af
PM
357
358/* Floating-point unavailable */
7bf1d7e1 359 START_EXCEPTION(0x800, FPUnavailable)
7d68c891 360#ifdef CONFIG_PPC_FPU
aa42c69c
KP
361BEGIN_FTR_SECTION
362/*
363 * Certain Freescale cores don't have a FPU and treat fp instructions
364 * as a FP Unavailable exception. Redirect to illegal/emulation handling.
365 */
366 b ProgramCheck
367END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE)
7fab6397 368 EXCEPTION_PROLOG INTERRUPT_FP_UNAVAIL FPUnavailable
6f3d8e69
MN
369 beq 1f
370 bl load_up_fpu /* if from user, just load it up */
371 b fast_exception_return
4c0104a8
CL
3721: prepare_transfer_to_handler
373 bl kernel_fp_unavailable_exception
374 b interrupt_return
7d68c891
CL
375#else
376 b ProgramCheck
377#endif
14cf11af
PM
378
379/* Decrementer */
7fab6397 380 EXCEPTION(INTERRUPT_DECREMENTER, Decrementer, timer_interrupt)
14cf11af 381
acc142b6
CL
382 EXCEPTION(0xa00, Trap_0a, unknown_exception)
383 EXCEPTION(0xb00, Trap_0b, unknown_exception)
14cf11af
PM
384
385/* System call */
7fab6397
CL
386 START_EXCEPTION(INTERRUPT_SYSCALL, SystemCall)
387 SYSCALL_ENTRY INTERRUPT_SYSCALL
14cf11af 388
7fab6397 389 EXCEPTION(INTERRUPT_TRACE, SingleStep, single_step_exception)
acc142b6 390 EXCEPTION(0xe00, Trap_0e, unknown_exception)
14cf11af
PM
391
392/*
393 * The Altivec unavailable trap is at 0x0f20. Foo.
394 * We effectively remap it to 0x3000.
395 * We include an altivec unavailable exception vector even if
396 * not configured for Altivec, so that you can't panic a
397 * non-altivec kernel running on a machine with altivec just
398 * by executing an altivec instruction.
399 */
7fab6397 400 START_EXCEPTION(INTERRUPT_PERFMON, PerformanceMonitorTrap)
555d97ac 401 b PerformanceMonitor
14cf11af 402
7fab6397 403 START_EXCEPTION(INTERRUPT_ALTIVEC_UNAVAIL, AltiVecUnavailableTrap)
14cf11af
PM
404 b AltiVecUnavailable
405
dc13b889 406 __HEAD
14cf11af
PM
407/*
408 * Handle TLB miss for instruction on 603/603e.
409 * Note: we get an alternate set of r0 - r3 to use automatically.
410 */
7fab6397 411 . = INTERRUPT_INST_TLB_MISS_603
14cf11af
PM
412InstructionTLBMiss:
413/*
00fcb147 414 * r0: scratch
14cf11af
PM
415 * r1: linux style pte ( later becomes ppc hardware pte )
416 * r2: ptr to linux-style pte
417 * r3: scratch
418 */
14cf11af
PM
419 /* Get PTE (linux-style) and check access */
420 mfspr r3,SPRN_IMISS
2a0fb3c1 421#ifdef CONFIG_MODULES
f1a1f7a1 422 lis r1, TASK_SIZE@h /* check if kernel address */
8a13c4f9 423 cmplw 0,r1,r3
a8a12199 424#endif
c4a22611 425 mfspr r2, SPRN_SDR1
c119565a 426 li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC | _PAGE_USER
c4a22611 427 rlwinm r2, r2, 28, 0xfffff000
2a0fb3c1 428#ifdef CONFIG_MODULES
f1a1f7a1 429 bgt- 112f
2c12393f 430 lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
c119565a 431 li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
2c12393f 432 addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
a8a12199 433#endif
93c4a162 434112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
14cf11af
PM
435 lwz r2,0(r2) /* get pmd entry */
436 rlwinm. r2,r2,0,0,19 /* extract address of pte page */
437 beq- InstructionAddressInvalid /* return if no mapping */
438 rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
eb3436a0
KG
439 lwz r0,0(r2) /* get linux-style pte */
440 andc. r1,r1,r0 /* check access & ~permission */
14cf11af 441 bne- InstructionAddressInvalid /* return if access not permitted */
14cf11af 442 /* Convert linux-style PTE to low word of PPC-style PTE */
40bb0e90 443 rlwimi r0,r0,32-2,31,31 /* _PAGE_USER -> PP lsb */
f342adca
CL
444 ori r1, r1, 0xe06 /* clear out reserved bits */
445 andc r1, r0, r1 /* PP = user? 1 : 0 */
345953cf
KG
446BEGIN_FTR_SECTION
447 rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */
448END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
14cf11af 449 mtspr SPRN_RPA,r1
14cf11af
PM
450 tlbli r3
451 mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
452 mtcrf 0x80,r3
453 rfi
454InstructionAddressInvalid:
455 mfspr r3,SPRN_SRR1
456 rlwinm r1,r3,9,6,6 /* Get load/store bit */
457
458 addis r1,r1,0x2000
459 mtspr SPRN_DSISR,r1 /* (shouldn't be needed) */
14cf11af
PM
460 andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
461 or r2,r2,r1
462 mtspr SPRN_SRR1,r2
463 mfspr r1,SPRN_IMISS /* Get failing address */
464 rlwinm. r2,r2,0,31,31 /* Check for little endian access */
465 rlwimi r2,r2,1,30,30 /* change 1 -> 3 */
466 xor r1,r1,r2
467 mtspr SPRN_DAR,r1 /* Set fault address */
468 mfmsr r0 /* Restore "normal" registers */
469 xoris r0,r0,MSR_TGPR>>16
470 mtcrf 0x80,r3 /* Restore CR0 */
471 mtmsr r0
472 b InstructionAccess
473
474/*
475 * Handle TLB miss for DATA Load operation on 603/603e
476 */
7fab6397 477 . = INTERRUPT_DATA_LOAD_TLB_MISS_603
14cf11af
PM
478DataLoadTLBMiss:
479/*
00fcb147 480 * r0: scratch
14cf11af
PM
481 * r1: linux style pte ( later becomes ppc hardware pte )
482 * r2: ptr to linux-style pte
483 * r3: scratch
484 */
14cf11af
PM
485 /* Get PTE (linux-style) and check access */
486 mfspr r3,SPRN_DMISS
f1a1f7a1 487 lis r1, TASK_SIZE@h /* check if kernel address */
8a13c4f9 488 cmplw 0,r1,r3
c4a22611 489 mfspr r2, SPRN_SDR1
c119565a 490 li r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER
c4a22611 491 rlwinm r2, r2, 28, 0xfffff000
f1a1f7a1 492 bgt- 112f
2c12393f 493 lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
c119565a 494 li r1, _PAGE_PRESENT | _PAGE_ACCESSED
2c12393f 495 addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
93c4a162 496112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
14cf11af
PM
497 lwz r2,0(r2) /* get pmd entry */
498 rlwinm. r2,r2,0,0,19 /* extract address of pte page */
499 beq- DataAddressInvalid /* return if no mapping */
500 rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
eb3436a0
KG
501 lwz r0,0(r2) /* get linux-style pte */
502 andc. r1,r1,r0 /* check access & ~permission */
14cf11af 503 bne- DataAddressInvalid /* return if access not permitted */
14cf11af 504 /* Convert linux-style PTE to low word of PPC-style PTE */
40bb0e90
CL
505 rlwinm r1,r0,32-9,30,30 /* _PAGE_RW -> PP msb */
506 rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */
4634bf44 507 rlwimi r1,r0,32-3,24,24 /* _PAGE_RW -> _PAGE_DIRTY */
40bb0e90 508 rlwimi r0,r0,32-1,31,31 /* _PAGE_USER -> PP lsb */
4634bf44 509 xori r1,r1,_PAGE_DIRTY /* clear dirty when not rw */
a4bd6a93 510 ori r1,r1,0xe04 /* clear out reserved bits */
f342adca 511 andc r1,r0,r1 /* PP = user? rw? 1: 3: 0 */
345953cf
KG
512BEGIN_FTR_SECTION
513 rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */
514END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
14cf11af 515 mtspr SPRN_RPA,r1
2319f123
KG
516BEGIN_MMU_FTR_SECTION
517 li r0,1
ee43eb78 518 mfspr r1,SPRN_SPRG_603_LRU
2319f123
KG
519 rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */
520 slw r0,r0,r2
521 xor r1,r0,r1
522 srw r0,r1,r2
ee43eb78 523 mtspr SPRN_SPRG_603_LRU,r1
2319f123
KG
524 mfspr r2,SPRN_SRR1
525 rlwimi r2,r0,31-14,14,14
526 mtspr SPRN_SRR1,r2
70d6ebf8
CL
527 mtcrf 0x80,r2
528 tlbld r3
529 rfi
530MMU_FTR_SECTION_ELSE
531 mfspr r2,SPRN_SRR1 /* Need to restore CR0 */
532 mtcrf 0x80,r2
14cf11af 533 tlbld r3
14cf11af 534 rfi
70d6ebf8 535ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
14cf11af
PM
536DataAddressInvalid:
537 mfspr r3,SPRN_SRR1
538 rlwinm r1,r3,9,6,6 /* Get load/store bit */
539 addis r1,r1,0x2000
540 mtspr SPRN_DSISR,r1
14cf11af
PM
541 andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
542 mtspr SPRN_SRR1,r2
543 mfspr r1,SPRN_DMISS /* Get failing address */
544 rlwinm. r2,r2,0,31,31 /* Check for little endian access */
545 beq 20f /* Jump if big endian */
546 xori r1,r1,3
54720: mtspr SPRN_DAR,r1 /* Set fault address */
548 mfmsr r0 /* Restore "normal" registers */
549 xoris r0,r0,MSR_TGPR>>16
550 mtcrf 0x80,r3 /* Restore CR0 */
551 mtmsr r0
552 b DataAccess
553
554/*
555 * Handle TLB miss for DATA Store on 603/603e
556 */
7fab6397 557 . = INTERRUPT_DATA_STORE_TLB_MISS_603
14cf11af
PM
558DataStoreTLBMiss:
559/*
00fcb147 560 * r0: scratch
14cf11af
PM
561 * r1: linux style pte ( later becomes ppc hardware pte )
562 * r2: ptr to linux-style pte
563 * r3: scratch
564 */
14cf11af
PM
565 /* Get PTE (linux-style) and check access */
566 mfspr r3,SPRN_DMISS
f1a1f7a1 567 lis r1, TASK_SIZE@h /* check if kernel address */
8a13c4f9 568 cmplw 0,r1,r3
c4a22611 569 mfspr r2, SPRN_SDR1
c119565a 570 li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER
c4a22611 571 rlwinm r2, r2, 28, 0xfffff000
f1a1f7a1 572 bgt- 112f
2c12393f 573 lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
c119565a 574 li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
2c12393f 575 addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
93c4a162 576112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
14cf11af
PM
577 lwz r2,0(r2) /* get pmd entry */
578 rlwinm. r2,r2,0,0,19 /* extract address of pte page */
579 beq- DataAddressInvalid /* return if no mapping */
580 rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
eb3436a0
KG
581 lwz r0,0(r2) /* get linux-style pte */
582 andc. r1,r1,r0 /* check access & ~permission */
14cf11af 583 bne- DataAddressInvalid /* return if access not permitted */
14cf11af 584 /* Convert linux-style PTE to low word of PPC-style PTE */
40bb0e90 585 rlwimi r0,r0,32-2,31,31 /* _PAGE_USER -> PP lsb */
f342adca
CL
586 li r1,0xe06 /* clear out reserved bits & PP msb */
587 andc r1,r0,r1 /* PP = user? 1: 0 */
345953cf
KG
588BEGIN_FTR_SECTION
589 rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */
590END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
14cf11af 591 mtspr SPRN_RPA,r1
2319f123
KG
592 mfspr r2,SPRN_SRR1 /* Need to restore CR0 */
593 mtcrf 0x80,r2
594BEGIN_MMU_FTR_SECTION
595 li r0,1
ee43eb78 596 mfspr r1,SPRN_SPRG_603_LRU
2319f123
KG
597 rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */
598 slw r0,r0,r2
599 xor r1,r0,r1
600 srw r0,r1,r2
ee43eb78 601 mtspr SPRN_SPRG_603_LRU,r1
2319f123
KG
602 mfspr r2,SPRN_SRR1
603 rlwimi r2,r0,31-14,14,14
604 mtspr SPRN_SRR1,r2
70d6ebf8
CL
605 mtcrf 0x80,r2
606 tlbld r3
607 rfi
608MMU_FTR_SECTION_ELSE
609 mfspr r2,SPRN_SRR1 /* Need to restore CR0 */
610 mtcrf 0x80,r2
14cf11af 611 tlbld r3
14cf11af 612 rfi
70d6ebf8 613ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
14cf11af
PM
614
615#ifndef CONFIG_ALTIVEC
dc1c1ca3 616#define altivec_assist_exception unknown_exception
69eeff02
ME
617#endif
618
619#ifndef CONFIG_TAU_INT
6c6aee00 620#define TAUException unknown_async_exception
14cf11af
PM
621#endif
622
acc142b6
CL
623 EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception)
624 EXCEPTION(0x1400, SMI, SMIException)
625 EXCEPTION(0x1500, Trap_15, unknown_exception)
626 EXCEPTION(0x1600, Trap_16, altivec_assist_exception)
627 EXCEPTION(0x1700, Trap_17, TAUException)
628 EXCEPTION(0x1800, Trap_18, unknown_exception)
629 EXCEPTION(0x1900, Trap_19, unknown_exception)
630 EXCEPTION(0x1a00, Trap_1a, unknown_exception)
631 EXCEPTION(0x1b00, Trap_1b, unknown_exception)
632 EXCEPTION(0x1c00, Trap_1c, unknown_exception)
633 EXCEPTION(0x1d00, Trap_1d, unknown_exception)
634 EXCEPTION(0x1e00, Trap_1e, unknown_exception)
635 EXCEPTION(0x1f00, Trap_1f, unknown_exception)
636 EXCEPTION(0x2000, RunMode, RunModeException)
637 EXCEPTION(0x2100, Trap_21, unknown_exception)
638 EXCEPTION(0x2200, Trap_22, unknown_exception)
639 EXCEPTION(0x2300, Trap_23, unknown_exception)
640 EXCEPTION(0x2400, Trap_24, unknown_exception)
641 EXCEPTION(0x2500, Trap_25, unknown_exception)
642 EXCEPTION(0x2600, Trap_26, unknown_exception)
643 EXCEPTION(0x2700, Trap_27, unknown_exception)
644 EXCEPTION(0x2800, Trap_28, unknown_exception)
645 EXCEPTION(0x2900, Trap_29, unknown_exception)
646 EXCEPTION(0x2a00, Trap_2a, unknown_exception)
647 EXCEPTION(0x2b00, Trap_2b, unknown_exception)
648 EXCEPTION(0x2c00, Trap_2c, unknown_exception)
649 EXCEPTION(0x2d00, Trap_2d, unknown_exception)
650 EXCEPTION(0x2e00, Trap_2e, unknown_exception)
651 EXCEPTION(0x2f00, Trap_2f, unknown_exception)
14cf11af 652
dc13b889 653 __HEAD
14cf11af
PM
654 . = 0x3000
655
259149cf 656#ifdef CONFIG_PPC_BOOK3S_604
232ca1ee
CL
657.macro save_regs_thread thread
658 stw r0, THR0(\thread)
659 stw r3, THR3(\thread)
660 stw r4, THR4(\thread)
661 stw r5, THR5(\thread)
662 stw r6, THR6(\thread)
663 stw r8, THR8(\thread)
664 stw r9, THR9(\thread)
665 mflr r0
666 stw r0, THLR(\thread)
667 mfctr r0
668 stw r0, THCTR(\thread)
669.endm
670
671.macro restore_regs_thread thread
672 lwz r0, THLR(\thread)
673 mtlr r0
674 lwz r0, THCTR(\thread)
675 mtctr r0
676 lwz r0, THR0(\thread)
677 lwz r3, THR3(\thread)
678 lwz r4, THR4(\thread)
679 lwz r5, THR5(\thread)
680 lwz r6, THR6(\thread)
681 lwz r8, THR8(\thread)
682 lwz r9, THR9(\thread)
683.endm
684
685hash_page_dsi:
686 save_regs_thread r10
687 mfdsisr r3
688 mfdar r4
689 mfsrr0 r5
690 mfsrr1 r9
691 rlwinm r3, r3, 32 - 15, _PAGE_RW /* DSISR_STORE -> _PAGE_RW */
692 bl hash_page
693 mfspr r10, SPRN_SPRG_THREAD
694 restore_regs_thread r10
695 b .Lhash_page_dsi_cont
696
697hash_page_isi:
698 mr r11, r10
699 mfspr r10, SPRN_SPRG_THREAD
700 save_regs_thread r10
701 li r3, 0
702 lwz r4, SRR0(r10)
703 lwz r9, SRR1(r10)
704 bl hash_page
705 mfspr r10, SPRN_SPRG_THREAD
706 restore_regs_thread r10
707 mr r10, r11
708 b .Lhash_page_isi_cont
709
710 .globl fast_hash_page_return
711fast_hash_page_return:
712 andis. r10, r9, SRR1_ISI_NOPT@h /* Set on ISI, cleared on DSI */
713 mfspr r10, SPRN_SPRG_THREAD
714 restore_regs_thread r10
715 bne 1f
716
717 /* DSI */
718 mtcr r11
719 lwz r11, THR11(r10)
de1cd079 720 mfspr r10, SPRN_SPRG_SCRATCH2
120c0518 721 rfi
232ca1ee
CL
722
7231: /* ISI */
724 mtcr r11
725 mfspr r11, SPRN_SPRG_SCRATCH1
726 mfspr r10, SPRN_SPRG_SCRATCH0
120c0518 727 rfi
259149cf 728#endif /* CONFIG_PPC_BOOK3S_604 */
232ca1ee 729
7aa8dd67 730#ifdef CONFIG_VMAP_STACK
cd08f109 731 vmap_stack_overflow_exception
232ca1ee 732#endif
cd08f109 733
dc13b889 734 __HEAD
14cf11af 735AltiVecUnavailable:
719e7e21 736 EXCEPTION_PROLOG 0xf20 AltiVecUnavailable
14cf11af 737#ifdef CONFIG_ALTIVEC
37f9ef55
BH
738 beq 1f
739 bl load_up_altivec /* if from user, just load it up */
740 b fast_exception_return
14cf11af 741#endif /* CONFIG_ALTIVEC */
4c0104a8
CL
7421: prepare_transfer_to_handler
743 bl altivec_unavailable_exception
744 b interrupt_return
14cf11af 745
dc13b889 746 __HEAD
555d97ac 747PerformanceMonitor:
719e7e21 748 EXCEPTION_PROLOG 0xf00 PerformanceMonitor
4c0104a8
CL
749 prepare_transfer_to_handler
750 bl performance_monitor_exception
751 b interrupt_return
555d97ac 752
14cf11af 753
dc13b889 754 __HEAD
14cf11af
PM
755/*
756 * This code is jumped to from the startup code to copy
ccdcef72 757 * the kernel image to physical address PHYSICAL_START.
14cf11af
PM
758 */
759relocate_kernel:
ccdcef72 760 lis r3,PHYSICAL_START@h /* Destination base address */
14cf11af
PM
761 li r6,0 /* Destination offset */
762 li r5,0x4000 /* # bytes of memory to copy */
763 bl copy_and_flush /* copy the first 0x4000 bytes */
764 addi r0,r3,4f@l /* jump to the address of 4f */
765 mtctr r0 /* in copy and do the rest. */
766 bctr /* jump to the copy */
56afad88
CL
7674: lis r5,_end-KERNELBASE@h
768 ori r5,r5,_end-KERNELBASE@l
14cf11af
PM
769 bl copy_and_flush /* copy the rest */
770 b turn_on_mmu
771
772/*
773 * Copy routine used to copy the kernel to start at physical address 0
774 * and flush and invalidate the caches as needed.
775 * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
776 * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
777 */
27e21e8f 778_GLOBAL(copy_and_flush)
14cf11af
PM
779 addi r5,r5,-4
780 addi r6,r6,-4
7dffb720 7814: li r0,L1_CACHE_BYTES/4
14cf11af
PM
782 mtctr r0
7833: addi r6,r6,4 /* copy a cache line */
784 lwzx r0,r6,r4
785 stwx r0,r6,r3
786 bdnz 3b
787 dcbst r6,r3 /* write it to memory */
788 sync
789 icbi r6,r3 /* flush the icache line */
790 cmplw 0,r6,r5
791 blt 4b
792 sync /* additional sync needed on g4 */
793 isync
794 addi r5,r5,4
795 addi r6,r6,4
796 blr
797
14cf11af 798#ifdef CONFIG_SMP
ee0339f2
JL
799 .globl __secondary_start_mpc86xx
800__secondary_start_mpc86xx:
801 mfspr r3, SPRN_PIR
802 stw r3, __secondary_hold_acknowledge@l(0)
803 mr r24, r3 /* cpu # */
804 b __secondary_start
805
14cf11af
PM
806 .globl __secondary_start_pmac_0
807__secondary_start_pmac_0:
808 /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
809 li r24,0
810 b 1f
811 li r24,1
812 b 1f
813 li r24,2
814 b 1f
815 li r24,3
8161:
817 /* on powersurge, we come in here with IR=0 and DR=1, and DBAT 0
818 set to map the 0xf0000000 - 0xffffffff region */
819 mfmsr r0
820 rlwinm r0,r0,0,28,26 /* clear DR (0x10) */
14cf11af
PM
821 mtmsr r0
822 isync
823
824 .globl __secondary_start
825__secondary_start:
14cf11af
PM
826 /* Copy some CPU settings from CPU 0 */
827 bl __restore_cpu_setup
828
829 lis r3,-KERNELBASE@h
830 mr r4,r24
14cf11af 831 bl call_setup_cpu /* Call setup_cpu for this CPU */
14cf11af
PM
832 lis r3,-KERNELBASE@h
833 bl init_idle_6xx
14cf11af 834
4e67bfd7 835 /* get current's stack and current */
7c19c2e5
CL
836 lis r2,secondary_current@ha
837 tophys(r2,r2)
838 lwz r2,secondary_current@l(r2)
ed1cd6de
CL
839 tophys(r1,r2)
840 lwz r1,TASK_STACK(r1)
14cf11af
PM
841
842 /* stack */
843 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
844 li r0,0
845 tophys(r3,r1)
846 stw r0,0(r3)
847
848 /* load up the MMU */
b7f8b440 849 bl load_segment_registers
14cf11af
PM
850 bl load_up_mmu
851
852 /* ptr to phys current thread */
853 tophys(r4,r2)
854 addi r4,r4,THREAD /* phys address of our thread_struct */
ee43eb78 855 mtspr SPRN_SPRG_THREAD,r4
c4a22611 856BEGIN_MMU_FTR_SECTION
4622a2d4
CL
857 lis r4, (swapper_pg_dir - PAGE_OFFSET)@h
858 ori r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l
c4a22611
CL
859 rlwinm r4, r4, 4, 0xffff01ff
860 mtspr SPRN_SDR1, r4
861END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
14cf11af
PM
862
863 /* enable MMU and jump to start_secondary */
864 li r4,MSR_KERNEL
14cf11af
PM
865 lis r3,start_secondary@h
866 ori r3,r3,start_secondary@l
867 mtspr SPRN_SRR0,r3
868 mtspr SPRN_SRR1,r4
120c0518 869 rfi
14cf11af
PM
870#endif /* CONFIG_SMP */
871
dd84c217
AG
872#ifdef CONFIG_KVM_BOOK3S_HANDLER
873#include "../kvm/book3s_rmhandlers.S"
874#endif
875
14cf11af
PM
876/*
877 * Load stuff into the MMU. Intended to be called with
878 * IR=0 and DR=0.
879 */
215b8237
CL
880early_hash_table:
881 sync /* Force all PTE updates to finish */
882 isync
883 tlbia /* Clear all TLB entries */
884 sync /* wait for tlbia/tlbie to finish */
885 TLBSYNC /* ... on all CPUs */
886 /* Load the SDR1 register (hash table base & size) */
887 lis r6, early_hash - PAGE_OFFSET@h
888 ori r6, r6, 3 /* 256kB table */
889 mtspr SPRN_SDR1, r6
890 blr
215b8237 891
14cf11af
PM
892load_up_mmu:
893 sync /* Force all PTE updates to finish */
894 isync
895 tlbia /* Clear all TLB entries */
896 sync /* wait for tlbia/tlbie to finish */
897 TLBSYNC /* ... on all CPUs */
c4a22611 898BEGIN_MMU_FTR_SECTION
14cf11af
PM
899 /* Load the SDR1 register (hash table base & size) */
900 lis r6,_SDR1@ha
901 tophys(r6,r6)
902 lwz r6,_SDR1@l(r6)
903 mtspr SPRN_SDR1,r6
c4a22611 904END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
187a0067 905
8b14e1df 906/* Load the BAT registers with the values set up by MMU_init. */
14cf11af
PM
907 lis r3,BATS@ha
908 addi r3,r3,BATS@l
909 tophys(r3,r3)
910 LOAD_BAT(0,r3,r4,r5)
911 LOAD_BAT(1,r3,r4,r5)
912 LOAD_BAT(2,r3,r4,r5)
913 LOAD_BAT(3,r3,r4,r5)
7c03d653 914BEGIN_MMU_FTR_SECTION
ee0339f2
JL
915 LOAD_BAT(4,r3,r4,r5)
916 LOAD_BAT(5,r3,r4,r5)
917 LOAD_BAT(6,r3,r4,r5)
918 LOAD_BAT(7,r3,r4,r5)
7c03d653 919END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
14cf11af
PM
920 blr
921
2c637d2d 922_GLOBAL(load_segment_registers)
215b8237
CL
923 li r0, NUM_USER_SEGMENTS /* load up user segment register values */
924 mtctr r0 /* for context 0 */
526d4a4c
CL
925#ifdef CONFIG_PPC_KUEP
926 lis r3, SR_NX@h /* Kp = 0, Ks = 0, VSID = 0 */
927#else
215b8237 928 li r3, 0 /* Kp = 0, Ks = 0, VSID = 0 */
526d4a4c 929#endif
215b8237
CL
930 li r4, 0
9313: mtsrin r3, r4
932 addi r3, r3, 0x111 /* increment VSID */
933 addis r4, r4, 0x1000 /* address of next segment */
934 bdnz 3b
935 li r0, 16 - NUM_USER_SEGMENTS /* load up kernel segment registers */
936 mtctr r0 /* for context 0 */
937 rlwinm r3, r3, 0, ~SR_NX /* Nx = 0 */
938 rlwinm r3, r3, 0, ~SR_KS /* Ks = 0 */
939 oris r3, r3, SR_KP@h /* Kp = 1 */
9403: mtsrin r3, r4
941 addi r3, r3, 0x111 /* increment VSID */
942 addis r4, r4, 0x1000 /* address of next segment */
943 bdnz 3b
944 blr
945
14cf11af
PM
946/*
947 * This is where the main kernel code starts.
948 */
949start_here:
950 /* ptr to current */
951 lis r2,init_task@h
952 ori r2,r2,init_task@l
953 /* Set up for using our exception vectors */
954 /* ptr to phys current thread */
955 tophys(r4,r2)
956 addi r4,r4,THREAD /* init task's THREAD */
ee43eb78 957 mtspr SPRN_SPRG_THREAD,r4
c4a22611 958BEGIN_MMU_FTR_SECTION
4622a2d4
CL
959 lis r4, (swapper_pg_dir - PAGE_OFFSET)@h
960 ori r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l
c4a22611
CL
961 rlwinm r4, r4, 4, 0xffff01ff
962 mtspr SPRN_SDR1, r4
963END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
14cf11af
PM
964
965 /* stack */
966 lis r1,init_thread_union@ha
967 addi r1,r1,init_thread_union@l
968 li r0,0
969 stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
970/*
187a0067 971 * Do early platform-specific initialization,
14cf11af
PM
972 * and set up the MMU.
973 */
2edb16ef
CL
974#ifdef CONFIG_KASAN
975 bl kasan_early_init
976#endif
6dece0eb
SW
977 li r3,0
978 mr r4,r31
14cf11af 979 bl machine_init
22c841c9 980 bl __save_cpu_setup
14cf11af 981 bl MMU_init
72f208c6 982 bl MMU_init_hw_patch
14cf11af 983
14cf11af
PM
984/*
985 * Go back to running unmapped so we can load up new values
986 * for SDR1 (hash table pointer) and the segment registers
987 * and change to using our exception vectors.
988 */
989 lis r4,2f@h
990 ori r4,r4,2f@l
991 tophys(r4,r4)
992 li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
94dd54c5
CL
993
994 .align 4
14cf11af
PM
995 mtspr SPRN_SRR0,r4
996 mtspr SPRN_SRR1,r3
120c0518 997 rfi
14cf11af
PM
998/* Load up the kernel context */
9992: bl load_up_mmu
1000
1001#ifdef CONFIG_BDI_SWITCH
1002 /* Add helper information for the Abatron bdiGDB debugger.
1003 * We do this here because we know the mmu is disabled, and
1004 * will be enabled for real in just a few instructions.
1005 */
1006 lis r5, abatron_pteptrs@h
1007 ori r5, r5, abatron_pteptrs@l
b51ba4fe 1008 stw r5, 0xf0(0) /* This much match your Abatron config */
14cf11af
PM
1009 lis r6, swapper_pg_dir@h
1010 ori r6, r6, swapper_pg_dir@l
1011 tophys(r5, r5)
1012 stw r6, 0(r5)
1013#endif /* CONFIG_BDI_SWITCH */
1014
1015/* Now turn on the MMU for real! */
1016 li r4,MSR_KERNEL
14cf11af
PM
1017 lis r3,start_kernel@h
1018 ori r3,r3,start_kernel@l
1019 mtspr SPRN_SRR0,r3
1020 mtspr SPRN_SRR1,r4
120c0518 1021 rfi
14cf11af 1022
14cf11af
PM
1023/*
1024 * An undocumented "feature" of 604e requires that the v bit
1025 * be cleared before changing BAT values.
1026 *
1027 * Also, newer IBM firmware does not clear bat3 and 4 so
1028 * this makes sure it's done.
1029 * -- Cort
1030 */
1031clear_bats:
1032 li r10,0
14cf11af
PM
1033
1034 mtspr SPRN_DBAT0U,r10
1035 mtspr SPRN_DBAT0L,r10
1036 mtspr SPRN_DBAT1U,r10
1037 mtspr SPRN_DBAT1L,r10
1038 mtspr SPRN_DBAT2U,r10
1039 mtspr SPRN_DBAT2L,r10
1040 mtspr SPRN_DBAT3U,r10
1041 mtspr SPRN_DBAT3L,r10
14cf11af
PM
1042 mtspr SPRN_IBAT0U,r10
1043 mtspr SPRN_IBAT0L,r10
1044 mtspr SPRN_IBAT1U,r10
1045 mtspr SPRN_IBAT1L,r10
1046 mtspr SPRN_IBAT2U,r10
1047 mtspr SPRN_IBAT2L,r10
1048 mtspr SPRN_IBAT3U,r10
1049 mtspr SPRN_IBAT3L,r10
7c03d653 1050BEGIN_MMU_FTR_SECTION
14cf11af
PM
1051 /* Here's a tweak: at this point, CPU setup have
1052 * not been called yet, so HIGH_BAT_EN may not be
1053 * set in HID0 for the 745x processors. However, it
1054 * seems that doesn't affect our ability to actually
1055 * write to these SPRs.
1056 */
1057 mtspr SPRN_DBAT4U,r10
1058 mtspr SPRN_DBAT4L,r10
1059 mtspr SPRN_DBAT5U,r10
1060 mtspr SPRN_DBAT5L,r10
1061 mtspr SPRN_DBAT6U,r10
1062 mtspr SPRN_DBAT6L,r10
1063 mtspr SPRN_DBAT7U,r10
1064 mtspr SPRN_DBAT7L,r10
1065 mtspr SPRN_IBAT4U,r10
1066 mtspr SPRN_IBAT4L,r10
1067 mtspr SPRN_IBAT5U,r10
1068 mtspr SPRN_IBAT5L,r10
1069 mtspr SPRN_IBAT6U,r10
1070 mtspr SPRN_IBAT6L,r10
1071 mtspr SPRN_IBAT7U,r10
1072 mtspr SPRN_IBAT7L,r10
7c03d653 1073END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
14cf11af
PM
1074 blr
1075
27e21e8f 1076_GLOBAL(update_bats)
5e04ae85
CL
1077 lis r4, 1f@h
1078 ori r4, r4, 1f@l
1079 tophys(r4, r4)
1080 mfmsr r6
1081 mflr r7
1082 li r3, MSR_KERNEL & ~(MSR_IR | MSR_DR)
1083 rlwinm r0, r6, 0, ~MSR_RI
1084 rlwinm r0, r0, 0, ~MSR_EE
1085 mtmsr r0
94dd54c5
CL
1086
1087 .align 4
5e04ae85
CL
1088 mtspr SPRN_SRR0, r4
1089 mtspr SPRN_SRR1, r3
120c0518 1090 rfi
5e04ae85
CL
10911: bl clear_bats
1092 lis r3, BATS@ha
1093 addi r3, r3, BATS@l
1094 tophys(r3, r3)
1095 LOAD_BAT(0, r3, r4, r5)
1096 LOAD_BAT(1, r3, r4, r5)
1097 LOAD_BAT(2, r3, r4, r5)
1098 LOAD_BAT(3, r3, r4, r5)
1099BEGIN_MMU_FTR_SECTION
1100 LOAD_BAT(4, r3, r4, r5)
1101 LOAD_BAT(5, r3, r4, r5)
1102 LOAD_BAT(6, r3, r4, r5)
1103 LOAD_BAT(7, r3, r4, r5)
1104END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
1105 li r3, MSR_KERNEL & ~(MSR_IR | MSR_DR | MSR_RI)
1106 mtmsr r3
1107 mtspr SPRN_SRR0, r7
1108 mtspr SPRN_SRR1, r6
120c0518 1109 rfi
5e04ae85 1110
14cf11af
PM
1111flush_tlbs:
1112 lis r10, 0x40
11131: addic. r10, r10, -0x1000
1114 tlbie r10
9acd57ca 1115 bgt 1b
14cf11af
PM
1116 sync
1117 blr
1118
1119mmu_off:
1120 addi r4, r3, __after_mmu_off - _start
1121 mfmsr r3
1122 andi. r0,r3,MSR_DR|MSR_IR /* MMU enabled? */
1123 beqlr
1124 andc r3,r3,r0
94dd54c5
CL
1125
1126 .align 4
14cf11af
PM
1127 mtspr SPRN_SRR0,r4
1128 mtspr SPRN_SRR1,r3
1129 sync
120c0518 1130 rfi
14cf11af 1131
8b14e1df 1132/* We use one BAT to map up to 256M of RAM at _PAGE_OFFSET */
14cf11af 1133initial_bats:
ccdcef72 1134 lis r11,PAGE_OFFSET@h
39097b9c 1135 tophys(r8,r11)
14cf11af
PM
1136#ifdef CONFIG_SMP
1137 ori r8,r8,0x12 /* R/W access, M=1 */
1138#else
1139 ori r8,r8,2 /* R/W access */
1140#endif /* CONFIG_SMP */
14cf11af 1141 ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
14cf11af 1142
8b14e1df 1143 mtspr SPRN_DBAT0L,r8 /* N.B. 6xx have valid */
14cf11af
PM
1144 mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
1145 mtspr SPRN_IBAT0L,r8
1146 mtspr SPRN_IBAT0U,r11
1147 isync
1148 blr
1149
f21f49ea 1150#ifdef CONFIG_BOOTX_TEXT
51d3082f
BH
1151setup_disp_bat:
1152 /*
1153 * setup the display bat prepared for us in prom.c
1154 */
1155 mflr r8
1156 bl reloc_offset
1157 mtlr r8
1158 addis r8,r3,disp_BAT@ha
1159 addi r8,r8,disp_BAT@l
1160 cmpwi cr0,r8,0
1161 beqlr
1162 lwz r11,0(r8)
1163 lwz r8,4(r8)
51d3082f
BH
1164 mtspr SPRN_DBAT3L,r8
1165 mtspr SPRN_DBAT3U,r11
51d3082f 1166 blr
f21f49ea 1167#endif /* CONFIG_BOOTX_TEXT */
51d3082f 1168
c374e00e
SW
1169#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
1170setup_cpm_bat:
1171 lis r8, 0xf000
1172 ori r8, r8, 0x002a
1173 mtspr SPRN_DBAT1L, r8
1174
1175 lis r11, 0xf000
1176 ori r11, r11, (BL_1M << 2) | 2
1177 mtspr SPRN_DBAT1U, r11
1178
1179 blr
1180#endif
1181
d1d56f8c
AH
1182#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
1183setup_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#endif
1203
14cf11af 1204 .data