linux/arch/powerpc/kernel/head_8xx.S
<<
>>
Prefs
   1/*
   2 *  PowerPC version
   3 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
   4 *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
   5 *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
   6 *  Low-level exception handlers and MMU support
   7 *  rewritten by Paul Mackerras.
   8 *    Copyright (C) 1996 Paul Mackerras.
   9 *  MPC8xx modifications by Dan Malek
  10 *    Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
  11 *
  12 *  This file contains low-level support and setup for PowerPC 8xx
  13 *  embedded processors, including trap and interrupt dispatch.
  14 *
  15 *  This program is free software; you can redistribute it and/or
  16 *  modify it under the terms of the GNU General Public License
  17 *  as published by the Free Software Foundation; either version
  18 *  2 of the License, or (at your option) any later version.
  19 *
  20 */
  21
  22#include <linux/init.h>
  23#include <asm/processor.h>
  24#include <asm/page.h>
  25#include <asm/mmu.h>
  26#include <asm/cache.h>
  27#include <asm/pgtable.h>
  28#include <asm/cputable.h>
  29#include <asm/thread_info.h>
  30#include <asm/ppc_asm.h>
  31#include <asm/asm-offsets.h>
  32#include <asm/ptrace.h>
  33
  34/* Macro to make the code more readable. */
  35#ifdef CONFIG_8xx_CPU6
  36#define SPRN_MI_TWC_ADDR        0x2b80
  37#define SPRN_MI_RPN_ADDR        0x2d80
  38#define SPRN_MD_TWC_ADDR        0x3b80
  39#define SPRN_MD_RPN_ADDR        0x3d80
  40
  41#define MTSPR_CPU6(spr, reg, treg)      \
  42        li      treg, spr##_ADDR;       \
  43        stw     treg, 12(r0);           \
  44        lwz     treg, 12(r0);           \
  45        mtspr   spr, reg
  46#else
  47#define MTSPR_CPU6(spr, reg, treg)      \
  48        mtspr   spr, reg
  49#endif
  50
  51/*
  52 * Value for the bits that have fixed value in RPN entries.
  53 * Also used for tagging DAR for DTLBerror.
  54 */
  55#ifdef CONFIG_PPC_16K_PAGES
  56#define RPN_PATTERN     (0x00f0 | MD_SPS16K)
  57#else
  58#define RPN_PATTERN     0x00f0
  59#endif
  60
  61        __HEAD
  62_ENTRY(_stext);
  63_ENTRY(_start);
  64
  65/* MPC8xx
  66 * This port was done on an MBX board with an 860.  Right now I only
  67 * support an ELF compressed (zImage) boot from EPPC-Bug because the
  68 * code there loads up some registers before calling us:
  69 *   r3: ptr to board info data
  70 *   r4: initrd_start or if no initrd then 0
  71 *   r5: initrd_end - unused if r4 is 0
  72 *   r6: Start of command line string
  73 *   r7: End of command line string
  74 *
  75 * I decided to use conditional compilation instead of checking PVR and
  76 * adding more processor specific branches around code I don't need.
  77 * Since this is an embedded processor, I also appreciate any memory
  78 * savings I can get.
  79 *
  80 * The MPC8xx does not have any BATs, but it supports large page sizes.
  81 * We first initialize the MMU to support 8M byte pages, then load one
  82 * entry into each of the instruction and data TLBs to map the first
  83 * 8M 1:1.  I also mapped an additional I/O space 1:1 so we can get to
  84 * the "internal" processor registers before MMU_init is called.
  85 *
  86 *      -- Dan
  87 */
  88        .globl  __start
  89__start:
  90        mr      r31,r3                  /* save device tree ptr */
  91
  92        /* We have to turn on the MMU right away so we get cache modes
  93         * set correctly.
  94         */
  95        bl      initial_mmu
  96
  97/* We now have the lower 8 Meg mapped into TLB entries, and the caches
  98 * ready to work.
  99 */
 100
 101turn_on_mmu:
 102        mfmsr   r0
 103        ori     r0,r0,MSR_DR|MSR_IR
 104        mtspr   SPRN_SRR1,r0
 105        lis     r0,start_here@h
 106        ori     r0,r0,start_here@l
 107        mtspr   SPRN_SRR0,r0
 108        SYNC
 109        rfi                             /* enables MMU */
 110
 111/*
 112 * Exception entry code.  This code runs with address translation
 113 * turned off, i.e. using physical addresses.
 114 * We assume sprg3 has the physical address of the current
 115 * task's thread_struct.
 116 */
 117#define EXCEPTION_PROLOG        \
 118        EXCEPTION_PROLOG_0;     \
 119        EXCEPTION_PROLOG_1;     \
 120        EXCEPTION_PROLOG_2
 121
 122#define EXCEPTION_PROLOG_0      \
 123        mtspr   SPRN_SPRG_SCRATCH0,r10; \
 124        mtspr   SPRN_SPRG_SCRATCH1,r11; \
 125        mfcr    r10
 126
 127#define EXCEPTION_PROLOG_1      \
 128        mfspr   r11,SPRN_SRR1;          /* check whether user or kernel */ \
 129        andi.   r11,r11,MSR_PR; \
 130        tophys(r11,r1);                 /* use tophys(r1) if kernel */ \
 131        beq     1f;             \
 132        mfspr   r11,SPRN_SPRG_THREAD;   \
 133        lwz     r11,THREAD_INFO-THREAD(r11);    \
 134        addi    r11,r11,THREAD_SIZE;    \
 135        tophys(r11,r11);        \
 1361:      subi    r11,r11,INT_FRAME_SIZE  /* alloc exc. frame */
 137
 138
 139#define EXCEPTION_PROLOG_2      \
 140        CLR_TOP32(r11);         \
 141        stw     r10,_CCR(r11);          /* save registers */ \
 142        stw     r12,GPR12(r11); \
 143        stw     r9,GPR9(r11);   \
 144        mfspr   r10,SPRN_SPRG_SCRATCH0; \
 145        stw     r10,GPR10(r11); \
 146        mfspr   r12,SPRN_SPRG_SCRATCH1; \
 147        stw     r12,GPR11(r11); \
 148        mflr    r10;            \
 149        stw     r10,_LINK(r11); \
 150        mfspr   r12,SPRN_SRR0;  \
 151        mfspr   r9,SPRN_SRR1;   \
 152        stw     r1,GPR1(r11);   \
 153        stw     r1,0(r11);      \
 154        tovirt(r1,r11);                 /* set new kernel sp */ \
 155        li      r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
 156        MTMSRD(r10);                    /* (except for mach check in rtas) */ \
 157        stw     r0,GPR0(r11);   \
 158        SAVE_4GPRS(3, r11);     \
 159        SAVE_2GPRS(7, r11)
 160
 161/*
 162 * Exception exit code.
 163 */
 164#define EXCEPTION_EPILOG_0      \
 165        mtcr    r10;            \
 166        mfspr   r10,SPRN_SPRG_SCRATCH0; \
 167        mfspr   r11,SPRN_SPRG_SCRATCH1
 168
 169/*
 170 * Note: code which follows this uses cr0.eq (set if from kernel),
 171 * r11, r12 (SRR0), and r9 (SRR1).
 172 *
 173 * Note2: once we have set r1 we are in a position to take exceptions
 174 * again, and we could thus set MSR:RI at that point.
 175 */
 176
 177/*
 178 * Exception vectors.
 179 */
 180#define EXCEPTION(n, label, hdlr, xfer)         \
 181        . = n;                                  \
 182label:                                          \
 183        EXCEPTION_PROLOG;                       \
 184        addi    r3,r1,STACK_FRAME_OVERHEAD;     \
 185        xfer(n, hdlr)
 186
 187#define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret)     \
 188        li      r10,trap;                                       \
 189        stw     r10,_TRAP(r11);                                 \
 190        li      r10,MSR_KERNEL;                                 \
 191        copyee(r10, r9);                                        \
 192        bl      tfer;                                           \
 193i##n:                                                           \
 194        .long   hdlr;                                           \
 195        .long   ret
 196
 197#define COPY_EE(d, s)           rlwimi d,s,0,16,16
 198#define NOCOPY(d, s)
 199
 200#define EXC_XFER_STD(n, hdlr)           \
 201        EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full, \
 202                          ret_from_except_full)
 203
 204#define EXC_XFER_LITE(n, hdlr)          \
 205        EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \
 206                          ret_from_except)
 207
 208#define EXC_XFER_EE(n, hdlr)            \
 209        EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \
 210                          ret_from_except_full)
 211
 212#define EXC_XFER_EE_LITE(n, hdlr)       \
 213        EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \
 214                          ret_from_except)
 215
 216/* System reset */
 217        EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)
 218
 219/* Machine check */
 220        . = 0x200
 221MachineCheck:
 222        EXCEPTION_PROLOG
 223        mfspr r4,SPRN_DAR
 224        stw r4,_DAR(r11)
 225        li r5,RPN_PATTERN
 226        mtspr SPRN_DAR,r5       /* Tag DAR, to be used in DTLB Error */
 227        mfspr r5,SPRN_DSISR
 228        stw r5,_DSISR(r11)
 229        addi r3,r1,STACK_FRAME_OVERHEAD
 230        EXC_XFER_STD(0x200, machine_check_exception)
 231
 232/* Data access exception.
 233 * This is "never generated" by the MPC8xx.
 234 */
 235        . = 0x300
 236DataAccess:
 237
 238/* Instruction access exception.
 239 * This is "never generated" by the MPC8xx.
 240 */
 241        . = 0x400
 242InstructionAccess:
 243
 244/* External interrupt */
 245        EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
 246
 247/* Alignment exception */
 248        . = 0x600
 249Alignment:
 250        EXCEPTION_PROLOG
 251        mfspr   r4,SPRN_DAR
 252        stw     r4,_DAR(r11)
 253        li      r5,RPN_PATTERN
 254        mtspr   SPRN_DAR,r5     /* Tag DAR, to be used in DTLB Error */
 255        mfspr   r5,SPRN_DSISR
 256        stw     r5,_DSISR(r11)
 257        addi    r3,r1,STACK_FRAME_OVERHEAD
 258        EXC_XFER_EE(0x600, alignment_exception)
 259
 260/* Program check exception */
 261        EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
 262
 263/* No FPU on MPC8xx.  This exception is not supposed to happen.
 264*/
 265        EXCEPTION(0x800, FPUnavailable, unknown_exception, EXC_XFER_STD)
 266
 267/* Decrementer */
 268        EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
 269
 270        EXCEPTION(0xa00, Trap_0a, unknown_exception, EXC_XFER_EE)
 271        EXCEPTION(0xb00, Trap_0b, unknown_exception, EXC_XFER_EE)
 272
 273/* System call */
 274        . = 0xc00
 275SystemCall:
 276        EXCEPTION_PROLOG
 277        EXC_XFER_EE_LITE(0xc00, DoSyscall)
 278
 279/* Single step - not used on 601 */
 280        EXCEPTION(0xd00, SingleStep, single_step_exception, EXC_XFER_STD)
 281        EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)
 282        EXCEPTION(0xf00, Trap_0f, unknown_exception, EXC_XFER_EE)
 283
 284/* On the MPC8xx, this is a software emulation interrupt.  It occurs
 285 * for all unimplemented and illegal instructions.
 286 */
 287        EXCEPTION(0x1000, SoftEmu, SoftwareEmulation, EXC_XFER_STD)
 288
 289        . = 0x1100
 290/*
 291 * For the MPC8xx, this is a software tablewalk to load the instruction
 292 * TLB.  The task switch loads the M_TW register with the pointer to the first
 293 * level table.
 294 * If we discover there is no second level table (value is zero) or if there
 295 * is an invalid pte, we load that into the TLB, which causes another fault
 296 * into the TLB Error interrupt where we can handle such problems.
 297 * We have to use the MD_xxx registers for the tablewalk because the
 298 * equivalent MI_xxx registers only perform the attribute functions.
 299 */
 300InstructionTLBMiss:
 301#ifdef CONFIG_8xx_CPU6
 302        mtspr   SPRN_DAR, r3
 303#endif
 304        EXCEPTION_PROLOG_0
 305        mtspr   SPRN_SPRG_SCRATCH2, r10
 306        mfspr   r10, SPRN_SRR0  /* Get effective address of fault */
 307#ifdef CONFIG_8xx_CPU15
 308        addi    r11, r10, PAGE_SIZE
 309        tlbie   r11
 310        addi    r11, r10, -PAGE_SIZE
 311        tlbie   r11
 312#endif
 313
 314        /* If we are faulting a kernel address, we have to use the
 315         * kernel page tables.
 316         */
 317#ifdef CONFIG_MODULES
 318        /* Only modules will cause ITLB Misses as we always
 319         * pin the first 8MB of kernel memory */
 320        andis.  r11, r10, 0x8000        /* Address >= 0x80000000 */
 321#endif
 322        mfspr   r11, SPRN_M_TW  /* Get level 1 table */
 323#ifdef CONFIG_MODULES
 324        beq     3f
 325        lis     r11, (swapper_pg_dir-PAGE_OFFSET)@ha
 3263:
 327#endif
 328        /* Insert level 1 index */
 329        rlwimi  r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
 330        lwz     r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11)        /* Get the level 1 entry */
 331
 332        /* Load the MI_TWC with the attributes for this "segment." */
 333        MTSPR_CPU6(SPRN_MI_TWC, r11, r3)        /* Set segment attributes */
 334        rlwinm  r11, r11,0,0,19 /* Extract page descriptor page address */
 335        /* Extract level 2 index */
 336        rlwinm  r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
 337        lwzx    r10, r10, r11   /* Get the pte */
 338
 339#ifdef CONFIG_SWAP
 340        rlwinm  r11, r10, 32-5, _PAGE_PRESENT
 341        and     r11, r11, r10
 342        rlwimi  r10, r11, 0, _PAGE_PRESENT
 343#endif
 344        li      r11, RPN_PATTERN
 345        /* The Linux PTE won't go exactly into the MMU TLB.
 346         * Software indicator bits 21 and 28 must be clear.
 347         * Software indicator bits 24, 25, 26, and 27 must be
 348         * set.  All other Linux PTE bits control the behavior
 349         * of the MMU.
 350         */
 351        rlwimi  r10, r11, 0, 0x07f8     /* Set 24-27, clear 21-23,28 */
 352        MTSPR_CPU6(SPRN_MI_RPN, r10, r3)        /* Update TLB entry */
 353
 354        /* Restore registers */
 355#ifdef CONFIG_8xx_CPU6
 356        mfspr   r3, SPRN_DAR
 357        mtspr   SPRN_DAR, r11   /* Tag DAR */
 358#endif
 359        mfspr   r10, SPRN_SPRG_SCRATCH2
 360        EXCEPTION_EPILOG_0
 361        rfi
 362
 363        . = 0x1200
 364DataStoreTLBMiss:
 365#ifdef CONFIG_8xx_CPU6
 366        mtspr   SPRN_DAR, r3
 367#endif
 368        EXCEPTION_PROLOG_0
 369        mtspr   SPRN_SPRG_SCRATCH2, r10
 370        mfspr   r10, SPRN_MD_EPN
 371
 372        /* If we are faulting a kernel address, we have to use the
 373         * kernel page tables.
 374         */
 375        andis.  r11, r10, 0x8000
 376        mfspr   r11, SPRN_M_TW  /* Get level 1 table */
 377        beq     3f
 378        lis     r11, (swapper_pg_dir-PAGE_OFFSET)@ha
 3793:
 380        /* Insert level 1 index */
 381        rlwimi  r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
 382        lwz     r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11)        /* Get the level 1 entry */
 383
 384        /* We have a pte table, so load fetch the pte from the table.
 385         */
 386        /* Extract level 2 index */
 387        rlwinm  r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
 388        rlwimi  r10, r11, 0, 0, 32 - PAGE_SHIFT - 1     /* Add level 2 base */
 389        lwz     r10, 0(r10)     /* Get the pte */
 390
 391        /* Insert the Guarded flag into the TWC from the Linux PTE.
 392         * It is bit 27 of both the Linux PTE and the TWC (at least
 393         * I got that right :-).  It will be better when we can put
 394         * this into the Linux pgd/pmd and load it in the operation
 395         * above.
 396         */
 397        rlwimi  r11, r10, 0, 27, 27
 398        /* Insert the WriteThru flag into the TWC from the Linux PTE.
 399         * It is bit 25 in the Linux PTE and bit 30 in the TWC
 400         */
 401        rlwimi  r11, r10, 32-5, 30, 30
 402        MTSPR_CPU6(SPRN_MD_TWC, r11, r3)
 403
 404        /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
 405         * We also need to know if the insn is a load/store, so:
 406         * Clear _PAGE_PRESENT and load that which will
 407         * trap into DTLB Error with store bit set accordinly.
 408         */
 409        /* PRESENT=0x1, ACCESSED=0x20
 410         * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
 411         * r10 = (r10 & ~PRESENT) | r11;
 412         */
 413#ifdef CONFIG_SWAP
 414        rlwinm  r11, r10, 32-5, _PAGE_PRESENT
 415        and     r11, r11, r10
 416        rlwimi  r10, r11, 0, _PAGE_PRESENT
 417#endif
 418        /* The Linux PTE won't go exactly into the MMU TLB.
 419         * Software indicator bits 22 and 28 must be clear.
 420         * Software indicator bits 24, 25, 26, and 27 must be
 421         * set.  All other Linux PTE bits control the behavior
 422         * of the MMU.
 423         */
 424        li      r11, RPN_PATTERN
 425        rlwimi  r10, r11, 0, 24, 28     /* Set 24-27, clear 28 */
 426        MTSPR_CPU6(SPRN_MD_RPN, r10, r3)        /* Update TLB entry */
 427
 428        /* Restore registers */
 429#ifdef CONFIG_8xx_CPU6
 430        mfspr   r3, SPRN_DAR
 431#endif
 432        mtspr   SPRN_DAR, r11   /* Tag DAR */
 433        mfspr   r10, SPRN_SPRG_SCRATCH2
 434        EXCEPTION_EPILOG_0
 435        rfi
 436
 437/* This is an instruction TLB error on the MPC8xx.  This could be due
 438 * to many reasons, such as executing guarded memory or illegal instruction
 439 * addresses.  There is nothing to do but handle a big time error fault.
 440 */
 441        . = 0x1300
 442InstructionTLBError:
 443        EXCEPTION_PROLOG
 444        mr      r4,r12
 445        mr      r5,r9
 446        andis.  r10,r5,0x4000
 447        beq+    1f
 448        tlbie   r4
 449        /* 0x400 is InstructionAccess exception, needed by bad_page_fault() */
 4501:      EXC_XFER_LITE(0x400, handle_page_fault)
 451
 452/* This is the data TLB error on the MPC8xx.  This could be due to
 453 * many reasons, including a dirty update to a pte.  We bail out to
 454 * a higher level function that can handle it.
 455 */
 456        . = 0x1400
 457DataTLBError:
 458        EXCEPTION_PROLOG_0
 459
 460        mfspr   r11, SPRN_DAR
 461        cmpwi   cr0, r11, RPN_PATTERN
 462        beq-    FixupDAR        /* must be a buggy dcbX, icbi insn. */
 463DARFixed:/* Return from dcbx instruction bug workaround */
 464        EXCEPTION_PROLOG_1
 465        EXCEPTION_PROLOG_2
 466        mfspr   r5,SPRN_DSISR
 467        stw     r5,_DSISR(r11)
 468        mfspr   r4,SPRN_DAR
 469        andis.  r10,r5,0x4000
 470        beq+    1f
 471        tlbie   r4
 4721:      li      r10,RPN_PATTERN
 473        mtspr   SPRN_DAR,r10    /* Tag DAR, to be used in DTLB Error */
 474        /* 0x300 is DataAccess exception, needed by bad_page_fault() */
 475        EXC_XFER_LITE(0x300, handle_page_fault)
 476
 477        EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
 478        EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
 479        EXCEPTION(0x1700, Trap_17, unknown_exception, EXC_XFER_EE)
 480        EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
 481        EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
 482        EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
 483        EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
 484
 485/* On the MPC8xx, these next four traps are used for development
 486 * support of breakpoints and such.  Someday I will get around to
 487 * using them.
 488 */
 489        EXCEPTION(0x1c00, Trap_1c, unknown_exception, EXC_XFER_EE)
 490        EXCEPTION(0x1d00, Trap_1d, unknown_exception, EXC_XFER_EE)
 491        EXCEPTION(0x1e00, Trap_1e, unknown_exception, EXC_XFER_EE)
 492        EXCEPTION(0x1f00, Trap_1f, unknown_exception, EXC_XFER_EE)
 493
 494        . = 0x2000
 495
 496/* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions
 497 * by decoding the registers used by the dcbx instruction and adding them.
 498 * DAR is set to the calculated address.
 499 */
 500 /* define if you don't want to use self modifying code */
 501#define NO_SELF_MODIFYING_CODE
 502FixupDAR:/* Entry point for dcbx workaround. */
 503        mtspr   SPRN_SPRG_SCRATCH2, r10
 504        /* fetch instruction from memory. */
 505        mfspr   r10, SPRN_SRR0
 506        andis.  r11, r10, 0x8000        /* Address >= 0x80000000 */
 507        mfspr   r11, SPRN_M_TW  /* Get level 1 table */
 508        beq     3f
 509        lis     r11, (swapper_pg_dir-PAGE_OFFSET)@ha
 510        /* Insert level 1 index */
 5113:      rlwimi  r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
 512        lwz     r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11)        /* Get the level 1 entry */
 513        rlwinm  r11, r11,0,0,19 /* Extract page descriptor page address */
 514        /* Insert level 2 index */
 515        rlwimi  r11, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
 516        lwz     r11, 0(r11)     /* Get the pte */
 517        /* concat physical page address(r11) and page offset(r10) */
 518        rlwimi  r11, r10, 0, 32 - PAGE_SHIFT, 31
 519        lwz     r11,0(r11)
 520/* Check if it really is a dcbx instruction. */
 521/* dcbt and dcbtst does not generate DTLB Misses/Errors,
 522 * no need to include them here */
 523        xoris   r10, r11, 0x7c00        /* check if major OP code is 31 */
 524        rlwinm  r10, r10, 0, 21, 5
 525        cmpwi   cr0, r10, 2028  /* Is dcbz? */
 526        beq+    142f
 527        cmpwi   cr0, r10, 940   /* Is dcbi? */
 528        beq+    142f
 529        cmpwi   cr0, r10, 108   /* Is dcbst? */
 530        beq+    144f            /* Fix up store bit! */
 531        cmpwi   cr0, r10, 172   /* Is dcbf? */
 532        beq+    142f
 533        cmpwi   cr0, r10, 1964  /* Is icbi? */
 534        beq+    142f
 535141:    mfspr   r10,SPRN_SPRG_SCRATCH2
 536        b       DARFixed        /* Nope, go back to normal TLB processing */
 537
 538144:    mfspr   r10, SPRN_DSISR
 539        rlwinm  r10, r10,0,7,5  /* Clear store bit for buggy dcbst insn */
 540        mtspr   SPRN_DSISR, r10
 541142:    /* continue, it was a dcbx, dcbi instruction. */
 542#ifndef NO_SELF_MODIFYING_CODE
 543        andis.  r10,r11,0x1f    /* test if reg RA is r0 */
 544        li      r10,modified_instr@l
 545        dcbtst  r0,r10          /* touch for store */
 546        rlwinm  r11,r11,0,0,20  /* Zero lower 10 bits */
 547        oris    r11,r11,640     /* Transform instr. to a "add r10,RA,RB" */
 548        ori     r11,r11,532
 549        stw     r11,0(r10)      /* store add/and instruction */
 550        dcbf    0,r10           /* flush new instr. to memory. */
 551        icbi    0,r10           /* invalidate instr. cache line */
 552        mfspr   r11, SPRN_SPRG_SCRATCH1 /* restore r11 */
 553        mfspr   r10, SPRN_SPRG_SCRATCH0 /* restore r10 */
 554        isync                   /* Wait until new instr is loaded from memory */
 555modified_instr:
 556        .space  4               /* this is where the add instr. is stored */
 557        bne+    143f
 558        subf    r10,r0,r10      /* r10=r10-r0, only if reg RA is r0 */
 559143:    mtdar   r10             /* store faulting EA in DAR */
 560        mfspr   r10,SPRN_SPRG_SCRATCH2
 561        b       DARFixed        /* Go back to normal TLB handling */
 562#else
 563        mfctr   r10
 564        mtdar   r10                     /* save ctr reg in DAR */
 565        rlwinm  r10, r11, 24, 24, 28    /* offset into jump table for reg RB */
 566        addi    r10, r10, 150f@l        /* add start of table */
 567        mtctr   r10                     /* load ctr with jump address */
 568        xor     r10, r10, r10           /* sum starts at zero */
 569        bctr                            /* jump into table */
 570150:
 571        add     r10, r10, r0    ;b      151f
 572        add     r10, r10, r1    ;b      151f
 573        add     r10, r10, r2    ;b      151f
 574        add     r10, r10, r3    ;b      151f
 575        add     r10, r10, r4    ;b      151f
 576        add     r10, r10, r5    ;b      151f
 577        add     r10, r10, r6    ;b      151f
 578        add     r10, r10, r7    ;b      151f
 579        add     r10, r10, r8    ;b      151f
 580        add     r10, r10, r9    ;b      151f
 581        mtctr   r11     ;b      154f    /* r10 needs special handling */
 582        mtctr   r11     ;b      153f    /* r11 needs special handling */
 583        add     r10, r10, r12   ;b      151f
 584        add     r10, r10, r13   ;b      151f
 585        add     r10, r10, r14   ;b      151f
 586        add     r10, r10, r15   ;b      151f
 587        add     r10, r10, r16   ;b      151f
 588        add     r10, r10, r17   ;b      151f
 589        add     r10, r10, r18   ;b      151f
 590        add     r10, r10, r19   ;b      151f
 591        add     r10, r10, r20   ;b      151f
 592        add     r10, r10, r21   ;b      151f
 593        add     r10, r10, r22   ;b      151f
 594        add     r10, r10, r23   ;b      151f
 595        add     r10, r10, r24   ;b      151f
 596        add     r10, r10, r25   ;b      151f
 597        add     r10, r10, r26   ;b      151f
 598        add     r10, r10, r27   ;b      151f
 599        add     r10, r10, r28   ;b      151f
 600        add     r10, r10, r29   ;b      151f
 601        add     r10, r10, r30   ;b      151f
 602        add     r10, r10, r31
 603151:
 604        rlwinm. r11,r11,19,24,28        /* offset into jump table for reg RA */
 605        beq     152f                    /* if reg RA is zero, don't add it */
 606        addi    r11, r11, 150b@l        /* add start of table */
 607        mtctr   r11                     /* load ctr with jump address */
 608        rlwinm  r11,r11,0,16,10         /* make sure we don't execute this more than once */
 609        bctr                            /* jump into table */
 610152:
 611        mfdar   r11
 612        mtctr   r11                     /* restore ctr reg from DAR */
 613        mtdar   r10                     /* save fault EA to DAR */
 614        mfspr   r10,SPRN_SPRG_SCRATCH2
 615        b       DARFixed                /* Go back to normal TLB handling */
 616
 617        /* special handling for r10,r11 since these are modified already */
 618153:    mfspr   r11, SPRN_SPRG_SCRATCH1 /* load r11 from SPRN_SPRG_SCRATCH1 */
 619        add     r10, r10, r11   /* add it */
 620        mfctr   r11             /* restore r11 */
 621        b       151b
 622154:    mfspr   r11, SPRN_SPRG_SCRATCH0 /* load r10 from SPRN_SPRG_SCRATCH0 */
 623        add     r10, r10, r11   /* add it */
 624        mfctr   r11             /* restore r11 */
 625        b       151b
 626#endif
 627
 628/*
 629 * This is where the main kernel code starts.
 630 */
 631start_here:
 632        /* ptr to current */
 633        lis     r2,init_task@h
 634        ori     r2,r2,init_task@l
 635
 636        /* ptr to phys current thread */
 637        tophys(r4,r2)
 638        addi    r4,r4,THREAD    /* init task's THREAD */
 639        mtspr   SPRN_SPRG_THREAD,r4
 640
 641        /* stack */
 642        lis     r1,init_thread_union@ha
 643        addi    r1,r1,init_thread_union@l
 644        li      r0,0
 645        stwu    r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
 646
 647        bl      early_init      /* We have to do this with MMU on */
 648
 649/*
 650 * Decide what sort of machine this is and initialize the MMU.
 651 */
 652        li      r3,0
 653        mr      r4,r31
 654        bl      machine_init
 655        bl      MMU_init
 656
 657/*
 658 * Go back to running unmapped so we can load up new values
 659 * and change to using our exception vectors.
 660 * On the 8xx, all we have to do is invalidate the TLB to clear
 661 * the old 8M byte TLB mappings and load the page table base register.
 662 */
 663        /* The right way to do this would be to track it down through
 664         * init's THREAD like the context switch code does, but this is
 665         * easier......until someone changes init's static structures.
 666         */
 667        lis     r6, swapper_pg_dir@ha
 668        tophys(r6,r6)
 669#ifdef CONFIG_8xx_CPU6
 670        lis     r4, cpu6_errata_word@h
 671        ori     r4, r4, cpu6_errata_word@l
 672        li      r3, 0x3f80
 673        stw     r3, 12(r4)
 674        lwz     r3, 12(r4)
 675#endif
 676        mtspr   SPRN_M_TW, r6
 677        lis     r4,2f@h
 678        ori     r4,r4,2f@l
 679        tophys(r4,r4)
 680        li      r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
 681        mtspr   SPRN_SRR0,r4
 682        mtspr   SPRN_SRR1,r3
 683        rfi
 684/* Load up the kernel context */
 6852:
 686        SYNC                    /* Force all PTE updates to finish */
 687        tlbia                   /* Clear all TLB entries */
 688        sync                    /* wait for tlbia/tlbie to finish */
 689        TLBSYNC                 /* ... on all CPUs */
 690
 691        /* set up the PTE pointers for the Abatron bdiGDB.
 692        */
 693        tovirt(r6,r6)
 694        lis     r5, abatron_pteptrs@h
 695        ori     r5, r5, abatron_pteptrs@l
 696        stw     r5, 0xf0(r0)    /* Must match your Abatron config file */
 697        tophys(r5,r5)
 698        stw     r6, 0(r5)
 699
 700/* Now turn on the MMU for real! */
 701        li      r4,MSR_KERNEL
 702        lis     r3,start_kernel@h
 703        ori     r3,r3,start_kernel@l
 704        mtspr   SPRN_SRR0,r3
 705        mtspr   SPRN_SRR1,r4
 706        rfi                     /* enable MMU and jump to start_kernel */
 707
 708/* Set up the initial MMU state so we can do the first level of
 709 * kernel initialization.  This maps the first 8 MBytes of memory 1:1
 710 * virtual to physical.  Also, set the cache mode since that is defined
 711 * by TLB entries and perform any additional mapping (like of the IMMR).
 712 * If configured to pin some TLBs, we pin the first 8 Mbytes of kernel,
 713 * 24 Mbytes of data, and the 8M IMMR space.  Anything not covered by
 714 * these mappings is mapped by page tables.
 715 */
 716initial_mmu:
 717        tlbia                   /* Invalidate all TLB entries */
 718/* Always pin the first 8 MB ITLB to prevent ITLB
 719   misses while mucking around with SRR0/SRR1 in asm
 720*/
 721        lis     r8, MI_RSV4I@h
 722        ori     r8, r8, 0x1c00
 723
 724        mtspr   SPRN_MI_CTR, r8 /* Set instruction MMU control */
 725
 726#ifdef CONFIG_PIN_TLB
 727        lis     r10, (MD_RSV4I | MD_RESETVAL)@h
 728        ori     r10, r10, 0x1c00
 729        mr      r8, r10
 730#else
 731        lis     r10, MD_RESETVAL@h
 732#endif
 733#ifndef CONFIG_8xx_COPYBACK
 734        oris    r10, r10, MD_WTDEF@h
 735#endif
 736        mtspr   SPRN_MD_CTR, r10        /* Set data TLB control */
 737
 738        /* Now map the lower 8 Meg into the TLBs.  For this quick hack,
 739         * we can load the instruction and data TLB registers with the
 740         * same values.
 741         */
 742        lis     r8, KERNELBASE@h        /* Create vaddr for TLB */
 743        ori     r8, r8, MI_EVALID       /* Mark it valid */
 744        mtspr   SPRN_MI_EPN, r8
 745        mtspr   SPRN_MD_EPN, r8
 746        li      r8, MI_PS8MEG           /* Set 8M byte page */
 747        ori     r8, r8, MI_SVALID       /* Make it valid */
 748        mtspr   SPRN_MI_TWC, r8
 749        mtspr   SPRN_MD_TWC, r8
 750        li      r8, MI_BOOTINIT         /* Create RPN for address 0 */
 751        mtspr   SPRN_MI_RPN, r8         /* Store TLB entry */
 752        mtspr   SPRN_MD_RPN, r8
 753        lis     r8, MI_Kp@h             /* Set the protection mode */
 754        mtspr   SPRN_MI_AP, r8
 755        mtspr   SPRN_MD_AP, r8
 756
 757        /* Map another 8 MByte at the IMMR to get the processor
 758         * internal registers (among other things).
 759         */
 760#ifdef CONFIG_PIN_TLB
 761        addi    r10, r10, 0x0100
 762        mtspr   SPRN_MD_CTR, r10
 763#endif
 764        mfspr   r9, 638                 /* Get current IMMR */
 765        andis.  r9, r9, 0xff80          /* Get 8Mbyte boundary */
 766
 767        mr      r8, r9                  /* Create vaddr for TLB */
 768        ori     r8, r8, MD_EVALID       /* Mark it valid */
 769        mtspr   SPRN_MD_EPN, r8
 770        li      r8, MD_PS8MEG           /* Set 8M byte page */
 771        ori     r8, r8, MD_SVALID       /* Make it valid */
 772        mtspr   SPRN_MD_TWC, r8
 773        mr      r8, r9                  /* Create paddr for TLB */
 774        ori     r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
 775        mtspr   SPRN_MD_RPN, r8
 776
 777#ifdef CONFIG_PIN_TLB
 778        /* Map two more 8M kernel data pages.
 779        */
 780        addi    r10, r10, 0x0100
 781        mtspr   SPRN_MD_CTR, r10
 782
 783        lis     r8, KERNELBASE@h        /* Create vaddr for TLB */
 784        addis   r8, r8, 0x0080          /* Add 8M */
 785        ori     r8, r8, MI_EVALID       /* Mark it valid */
 786        mtspr   SPRN_MD_EPN, r8
 787        li      r9, MI_PS8MEG           /* Set 8M byte page */
 788        ori     r9, r9, MI_SVALID       /* Make it valid */
 789        mtspr   SPRN_MD_TWC, r9
 790        li      r11, MI_BOOTINIT        /* Create RPN for address 0 */
 791        addis   r11, r11, 0x0080        /* Add 8M */
 792        mtspr   SPRN_MD_RPN, r11
 793
 794        addi    r10, r10, 0x0100
 795        mtspr   SPRN_MD_CTR, r10
 796
 797        addis   r8, r8, 0x0080          /* Add 8M */
 798        mtspr   SPRN_MD_EPN, r8
 799        mtspr   SPRN_MD_TWC, r9
 800        addis   r11, r11, 0x0080        /* Add 8M */
 801        mtspr   SPRN_MD_RPN, r11
 802#endif
 803
 804        /* Since the cache is enabled according to the information we
 805         * just loaded into the TLB, invalidate and enable the caches here.
 806         * We should probably check/set other modes....later.
 807         */
 808        lis     r8, IDC_INVALL@h
 809        mtspr   SPRN_IC_CST, r8
 810        mtspr   SPRN_DC_CST, r8
 811        lis     r8, IDC_ENABLE@h
 812        mtspr   SPRN_IC_CST, r8
 813#ifdef CONFIG_8xx_COPYBACK
 814        mtspr   SPRN_DC_CST, r8
 815#else
 816        /* For a debug option, I left this here to easily enable
 817         * the write through cache mode
 818         */
 819        lis     r8, DC_SFWT@h
 820        mtspr   SPRN_DC_CST, r8
 821        lis     r8, IDC_ENABLE@h
 822        mtspr   SPRN_DC_CST, r8
 823#endif
 824        blr
 825
 826
 827/*
 828 * Set up to use a given MMU context.
 829 * r3 is context number, r4 is PGD pointer.
 830 *
 831 * We place the physical address of the new task page directory loaded
 832 * into the MMU base register, and set the ASID compare register with
 833 * the new "context."
 834 */
 835_GLOBAL(set_context)
 836
 837#ifdef CONFIG_BDI_SWITCH
 838        /* Context switch the PTE pointer for the Abatron BDI2000.
 839         * The PGDIR is passed as second argument.
 840         */
 841        lis     r5, KERNELBASE@h
 842        lwz     r5, 0xf0(r5)
 843        stw     r4, 0x4(r5)
 844#endif
 845
 846        /* Register M_TW will contain base address of level 1 table minus the
 847         * lower part of the kernel PGDIR base address, so that all accesses to
 848         * level 1 table are done relative to lower part of kernel PGDIR base
 849         * address.
 850         */
 851        li      r5, (swapper_pg_dir-PAGE_OFFSET)@l
 852        sub     r4, r4, r5
 853        tophys  (r4, r4)
 854#ifdef CONFIG_8xx_CPU6
 855        lis     r6, cpu6_errata_word@h
 856        ori     r6, r6, cpu6_errata_word@l
 857        li      r7, 0x3f80
 858        stw     r7, 12(r6)
 859        lwz     r7, 12(r6)
 860#endif
 861        mtspr   SPRN_M_TW, r4           /* Update pointeur to level 1 table */
 862#ifdef CONFIG_8xx_CPU6
 863        li      r7, 0x3380
 864        stw     r7, 12(r6)
 865        lwz     r7, 12(r6)
 866#endif
 867        mtspr   SPRN_M_CASID, r3        /* Update context */
 868        SYNC
 869        blr
 870
 871#ifdef CONFIG_8xx_CPU6
 872/* It's here because it is unique to the 8xx.
 873 * It is important we get called with interrupts disabled.  I used to
 874 * do that, but it appears that all code that calls this already had
 875 * interrupt disabled.
 876 */
 877        .globl  set_dec_cpu6
 878set_dec_cpu6:
 879        lis     r7, cpu6_errata_word@h
 880        ori     r7, r7, cpu6_errata_word@l
 881        li      r4, 0x2c00
 882        stw     r4, 8(r7)
 883        lwz     r4, 8(r7)
 884        mtspr   22, r3          /* Update Decrementer */
 885        SYNC
 886        blr
 887#endif
 888
 889/*
 890 * We put a few things here that have to be page-aligned.
 891 * This stuff goes at the beginning of the data segment,
 892 * which is page-aligned.
 893 */
 894        .data
 895        .globl  sdata
 896sdata:
 897        .globl  empty_zero_page
 898        .align  PAGE_SHIFT
 899empty_zero_page:
 900        .space  PAGE_SIZE
 901
 902        .globl  swapper_pg_dir
 903swapper_pg_dir:
 904        .space  PGD_TABLE_SIZE
 905
 906/* Room for two PTE table poiners, usually the kernel and current user
 907 * pointer to their respective root page table (pgdir).
 908 */
 909abatron_pteptrs:
 910        .space  8
 911
 912#ifdef CONFIG_8xx_CPU6
 913        .globl  cpu6_errata_word
 914cpu6_errata_word:
 915        .space  16
 916#endif
 917
 918