Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  *  PowerPC version
0004  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
0005  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
0006  *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
0007  *  Low-level exception handlers and MMU support
0008  *  rewritten by Paul Mackerras.
0009  *    Copyright (C) 1996 Paul Mackerras.
0010  *  MPC8xx modifications by Dan Malek
0011  *    Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
0012  *
0013  *  This file contains low-level support and setup for PowerPC 8xx
0014  *  embedded processors, including trap and interrupt dispatch.
0015  */
0016 
0017 #include <linux/init.h>
0018 #include <linux/magic.h>
0019 #include <linux/pgtable.h>
0020 #include <linux/sizes.h>
0021 #include <asm/processor.h>
0022 #include <asm/page.h>
0023 #include <asm/mmu.h>
0024 #include <asm/cache.h>
0025 #include <asm/cputable.h>
0026 #include <asm/thread_info.h>
0027 #include <asm/ppc_asm.h>
0028 #include <asm/asm-offsets.h>
0029 #include <asm/ptrace.h>
0030 #include <asm/export.h>
0031 #include <asm/code-patching-asm.h>
0032 #include <asm/interrupt.h>
0033 
0034 /*
0035  * Value for the bits that have fixed value in RPN entries.
0036  * Also used for tagging DAR for DTLBerror.
0037  */
0038 #define RPN_PATTERN 0x00f0
0039 
0040 #include "head_32.h"
0041 
0042 .macro compare_to_kernel_boundary scratch, addr
0043 #if CONFIG_TASK_SIZE <= 0x80000000 && CONFIG_PAGE_OFFSET >= 0x80000000
0044 /* By simply checking Address >= 0x80000000, we know if its a kernel address */
0045     not.    \scratch, \addr
0046 #else
0047     rlwinm  \scratch, \addr, 16, 0xfff8
0048     cmpli   cr0, \scratch, PAGE_OFFSET@h
0049 #endif
0050 .endm
0051 
0052 #define PAGE_SHIFT_512K     19
0053 #define PAGE_SHIFT_8M       23
0054 
0055     __HEAD
0056 _GLOBAL(_stext);
0057 _GLOBAL(_start);
0058 
0059 /* MPC8xx
0060  * This port was done on an MBX board with an 860.  Right now I only
0061  * support an ELF compressed (zImage) boot from EPPC-Bug because the
0062  * code there loads up some registers before calling us:
0063  *   r3: ptr to board info data
0064  *   r4: initrd_start or if no initrd then 0
0065  *   r5: initrd_end - unused if r4 is 0
0066  *   r6: Start of command line string
0067  *   r7: End of command line string
0068  *
0069  * I decided to use conditional compilation instead of checking PVR and
0070  * adding more processor specific branches around code I don't need.
0071  * Since this is an embedded processor, I also appreciate any memory
0072  * savings I can get.
0073  *
0074  * The MPC8xx does not have any BATs, but it supports large page sizes.
0075  * We first initialize the MMU to support 8M byte pages, then load one
0076  * entry into each of the instruction and data TLBs to map the first
0077  * 8M 1:1.  I also mapped an additional I/O space 1:1 so we can get to
0078  * the "internal" processor registers before MMU_init is called.
0079  *
0080  *  -- Dan
0081  */
0082     .globl  __start
0083 __start:
0084     mr  r31,r3          /* save device tree ptr */
0085 
0086     /* We have to turn on the MMU right away so we get cache modes
0087      * set correctly.
0088      */
0089     bl  initial_mmu
0090 
0091 /* We now have the lower 8 Meg mapped into TLB entries, and the caches
0092  * ready to work.
0093  */
0094 
0095 turn_on_mmu:
0096     mfmsr   r0
0097     ori r0,r0,MSR_DR|MSR_IR
0098     mtspr   SPRN_SRR1,r0
0099     lis r0,start_here@h
0100     ori r0,r0,start_here@l
0101     mtspr   SPRN_SRR0,r0
0102     rfi             /* enables MMU */
0103 
0104 
0105 #ifdef CONFIG_PERF_EVENTS
0106     .align  4
0107 
0108     .globl  itlb_miss_counter
0109 itlb_miss_counter:
0110     .space  4
0111 
0112     .globl  dtlb_miss_counter
0113 dtlb_miss_counter:
0114     .space  4
0115 
0116     .globl  instruction_counter
0117 instruction_counter:
0118     .space  4
0119 #endif
0120 
0121 /* System reset */
0122     EXCEPTION(INTERRUPT_SYSTEM_RESET, Reset, system_reset_exception)
0123 
0124 /* Machine check */
0125     START_EXCEPTION(INTERRUPT_MACHINE_CHECK, MachineCheck)
0126     EXCEPTION_PROLOG INTERRUPT_MACHINE_CHECK MachineCheck handle_dar_dsisr=1
0127     prepare_transfer_to_handler
0128     bl  machine_check_exception
0129     b   interrupt_return
0130 
0131 /* External interrupt */
0132     EXCEPTION(INTERRUPT_EXTERNAL, HardwareInterrupt, do_IRQ)
0133 
0134 /* Alignment exception */
0135     START_EXCEPTION(INTERRUPT_ALIGNMENT, Alignment)
0136     EXCEPTION_PROLOG INTERRUPT_ALIGNMENT Alignment handle_dar_dsisr=1
0137     prepare_transfer_to_handler
0138     bl  alignment_exception
0139     REST_NVGPRS(r1)
0140     b   interrupt_return
0141 
0142 /* Program check exception */
0143     START_EXCEPTION(INTERRUPT_PROGRAM, ProgramCheck)
0144     EXCEPTION_PROLOG INTERRUPT_PROGRAM ProgramCheck
0145     prepare_transfer_to_handler
0146     bl  program_check_exception
0147     REST_NVGPRS(r1)
0148     b   interrupt_return
0149 
0150 /* Decrementer */
0151     EXCEPTION(INTERRUPT_DECREMENTER, Decrementer, timer_interrupt)
0152 
0153 /* System call */
0154     START_EXCEPTION(INTERRUPT_SYSCALL, SystemCall)
0155     SYSCALL_ENTRY   INTERRUPT_SYSCALL
0156 
0157 /* Single step - not used on 601 */
0158     EXCEPTION(INTERRUPT_TRACE, SingleStep, single_step_exception)
0159 
0160 /* On the MPC8xx, this is a software emulation interrupt.  It occurs
0161  * for all unimplemented and illegal instructions.
0162  */
0163     START_EXCEPTION(INTERRUPT_SOFT_EMU_8xx, SoftEmu)
0164     EXCEPTION_PROLOG INTERRUPT_SOFT_EMU_8xx SoftEmu
0165     prepare_transfer_to_handler
0166     bl  emulation_assist_interrupt
0167     REST_NVGPRS(r1)
0168     b   interrupt_return
0169 
0170 /*
0171  * For the MPC8xx, this is a software tablewalk to load the instruction
0172  * TLB.  The task switch loads the M_TWB register with the pointer to the first
0173  * level table.
0174  * If we discover there is no second level table (value is zero) or if there
0175  * is an invalid pte, we load that into the TLB, which causes another fault
0176  * into the TLB Error interrupt where we can handle such problems.
0177  * We have to use the MD_xxx registers for the tablewalk because the
0178  * equivalent MI_xxx registers only perform the attribute functions.
0179  */
0180 
0181 #ifdef CONFIG_8xx_CPU15
0182 #define INVALIDATE_ADJACENT_PAGES_CPU15(addr, tmp)  \
0183     addi    tmp, addr, PAGE_SIZE;   \
0184     tlbie   tmp;            \
0185     addi    tmp, addr, -PAGE_SIZE;  \
0186     tlbie   tmp
0187 #else
0188 #define INVALIDATE_ADJACENT_PAGES_CPU15(addr, tmp)
0189 #endif
0190 
0191     START_EXCEPTION(INTERRUPT_INST_TLB_MISS_8xx, InstructionTLBMiss)
0192     mtspr   SPRN_SPRG_SCRATCH2, r10
0193     mtspr   SPRN_M_TW, r11
0194 
0195     /* If we are faulting a kernel address, we have to use the
0196      * kernel page tables.
0197      */
0198     mfspr   r10, SPRN_SRR0  /* Get effective address of fault */
0199     INVALIDATE_ADJACENT_PAGES_CPU15(r10, r11)
0200     mtspr   SPRN_MD_EPN, r10
0201 #ifdef CONFIG_MODULES
0202     mfcr    r11
0203     compare_to_kernel_boundary r10, r10
0204 #endif
0205     mfspr   r10, SPRN_M_TWB /* Get level 1 table */
0206 #ifdef CONFIG_MODULES
0207     blt+    3f
0208     rlwinm  r10, r10, 0, 20, 31
0209     oris    r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha
0210 3:
0211     mtcr    r11
0212 #endif
0213     lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10)    /* Get level 1 entry */
0214     mtspr   SPRN_MD_TWC, r11
0215     mfspr   r10, SPRN_MD_TWC
0216     lwz r10, 0(r10) /* Get the pte */
0217     rlwimi  r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
0218     rlwimi  r11, r10, 32 - 9, _PMD_PAGE_512K
0219     mtspr   SPRN_MI_TWC, r11
0220     /* The Linux PTE won't go exactly into the MMU TLB.
0221      * Software indicator bits 20 and 23 must be clear.
0222      * Software indicator bits 22, 24, 25, 26, and 27 must be
0223      * set.  All other Linux PTE bits control the behavior
0224      * of the MMU.
0225      */
0226     rlwinm  r10, r10, 0, ~0x0f00    /* Clear bits 20-23 */
0227     rlwimi  r10, r10, 4, 0x0400 /* Copy _PAGE_EXEC into bit 21 */
0228     ori r10, r10, RPN_PATTERN | 0x200 /* Set 22 and 24-27 */
0229     mtspr   SPRN_MI_RPN, r10    /* Update TLB entry */
0230 
0231     /* Restore registers */
0232 0:  mfspr   r10, SPRN_SPRG_SCRATCH2
0233     mfspr   r11, SPRN_M_TW
0234     rfi
0235     patch_site  0b, patch__itlbmiss_exit_1
0236 
0237 #ifdef CONFIG_PERF_EVENTS
0238     patch_site  0f, patch__itlbmiss_perf
0239 0:  lwz r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
0240     addi    r10, r10, 1
0241     stw r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
0242     mfspr   r10, SPRN_SPRG_SCRATCH2
0243     mfspr   r11, SPRN_M_TW
0244     rfi
0245 #endif
0246 
0247     START_EXCEPTION(INTERRUPT_DATA_TLB_MISS_8xx, DataStoreTLBMiss)
0248     mtspr   SPRN_SPRG_SCRATCH2, r10
0249     mtspr   SPRN_M_TW, r11
0250     mfcr    r11
0251 
0252     /* If we are faulting a kernel address, we have to use the
0253      * kernel page tables.
0254      */
0255     mfspr   r10, SPRN_MD_EPN
0256     compare_to_kernel_boundary r10, r10
0257     mfspr   r10, SPRN_M_TWB /* Get level 1 table */
0258     blt+    3f
0259     rlwinm  r10, r10, 0, 20, 31
0260     oris    r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha
0261 3:
0262     mtcr    r11
0263     lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10)    /* Get level 1 entry */
0264 
0265     mtspr   SPRN_MD_TWC, r11
0266     mfspr   r10, SPRN_MD_TWC
0267     lwz r10, 0(r10) /* Get the pte */
0268 
0269     /* Insert Guarded and Accessed flags into the TWC from the Linux PTE.
0270      * It is bit 27 of both the Linux PTE and the TWC (at least
0271      * I got that right :-).  It will be better when we can put
0272      * this into the Linux pgd/pmd and load it in the operation
0273      * above.
0274      */
0275     rlwimi  r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
0276     rlwimi  r11, r10, 32 - 9, _PMD_PAGE_512K
0277     mtspr   SPRN_MD_TWC, r11
0278 
0279     /* The Linux PTE won't go exactly into the MMU TLB.
0280      * Software indicator bits 24, 25, 26, and 27 must be
0281      * set.  All other Linux PTE bits control the behavior
0282      * of the MMU.
0283      */
0284     li  r11, RPN_PATTERN
0285     rlwimi  r10, r11, 0, 24, 27 /* Set 24-27 */
0286     mtspr   SPRN_MD_RPN, r10    /* Update TLB entry */
0287     mtspr   SPRN_DAR, r11       /* Tag DAR */
0288 
0289     /* Restore registers */
0290 
0291 0:  mfspr   r10, SPRN_SPRG_SCRATCH2
0292     mfspr   r11, SPRN_M_TW
0293     rfi
0294     patch_site  0b, patch__dtlbmiss_exit_1
0295 
0296 #ifdef CONFIG_PERF_EVENTS
0297     patch_site  0f, patch__dtlbmiss_perf
0298 0:  lwz r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
0299     addi    r10, r10, 1
0300     stw r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
0301     mfspr   r10, SPRN_SPRG_SCRATCH2
0302     mfspr   r11, SPRN_M_TW
0303     rfi
0304 #endif
0305 
0306 /* This is an instruction TLB error on the MPC8xx.  This could be due
0307  * to many reasons, such as executing guarded memory or illegal instruction
0308  * addresses.  There is nothing to do but handle a big time error fault.
0309  */
0310     START_EXCEPTION(INTERRUPT_INST_TLB_ERROR_8xx, InstructionTLBError)
0311     /* 0x400 is InstructionAccess exception, needed by bad_page_fault() */
0312     EXCEPTION_PROLOG INTERRUPT_INST_STORAGE InstructionTLBError
0313     andis.  r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */
0314     andis.  r10,r9,SRR1_ISI_NOPT@h
0315     beq+    .Litlbie
0316     tlbie   r12
0317 .Litlbie:
0318     stw r12, _DAR(r11)
0319     stw r5, _DSISR(r11)
0320     prepare_transfer_to_handler
0321     bl  do_page_fault
0322     b   interrupt_return
0323 
0324 /* This is the data TLB error on the MPC8xx.  This could be due to
0325  * many reasons, including a dirty update to a pte.  We bail out to
0326  * a higher level function that can handle it.
0327  */
0328     START_EXCEPTION(INTERRUPT_DATA_TLB_ERROR_8xx, DataTLBError)
0329     EXCEPTION_PROLOG_0 handle_dar_dsisr=1
0330     mfspr   r11, SPRN_DAR
0331     cmpwi   cr1, r11, RPN_PATTERN
0332     beq-    cr1, FixupDAR   /* must be a buggy dcbX, icbi insn. */
0333 DARFixed:/* Return from dcbx instruction bug workaround */
0334     EXCEPTION_PROLOG_1
0335     /* 0x300 is DataAccess exception, needed by bad_page_fault() */
0336     EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataTLBError handle_dar_dsisr=1
0337     lwz r4, _DAR(r11)
0338     lwz r5, _DSISR(r11)
0339     andis.  r10,r5,DSISR_NOHPTE@h
0340     beq+    .Ldtlbie
0341     tlbie   r4
0342 .Ldtlbie:
0343     prepare_transfer_to_handler
0344     bl  do_page_fault
0345     b   interrupt_return
0346 
0347 #ifdef CONFIG_VMAP_STACK
0348     vmap_stack_overflow_exception
0349 #endif
0350 
0351 /* On the MPC8xx, these next four traps are used for development
0352  * support of breakpoints and such.  Someday I will get around to
0353  * using them.
0354  */
0355     START_EXCEPTION(INTERRUPT_DATA_BREAKPOINT_8xx, DataBreakpoint)
0356     EXCEPTION_PROLOG_0 handle_dar_dsisr=1
0357     mfspr   r11, SPRN_SRR0
0358     cmplwi  cr1, r11, (.Ldtlbie - PAGE_OFFSET)@l
0359     cmplwi  cr7, r11, (.Litlbie - PAGE_OFFSET)@l
0360     cror    4*cr1+eq, 4*cr1+eq, 4*cr7+eq
0361     bne cr1, 1f
0362     mtcr    r10
0363     mfspr   r10, SPRN_SPRG_SCRATCH0
0364     mfspr   r11, SPRN_SPRG_SCRATCH1
0365     rfi
0366 
0367 1:  EXCEPTION_PROLOG_1
0368     EXCEPTION_PROLOG_2 INTERRUPT_DATA_BREAKPOINT_8xx DataBreakpoint handle_dar_dsisr=1
0369     mfspr   r4,SPRN_BAR
0370     stw r4,_DAR(r11)
0371     prepare_transfer_to_handler
0372     bl  do_break
0373     REST_NVGPRS(r1)
0374     b   interrupt_return
0375 
0376 #ifdef CONFIG_PERF_EVENTS
0377     START_EXCEPTION(INTERRUPT_INST_BREAKPOINT_8xx, InstructionBreakpoint)
0378     mtspr   SPRN_SPRG_SCRATCH0, r10
0379     lwz r10, (instruction_counter - PAGE_OFFSET)@l(0)
0380     addi    r10, r10, -1
0381     stw r10, (instruction_counter - PAGE_OFFSET)@l(0)
0382     lis r10, 0xffff
0383     ori r10, r10, 0x01
0384     mtspr   SPRN_COUNTA, r10
0385     mfspr   r10, SPRN_SPRG_SCRATCH0
0386     rfi
0387 #else
0388     EXCEPTION(INTERRUPT_INST_BREAKPOINT_8xx, Trap_1d, unknown_exception)
0389 #endif
0390     EXCEPTION(0x1e00, Trap_1e, unknown_exception)
0391     EXCEPTION(0x1f00, Trap_1f, unknown_exception)
0392 
0393     __HEAD
0394     . = 0x2000
0395 
0396 /* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions
0397  * by decoding the registers used by the dcbx instruction and adding them.
0398  * DAR is set to the calculated address.
0399  */
0400 FixupDAR:/* Entry point for dcbx workaround. */
0401     mtspr   SPRN_M_TW, r10
0402     /* fetch instruction from memory. */
0403     mfspr   r10, SPRN_SRR0
0404     mtspr   SPRN_MD_EPN, r10
0405     rlwinm  r11, r10, 16, 0xfff8
0406     cmpli   cr1, r11, PAGE_OFFSET@h
0407     mfspr   r11, SPRN_M_TWB /* Get level 1 table */
0408     blt+    cr1, 3f
0409 
0410     /* create physical page address from effective address */
0411     tophys(r11, r10)
0412     mfspr   r11, SPRN_M_TWB /* Get level 1 table */
0413     rlwinm  r11, r11, 0, 20, 31
0414     oris    r11, r11, (swapper_pg_dir - PAGE_OFFSET)@ha
0415 3:
0416     lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11)    /* Get the level 1 entry */
0417     mtspr   SPRN_MD_TWC, r11
0418     mtcrf   0x01, r11
0419     mfspr   r11, SPRN_MD_TWC
0420     lwz r11, 0(r11) /* Get the pte */
0421     bt  28,200f     /* bit 28 = Large page (8M) */
0422     /* concat physical page address(r11) and page offset(r10) */
0423     rlwimi  r11, r10, 0, 32 - PAGE_SHIFT, 31
0424 201:    lwz r11,0(r11)
0425 /* Check if it really is a dcbx instruction. */
0426 /* dcbt and dcbtst does not generate DTLB Misses/Errors,
0427  * no need to include them here */
0428     xoris   r10, r11, 0x7c00    /* check if major OP code is 31 */
0429     rlwinm  r10, r10, 0, 21, 5
0430     cmpwi   cr1, r10, 2028  /* Is dcbz? */
0431     beq+    cr1, 142f
0432     cmpwi   cr1, r10, 940   /* Is dcbi? */
0433     beq+    cr1, 142f
0434     cmpwi   cr1, r10, 108   /* Is dcbst? */
0435     beq+    cr1, 144f       /* Fix up store bit! */
0436     cmpwi   cr1, r10, 172   /* Is dcbf? */
0437     beq+    cr1, 142f
0438     cmpwi   cr1, r10, 1964  /* Is icbi? */
0439     beq+    cr1, 142f
0440 141:    mfspr   r10,SPRN_M_TW
0441     b   DARFixed    /* Nope, go back to normal TLB processing */
0442 
0443 200:
0444     /* concat physical page address(r11) and page offset(r10) */
0445     rlwimi  r11, r10, 0, 32 - PAGE_SHIFT_8M, 31
0446     b   201b
0447 
0448 144:    mfspr   r10, SPRN_DSISR
0449     rlwinm  r10, r10,0,7,5  /* Clear store bit for buggy dcbst insn */
0450     mtspr   SPRN_DSISR, r10
0451 142:    /* continue, it was a dcbx, dcbi instruction. */
0452     mfctr   r10
0453     mtdar   r10         /* save ctr reg in DAR */
0454     rlwinm  r10, r11, 24, 24, 28    /* offset into jump table for reg RB */
0455     addi    r10, r10, 150f@l    /* add start of table */
0456     mtctr   r10         /* load ctr with jump address */
0457     xor r10, r10, r10       /* sum starts at zero */
0458     bctr                /* jump into table */
0459 150:
0460     add r10, r10, r0    ;b  151f
0461     add r10, r10, r1    ;b  151f
0462     add r10, r10, r2    ;b  151f
0463     add r10, r10, r3    ;b  151f
0464     add r10, r10, r4    ;b  151f
0465     add r10, r10, r5    ;b  151f
0466     add r10, r10, r6    ;b  151f
0467     add r10, r10, r7    ;b  151f
0468     add r10, r10, r8    ;b  151f
0469     add r10, r10, r9    ;b  151f
0470     mtctr   r11 ;b  154f    /* r10 needs special handling */
0471     mtctr   r11 ;b  153f    /* r11 needs special handling */
0472     add r10, r10, r12   ;b  151f
0473     add r10, r10, r13   ;b  151f
0474     add r10, r10, r14   ;b  151f
0475     add r10, r10, r15   ;b  151f
0476     add r10, r10, r16   ;b  151f
0477     add r10, r10, r17   ;b  151f
0478     add r10, r10, r18   ;b  151f
0479     add r10, r10, r19   ;b  151f
0480     add r10, r10, r20   ;b  151f
0481     add r10, r10, r21   ;b  151f
0482     add r10, r10, r22   ;b  151f
0483     add r10, r10, r23   ;b  151f
0484     add r10, r10, r24   ;b  151f
0485     add r10, r10, r25   ;b  151f
0486     add r10, r10, r26   ;b  151f
0487     add r10, r10, r27   ;b  151f
0488     add r10, r10, r28   ;b  151f
0489     add r10, r10, r29   ;b  151f
0490     add r10, r10, r30   ;b  151f
0491     add r10, r10, r31
0492 151:
0493     rlwinm  r11,r11,19,24,28    /* offset into jump table for reg RA */
0494     cmpwi   cr1, r11, 0
0495     beq cr1, 152f       /* if reg RA is zero, don't add it */
0496     addi    r11, r11, 150b@l    /* add start of table */
0497     mtctr   r11         /* load ctr with jump address */
0498     rlwinm  r11,r11,0,16,10     /* make sure we don't execute this more than once */
0499     bctr                /* jump into table */
0500 152:
0501     mfdar   r11
0502     mtctr   r11         /* restore ctr reg from DAR */
0503     mfspr   r11, SPRN_SPRG_THREAD
0504     stw r10, DAR(r11)
0505     mfspr   r10, SPRN_DSISR
0506     stw r10, DSISR(r11)
0507     mfspr   r10,SPRN_M_TW
0508     b   DARFixed        /* Go back to normal TLB handling */
0509 
0510     /* special handling for r10,r11 since these are modified already */
0511 153:    mfspr   r11, SPRN_SPRG_SCRATCH1 /* load r11 from SPRN_SPRG_SCRATCH1 */
0512     add r10, r10, r11   /* add it */
0513     mfctr   r11     /* restore r11 */
0514     b   151b
0515 154:    mfspr   r11, SPRN_SPRG_SCRATCH0 /* load r10 from SPRN_SPRG_SCRATCH0 */
0516     add r10, r10, r11   /* add it */
0517     mfctr   r11     /* restore r11 */
0518     b   151b
0519 
0520 /*
0521  * This is where the main kernel code starts.
0522  */
0523 start_here:
0524     /* ptr to current */
0525     lis r2,init_task@h
0526     ori r2,r2,init_task@l
0527 
0528     /* ptr to phys current thread */
0529     tophys(r4,r2)
0530     addi    r4,r4,THREAD    /* init task's THREAD */
0531     mtspr   SPRN_SPRG_THREAD,r4
0532 
0533     /* stack */
0534     lis r1,init_thread_union@ha
0535     addi    r1,r1,init_thread_union@l
0536     lis r0, STACK_END_MAGIC@h
0537     ori r0, r0, STACK_END_MAGIC@l
0538     stw r0, 0(r1)
0539     li  r0,0
0540     stwu    r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
0541 
0542     lis r6, swapper_pg_dir@ha
0543     tophys(r6,r6)
0544     mtspr   SPRN_M_TWB, r6
0545 
0546     bl  early_init  /* We have to do this with MMU on */
0547 
0548 /*
0549  * Decide what sort of machine this is and initialize the MMU.
0550  */
0551 #ifdef CONFIG_KASAN
0552     bl  kasan_early_init
0553 #endif
0554     li  r3,0
0555     mr  r4,r31
0556     bl  machine_init
0557     bl  MMU_init
0558 
0559 /*
0560  * Go back to running unmapped so we can load up new values
0561  * and change to using our exception vectors.
0562  * On the 8xx, all we have to do is invalidate the TLB to clear
0563  * the old 8M byte TLB mappings and load the page table base register.
0564  */
0565     /* The right way to do this would be to track it down through
0566      * init's THREAD like the context switch code does, but this is
0567      * easier......until someone changes init's static structures.
0568      */
0569     lis r4,2f@h
0570     ori r4,r4,2f@l
0571     tophys(r4,r4)
0572     li  r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
0573     mtspr   SPRN_SRR0,r4
0574     mtspr   SPRN_SRR1,r3
0575     rfi
0576 /* Load up the kernel context */
0577 2:
0578 #ifdef CONFIG_PIN_TLB_IMMR
0579     lis r0, MD_TWAM@h
0580     oris    r0, r0, 0x1f00
0581     mtspr   SPRN_MD_CTR, r0
0582     LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
0583     tlbie   r0
0584     mtspr   SPRN_MD_EPN, r0
0585     LOAD_REG_IMMEDIATE(r0, MD_SVALID | MD_PS512K | MD_GUARDED)
0586     mtspr   SPRN_MD_TWC, r0
0587     mfspr   r0, SPRN_IMMR
0588     rlwinm  r0, r0, 0, 0xfff80000
0589     ori r0, r0, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
0590             _PAGE_NO_CACHE | _PAGE_PRESENT
0591     mtspr   SPRN_MD_RPN, r0
0592     lis r0, (MD_TWAM | MD_RSV4I)@h
0593     mtspr   SPRN_MD_CTR, r0
0594 #endif
0595 #if !defined(CONFIG_PIN_TLB_DATA) && !defined(CONFIG_PIN_TLB_IMMR)
0596     lis r0, MD_TWAM@h
0597     mtspr   SPRN_MD_CTR, r0
0598 #endif
0599     tlbia           /* Clear all TLB entries */
0600     sync            /* wait for tlbia/tlbie to finish */
0601 
0602     /* set up the PTE pointers for the Abatron bdiGDB.
0603     */
0604     lis r5, abatron_pteptrs@h
0605     ori r5, r5, abatron_pteptrs@l
0606     stw r5, 0xf0(0) /* Must match your Abatron config file */
0607     tophys(r5,r5)
0608     lis r6, swapper_pg_dir@h
0609     ori r6, r6, swapper_pg_dir@l
0610     stw r6, 0(r5)
0611 
0612 /* Now turn on the MMU for real! */
0613     li  r4,MSR_KERNEL
0614     lis r3,start_kernel@h
0615     ori r3,r3,start_kernel@l
0616     mtspr   SPRN_SRR0,r3
0617     mtspr   SPRN_SRR1,r4
0618     rfi         /* enable MMU and jump to start_kernel */
0619 
0620 /* Set up the initial MMU state so we can do the first level of
0621  * kernel initialization.  This maps the first 8 MBytes of memory 1:1
0622  * virtual to physical.  Also, set the cache mode since that is defined
0623  * by TLB entries and perform any additional mapping (like of the IMMR).
0624  * If configured to pin some TLBs, we pin the first 8 Mbytes of kernel,
0625  * 24 Mbytes of data, and the 512k IMMR space.  Anything not covered by
0626  * these mappings is mapped by page tables.
0627  */
0628 initial_mmu:
0629     li  r8, 0
0630     mtspr   SPRN_MI_CTR, r8     /* remove PINNED ITLB entries */
0631     lis r10, MD_TWAM@h
0632     mtspr   SPRN_MD_CTR, r10    /* remove PINNED DTLB entries */
0633 
0634     tlbia           /* Invalidate all TLB entries */
0635 
0636     lis r8, MI_APG_INIT@h   /* Set protection modes */
0637     ori r8, r8, MI_APG_INIT@l
0638     mtspr   SPRN_MI_AP, r8
0639     lis r8, MD_APG_INIT@h
0640     ori r8, r8, MD_APG_INIT@l
0641     mtspr   SPRN_MD_AP, r8
0642 
0643     /* Map the lower RAM (up to 32 Mbytes) into the ITLB and DTLB */
0644     lis r8, MI_RSV4I@h
0645     ori r8, r8, 0x1c00
0646     oris    r12, r10, MD_RSV4I@h
0647     ori r12, r12, 0x1c00
0648     li  r9, 4               /* up to 4 pages of 8M */
0649     mtctr   r9
0650     lis r9, KERNELBASE@h        /* Create vaddr for TLB */
0651     li  r10, MI_PS8MEG | _PMD_ACCESSED | MI_SVALID
0652     li  r11, MI_BOOTINIT        /* Create RPN for address 0 */
0653 1:
0654     mtspr   SPRN_MI_CTR, r8 /* Set instruction MMU control */
0655     addi    r8, r8, 0x100
0656     ori r0, r9, MI_EVALID       /* Mark it valid */
0657     mtspr   SPRN_MI_EPN, r0
0658     mtspr   SPRN_MI_TWC, r10
0659     mtspr   SPRN_MI_RPN, r11        /* Store TLB entry */
0660     mtspr   SPRN_MD_CTR, r12
0661     addi    r12, r12, 0x100
0662     mtspr   SPRN_MD_EPN, r0
0663     mtspr   SPRN_MD_TWC, r10
0664     mtspr   SPRN_MD_RPN, r11
0665     addis   r9, r9, 0x80
0666     addis   r11, r11, 0x80
0667 
0668     bdnz    1b
0669 
0670     /* Since the cache is enabled according to the information we
0671      * just loaded into the TLB, invalidate and enable the caches here.
0672      * We should probably check/set other modes....later.
0673      */
0674     lis r8, IDC_INVALL@h
0675     mtspr   SPRN_IC_CST, r8
0676     mtspr   SPRN_DC_CST, r8
0677     lis r8, IDC_ENABLE@h
0678     mtspr   SPRN_IC_CST, r8
0679     mtspr   SPRN_DC_CST, r8
0680     /* Disable debug mode entry on breakpoints */
0681     mfspr   r8, SPRN_DER
0682 #ifdef CONFIG_PERF_EVENTS
0683     rlwinm  r8, r8, 0, ~0xc
0684 #else
0685     rlwinm  r8, r8, 0, ~0x8
0686 #endif
0687     mtspr   SPRN_DER, r8
0688     blr
0689 
0690 _GLOBAL(mmu_pin_tlb)
0691     lis r9, (1f - PAGE_OFFSET)@h
0692     ori r9, r9, (1f - PAGE_OFFSET)@l
0693     mfmsr   r10
0694     mflr    r11
0695     li  r12, MSR_KERNEL & ~(MSR_IR | MSR_DR | MSR_RI)
0696     rlwinm  r0, r10, 0, ~MSR_RI
0697     rlwinm  r0, r0, 0, ~MSR_EE
0698     mtmsr   r0
0699     isync
0700     .align  4
0701     mtspr   SPRN_SRR0, r9
0702     mtspr   SPRN_SRR1, r12
0703     rfi
0704 1:
0705     li  r5, 0
0706     lis r6, MD_TWAM@h
0707     mtspr   SPRN_MI_CTR, r5
0708     mtspr   SPRN_MD_CTR, r6
0709     tlbia
0710 
0711     LOAD_REG_IMMEDIATE(r5, 28 << 8)
0712     LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
0713     LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
0714     LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
0715     LOAD_REG_ADDR(r9, _sinittext)
0716     li  r0, 4
0717     mtctr   r0
0718 
0719 2:  ori r0, r6, MI_EVALID
0720     mtspr   SPRN_MI_CTR, r5
0721     mtspr   SPRN_MI_EPN, r0
0722     mtspr   SPRN_MI_TWC, r7
0723     mtspr   SPRN_MI_RPN, r8
0724     addi    r5, r5, 0x100
0725     addis   r6, r6, SZ_8M@h
0726     addis   r8, r8, SZ_8M@h
0727     cmplw   r6, r9
0728     bdnzt   lt, 2b
0729     lis r0, MI_RSV4I@h
0730     mtspr   SPRN_MI_CTR, r0
0731 
0732     LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM)
0733 #ifdef CONFIG_PIN_TLB_DATA
0734     LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
0735     LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
0736     li  r8, 0
0737 #ifdef CONFIG_PIN_TLB_IMMR
0738     li  r0, 3
0739 #else
0740     li  r0, 4
0741 #endif
0742     mtctr   r0
0743     cmpwi   r4, 0
0744     beq 4f
0745     LOAD_REG_ADDR(r9, _sinittext)
0746 
0747 2:  ori r0, r6, MD_EVALID
0748     ori r12, r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT
0749     mtspr   SPRN_MD_CTR, r5
0750     mtspr   SPRN_MD_EPN, r0
0751     mtspr   SPRN_MD_TWC, r7
0752     mtspr   SPRN_MD_RPN, r12
0753     addi    r5, r5, 0x100
0754     addis   r6, r6, SZ_8M@h
0755     addis   r8, r8, SZ_8M@h
0756     cmplw   r6, r9
0757     bdnzt   lt, 2b
0758 4:
0759 2:  ori r0, r6, MD_EVALID
0760     ori r12, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT
0761     mtspr   SPRN_MD_CTR, r5
0762     mtspr   SPRN_MD_EPN, r0
0763     mtspr   SPRN_MD_TWC, r7
0764     mtspr   SPRN_MD_RPN, r12
0765     addi    r5, r5, 0x100
0766     addis   r6, r6, SZ_8M@h
0767     addis   r8, r8, SZ_8M@h
0768     cmplw   r6, r3
0769     bdnzt   lt, 2b
0770 #endif
0771 #ifdef CONFIG_PIN_TLB_IMMR
0772     LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
0773     LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED | _PMD_ACCESSED)
0774     mfspr   r8, SPRN_IMMR
0775     rlwinm  r8, r8, 0, 0xfff80000
0776     ori r8, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
0777             _PAGE_NO_CACHE | _PAGE_PRESENT
0778     mtspr   SPRN_MD_CTR, r5
0779     mtspr   SPRN_MD_EPN, r0
0780     mtspr   SPRN_MD_TWC, r7
0781     mtspr   SPRN_MD_RPN, r8
0782 #endif
0783 #if defined(CONFIG_PIN_TLB_IMMR) || defined(CONFIG_PIN_TLB_DATA)
0784     lis r0, (MD_RSV4I | MD_TWAM)@h
0785     mtspr   SPRN_MD_CTR, r0
0786 #endif
0787     mtspr   SPRN_SRR1, r10
0788     mtspr   SPRN_SRR0, r11
0789     rfi