linux-old/arch/ppc/kernel/head_44x.S
<<
>>
Prefs
   1/*
   2 * arch/ppc/kernel/head_44x.S
   3 *
   4 * Kernel execution entry point code.
   5 *
   6 *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
   7 *      Initial PowerPC version.
   8 *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
   9 *      Rewritten for PReP
  10 *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
  11 *      Low-level exception handers, MMU support, and rewrite.
  12 *    Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
  13 *      PowerPC 8xx modifications.
  14 *    Copyright (c) 1998-1999 TiVo, Inc.
  15 *      PowerPC 403GCX modifications.
  16 *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  17 *      PowerPC 403GCX/405GP modifications.
  18 *    Copyright 2000 MontaVista Software Inc.
  19 *      PPC405 modifications
  20 *      PowerPC 403GCX/405GP modifications.
  21 *      Author: MontaVista Software, Inc.
  22 *              frank_rowand@mvista.com or source@mvista.com
  23 *              debbie_chu@mvista.com
  24 *    Copyright 2002-2004 MontaVista Software, Inc.
  25 *      PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org>
  26 *
  27 * This program is free software; you can redistribute  it and/or modify it
  28 * under  the terms of  the GNU General Public License as published by the
  29 * Free Software Foundation;  either version 2 of the  License, or (at your
  30 * option) any later version.
  31 */
  32
  33#include <linux/config.h>
  34#include <asm/processor.h>
  35#include <asm/page.h>
  36#include <asm/mmu.h>
  37#include <asm/pgtable.h>
  38#include <asm/ibm44x.h>
  39#include <asm/cputable.h>
  40#include <asm/ppc_asm.h>
  41#include "ppc_defs.h"
  42
  43/*
  44 * Preprocessor Defines
  45 */
  46
  47#define STND_EXC        0
  48#define CRIT_EXC        1
  49
  50#ifdef CONFIG_440A
  51#define MCHK_EXC        2
  52#define __SPRN_MCSRR0   SPRN_MCSRR0
  53#define __SPRN_MCSRR1   SPRN_MCSRR1
  54#else
  55#define MCHK_EXC        CRIT_EXC
  56#define __SPRN_MCSRR0   SPRN_CSRR0
  57#define __SPRN_MCSRR1   SPRN_CSRR1
  58#endif
  59
  60/*
  61 * Macros
  62 */
  63
  64#define SET_IVOR(vector_number, vector_label)           \
  65                li      r26,vector_label@l;             \
  66                mtspr   SPRN_IVOR##vector_number,r26;   \
  67                sync
  68                                        
  69/* As with the other PowerPC ports, it is expected that when code
  70 * execution begins here, the following registers contain valid, yet
  71 * optional, information:
  72 *
  73 *   r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
  74 *   r4 - Starting address of the init RAM disk
  75 *   r5 - Ending address of the init RAM disk
  76 *   r6 - Start of kernel command line string (e.g. "mem=128")
  77 *   r7 - End of kernel command line string
  78 *
  79 */ 
  80        .text
  81_GLOBAL(_stext)
  82_GLOBAL(_start)
  83        /*
  84         * Reserve a word at a fixed location to store the address
  85         * of abatron_pteptrs
  86         */
  87        nop
  88
  89/*
  90 * Save parameters we are passed
  91 */
  92        mr      r31,r3
  93        mr      r30,r4
  94        mr      r29,r5
  95        mr      r28,r6
  96        mr      r27,r7
  97        li      r24,0           /* CPU number */
  98
  99/*
 100 * Set up the initial MMU state
 101 *
 102 * We are still executing code at the virtual address
 103 * mappings set by the firmware for the base of RAM.
 104 *
 105 * We first invalidate all TLB entries but the one
 106 * we are running from.  We then load the KERNELBASE
 107 * mappings so we can begin to use kernel addresses
 108 * natively and so the interrupt vector locations are
 109 * permanently pinned (necessary since Book E
 110 * implementations always have translation enabled).
 111 *
 112 * TODO: Use the known TLB entry we are running from to
 113 *       determine which physical region we are located
 114 *       in.  This can be used to determine where in RAM
 115 *       (on a shared CPU system) or PCI memory space
 116 *       (on a DRAMless system) we are located.
 117 *       For now, we assume a perfect world which means
 118 *       we are located at the base of DRAM (physical 0).
 119 */
 120
 121/*
 122 * Search TLB for entry that we are currently using.
 123 * Invalidate all entries but the one we are using.
 124 */
 125        /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
 126        mfspr   r3,SPRN_MMUCR                   /* Get MMUCR */
 127        lis     r4,PPC44x_MMUCR_STS@h
 128        ori     r4,r4,PPC44x_MMUCR_TID@l        /* Create mask */
 129        andc    r3,r3,r4                        /* Clear out TID/STS bits */
 130        mfspr   r4,SPRN_PID                     /* Get PID */
 131        or      r3,r3,r4                        /* Set TID bits */
 132        mfmsr   r5                              /* Get MSR */
 133        andi.   r5,r5,MSR_IS@l                  /* TS=1? */
 134        beq     wmmucr                          /* If not, leave STS=0 */
 135        oris    r3,r3,PPC44x_MMUCR_STS@h        /* Set STS=1 */
 136wmmucr: mtspr   SPRN_MMUCR,r3                   /* Put MMUCR */
 137        sync
 138        
 139        bl      invstr                          /* Find our address */
 140invstr: mflr    r5                              /* Make it accessible */
 141        tlbsx   r23,0,r5                        /* Find entry we are in */
 142        li      r4,0                            /* Start at TLB entry 0 */
 143        li      r3,0                            /* Set PAGEID inval value */
 1441:      cmpw    r23,r4                          /* Is this our entry? */
 145        beq     skpinv                          /* If so, skip the inval */
 146        tlbwe   r3,r4,PPC44x_TLB_PAGEID         /* If not, inval the entry */
 147skpinv: addi    r4,r4,1                         /* Increment */
 148        cmpwi   r4,64                           /* Are we done? */
 149        bne     1b                              /* If not, repeat */
 150        isync                                   /* If so, context change */
 151
 152/*
 153 * Configure and load pinned entries into TLB slots 62 and 63.
 154 */
 155
 156        lis     r3,KERNELBASE@h         /* Load the kernel virtual address */
 157        ori     r3,r3,KERNELBASE@l
 158
 159        /* Kernel is at the base of RAM */
 160        li r4, 0                        /* Load the kernel physical address */
 161
 162        /* Load the kernel PID = 0 */
 163        li      r0,0
 164        mtspr   SPRN_PID,r0
 165        sync
 166
 167        /* Load the kernel TID  = 0 */
 168        mfspr   r5,SPRN_MMUCR
 169        lis     r6, PPC44x_MMUCR_TID@h
 170        ori     r6,r6,PPC44x_MMUCR_TID@l
 171        andc    r5,r5,r6
 172        mtspr   SPRN_MMUCR,r5
 173        sync
 174
 175        /* pageid fields */
 176        clrrwi  r3,r3,10                /* Mask off the effective page number */
 177        ori     r3,r3,(PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M))
 178
 179        /* xlat fields */
 180        clrrwi  r4,r4,10                /* Mask off the real page number */
 181                                        /* ERPN is 0 for first 4GB page */
 182
 183        /* attrib fields */
 184        /* Added guarded bit to protect against speculative loads/stores */
 185        li      r5,0
 186        ori     r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
 187
 188        li      r0,62                    /* TLB slot 62 */
 189
 190        tlbwe   r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
 191        tlbwe   r4,r0,PPC44x_TLB_XLAT   /* Load the translation fields */
 192        tlbwe   r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
 193
 194        /* Force context change */
 195        mfmsr   r0
 196        mtspr   SRR1, r0
 197        lis     r0,3f@h
 198        ori     r0,r0,3f@l
 199        mtspr   SRR0,r0
 200        sync
 201        rfi
 202
 203        /* If necessary, invalidate original entry we used */
 2043:      cmpwi   r23,62
 205        beq     4f
 206        li      r6,0
 207        tlbwe   r6,r23,PPC44x_TLB_PAGEID
 208        sync
 209
 2104:      ori     r3,r3,PPC44x_TLB_TS     /* TS = 1 */
 211
 212        li      r0,63                   /* TLB slot 63 */
 213
 214        tlbwe   r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
 215        tlbwe   r4,r0,PPC44x_TLB_XLAT   /* Load the translation fields */
 216        tlbwe   r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
 217
 218#ifdef CONFIG_SERIAL_TEXT_DEBUG
 219        /*
 220         * Add temporary UART mapping for early debug.  This
 221         * mapping must be identical to that used by the early
 222         * bootloader code since the same asm/serial.h parameters
 223         * are used for polled operation.
 224         */
 225        /* pageid fields */
 226        lis     r3,0xe000               
 227        ori     r3,r3,(PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M))
 228
 229        /* xlat fields */
 230        lis     r4,0x4000               /* RPN is 0x40000000 */
 231        ori     r4,r4,0x0001            /* ERPN is 1 for second 4GB page */
 232
 233        /* attrib fields */
 234        li      r5,0
 235        ori     r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G)
 236
 237        li      r0,60                    /* TLB slot 60 */
 238
 239        tlbwe   r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
 240        tlbwe   r4,r0,PPC44x_TLB_XLAT   /* Load the translation fields */
 241        tlbwe   r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
 242
 243        ori     r3,r3,PPC44x_TLB_TS     /* Translation state 1 */
 244
 245        li      r0,61                   /* TLB slot 61 */
 246
 247        tlbwe   r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
 248        tlbwe   r4,r0,PPC44x_TLB_XLAT   /* Load the translation fields */
 249        tlbwe   r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
 250#endif /* CONFIG_SERIAL_TEXT_DEBUG */
 251
 252        /* Force context change */
 253        isync
 254
 255        /* Establish the interrupt vector offsets */
 256        SET_IVOR(0,  CriticalInput);
 257        SET_IVOR(1,  MachineCheck);
 258        SET_IVOR(2,  DataStorage);
 259        SET_IVOR(3,  InstructionStorage);
 260        SET_IVOR(4,  ExternalInput);
 261        SET_IVOR(5,  Alignment);
 262        SET_IVOR(6,  Program);
 263        SET_IVOR(7,  FloatingPointUnavailable);
 264        SET_IVOR(8,  SystemCall);
 265        SET_IVOR(9,  AuxillaryProcessorUnavailable);
 266        SET_IVOR(10, Decrementer);
 267        SET_IVOR(11, FixedIntervalTimer);
 268        SET_IVOR(12, WatchdogTimer);
 269        SET_IVOR(13, DataTLBError);
 270        SET_IVOR(14, InstructionTLBError);
 271        SET_IVOR(15, Debug);
 272
 273        /* Establish the interrupt vector base */
 274        lis     r4,interrupt_base@h     /* IVPR only uses the high 16-bits */
 275        mtspr   SPRN_IVPR,r4
 276
 277        /*
 278         * This is where the main kernel code starts.
 279         */ 
 280
 281        /* ptr to current */
 282        lis     r2,init_task_union@h
 283        ori     r2,r2,init_task_union@l
 284
 285        /* ptr to current thread */
 286        addi    r4,r2,THREAD    /* init task's THREAD */
 287        mtspr   SPRG3,r4
 288        li      r3,0
 289        mtspr   SPRG2,r3        /* 0 => r1 has kernel sp */
 290
 291        /* stack */
 292        addi    r1,r2,TASK_UNION_SIZE
 293        li      r0,0
 294        stwu    r0,-STACK_FRAME_OVERHEAD(r1)
 295
 296        bl      early_init
 297
 298/*
 299 * Decide what sort of machine this is and initialize the MMU.
 300 */
 301        mr      r3,r31
 302        mr      r4,r30
 303        mr      r5,r29
 304        mr      r6,r28
 305        mr      r7,r27
 306        bl      machine_init
 307        bl      MMU_init
 308
 309        /* Setup PTE pointers for the Abatron bdiGDB */
 310        lis     r6, swapper_pg_dir@h
 311        ori     r6, r6, swapper_pg_dir@l
 312        lis     r5, abatron_pteptrs@h
 313        ori     r5, r5, abatron_pteptrs@l
 314        lis     r4, KERNELBASE@h
 315        ori     r4, r4, KERNELBASE@l
 316        stw     r5, 0(r4)       /* Save abatron_pteptrs at a fixed location */
 317        stw     r6, 0(r5)
 318
 319        /* Let's move on */
 320        lis     r4,start_kernel@h
 321        ori     r4,r4,start_kernel@l
 322        lis     r3,MSR_KERNEL@h
 323        ori     r3,r3,MSR_KERNEL@l
 324        mtspr   SRR0,r4
 325        mtspr   SRR1,r3
 326        rfi                     /* change context and jump to start_kernel */
 327
 328/*
 329 * Interrupt vector entry code
 330 *
 331 * The Book E MMUs are always on so we don't need to handle
 332 * interrupts in real mode as with previous PPC processors. In
 333 * this case we handle interrupts in the kernel virtual address
 334 * space.
 335 *
 336 * Interrupt vectors are dynamically placed relative to the 
 337 * interrupt prefix as determined by the address of interrupt_base.
 338 * The interrupt vectors offsets are programmed using the labels
 339 * for each interrupt vector entry.
 340 *
 341 * Interrupt vectors must be aligned on a 16 byte boundary.
 342 * We align on a 32 byte cache line boundary for good measure.
 343 */
 344
 345#define COMMON_PROLOG                                                        \
 3460:      mtspr   SPRN_SPRG0,r20;         /* We need r20, move it to SPRG0   */\
 347        mtspr   SPRN_SPRG1,r21;         /* We need r21, move it to SPRG1   */\
 348        mfcr    r20;                    /* We need the CR, move it to r20  */\
 349        mfspr   r21,SPRN_SPRG2;         /* Exception stack to use          */\
 350        cmpwi   cr0,r21,0;              /* From user mode or RTAS?         */\
 351        bne     1f;                     /* Not RTAS, branch                */\
 352        mr      r21, r1;                /* Move vka in r1 to r21           */\
 353        subi    r21,r21,INT_FRAME_SIZE; /* Allocate an exception frame     */\
 3541:      stw     r20,_CCR(r21);          /* Save CR on the stack            */\
 355        stw     r22,GPR22(r21);         /* Save r22 on the stack           */\
 356        stw     r23,GPR23(r21);         /* r23 Save on the stack           */\
 357        mfspr   r20,SPRN_SPRG0;         /* Get r20 back out of SPRG0       */\
 358        stw     r20,GPR20(r21);         /* Save r20 on the stack           */\
 359        mfspr   r22,SPRN_SPRG1;         /* Get r21 back out of SPRG0       */\
 360        stw     r22,GPR21(r21);         /* Save r21 on the stack           */\
 361        mflr    r20;                                                         \
 362        stw     r20,_LINK(r21);         /* Save LR on the stack            */\
 363        mfctr   r22;                                                         \
 364        stw     r22,_CTR(r21);          /* Save CTR on the stack           */\
 365        mfspr   r20,XER;                                                     \
 366        stw     r20,_XER(r21);          /* Save XER on the stack           */
 367
 368#define COMMON_EPILOG                                                        \
 369        stw     r0,GPR0(r21);           /* Save r0 on the stack            */\
 370        stw     r1,GPR1(r21);           /* Save r1 on the stack            */\
 371        stw     r2,GPR2(r21);           /* Save r2 on the stack            */\
 372        stw     r1,0(r21);                                                   \
 373        mr      r1,r21;                 /* Set-up new kernel stack pointer */\
 374        SAVE_4GPRS(3, r21);             /* Save r3 through r6 on the stack */\
 375        SAVE_GPR(7, r21);               /* Save r7 on the stack            */
 376
 377#define STND_EXCEPTION_PROLOG                                                \
 378        COMMON_PROLOG;                                                       \
 379        mfspr   r22,SPRN_SRR0;          /* Faulting instruction address    */\
 380        lis     r20,MSR_WE@h;                                                \
 381        mfspr   r23,SPRN_SRR1;          /* MSR at the time of fault        */\
 382        andc    r23,r23,r20;            /* disable processor wait state    */\
 383        COMMON_EPILOG;
 384
 385#define CRIT_EXCEPTION_PROLOG                                                \
 386        COMMON_PROLOG;                                                       \
 387        mfspr   r22,SPRN_CSRR0;         /* Faulting instruction address    */\
 388        lis     r20,MSR_WE@h;                                                \
 389        mfspr   r23,SPRN_CSRR1;         /* MSR at the time of fault        */\
 390        andc    r23,r23,r20;            /* disable processor wait state    */\
 391        COMMON_EPILOG;
 392
 393#define START_EXCEPTION(label) \
 394        .align 5;              \
 395label:
 396
 397#define FINISH_EXCEPTION(n, func)                                            \
 398        bl      transfer_to_handler;                                         \
 399        .long   func;                                                        \
 400        .long   ret_from_except;                                             \
 401        .long   n
 402
 403#define STND_EXCEPTION(n, label, func)                                       \
 404        START_EXCEPTION(label)                                               \
 405        STND_EXCEPTION_PROLOG;                                               \
 406        addi    r3,r1,STACK_FRAME_OVERHEAD;                                  \
 407        li      r7,STND_EXC;                                                 \
 408        li      r20,MSR_KERNEL;                                              \
 409        FINISH_EXCEPTION(n, func)
 410
 411#define CRIT_EXCEPTION(n, label, func)                                       \
 412        START_EXCEPTION(label)                                               \
 413        CRIT_EXCEPTION_PROLOG;                                               \
 414        addi    r3,r1,STACK_FRAME_OVERHEAD;                                  \
 415        li      r7,CRIT_EXC;                                                 \
 416        li      r20,MSR_KERNEL;                                              \
 417        FINISH_EXCEPTION(n, func)
 418
 419interrupt_base:
 420
 421        /* Critical Input Interrupt */
 422        CRIT_EXCEPTION(0x100, CriticalInput,UnknownException);
 423
 424        /* Machine Check Interrupt */
 425        /* TODO: provide bus error register status */
 426        START_EXCEPTION(MachineCheck)
 427        COMMON_PROLOG;
 428        mfspr   r22,__SPRN_MCSRR0       /* Faulting instruction address    */
 429        lis     r20,MSR_WE@h
 430        mfspr   r23,__SPRN_MCSRR1       /* MSR at the time of fault        */
 431        andc    r23,r23,r20             /* disable processor wait state    */
 432        COMMON_EPILOG;
 433#ifdef CONFIG_440A
 434        lis     r20,MCSR_MCS@h
 435        mfspr   r4,SPRN_MCSR            /* We may want to access original
 436                                           MCSR as arg2 in the future. --ebs */
 437        mtspr   SPRN_MCSR,r20           /* Clear Machine Check Summary field */
 438#endif  
 439        mfspr   r5,SPRN_ESR             /* Grab the ESR, save it */
 440        stw     r5,_ESR(r21)
 441        addi    r3,r1,STACK_FRAME_OVERHEAD
 442        li      r7,MCHK_EXC
 443        li      r20,MSR_KERNEL
 444        FINISH_EXCEPTION(0x200, MachineCheckException)
 445
 446        /* Data Storage Interrupt */
 447        START_EXCEPTION(DataStorage)
 448        mtspr   SPRG0, r20              /* Save some working registers */
 449        mtspr   SPRG1, r21
 450        mtspr   SPRG4W, r22
 451        mtspr   SPRG5W, r23
 452        mtspr   SPRG6W, r24
 453        mfcr    r21
 454        mtspr   SPRG7W, r21
 455
 456        /*
 457         * Check if it was a store fault, if not then bail
 458         * because a user tried to access a kernel or
 459         * read-protected page.  Otherwise, get the
 460         * offending address and handle it.
 461         */
 462        mfspr   r20, SPRN_ESR
 463        andis.  r20, r20, ESR_DST@h
 464        beq     2f
 465
 466        mfspr   r20, SPRN_DEAR          /* Get faulting address */
 467
 468        /* If we are faulting a kernel address, we have to use the
 469         * kernel page tables.
 470         */
 471        andis.  r21, r20, 0x8000
 472        beq     3f
 473        lis     r21, swapper_pg_dir@h
 474        ori     r21, r21, swapper_pg_dir@l
 475
 476        mfspr   r22,SPRN_MMUCR          /* Set TID to 0 */
 477        li      r23,PPC44x_MMUCR_TID@l
 478        andc    r22,r22,r23
 479        mtspr   SPRN_MMUCR,r22
 480
 481        b       4f
 482
 483        /* Get the PGD for the current thread */
 4843:
 485        mfspr   r21,SPRG3
 486        lwz     r21,PGDIR(r21)
 487
 488        /* Load MMUCR with our PID and STS=<current TS> */
 489        mfspr   r22,SPRN_MMUCR                  /* Get MMUCR */
 490        lis     r23,PPC44x_MMUCR_STS@h
 491        ori     r23,r23,PPC44x_MMUCR_TID@l      /* Create mask */
 492        andc    r22,r22,r23                     /* Clear out TID/STS bits */
 493        mfspr   r23,SPRN_PID                    /* Get PID */
 494        or      r22,r22,r23                     /* Set TID bits */
 495        mfspr   r24,SPRN_SRR1                   /* Get SRR1 */
 496        andi.   r24,r24,MSR_IS@l                /* TS=1? */
 497        beq     4f                              /* If not, leave STS=0 */
 498        oris    r22,r22,PPC44x_MMUCR_STS@h      /* Set STS=1 */
 499        mtspr   SPRN_MMUCR,r22
 5004:
 501        rlwinm  r22, r20, 13, 19, 29    /* Compute pgdir/pmd offset */
 502        lwzx    r21, r22, r21           /* Get pgd/pmd entry */
 503        rlwinm. r22, r21, 0, 0, 20      /* Extract pt base address */
 504        beq     2f                      /* Bail if no table */
 505
 506        rlwimi  r22, r20, 23, 20, 28    /* Compute pte address */
 507        lwz     r21, 4(r22)             /* Get pte entry */
 508        
 509        andi.   r23, r21, _PAGE_RW      /* Is it writeable? */
 510        beq     2f                      /* Bail if not */
 511
 512        /* Update 'changed'.
 513        */
 514        ori     r21, r21, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
 515        stw     r21, 4(r22)             /* Update Linux page table */
 516
 517        /* FIXME: Staticly setting some permissions */
 518        li      r23, 0x003f             /* Set UX,UW,UR,SX,SW,SR */
 519        andi.   r21,r21,0xffff          /* Clear MS 16 bits */
 520        /* FIXME: Force attributes */
 521        ori     r21,r21, 0x0100         /* Set G */
 522        /* FIXME: Already set in PTE */
 523        rlwimi  r21,r23,0,26,31         /* Insert static perms */
 524
 525        lis     r23,0xffff
 526        ori     r23,r23,0x0fff                  /* Set U0-U3 mask */
 527        and     r21,r21,r23                     /* Clear U0-U3 */
 528
 529        /* find the TLB index that caused the fault.  It has to be here. */
 530        tlbsx   r24, 0, r20
 531
 532        tlbwe   r21, r24, PPC44x_TLB_ATTRIB             /* Write ATTRIB */
 533
 534        /* Done...restore registers and get out of here.
 535        */
 536        mfspr   r21, SPRG7R
 537        mtcr    r21
 538        mfspr   r24, SPRG6R
 539        mfspr   r23, SPRG5R
 540        mfspr   r22, SPRG4R
 541
 542        mfspr   r21, SPRG1
 543        mfspr   r20, SPRG0
 544        rfi                     /* Force context change */
 545
 5462:
 547        /*
 548         * The bailout.  Restore registers to pre-exception conditions
 549         * and call the heavyweights to help us out.
 550         */
 551        mfspr   r21, SPRG7R
 552        mtcr    r21
 553        mfspr   r24, SPRG6R
 554        mfspr   r23, SPRG5R
 555        mfspr   r22, SPRG4R
 556
 557        mfspr   r21, SPRG1
 558        mfspr   r20, SPRG0
 559        b       data_access
 560
 561        /* Instruction Storage Interrupt */
 562        START_EXCEPTION(InstructionStorage)
 563        STND_EXCEPTION_PROLOG
 564        mfspr   r5,SPRN_ESR             /* Grab the ESR, save it */
 565        stw     r5,_ESR(r21)
 566        mr      r4,r22                  /* Pass SRR0 as arg2 */
 567        li      r5,0                    /* Pass zero as arg3 */
 568        addi    r3,r1,STACK_FRAME_OVERHEAD
 569        li      r7,STND_EXC
 570        li      r20,MSR_KERNEL
 571        rlwimi  r20,r23,0,16,16         /* Copy EE bit from the saved MSR */
 572        FINISH_EXCEPTION(0x400, do_page_fault)/* do_page_fault(regs, SRR0, SRR1) */
 573
 574        /* External Input Interrupt */
 575        START_EXCEPTION(ExternalInput)
 576        STND_EXCEPTION_PROLOG
 577        addi    r3,r1,STACK_FRAME_OVERHEAD
 578        li      r7,STND_EXC
 579        li      r20,MSR_KERNEL
 580        li      r4,0
 581        bl      transfer_to_handler
 582_GLOBAL(do_IRQ_intercept)
 583        .long   do_IRQ
 584        .long   ret_from_intercept
 585        .long   0x500
 586
 587        /* Alignment Interrupt */
 588        START_EXCEPTION(Alignment)
 589        STND_EXCEPTION_PROLOG
 590        mfspr   r4,SPRN_DEAR            /* Grab the DEAR and save it */
 591        stw     r4,_DEAR(r21)
 592        addi    r3,r1,STACK_FRAME_OVERHEAD
 593        li      r7,STND_EXC
 594        li      r20,MSR_KERNEL
 595        rlwimi  r20,r23,0,16,16         /* Copy EE bit from the saved MSR */
 596        FINISH_EXCEPTION(0x600, AlignmentException)
 597
 598        /* Program Interrupt */
 599        START_EXCEPTION(Program)
 600        STND_EXCEPTION_PROLOG
 601        mfspr   r4,SPRN_ESR             /* Grab the ESR, save it */
 602        stw     r4,_ESR(r21)
 603        addi    r3,r1,STACK_FRAME_OVERHEAD
 604        li      r7,STND_EXC
 605        li      r20,MSR_KERNEL
 606        rlwimi  r20,r23,0,16,16         /* Copy EE bit from the saved MSR */
 607        FINISH_EXCEPTION(0x700, ProgramCheckException)
 608
 609        /* Floating Point Unavailable Interrupt */
 610        STND_EXCEPTION(0x2010, FloatingPointUnavailable,UnknownException);
 611
 612        /* System Call Interrupt */
 613        START_EXCEPTION(SystemCall)
 614        STND_EXCEPTION_PROLOG
 615        stw     r3,ORIG_GPR3(r21)
 616        li      r7,STND_EXC
 617        li      r20,MSR_KERNEL
 618        rlwimi  r20,r23,0,16,16         /* Copy EE bit from the saved MSR */
 619        FINISH_EXCEPTION(0xc00, DoSyscall)
 620
 621        /* Auxillary Processor Unavailable */
 622        STND_EXCEPTION(0x2020, AuxillaryProcessorUnavailable,UnknownException);
 623
 624        /* Decrementer Interrupt */
 625        START_EXCEPTION(Decrementer)
 626        STND_EXCEPTION_PROLOG
 627        lis     r0,TSR_DIS@h            /* Setup the DEC interrupt mask */
 628        mtspr   SPRN_TSR,r0            /* Clear the DEC interrupt */
 629        addi    r3,r1,STACK_FRAME_OVERHEAD
 630        li      r7,STND_EXC
 631        li      r20,MSR_KERNEL
 632        bl      transfer_to_handler
 633_GLOBAL(timer_interrupt_intercept)
 634        .long   timer_interrupt
 635        .long   ret_from_intercept
 636        .long   0x1000
 637
 638        /* Fixed Internal Timer Interrupt */
 639        /* TODO: Add FIT support */
 640        STND_EXCEPTION(0x1010, FixedIntervalTimer,UnknownException);
 641
 642        /* Watchdog Timer Interrupt */
 643        /* TODO: Add watchdog support */
 644        CRIT_EXCEPTION(0x1020, WatchdogTimer,UnknownException);
 645
 646        /* Data TLB Error Interrupt */
 647        START_EXCEPTION(DataTLBError)
 648        mtspr   SPRG0, r20              /* Save some working registers */
 649        mtspr   SPRG1, r21
 650        mtspr   SPRG4W, r22
 651        mtspr   SPRG5W, r23
 652        mtspr   SPRG6W, r24
 653        mfcr    r21
 654        mtspr   SPRG7W, r21
 655        mfspr   r20, SPRN_DEAR          /* Get faulting address */
 656
 657        /* If we are faulting a kernel address, we have to use the
 658         * kernel page tables.
 659         */
 660        andis.  r21, r20, 0x8000
 661        beq     3f
 662        lis     r21, swapper_pg_dir@h
 663        ori     r21, r21, swapper_pg_dir@l
 664
 665        mfspr   r22,SPRN_MMUCR          /* Set TID to 0 */
 666        li      r23,PPC44x_MMUCR_TID@l
 667        andc    r22,r22,r23
 668        mtspr   SPRN_MMUCR,r22
 669
 670        b       4f
 671
 672        /* Get the PGD for the current thread */
 6733:
 674        mfspr   r21,SPRG3
 675        lwz     r21,PGDIR(r21)
 676
 677        /* Load PID into MMUCR TID */
 678        li      r23,PPC44x_MMUCR_TID@l           /* Create mask */
 679        andc    r22,r22,r23                      /* Clear out TID/STS bits */
 680        mfspr   r23,SPRN_PID                     /* Get PID */
 681        or      r22,r22,r23
 682        mtspr   SPRN_MMUCR,r22
 6834:
 684        rlwinm  r22, r20, 13, 19, 29    /* Compute pgdir/pmd offset */
 685        lwzx    r21, r22, r21           /* Get pgd/pmd entry */
 686        rlwinm. r22, r21, 0, 0, 20      /* Extract pt base address */
 687        beq     2f                      /* Bail if no table */
 688
 689        rlwimi  r22, r20, 23, 20, 28    /* Compute pte address */
 690        lwz     r21, 4(r22)             /* Get pte entry */
 691        andi.   r23, r21, _PAGE_PRESENT /* Is the page present? */
 692        beq     2f                      /* Bail if not present */
 693
 694        ori     r21, r21, _PAGE_ACCESSED
 695        stw     r21, 4(r22)
 696
 697         /* Jump to common tlb load */
 698        b       finish_tlb_load
 699
 7002:
 701        /* The bailout.  Restore registers to pre-exception conditions
 702         * and call the heavyweights to help us out.
 703         */
 704        mfspr   r21, SPRG7R
 705        mtcr    r21
 706        mfspr   r24, SPRG6R
 707        mfspr   r23, SPRG5R
 708        mfspr   r22, SPRG4R
 709        mfspr   r21, SPRG1
 710        mfspr   r20, SPRG0
 711        b       data_access
 712
 713        /* Instruction TLB Error Interrupt */
 714        /*
 715         * Nearly the same as above, except we get our
 716         * information from different registers and bailout
 717         * to a different point.
 718         */
 719        START_EXCEPTION(InstructionTLBError)
 720        mtspr   SPRG0, r20              /* Save some working registers */
 721        mtspr   SPRG1, r21
 722        mtspr   SPRG4W, r22
 723        mtspr   SPRG5W, r23
 724        mtspr   SPRG6W, r24
 725        mfcr    r21
 726        mtspr   SPRG7W, r21
 727        mfspr   r20, SRR0               /* Get faulting address */
 728
 729        /* If we are faulting a kernel address, we have to use the
 730         * kernel page tables.
 731         */
 732        andis.  r21, r20, 0x8000
 733        beq     3f
 734        lis     r21, swapper_pg_dir@h
 735        ori     r21, r21, swapper_pg_dir@l
 736
 737        mfspr   r22,SPRN_MMUCR          /* Set TID to 0 */
 738        li      r23,PPC44x_MMUCR_TID@l
 739        andc    r22,r22,r23
 740        mtspr   SPRN_MMUCR,r22
 741
 742        b       4f
 743
 744        /* Get the PGD for the current thread */
 7453:
 746        mfspr   r21,SPRG3
 747        lwz     r21,PGDIR(r21)
 748
 749        /* Load PID into MMUCR TID */
 750        li      r23,PPC44x_MMUCR_TID@l           /* Create mask */
 751        andc    r22,r23,r23                      /* Clear out TID/STS bits */
 752        mfspr   r23,SPRN_PID                     /* Get PID */
 753        or      r22,r22,r23
 754        mtspr   SPRN_MMUCR,r22
 755
 7564:
 757        rlwinm  r22, r20, 13, 19, 29    /* Compute pgdir/pmd offset */
 758        lwzx    r21, r22, r21           /* Get pgd/pmd entry */
 759        rlwinm. r22, r21, 0, 0, 20      /* Extract pt base address */
 760        beq     2f                      /* Bail if no table */
 761
 762        rlwimi  r22, r20, 23, 20, 28    /* Compute pte address */
 763        lwz     r21, 4(r22)             /* Get pte entry */
 764        andi.   r23, r21, _PAGE_PRESENT /* Is the page present? */
 765        beq     2f                      /* Bail if not present */
 766
 767        ori     r21, r21, _PAGE_ACCESSED
 768        stw     r21, 4(r22)
 769
 770        /* Jump to common TLB load point */
 771        b       finish_tlb_load
 772
 7732:
 774        /* The bailout.  Restore registers to pre-exception conditions
 775         * and call the heavyweights to help us out.
 776         */
 777        mfspr   r21, SPRG7R
 778        mtcr    r21
 779        mfspr   r24, SPRG6R
 780        mfspr   r23, SPRG5R
 781        mfspr   r22, SPRG4R
 782        mfspr   r21, SPRG1
 783        mfspr   r20, SPRG0
 784        b       InstructionStorage
 785
 786/* Check for a single step debug exception while in an exception
 787 * handler before state has been saved.  This is to catch the case
 788 * where an instruction that we are trying to single step causes
 789 * an exception (eg ITLB/DTLB miss) and thus the first instruction of
 790 * the exception handler generates a single step debug exception.
 791 *
 792 * If we get a debug trap on the first instruction of an exception handler,
 793 * we reset the MSR_DE in the _exception handlers_ MSR (the debug trap is
 794 * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
 795 * The exception handler was handling a non-critical interrupt, so it will
 796 * save (and later restore) the MSR via SPRN_SRR1, which will still have
 797 * the MSR_DE bit set.
 798 */
 799        /* Debug Interrupt */
 800        START_EXCEPTION(Debug)
 801        /* This first instruction was already executed by the exception
 802         * handler and must be the first instruction of every exception
 803         * handler.
 804         */
 805        mtspr   SPRN_SPRG0,r20          /* Save some working registers... */
 806        mtspr   SPRN_SPRG1,r21
 807        mtspr   SPRN_SPRG4W,r22
 808        mfcr    r20                     /* ..and the cr because we change it */
 809
 810        mfspr   r21,SPRN_CSRR1          /* MSR at the time of fault */
 811        andi.   r21,r21,MSR_PR
 812        bne+    2f                      /* trapped from problem state */
 813
 814        mfspr   r21,SPRN_CSRR0          /* Faulting instruction address */
 815        lis     r22, KERNELBASE@h
 816        ori     r22, r22, KERNELBASE@l
 817        cmplw   r21,r22
 818        blt+    2f                      /* addr below exception vectors */
 819
 820        lis     r22, Debug@h
 821        ori     r22, r22, Debug@l
 822        cmplw   r21,r22
 823        bgt+    2f                      /* addr above TLB exception vectors */
 824
 825        lis     r21,DBSR_IC@h           /* Remove the trap status */
 826        mtspr   SPRN_DBSR,r21
 827
 828        mfspr   r21,SPRN_CSRR1
 829        rlwinm  r21,r21,0,23,21         /* clear MSR_DE */
 830        mtspr   SPRN_CSRR1, r21         /* restore MSR at rcfi without DE */
 831
 832        mtcrf   0xff,r20                /* restore registers */
 833        mfspr   r22,SPRN_SPRG4R
 834        mfspr   r21,SPRN_SPRG1
 835        mfspr   r20,SPRN_SPRG0
 836
 837        sync
 838        rfci                            /* return to the exception handler  */
 839        b       .                       /* prevent prefetch past rfci */
 840
 8412:
 842        mtcrf   0xff,r20                /* restore registers */
 843        mfspr   r22,SPRN_SPRG4R
 844        mfspr   r21,SPRN_SPRG1
 845        mfspr   r20,SPRN_SPRG0
 846
 847        CRIT_EXCEPTION_PROLOG
 848        addi    r3,r1,STACK_FRAME_OVERHEAD
 849        li      r7,CRIT_EXC;
 850        li      r20,MSR_KERNEL
 851        FINISH_EXCEPTION(0x2000, DebugException)
 852
 853/*
 854 * Local functions
 855 */
 856
 857        /*
 858         * Data TLB exceptions will bail out to this point
 859         * if they can't resolve the lightweight TLB fault.
 860         */
 861data_access:
 862        STND_EXCEPTION_PROLOG
 863        mfspr   r5,SPRN_ESR             /* Grab the ESR, save it, pass arg3 */
 864        stw     r5,_ESR(r21)
 865        mfspr   r4,SPRN_DEAR            /* Grab the DEAR, save it, pass arg2 */
 866        stw     r4,_DEAR(r21)
 867        addi    r3,r1,STACK_FRAME_OVERHEAD
 868        li      r7,STND_EXC
 869        li      r20,MSR_KERNEL
 870        rlwimi  r20,r23,0,16,16         /* Copy EE bit from the saved MSR */
 871        FINISH_EXCEPTION(0x800, do_page_fault) /* do_page_fault(regs, ESR, DEAR) */
 872
 873/*
 874 * Both the instruction and data TLB miss get to this
 875 * point to load the TLB.
 876 *      r20 - EA of fault
 877 *      r21 - available to use
 878 *      r22 - Pointer to the 64-bit PTE
 879 *      r23 - available to use
 880 *      r24 - available to use
 881 *      MMUCR - loaded with proper value when we get here
 882 *      Upon exit, we reload everything and RFI.
 883 */
 884finish_tlb_load:
 885        /*
 886         * We set execute, because we don't have the granularity to
 887         * properly set this at the page level (Linux problem).
 888         * If shared is set, we cause a zero PID->TID load.
 889         * Many of these bits are software only.  Bits we don't set
 890         * here we (properly should) assume have the appropriate value.
 891         */
 892
 893        /* Load the next available TLB index */
 894        lis     r23, tlb_44x_index@h
 895        ori     r23, r23, tlb_44x_index@l
 896        lwz     r24, 0(r23)
 897        /* Load the TLB high watermark */
 898        lis     r23, tlb_44x_hwater@h
 899        ori     r23, r23, tlb_44x_hwater@l
 900        lwz     r21, 0(r23)
 901
 902        
 903        /* Increment, rollover, and store TLB index */
 904        addi    r24, r24, 1
 905        cmpw    0, r24, r21             /* reserve entries 62-63 for kernel */
 906        ble     7f
 907        li      r24, 0
 9087:
 909        /* Load the next available TLB index */
 910        lis     r23, tlb_44x_index@h
 911        ori     r23, r23, tlb_44x_index@l
 912        stw     r24, 0(r23)
 913
 9146:
 915        lwz     r23, 0(r22)                     /* Get MS word of PTE */
 916        lwz     r21, 4(r22)                     /* Get LS word of PTE */
 917        rlwimi  r23, r21, 0, 0 , 19             /* Insert RPN */
 918        tlbwe   r23, r24, PPC44x_TLB_XLAT       /* Write XLAT */
 919
 920        /*
 921         * Create PAGEID. This is the faulting address plus
 922         * a set of static bits. The static bits are page
 923         * size and valid. Bits 20  and 21 should be zero
 924         * for a page size of 4KB.
 925         */
 926        li      r22, 0x0210                     /* Set size and valid */
 927        mfspr   r23, SPRN_SRR1                  /* Get SRR1 */
 928        andi.   r23, r23, MSR_IS@l
 929        beq     7f
 930        ori     r22, r22, PPC44x_TLB_TS@l       /* Set TS=1 */
 9317:      rlwimi  r20, r22, 0, 20, 31             /* Insert statics */
 932        tlbwe   r20, r24, PPC44x_TLB_PAGEID     /* Write PAGEID */
 933
 934        /* FIXME: Staticly setting some permissions */
 935        li      r23, 0x002d                     /* Set UX,UR,SX,SR */
 936        andi.   r21, r21, 0xffff                /* Clear MS 16 bits */
 937        andi.   r22, r21, 0x0002                /* _PAGE_HWWRITE? */
 938        beq     8f
 939        ori     r23, r23, 0x0002                /* Set SW */
 940        /* FIXME: Force attributes */
 9418:      ori     r21, r21, 0x0100                /* Set G */
 942        /* FIXME: Already set in PTE */
 943        rlwimi  r21, r23, 0, 26, 31             /* Insert static perms */
 944
 945        lis     r23,0xffff
 946        ori     r23,r23,0x0fff                  /* Set U0-U3 mask */
 947        and     r21,r21,r23                     /* Clear U0-U3 */
 948        tlbwe   r21, r24, PPC44x_TLB_ATTRIB     /* Write ATTRIB */
 949
 950        /* Done...restore registers and get out of here.
 951        */
 952        mfspr   r21, SPRG7R
 953        mtcr    r21
 954        mfspr   r24, SPRG6R
 955        mfspr   r23, SPRG5R
 956        mfspr   r22, SPRG4R
 957        mfspr   r21, SPRG1
 958        mfspr   r20, SPRG0
 959        rfi                                     /* Force context change */
 960
 961/*
 962 * Global functions
 963 */
 964
 965/*
 966 * extern void giveup_altivec(struct task_struct *prev)
 967 *
 968 * The 44x core does not have an AltiVec unit.
 969 */
 970_GLOBAL(giveup_altivec)
 971        blr
 972
 973/*
 974 * extern void giveup_fpu(struct task_struct *prev)
 975 *
 976 * The 44x core does not have an FPU.
 977 */
 978_GLOBAL(giveup_fpu)
 979        blr
 980
 981/*
 982 * extern void abort(void)
 983 *
 984 * At present, this routine just applies a system reset.
 985 */ 
 986_GLOBAL(abort)
 987        mfspr   r13,SPRN_DBCR0
 988        oris    r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h
 989        mtspr   SPRN_DBCR0,r13
 990
 991_GLOBAL(set_context)
 992
 993#ifdef CONFIG_BDI_SWITCH
 994        /* Context switch the PTE pointer for the Abatron BDI2000.
 995         * The PGDIR is the second parameter.
 996         */
 997        lis     r5, abatron_pteptrs@h
 998        ori     r5, r5, abatron_pteptrs@l
 999        stw     r4, 0x4(r5)
1000#endif
1001        mtspr   SPRN_PID,r3
1002        isync                   /* Force context change */
1003        blr
1004
1005/*
1006 * This code finishes saving the registers to the exception frame
1007 * and jumps to the appropriate handler for the exception, turning
1008 * on address translation.
1009 */
1010_GLOBAL(transfer_to_handler)
1011        stw     r22,_NIP(r21)           /* Save the faulting IP on the stack */
1012        stw     r23,_MSR(r21)           /* Save the exception MSR on stack */
1013        SAVE_4GPRS(8, r21)              /* Save r8 through r11 on the stack */
1014        SAVE_8GPRS(12, r21)             /* Save r12 through r19 on the stack */
1015        SAVE_8GPRS(24, r21)             /* Save r24 through r31 on the stack */
1016        andi.   r23,r23,MSR_PR          /* Is this from user space? */
1017        mfspr   r23,SPRN_SPRG3          /* If from user, fix up THREAD.regs */
1018        beq     2f                      /* No, it is from the kernel; branch. */
1019        mfspr   r24,SPRN_DBCR0
1020        stw     r24,THREAD_DBCR0(r23)   /* Save Debug Control in thread_struct */
1021        addi    r24,r1,STACK_FRAME_OVERHEAD
1022        stw     r24,PT_REGS(r23)
10232:      addi    r2,r23,-THREAD          /* Set r2 to current thread */
1024        mflr    r23
1025        lwz     r24,8(r23)              /* Emulate classic PPC vectors */
1026        stw     r24,TRAP(r21)
1027        li      r22,RESULT
1028        /* No need to put an erratum #77 workaround here
1029                because interrupts are currently disabled */
1030        stwcx.  r22,r22,r21             /* Clear the reservation */
1031        li      r22,0
1032        stw     r22,RESULT(r21)
1033        mtspr   SPRN_SPRG2,r22          /* r1 is now the kernel stack pointer */
1034        addi    r24,r2,TASK_STRUCT_SIZE /* Check for kernel stack overflow */
1035        cmplw   cr0,r1,r2
1036        cmplw   cr1,r1,r24
1037        crand   cr1,cr1,cr4
1038        bgt-    stack_ovf               /* If r2 < r1 < r2 + TASK_STRUCT_SIZE */
1039        lwz     r24,0(r23)              /* Virtual address of the handler */
1040        lwz     r23,4(r23)              /* Handler return pointer */
1041        cmpwi   cr0,r7,STND_EXC         /* What type of exception is this? */
1042        bne     3f                      /* It is a critical/machine check exception... */
1043
1044        /* Standard exception jump path
1045        */
1046
1047        /* We have to recover r7 from the register save stack.
1048         * It was used to indicate standard/critical exception.  In
1049         * the case of a standard exception that is the system call
1050         * trap, it may have originally contained one of the syscall
1051         * parameters and we have to get it back now.
1052         */
1053        lwz     r7,GPR7(r21)
1054        mtspr   SPRN_SRR0,r24           /* Set up the instruction pointer */
1055        mtspr   SPRN_SRR1,r20           /* Set up the machine state register */
1056        mtlr    r23                     /* Set up the return pointer */
1057        SYNC
1058        rfi
1059
1060        /* Critical/Machine check exception jump path
1061        */
10623:      cmpwi   r7,CRIT_EXC             /* Critical or machine check ? */
1063        mtlr    r23                     /* Set up the return pointer */
1064        bne     4f
1065        mtspr   SPRN_CSRR0,r24          /* Set up the instruction pointer */
1066        mtspr   SPRN_CSRR1,r20          /* Set up the machine state register */
1067        SYNC
1068        rfci
1069
10704:      mtspr   SPRN_MCSRR0,r24         /* Set up the instruction pointer */
1071        mtspr   SPRN_MCSRR1,r20         /* Set up the machine state register */
1072        SYNC    
1073        RFMCI
1074
1075/* On kernel stack overlow, load up an initial stack pointer and call
1076 * StackOverflow(regs), which should NOT return.
1077 */ 
1078
1079stack_ovf:
1080        addi    r3,r1,STACK_FRAME_OVERHEAD
1081        lis     r1,init_task_union@ha
1082        addi    r1,r1,init_task_union@l
1083        addi    r1,r1,TASK_UNION_SIZE - STACK_FRAME_OVERHEAD
1084        lis     r24,StackOverflow@ha
1085        addi    r24,r24,StackOverflow@l
1086        li      r20,MSR_KERNEL
1087        mtspr   SPRN_SRR0,r24
1088        mtspr   SPRN_SRR1,r20
1089        SYNC
1090        rfi
1091
1092/*
1093 * We put a few things here that have to be page-aligned. This stuff
1094 * goes at the beginning of the data segment, which is page-aligned.
1095 */
1096        .data
1097_GLOBAL(sdata)
1098_GLOBAL(empty_zero_page)
1099        .space  4096
1100
1101/*
1102 * To support >32-bit physical addresses, we use an 8KB pgdir.
1103 */
1104_GLOBAL(swapper_pg_dir)
1105        .space  8192
1106
1107/*
1108 * This space gets a copy of optional info passed to us by the bootstrap
1109 * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
1110 */
1111_GLOBAL(cmd_line)
1112        .space  512
1113
1114/*
1115 * Room for two PTE pointers, usually the kernel and current user pointers
1116 * to their respective root page table.
1117 */
1118abatron_pteptrs:
1119        .space  8
1120
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.