~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/kernel/head_book3s_32.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php