linux/arch/microblaze/kernel/hw_exception_handler.S
<<
>>
Prefs
   1/*
   2 * Exception handling for Microblaze
   3 *
   4 * Rewriten interrupt handling
   5 *
   6 * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
   7 * Copyright (C) 2008-2009 PetaLogix
   8 *
   9 * uClinux customisation (C) 2005 John Williams
  10 *
  11 * MMU code derived from arch/ppc/kernel/head_4xx.S:
  12 *      Copyright (C) 1995-1996 Gary Thomas <gdt@linuxppc.org>
  13 *              Initial PowerPC version.
  14 *      Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
  15 *              Rewritten for PReP
  16 *      Copyright (C) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
  17 *              Low-level exception handers, MMU support, and rewrite.
  18 *      Copyright (C) 1997 Dan Malek <dmalek@jlc.net>
  19 *              PowerPC 8xx modifications.
  20 *      Copyright (C) 1998-1999 TiVo, Inc.
  21 *              PowerPC 403GCX modifications.
  22 *      Copyright (C) 1999 Grant Erickson <grant@lcse.umn.edu>
  23 *              PowerPC 403GCX/405GP modifications.
  24 *      Copyright 2000 MontaVista Software Inc.
  25 *              PPC405 modifications
  26 *      PowerPC 403GCX/405GP modifications.
  27 *              Author: MontaVista Software, Inc.
  28 *              frank_rowand@mvista.com or source@mvista.com
  29 *              debbie_chu@mvista.com
  30 *
  31 * Original code
  32 * Copyright (C) 2004 Xilinx, Inc.
  33 *
  34 * This program is free software; you can redistribute it and/or modify it
  35 * under the terms of the GNU General Public License version 2 as published
  36 * by the Free Software Foundation.
  37 */
  38
  39/*
  40 * Here are the handlers which don't require enabling translation
  41 * and calling other kernel code thus we can keep their design very simple
  42 * and do all processing in real mode. All what they need is a valid current
  43 * (that is an issue for the CONFIG_REGISTER_TASK_PTR case)
  44 * This handlers use r3,r4,r5,r6 and optionally r[current] to work therefore
  45 * these registers are saved/restored
  46 * The handlers which require translation are in entry.S --KAA
  47 *
  48 * Microblaze HW Exception Handler
  49 * - Non self-modifying exception handler for the following exception conditions
  50 *   - Unalignment
  51 *   - Instruction bus error
  52 *   - Data bus error
  53 *   - Illegal instruction opcode
  54 *   - Divide-by-zero
  55 *
  56 *   - Privileged instruction exception (MMU)
  57 *   - Data storage exception (MMU)
  58 *   - Instruction storage exception (MMU)
  59 *   - Data TLB miss exception (MMU)
  60 *   - Instruction TLB miss exception (MMU)
  61 *
  62 * Note we disable interrupts during exception handling, otherwise we will
  63 * possibly get multiple re-entrancy if interrupt handles themselves cause
  64 * exceptions. JW
  65 */
  66
  67#include <asm/exceptions.h>
  68#include <asm/unistd.h>
  69#include <asm/page.h>
  70
  71#include <asm/entry.h>
  72#include <asm/current.h>
  73#include <linux/linkage.h>
  74
  75#include <asm/mmu.h>
  76#include <asm/pgtable.h>
  77#include <asm/signal.h>
  78#include <asm/registers.h>
  79#include <asm/asm-offsets.h>
  80
  81#undef DEBUG
  82
  83/* Helpful Macros */
  84#define NUM_TO_REG(num)         r ## num
  85
  86#ifdef CONFIG_MMU
  87        #define RESTORE_STATE                   \
  88                lwi     r5, r1, 0;              \
  89                mts     rmsr, r5;               \
  90                nop;                            \
  91                lwi     r3, r1, PT_R3;          \
  92                lwi     r4, r1, PT_R4;          \
  93                lwi     r5, r1, PT_R5;          \
  94                lwi     r6, r1, PT_R6;          \
  95                lwi     r11, r1, PT_R11;        \
  96                lwi     r31, r1, PT_R31;        \
  97                lwi     r1, r1, PT_R1;
  98#endif /* CONFIG_MMU */
  99
 100#define LWREG_NOP                       \
 101        bri     ex_handler_unhandled;   \
 102        nop;
 103
 104#define SWREG_NOP                       \
 105        bri     ex_handler_unhandled;   \
 106        nop;
 107
 108/* FIXME this is weird - for noMMU kernel is not possible to use brid
 109 * instruction which can shorten executed time
 110 */
 111
 112/* r3 is the source */
 113#define R3_TO_LWREG_V(regnum)                           \
 114        swi     r3, r1, 4 * regnum;                             \
 115        bri     ex_handler_done;
 116
 117/* r3 is the source */
 118#define R3_TO_LWREG(regnum)                             \
 119        or      NUM_TO_REG (regnum), r0, r3;            \
 120        bri     ex_handler_done;
 121
 122/* r3 is the target */
 123#define SWREG_TO_R3_V(regnum)                           \
 124        lwi     r3, r1, 4 * regnum;                             \
 125        bri     ex_sw_tail;
 126
 127/* r3 is the target */
 128#define SWREG_TO_R3(regnum)                             \
 129        or      r3, r0, NUM_TO_REG (regnum);            \
 130        bri     ex_sw_tail;
 131
 132#ifdef CONFIG_MMU
 133        #define R3_TO_LWREG_VM_V(regnum)                \
 134                brid    ex_lw_end_vm;                   \
 135                swi     r3, r7, 4 * regnum;
 136
 137        #define R3_TO_LWREG_VM(regnum)                  \
 138                brid    ex_lw_end_vm;                   \
 139                or      NUM_TO_REG (regnum), r0, r3;
 140
 141        #define SWREG_TO_R3_VM_V(regnum)                \
 142                brid    ex_sw_tail_vm;                  \
 143                lwi     r3, r7, 4 * regnum;
 144
 145        #define SWREG_TO_R3_VM(regnum)                  \
 146                brid    ex_sw_tail_vm;                  \
 147                or      r3, r0, NUM_TO_REG (regnum);
 148
 149        /* Shift right instruction depending on available configuration */
 150        #if CONFIG_XILINX_MICROBLAZE0_USE_BARREL == 0
 151        /* Only the used shift constants defined here - add more if needed */
 152        #define BSRLI2(rD, rA)                          \
 153                srl rD, rA;             /* << 1 */      \
 154                srl rD, rD;             /* << 2 */
 155        #define BSRLI4(rD, rA)          \
 156                BSRLI2(rD, rA);         \
 157                BSRLI2(rD, rD)
 158        #define BSRLI10(rD, rA)                         \
 159                srl rD, rA;             /* << 1 */      \
 160                srl rD, rD;             /* << 2 */      \
 161                srl rD, rD;             /* << 3 */      \
 162                srl rD, rD;             /* << 4 */      \
 163                srl rD, rD;             /* << 5 */      \
 164                srl rD, rD;             /* << 6 */      \
 165                srl rD, rD;             /* << 7 */      \
 166                srl rD, rD;             /* << 8 */      \
 167                srl rD, rD;             /* << 9 */      \
 168                srl rD, rD              /* << 10 */
 169        #define BSRLI20(rD, rA)         \
 170                BSRLI10(rD, rA);        \
 171                BSRLI10(rD, rD)
 172
 173        .macro  bsrli, rD, rA, IMM
 174        .if (\IMM) == 2
 175                BSRLI2(\rD, \rA)
 176        .elseif (\IMM) == 10
 177                BSRLI10(\rD, \rA)
 178        .elseif (\IMM) == 12
 179                BSRLI2(\rD, \rA)
 180                BSRLI10(\rD, \rD)
 181        .elseif (\IMM) == 14
 182                BSRLI4(\rD, \rA)
 183                BSRLI10(\rD, \rD)
 184        .elseif (\IMM) == 20
 185                BSRLI20(\rD, \rA)
 186        .elseif (\IMM) == 24
 187                BSRLI4(\rD, \rA)
 188                BSRLI20(\rD, \rD)
 189        .elseif (\IMM) == 28
 190                BSRLI4(\rD, \rA)
 191                BSRLI4(\rD, \rD)
 192                BSRLI20(\rD, \rD)
 193        .else
 194        .error "BSRLI shift macros \IMM"
 195        .endif
 196        .endm
 197        #endif
 198
 199#endif /* CONFIG_MMU */
 200
 201.extern other_exception_handler /* Defined in exception.c */
 202
 203/*
 204 * hw_exception_handler - Handler for exceptions
 205 *
 206 * Exception handler notes:
 207 * - Handles all exceptions
 208 * - Does not handle unaligned exceptions during load into r17, r1, r0.
 209 * - Does not handle unaligned exceptions during store from r17 (cannot be
 210 *   done) and r1 (slows down common case)
 211 *
 212 *  Relevant register structures
 213 *
 214 *  EAR - |----|----|----|----|----|----|----|----|
 215 *      - <  ##   32 bit faulting address     ##  >
 216 *
 217 *  ESR - |----|----|----|----|----| - | - |-----|-----|
 218 *      -                            W   S   REG   EXC
 219 *
 220 *
 221 * STACK FRAME STRUCTURE (for CONFIG_MMU=n)
 222 * ----------------------------------------
 223 *
 224 *      +-------------+         + 0
 225 *      |     MSR     |
 226 *      +-------------+         + 4
 227 *      |     r1      |
 228 *      |      .      |
 229 *      |      .      |
 230 *      |      .      |
 231 *      |      .      |
 232 *      |     r18     |
 233 *      +-------------+         + 76
 234 *      |      .      |
 235 *      |      .      |
 236 *
 237 * MMU kernel uses the same 'pt_pool_space' pointed space
 238 * which is used for storing register values - noMMu style was, that values were
 239 * stored in stack but in case of failure you lost information about register.
 240 * Currently you can see register value in memory in specific place.
 241 * In compare to with previous solution the speed should be the same.
 242 *
 243 * MMU exception handler has different handling compare to no MMU kernel.
 244 * Exception handler use jump table for directing of what happen. For MMU kernel
 245 * is this approach better because MMU relate exception are handled by asm code
 246 * in this file. In compare to with MMU expect of unaligned exception
 247 * is everything handled by C code.
 248 */
 249
 250/*
 251 * every of these handlers is entered having R3/4/5/6/11/current saved on stack
 252 * and clobbered so care should be taken to restore them if someone is going to
 253 * return from exception
 254 */
 255
 256/* wrappers to restore state before coming to entry.S */
 257#ifdef CONFIG_MMU
 258.section .data
 259.align 4
 260pt_pool_space:
 261        .space  PT_SIZE
 262
 263#ifdef DEBUG
 264/* Create space for exception counting. */
 265.section .data
 266.global exception_debug_table
 267.align 4
 268exception_debug_table:
 269        /* Look at exception vector table. There is 32 exceptions * word size */
 270        .space  (32 * 4)
 271#endif /* DEBUG */
 272
 273.section .rodata
 274.align 4
 275_MB_HW_ExceptionVectorTable:
 276/*  0 - Undefined */
 277        .long   TOPHYS(ex_handler_unhandled)
 278/*  1 - Unaligned data access exception */
 279        .long   TOPHYS(handle_unaligned_ex)
 280/*  2 - Illegal op-code exception */
 281        .long   TOPHYS(full_exception_trapw)
 282/*  3 - Instruction bus error exception */
 283        .long   TOPHYS(full_exception_trapw)
 284/*  4 - Data bus error exception */
 285        .long   TOPHYS(full_exception_trapw)
 286/*  5 - Divide by zero exception */
 287        .long   TOPHYS(full_exception_trapw)
 288/*  6 - Floating point unit exception */
 289        .long   TOPHYS(full_exception_trapw)
 290/*  7 - Privileged instruction exception */
 291        .long   TOPHYS(full_exception_trapw)
 292/*  8 - 15 - Undefined */
 293        .long   TOPHYS(ex_handler_unhandled)
 294        .long   TOPHYS(ex_handler_unhandled)
 295        .long   TOPHYS(ex_handler_unhandled)
 296        .long   TOPHYS(ex_handler_unhandled)
 297        .long   TOPHYS(ex_handler_unhandled)
 298        .long   TOPHYS(ex_handler_unhandled)
 299        .long   TOPHYS(ex_handler_unhandled)
 300        .long   TOPHYS(ex_handler_unhandled)
 301/* 16 - Data storage exception */
 302        .long   TOPHYS(handle_data_storage_exception)
 303/* 17 - Instruction storage exception */
 304        .long   TOPHYS(handle_instruction_storage_exception)
 305/* 18 - Data TLB miss exception */
 306        .long   TOPHYS(handle_data_tlb_miss_exception)
 307/* 19 - Instruction TLB miss exception */
 308        .long   TOPHYS(handle_instruction_tlb_miss_exception)
 309/* 20 - 31 - Undefined */
 310        .long   TOPHYS(ex_handler_unhandled)
 311        .long   TOPHYS(ex_handler_unhandled)
 312        .long   TOPHYS(ex_handler_unhandled)
 313        .long   TOPHYS(ex_handler_unhandled)
 314        .long   TOPHYS(ex_handler_unhandled)
 315        .long   TOPHYS(ex_handler_unhandled)
 316        .long   TOPHYS(ex_handler_unhandled)
 317        .long   TOPHYS(ex_handler_unhandled)
 318        .long   TOPHYS(ex_handler_unhandled)
 319        .long   TOPHYS(ex_handler_unhandled)
 320        .long   TOPHYS(ex_handler_unhandled)
 321        .long   TOPHYS(ex_handler_unhandled)
 322#endif
 323
 324.global _hw_exception_handler
 325.section .text
 326.align 4
 327.ent _hw_exception_handler
 328_hw_exception_handler:
 329#ifndef CONFIG_MMU
 330        addik   r1, r1, -(EX_HANDLER_STACK_SIZ); /* Create stack frame */
 331#else
 332        swi     r1, r0, TOPHYS(pt_pool_space + PT_R1); /* GET_SP */
 333        /* Save date to kernel memory. Here is the problem
 334         * when you came from user space */
 335        ori     r1, r0, TOPHYS(pt_pool_space);
 336#endif
 337        swi     r3, r1, PT_R3
 338        swi     r4, r1, PT_R4
 339        swi     r5, r1, PT_R5
 340        swi     r6, r1, PT_R6
 341
 342#ifdef CONFIG_MMU
 343        swi     r11, r1, PT_R11
 344        swi     r31, r1, PT_R31
 345        lwi     r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)) /* get saved current */
 346#endif
 347
 348        mfs     r5, rmsr;
 349        nop
 350        swi     r5, r1, 0;
 351        mfs     r4, resr
 352        nop
 353        mfs     r3, rear;
 354        nop
 355
 356#ifndef CONFIG_MMU
 357        andi    r5, r4, 0x1000;         /* Check ESR[DS] */
 358        beqi    r5, not_in_delay_slot;  /* Branch if ESR[DS] not set */
 359        mfs     r17, rbtr;      /* ESR[DS] set - return address in BTR */
 360        nop
 361not_in_delay_slot:
 362        swi     r17, r1, PT_R17
 363#endif
 364
 365        andi    r5, r4, 0x1F;           /* Extract ESR[EXC] */
 366
 367#ifdef CONFIG_MMU
 368        /* Calculate exception vector offset = r5 << 2 */
 369        addk    r6, r5, r5; /* << 1 */
 370        addk    r6, r6, r6; /* << 2 */
 371
 372#ifdef DEBUG
 373/* counting which exception happen */
 374        lwi     r5, r0, TOPHYS(exception_debug_table)
 375        addi    r5, r5, 1
 376        swi     r5, r0, TOPHYS(exception_debug_table)
 377        lwi     r5, r6, TOPHYS(exception_debug_table)
 378        addi    r5, r5, 1
 379        swi     r5, r6, TOPHYS(exception_debug_table)
 380#endif
 381/* end */
 382        /* Load the HW Exception vector */
 383        lwi     r6, r6, TOPHYS(_MB_HW_ExceptionVectorTable)
 384        bra     r6
 385
 386full_exception_trapw:
 387        RESTORE_STATE
 388        bri     full_exception_trap
 389#else
 390        /* Exceptions enabled here. This will allow nested exceptions */
 391        mfs     r6, rmsr;
 392        nop
 393        swi     r6, r1, 0; /* RMSR_OFFSET */
 394        ori     r6, r6, 0x100; /* Turn ON the EE bit */
 395        andi    r6, r6, ~2; /* Disable interrupts */
 396        mts     rmsr, r6;
 397        nop
 398
 399        xori    r6, r5, 1; /* 00001 = Unaligned Exception */
 400        /* Jump to unalignment exception handler */
 401        beqi    r6, handle_unaligned_ex;
 402
 403handle_other_ex: /* Handle Other exceptions here */
 404        /* Save other volatiles before we make procedure calls below */
 405        swi     r7, r1, PT_R7
 406        swi     r8, r1, PT_R8
 407        swi     r9, r1, PT_R9
 408        swi     r10, r1, PT_R10
 409        swi     r11, r1, PT_R11
 410        swi     r12, r1, PT_R12
 411        swi     r14, r1, PT_R14
 412        swi     r15, r1, PT_R15
 413        swi     r18, r1, PT_R18
 414
 415        or      r5, r1, r0
 416        andi    r6, r4, 0x1F; /* Load ESR[EC] */
 417        lwi     r7, r0, PER_CPU(KM) /* MS: saving current kernel mode to regs */
 418        swi     r7, r1, PT_MODE
 419        mfs     r7, rfsr
 420        nop
 421        addk    r8, r17, r0; /* Load exception address */
 422        bralid  r15, full_exception; /* Branch to the handler */
 423        nop;
 424        mts     rfsr, r0;       /* Clear sticky fsr */
 425        nop
 426
 427        /*
 428         * Trigger execution of the signal handler by enabling
 429         * interrupts and calling an invalid syscall.
 430         */
 431        mfs     r5, rmsr;
 432        nop
 433        ori     r5, r5, 2;
 434        mts     rmsr, r5; /* enable interrupt */
 435        nop
 436        addi    r12, r0, __NR_syscalls;
 437        brki    r14, 0x08;
 438        mfs     r5, rmsr; /* disable interrupt */
 439        nop
 440        andi    r5, r5, ~2;
 441        mts     rmsr, r5;
 442        nop
 443
 444        lwi     r7, r1, PT_R7
 445        lwi     r8, r1, PT_R8
 446        lwi     r9, r1, PT_R9
 447        lwi     r10, r1, PT_R10
 448        lwi     r11, r1, PT_R11
 449        lwi     r12, r1, PT_R12
 450        lwi     r14, r1, PT_R14
 451        lwi     r15, r1, PT_R15
 452        lwi     r18, r1, PT_R18
 453
 454        bri     ex_handler_done; /* Complete exception handling */
 455#endif
 456
 457/* 0x01 - Unaligned data access exception
 458 * This occurs when a word access is not aligned on a word boundary,
 459 * or when a 16-bit access is not aligned on a 16-bit boundary.
 460 * This handler perform the access, and returns, except for MMU when
 461 * the unaligned address is last on a 4k page or the physical address is
 462 * not found in the page table, in which case unaligned_data_trap is called.
 463 */
 464handle_unaligned_ex:
 465        /* Working registers already saved: R3, R4, R5, R6
 466         *  R4 = ESR
 467         *  R3 = EAR
 468         */
 469#ifdef CONFIG_MMU
 470        andi    r6, r4, 0x1000                  /* Check ESR[DS] */
 471        beqi    r6, _no_delayslot               /* Branch if ESR[DS] not set */
 472        mfs     r17, rbtr;      /* ESR[DS] set - return address in BTR */
 473        nop
 474_no_delayslot:
 475        /* jump to high level unaligned handler */
 476        RESTORE_STATE;
 477        bri     unaligned_data_trap
 478#endif
 479        andi    r6, r4, 0x3E0; /* Mask and extract the register operand */
 480        srl     r6, r6; /* r6 >> 5 */
 481        srl     r6, r6;
 482        srl     r6, r6;
 483        srl     r6, r6;
 484        srl     r6, r6;
 485        /* Store the register operand in a temporary location */
 486        sbi     r6, r0, TOPHYS(ex_reg_op);
 487
 488        andi    r6, r4, 0x400; /* Extract ESR[S] */
 489        bnei    r6, ex_sw;
 490ex_lw:
 491        andi    r6, r4, 0x800; /* Extract ESR[W] */
 492        beqi    r6, ex_lhw;
 493        lbui    r5, r3, 0; /* Exception address in r3 */
 494        /* Load a word, byte-by-byte from destination address
 495                and save it in tmp space */
 496        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_0);
 497        lbui    r5, r3, 1;
 498        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_1);
 499        lbui    r5, r3, 2;
 500        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_2);
 501        lbui    r5, r3, 3;
 502        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_3);
 503        /* Get the destination register value into r4 */
 504        lwi     r4, r0, TOPHYS(ex_tmp_data_loc_0);
 505        bri     ex_lw_tail;
 506ex_lhw:
 507        lbui    r5, r3, 0; /* Exception address in r3 */
 508        /* Load a half-word, byte-by-byte from destination
 509                address and save it in tmp space */
 510        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_0);
 511        lbui    r5, r3, 1;
 512        sbi     r5, r0, TOPHYS(ex_tmp_data_loc_1);
 513        /* Get the destination register value into r4 */
 514        lhui    r4, r0, TOPHYS(ex_tmp_data_loc_0);
 515ex_lw_tail:
 516        /* Get the destination register number into r5 */
 517        lbui    r5, r0, TOPHYS(ex_reg_op);
 518        /* Form load_word jump table offset (lw_table + (8 * regnum)) */
 519        addik   r6, r0, TOPHYS(lw_table);
 520        addk    r5, r5, r5;
 521        addk    r5, r5, r5;
 522        addk    r5, r5, r5;
 523        addk    r5, r5, r6;
 524        bra     r5;
 525ex_lw_end: /* Exception handling of load word, ends */
 526ex_sw:
 527        /* Get the destination register number into r5 */
 528        lbui    r5, r0, TOPHYS(ex_reg_op);
 529        /* Form store_word jump table offset (sw_table + (8 * regnum)) */
 530        addik   r6, r0, TOPHYS(sw_table);
 531        add     r5, r5, r5;
 532        add     r5, r5, r5;
 533        add     r5, r5, r5;
 534        add     r5, r5, r6;
 535        bra     r5;
 536ex_sw_tail:
 537        mfs     r6, resr;
 538        nop
 539        andi    r6, r6, 0x800; /* Extract ESR[W] */
 540        beqi    r6, ex_shw;
 541        /* Get the word - delay slot */
 542        swi     r4, r0, TOPHYS(ex_tmp_data_loc_0);
 543        /* Store the word, byte-by-byte into destination address */
 544        lbui    r4, r0, TOPHYS(ex_tmp_data_loc_0);
 545        sbi     r4, r3, 0;
 546        lbui    r4, r0, TOPHYS(ex_tmp_data_loc_1);
 547        sbi     r4, r3, 1;
 548        lbui    r4, r0, TOPHYS(ex_tmp_data_loc_2);
 549        sbi     r4, r3, 2;
 550        lbui    r4, r0, TOPHYS(ex_tmp_data_loc_3);
 551        sbi     r4, r3, 3;
 552        bri     ex_handler_done;
 553
 554ex_shw:
 555        /* Store the lower half-word, byte-by-byte into destination address */
 556        swi     r4, r0, TOPHYS(ex_tmp_data_loc_0);
 557        lbui    r4, r0, TOPHYS(ex_tmp_data_loc_2);
 558        sbi     r4, r3, 0;
 559        lbui    r4, r0, TOPHYS(ex_tmp_data_loc_3);
 560        sbi     r4, r3, 1;
 561ex_sw_end: /* Exception handling of store word, ends. */
 562
 563ex_handler_done:
 564#ifndef CONFIG_MMU
 565        lwi     r5, r1, 0 /* RMSR */
 566        mts     rmsr, r5
 567        nop
 568        lwi     r3, r1, PT_R3
 569        lwi     r4, r1, PT_R4
 570        lwi     r5, r1, PT_R5
 571        lwi     r6, r1, PT_R6
 572        lwi     r17, r1, PT_R17
 573
 574        rted    r17, 0
 575        addik   r1, r1, (EX_HANDLER_STACK_SIZ); /* Restore stack frame */
 576#else
 577        RESTORE_STATE;
 578        rted    r17, 0
 579        nop
 580#endif
 581
 582#ifdef CONFIG_MMU
 583        /* Exception vector entry code. This code runs with address translation
 584         * turned off (i.e. using physical addresses). */
 585
 586        /* Exception vectors. */
 587
 588        /* 0x10 - Data Storage Exception
 589         * This happens for just a few reasons. U0 set (but we don't do that),
 590         * or zone protection fault (user violation, write to protected page).
 591         * If this is just an update of modified status, we do that quickly
 592         * and exit. Otherwise, we call heavyweight functions to do the work.
 593         */
 594        handle_data_storage_exception:
 595                /* Working registers already saved: R3, R4, R5, R6
 596                 * R3 = ESR
 597                 */
 598                mfs     r11, rpid
 599                nop
 600                /* If we are faulting a kernel address, we have to use the
 601                 * kernel page tables.
 602                 */
 603                ori     r5, r0, CONFIG_KERNEL_START
 604                cmpu    r5, r3, r5
 605                bgti    r5, ex3
 606                /* First, check if it was a zone fault (which means a user
 607                 * tried to access a kernel or read-protected page - always
 608                 * a SEGV). All other faults here must be stores, so no
 609                 * need to check ESR_S as well. */
 610                andi    r4, r4, ESR_DIZ         /* ESR_Z - zone protection */
 611                bnei    r4, ex2
 612
 613                ori     r4, r0, swapper_pg_dir
 614                mts     rpid, r0                /* TLB will have 0 TID */
 615                nop
 616                bri     ex4
 617
 618                /* Get the PGD for the current thread. */
 619        ex3:
 620                /* First, check if it was a zone fault (which means a user
 621                 * tried to access a kernel or read-protected page - always
 622                 * a SEGV). All other faults here must be stores, so no
 623                 * need to check ESR_S as well. */
 624                andi    r4, r4, ESR_DIZ         /* ESR_Z */
 625                bnei    r4, ex2
 626                /* get current task address */
 627                addi    r4 ,CURRENT_TASK, TOPHYS(0);
 628                lwi     r4, r4, TASK_THREAD+PGDIR
 629        ex4:
 630                tophys(r4,r4)
 631                /* Create L1 (pgdir/pmd) address */
 632                bsrli   r5, r3, PGDIR_SHIFT - 2
 633                andi    r5, r5, PAGE_SIZE - 4
 634/* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
 635                or      r4, r4, r5
 636                lwi     r4, r4, 0               /* Get L1 entry */
 637                andi    r5, r4, PAGE_MASK /* Extract L2 (pte) base address */
 638                beqi    r5, ex2                 /* Bail if no table */
 639
 640                tophys(r5,r5)
 641                bsrli   r6, r3, PTE_SHIFT /* Compute PTE address */
 642                andi    r6, r6, PAGE_SIZE - 4
 643                or      r5, r5, r6
 644                lwi     r4, r5, 0               /* Get Linux PTE */
 645
 646                andi    r6, r4, _PAGE_RW        /* Is it writeable? */
 647                beqi    r6, ex2                 /* Bail if not */
 648
 649                /* Update 'changed' */
 650                ori     r4, r4, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
 651                swi     r4, r5, 0               /* Update Linux page table */
 652
 653                /* Most of the Linux PTE is ready to load into the TLB LO.
 654                 * We set ZSEL, where only the LS-bit determines user access.
 655                 * We set execute, because we don't have the granularity to
 656                 * properly set this at the page level (Linux problem).
 657                 * If shared is set, we cause a zero PID->TID load.
 658                 * Many of these bits are software only. Bits we don't set
 659                 * here we (properly should) assume have the appropriate value.
 660                 */
 661/* Ignore memory coherent, just LSB on ZSEL is used + EX/WR */
 662                andi    r4, r4, PAGE_MASK | TLB_EX | TLB_WR | \
 663                                                TLB_ZSEL(1) | TLB_ATTR_MASK
 664                ori     r4, r4, _PAGE_HWEXEC    /* make it executable */
 665
 666                /* find the TLB index that caused the fault. It has to be here*/
 667                mts     rtlbsx, r3
 668                nop
 669                mfs     r5, rtlbx               /* DEBUG: TBD */
 670                nop
 671                mts     rtlblo, r4              /* Load TLB LO */
 672                nop
 673                                                /* Will sync shadow TLBs */
 674
 675                /* Done...restore registers and get out of here. */
 676                mts     rpid, r11
 677                nop
 678                bri 4
 679
 680                RESTORE_STATE;
 681                rted    r17, 0
 682                nop
 683        ex2:
 684                /* The bailout. Restore registers to pre-exception conditions
 685                 * and call the heavyweights to help us out. */
 686                mts     rpid, r11
 687                nop
 688                bri 4
 689                RESTORE_STATE;
 690                bri     page_fault_data_trap
 691
 692
 693        /* 0x11 - Instruction Storage Exception
 694         * This is caused by a fetch from non-execute or guarded pages. */
 695        handle_instruction_storage_exception:
 696                /* Working registers already saved: R3, R4, R5, R6
 697                 * R3 = ESR
 698                 */
 699
 700                RESTORE_STATE;
 701                bri     page_fault_instr_trap
 702
 703        /* 0x12 - Data TLB Miss Exception
 704         * As the name implies, translation is not in the MMU, so search the
 705         * page tables and fix it. The only purpose of this function is to
 706         * load TLB entries from the page table if they exist.
 707         */
 708        handle_data_tlb_miss_exception:
 709                /* Working registers already saved: R3, R4, R5, R6
 710                 * R3 = EAR, R4 = ESR
 711                 */
 712                mfs     r11, rpid
 713                nop
 714
 715                /* If we are faulting a kernel address, we have to use the
 716                 * kernel page tables. */
 717                ori     r6, r0, CONFIG_KERNEL_START
 718                cmpu    r4, r3, r6
 719                bgti    r4, ex5
 720                ori     r4, r0, swapper_pg_dir
 721                mts     rpid, r0                /* TLB will have 0 TID */
 722                nop
 723                bri     ex6
 724
 725                /* Get the PGD for the current thread. */
 726        ex5:
 727                /* get current task address */
 728                addi    r4 ,CURRENT_TASK, TOPHYS(0);
 729                lwi     r4, r4, TASK_THREAD+PGDIR
 730        ex6:
 731                tophys(r4,r4)
 732                /* Create L1 (pgdir/pmd) address */
 733                bsrli   r5, r3, PGDIR_SHIFT - 2
 734                andi    r5, r5, PAGE_SIZE - 4
 735/* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
 736                or      r4, r4, r5
 737                lwi     r4, r4, 0               /* Get L1 entry */
 738                andi    r5, r4, PAGE_MASK /* Extract L2 (pte) base address */
 739                beqi    r5, ex7                 /* Bail if no table */
 740
 741                tophys(r5,r5)
 742                bsrli   r6, r3, PTE_SHIFT /* Compute PTE address */
 743                andi    r6, r6, PAGE_SIZE - 4
 744                or      r5, r5, r6
 745                lwi     r4, r5, 0               /* Get Linux PTE */
 746
 747                andi    r6, r4, _PAGE_PRESENT
 748                beqi    r6, ex7
 749
 750                ori     r4, r4, _PAGE_ACCESSED
 751                swi     r4, r5, 0
 752
 753                /* Most of the Linux PTE is ready to load into the TLB LO.
 754                 * We set ZSEL, where only the LS-bit determines user access.
 755                 * We set execute, because we don't have the granularity to
 756                 * properly set this at the page level (Linux problem).
 757                 * If shared is set, we cause a zero PID->TID load.
 758                 * Many of these bits are software only. Bits we don't set
 759                 * here we (properly should) assume have the appropriate value.
 760                 */
 761                brid    finish_tlb_load
 762                andi    r4, r4, PAGE_MASK | TLB_EX | TLB_WR | \
 763                                                TLB_ZSEL(1) | TLB_ATTR_MASK
 764        ex7:
 765                /* The bailout. Restore registers to pre-exception conditions
 766                 * and call the heavyweights to help us out.
 767                 */
 768                mts     rpid, r11
 769                nop
 770                bri     4
 771                RESTORE_STATE;
 772                bri     page_fault_data_trap
 773
 774        /* 0x13 - Instruction TLB Miss Exception
 775         * Nearly the same as above, except we get our information from
 776         * different registers and bailout to a different point.
 777         */
 778        handle_instruction_tlb_miss_exception:
 779                /* Working registers already saved: R3, R4, R5, R6
 780                 *  R3 = ESR
 781                 */
 782                mfs     r11, rpid
 783                nop
 784
 785                /* If we are faulting a kernel address, we have to use the
 786                 * kernel page tables.
 787                 */
 788                ori     r4, r0, CONFIG_KERNEL_START
 789                cmpu    r4, r3, r4
 790                bgti    r4, ex8
 791                ori     r4, r0, swapper_pg_dir
 792                mts     rpid, r0                /* TLB will have 0 TID */
 793                nop
 794                bri     ex9
 795
 796                /* Get the PGD for the current thread. */
 797        ex8:
 798                /* get current task address */
 799                addi    r4 ,CURRENT_TASK, TOPHYS(0);
 800                lwi     r4, r4, TASK_THREAD+PGDIR
 801        ex9:
 802                tophys(r4,r4)
 803                /* Create L1 (pgdir/pmd) address */
 804                bsrli   r5, r3, PGDIR_SHIFT - 2
 805                andi    r5, r5, PAGE_SIZE - 4
 806/* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
 807                or      r4, r4, r5
 808                lwi     r4, r4, 0               /* Get L1 entry */
 809                andi    r5, r4, PAGE_MASK /* Extract L2 (pte) base address */
 810                beqi    r5, ex10                /* Bail if no table */
 811
 812                tophys(r5,r5)
 813                bsrli   r6, r3, PTE_SHIFT /* Compute PTE address */
 814                andi    r6, r6, PAGE_SIZE - 4
 815                or      r5, r5, r6
 816                lwi     r4, r5, 0               /* Get Linux PTE */
 817
 818                andi    r6, r4, _PAGE_PRESENT
 819                beqi    r6, ex10
 820
 821                ori     r4, r4, _PAGE_ACCESSED
 822                swi     r4, r5, 0
 823
 824                /* Most of the Linux PTE is ready to load into the TLB LO.
 825                 * We set ZSEL, where only the LS-bit determines user access.
 826                 * We set execute, because we don't have the granularity to
 827                 * properly set this at the page level (Linux problem).
 828                 * If shared is set, we cause a zero PID->TID load.
 829                 * Many of these bits are software only. Bits we don't set
 830                 * here we (properly should) assume have the appropriate value.
 831                 */
 832                brid    finish_tlb_load
 833                andi    r4, r4, PAGE_MASK | TLB_EX | TLB_WR | \
 834                                                TLB_ZSEL(1) | TLB_ATTR_MASK
 835        ex10:
 836                /* The bailout. Restore registers to pre-exception conditions
 837                 * and call the heavyweights to help us out.
 838                 */
 839                mts     rpid, r11
 840                nop
 841                bri 4
 842                RESTORE_STATE;
 843                bri     page_fault_instr_trap
 844
 845/* Both the instruction and data TLB miss get to this point to load the TLB.
 846 *      r3 - EA of fault
 847 *      r4 - TLB LO (info from Linux PTE)
 848 *      r5, r6 - available to use
 849 *      PID - loaded with proper value when we get here
 850 *      Upon exit, we reload everything and RFI.
 851 * A common place to load the TLB.
 852 */
 853.section .data
 854.align 4
 855.global tlb_skip
 856        tlb_skip:
 857                .long   MICROBLAZE_TLB_SKIP
 858        tlb_index:
 859                /* MS: storing last used tlb index */
 860                .long   MICROBLAZE_TLB_SIZE/2
 861.previous
 862        finish_tlb_load:
 863                /* MS: load the last used TLB index. */
 864                lwi     r5, r0, TOPHYS(tlb_index)
 865                addik   r5, r5, 1 /* MS: inc tlb_index -> use next one */
 866
 867/* MS: FIXME this is potential fault, because this is mask not count */
 868                andi    r5, r5, MICROBLAZE_TLB_SIZE - 1
 869                ori     r6, r0, 1
 870                cmp     r31, r5, r6
 871                blti    r31, ex12
 872                lwi     r5, r0, TOPHYS(tlb_skip)
 873        ex12:
 874                /* MS: save back current TLB index */
 875                swi     r5, r0, TOPHYS(tlb_index)
 876
 877                ori     r4, r4, _PAGE_HWEXEC    /* make it executable */
 878                mts     rtlbx, r5               /* MS: save current TLB */
 879                nop
 880                mts     rtlblo, r4              /* MS: save to TLB LO */
 881                nop
 882
 883                /* Create EPN. This is the faulting address plus a static
 884                 * set of bits. These are size, valid, E, U0, and ensure
 885                 * bits 20 and 21 are zero.
 886                 */
 887                andi    r3, r3, PAGE_MASK
 888#ifdef CONFIG_MICROBLAZE_64K_PAGES
 889                ori     r3, r3, TLB_VALID | TLB_PAGESZ(PAGESZ_64K)
 890#elif CONFIG_MICROBLAZE_16K_PAGES
 891                ori     r3, r3, TLB_VALID | TLB_PAGESZ(PAGESZ_16K)
 892#else
 893                ori     r3, r3, TLB_VALID | TLB_PAGESZ(PAGESZ_4K)
 894#endif
 895                mts     rtlbhi, r3              /* Load TLB HI */
 896                nop
 897
 898                /* Done...restore registers and get out of here. */
 899                mts     rpid, r11
 900                nop
 901                bri 4
 902                RESTORE_STATE;
 903                rted    r17, 0
 904                nop
 905
 906        /* extern void giveup_fpu(struct task_struct *prev)
 907         *
 908         * The MicroBlaze processor may have an FPU, so this should not just
 909         * return: TBD.
 910         */
 911        .globl giveup_fpu;
 912        .align 4;
 913        giveup_fpu:
 914                bralid  r15,0                   /* TBD */
 915                nop
 916
 917        /* At present, this routine just hangs. - extern void abort(void) */
 918        .globl abort;
 919        .align 4;
 920        abort:
 921                br      r0
 922
 923        .globl set_context;
 924        .align 4;
 925        set_context:
 926                mts     rpid, r5        /* Shadow TLBs are automatically */
 927                nop
 928                bri     4               /* flushed by changing PID */
 929                rtsd    r15,8
 930                nop
 931
 932#endif
 933.end _hw_exception_handler
 934
 935#ifdef CONFIG_MMU
 936/* Unaligned data access exception last on a 4k page for MMU.
 937 * When this is called, we are in virtual mode with exceptions enabled
 938 * and registers 1-13,15,17,18 saved.
 939 *
 940 * R3 = ESR
 941 * R4 = EAR
 942 * R7 = pointer to saved registers (struct pt_regs *regs)
 943 *
 944 * This handler perform the access, and returns via ret_from_exc.
 945 */
 946.global _unaligned_data_exception
 947.ent _unaligned_data_exception
 948_unaligned_data_exception:
 949        andi    r8, r3, 0x3E0;  /* Mask and extract the register operand */
 950        bsrli   r8, r8, 2;              /* r8 >> 2 = register operand * 8 */
 951        andi    r6, r3, 0x400;  /* Extract ESR[S] */
 952        bneid   r6, ex_sw_vm;
 953        andi    r6, r3, 0x800;  /* Extract ESR[W] - delay slot */
 954ex_lw_vm:
 955        beqid   r6, ex_lhw_vm;
 956load1:  lbui    r5, r4, 0;      /* Exception address in r4 - delay slot */
 957/* Load a word, byte-by-byte from destination address and save it in tmp space*/
 958        addik   r6, r0, ex_tmp_data_loc_0;
 959        sbi     r5, r6, 0;
 960load2:  lbui    r5, r4, 1;
 961        sbi     r5, r6, 1;
 962load3:  lbui    r5, r4, 2;
 963        sbi     r5, r6, 2;
 964load4:  lbui    r5, r4, 3;
 965        sbi     r5, r6, 3;
 966        brid    ex_lw_tail_vm;
 967/* Get the destination register value into r3 - delay slot */
 968        lwi     r3, r6, 0;
 969ex_lhw_vm:
 970        /* Load a half-word, byte-by-byte from destination address and
 971         * save it in tmp space */
 972        addik   r6, r0, ex_tmp_data_loc_0;
 973        sbi     r5, r6, 0;
 974load5:  lbui    r5, r4, 1;
 975        sbi     r5, r6, 1;
 976        lhui    r3, r6, 0;      /* Get the destination register value into r3 */
 977ex_lw_tail_vm:
 978        /* Form load_word jump table offset (lw_table_vm + (8 * regnum)) */
 979        addik   r5, r8, lw_table_vm;
 980        bra     r5;
 981ex_lw_end_vm:                   /* Exception handling of load word, ends */
 982        brai    ret_from_exc;
 983ex_sw_vm:
 984/* Form store_word jump table offset (sw_table_vm + (8 * regnum)) */
 985        addik   r5, r8, sw_table_vm;
 986        bra     r5;
 987ex_sw_tail_vm:
 988        addik   r5, r0, ex_tmp_data_loc_0;
 989        beqid   r6, ex_shw_vm;
 990        swi     r3, r5, 0;      /* Get the word - delay slot */
 991        /* Store the word, byte-by-byte into destination address */
 992        lbui    r3, r5, 0;
 993store1: sbi     r3, r4, 0;
 994        lbui    r3, r5, 1;
 995store2: sbi     r3, r4, 1;
 996        lbui    r3, r5, 2;
 997store3: sbi     r3, r4, 2;
 998        lbui    r3, r5, 3;
 999        brid    ret_from_exc;
1000store4: sbi     r3, r4, 3;      /* Delay slot */
1001ex_shw_vm:
1002        /* Store the lower half-word, byte-by-byte into destination address */
1003#ifdef __MICROBLAZEEL__
1004        lbui    r3, r5, 0;
1005store5: sbi     r3, r4, 0;
1006        lbui    r3, r5, 1;
1007        brid    ret_from_exc;
1008store6: sbi     r3, r4, 1;      /* Delay slot */
1009#else
1010        lbui    r3, r5, 2;
1011store5: sbi     r3, r4, 0;
1012        lbui    r3, r5, 3;
1013        brid    ret_from_exc;
1014store6: sbi     r3, r4, 1;      /* Delay slot */
1015#endif
1016
1017ex_sw_end_vm:                   /* Exception handling of store word, ends. */
1018
1019/* We have to prevent cases that get/put_user macros get unaligned pointer
1020 * to bad page area. We have to find out which origin instruction caused it
1021 * and called fixup for that origin instruction not instruction in unaligned
1022 * handler */
1023ex_unaligned_fixup:
1024        ori     r5, r7, 0 /* setup pointer to pt_regs */
1025        lwi     r6, r7, PT_PC; /* faulting address is one instruction above */
1026        addik   r6, r6, -4 /* for finding proper fixup */
1027        swi     r6, r7, PT_PC; /* a save back it to PT_PC */
1028        addik   r7, r0, SIGSEGV
1029        /* call bad_page_fault for finding aligned fixup, fixup address is saved
1030         * in PT_PC which is used as return address from exception */
1031        addik   r15, r0, ret_from_exc-8 /* setup return address */
1032        brid    bad_page_fault
1033        nop
1034
1035/* We prevent all load/store because it could failed any attempt to access */
1036.section __ex_table,"a";
1037        .word   load1,ex_unaligned_fixup;
1038        .word   load2,ex_unaligned_fixup;
1039        .word   load3,ex_unaligned_fixup;
1040        .word   load4,ex_unaligned_fixup;
1041        .word   load5,ex_unaligned_fixup;
1042        .word   store1,ex_unaligned_fixup;
1043        .word   store2,ex_unaligned_fixup;
1044        .word   store3,ex_unaligned_fixup;
1045        .word   store4,ex_unaligned_fixup;
1046        .word   store5,ex_unaligned_fixup;
1047        .word   store6,ex_unaligned_fixup;
1048.previous;
1049.end _unaligned_data_exception
1050#endif /* CONFIG_MMU */
1051
1052.global ex_handler_unhandled
1053ex_handler_unhandled:
1054/* FIXME add handle function for unhandled exception - dump register */
1055        bri 0
1056
1057/*
1058 * hw_exception_handler Jump Table
1059 * - Contains code snippets for each register that caused the unalign exception
1060 * - Hence exception handler is NOT self-modifying
1061 * - Separate table for load exceptions and store exceptions.
1062 * - Each table is of size: (8 * 32) = 256 bytes
1063 */
1064
1065.section .text
1066.align 4
1067lw_table:
1068lw_r0:          R3_TO_LWREG     (0);
1069lw_r1:          LWREG_NOP;
1070lw_r2:          R3_TO_LWREG     (2);
1071lw_r3:          R3_TO_LWREG_V   (3);
1072lw_r4:          R3_TO_LWREG_V   (4);
1073lw_r5:          R3_TO_LWREG_V   (5);
1074lw_r6:          R3_TO_LWREG_V   (6);
1075lw_r7:          R3_TO_LWREG     (7);
1076lw_r8:          R3_TO_LWREG     (8);
1077lw_r9:          R3_TO_LWREG     (9);
1078lw_r10:         R3_TO_LWREG     (10);
1079lw_r11:         R3_TO_LWREG     (11);
1080lw_r12:         R3_TO_LWREG     (12);
1081lw_r13:         R3_TO_LWREG     (13);
1082lw_r14:         R3_TO_LWREG     (14);
1083lw_r15:         R3_TO_LWREG     (15);
1084lw_r16:         R3_TO_LWREG     (16);
1085lw_r17:         LWREG_NOP;
1086lw_r18:         R3_TO_LWREG     (18);
1087lw_r19:         R3_TO_LWREG     (19);
1088lw_r20:         R3_TO_LWREG     (20);
1089lw_r21:         R3_TO_LWREG     (21);
1090lw_r22:         R3_TO_LWREG     (22);
1091lw_r23:         R3_TO_LWREG     (23);
1092lw_r24:         R3_TO_LWREG     (24);
1093lw_r25:         R3_TO_LWREG     (25);
1094lw_r26:         R3_TO_LWREG     (26);
1095lw_r27:         R3_TO_LWREG     (27);
1096lw_r28:         R3_TO_LWREG     (28);
1097lw_r29:         R3_TO_LWREG     (29);
1098lw_r30:         R3_TO_LWREG     (30);
1099#ifdef CONFIG_MMU
1100lw_r31:         R3_TO_LWREG_V   (31);
1101#else
1102lw_r31:         R3_TO_LWREG     (31);
1103#endif
1104
1105sw_table:
1106sw_r0:          SWREG_TO_R3     (0);
1107sw_r1:          SWREG_NOP;
1108sw_r2:          SWREG_TO_R3     (2);
1109sw_r3:          SWREG_TO_R3_V   (3);
1110sw_r4:          SWREG_TO_R3_V   (4);
1111sw_r5:          SWREG_TO_R3_V   (5);
1112sw_r6:          SWREG_TO_R3_V   (6);
1113sw_r7:          SWREG_TO_R3     (7);
1114sw_r8:          SWREG_TO_R3     (8);
1115sw_r9:          SWREG_TO_R3     (9);
1116sw_r10:         SWREG_TO_R3     (10);
1117sw_r11:         SWREG_TO_R3     (11);
1118sw_r12:         SWREG_TO_R3     (12);
1119sw_r13:         SWREG_TO_R3     (13);
1120sw_r14:         SWREG_TO_R3     (14);
1121sw_r15:         SWREG_TO_R3     (15);
1122sw_r16:         SWREG_TO_R3     (16);
1123sw_r17:         SWREG_NOP;
1124sw_r18:         SWREG_TO_R3     (18);
1125sw_r19:         SWREG_TO_R3     (19);
1126sw_r20:         SWREG_TO_R3     (20);
1127sw_r21:         SWREG_TO_R3     (21);
1128sw_r22:         SWREG_TO_R3     (22);
1129sw_r23:         SWREG_TO_R3     (23);
1130sw_r24:         SWREG_TO_R3     (24);
1131sw_r25:         SWREG_TO_R3     (25);
1132sw_r26:         SWREG_TO_R3     (26);
1133sw_r27:         SWREG_TO_R3     (27);
1134sw_r28:         SWREG_TO_R3     (28);
1135sw_r29:         SWREG_TO_R3     (29);
1136sw_r30:         SWREG_TO_R3     (30);
1137#ifdef CONFIG_MMU
1138sw_r31:         SWREG_TO_R3_V   (31);
1139#else
1140sw_r31:         SWREG_TO_R3     (31);
1141#endif
1142
1143#ifdef CONFIG_MMU
1144lw_table_vm:
1145lw_r0_vm:       R3_TO_LWREG_VM          (0);
1146lw_r1_vm:       R3_TO_LWREG_VM_V        (1);
1147lw_r2_vm:       R3_TO_LWREG_VM_V        (2);
1148lw_r3_vm:       R3_TO_LWREG_VM_V        (3);
1149lw_r4_vm:       R3_TO_LWREG_VM_V        (4);
1150lw_r5_vm:       R3_TO_LWREG_VM_V        (5);
1151lw_r6_vm:       R3_TO_LWREG_VM_V        (6);
1152lw_r7_vm:       R3_TO_LWREG_VM_V        (7);
1153lw_r8_vm:       R3_TO_LWREG_VM_V        (8);
1154lw_r9_vm:       R3_TO_LWREG_VM_V        (9);
1155lw_r10_vm:      R3_TO_LWREG_VM_V        (10);
1156lw_r11_vm:      R3_TO_LWREG_VM_V        (11);
1157lw_r12_vm:      R3_TO_LWREG_VM_V        (12);
1158lw_r13_vm:      R3_TO_LWREG_VM_V        (13);
1159lw_r14_vm:      R3_TO_LWREG_VM_V        (14);
1160lw_r15_vm:      R3_TO_LWREG_VM_V        (15);
1161lw_r16_vm:      R3_TO_LWREG_VM_V        (16);
1162lw_r17_vm:      R3_TO_LWREG_VM_V        (17);
1163lw_r18_vm:      R3_TO_LWREG_VM_V        (18);
1164lw_r19_vm:      R3_TO_LWREG_VM_V        (19);
1165lw_r20_vm:      R3_TO_LWREG_VM_V        (20);
1166lw_r21_vm:      R3_TO_LWREG_VM_V        (21);
1167lw_r22_vm:      R3_TO_LWREG_VM_V        (22);
1168lw_r23_vm:      R3_TO_LWREG_VM_V        (23);
1169lw_r24_vm:      R3_TO_LWREG_VM_V        (24);
1170lw_r25_vm:      R3_TO_LWREG_VM_V        (25);
1171lw_r26_vm:      R3_TO_LWREG_VM_V        (26);
1172lw_r27_vm:      R3_TO_LWREG_VM_V        (27);
1173lw_r28_vm:      R3_TO_LWREG_VM_V        (28);
1174lw_r29_vm:      R3_TO_LWREG_VM_V        (29);
1175lw_r30_vm:      R3_TO_LWREG_VM_V        (30);
1176lw_r31_vm:      R3_TO_LWREG_VM_V        (31);
1177
1178sw_table_vm:
1179sw_r0_vm:       SWREG_TO_R3_VM          (0);
1180sw_r1_vm:       SWREG_TO_R3_VM_V        (1);
1181sw_r2_vm:       SWREG_TO_R3_VM_V        (2);
1182sw_r3_vm:       SWREG_TO_R3_VM_V        (3);
1183sw_r4_vm:       SWREG_TO_R3_VM_V        (4);
1184sw_r5_vm:       SWREG_TO_R3_VM_V        (5);
1185sw_r6_vm:       SWREG_TO_R3_VM_V        (6);
1186sw_r7_vm:       SWREG_TO_R3_VM_V        (7);
1187sw_r8_vm:       SWREG_TO_R3_VM_V        (8);
1188sw_r9_vm:       SWREG_TO_R3_VM_V        (9);
1189sw_r10_vm:      SWREG_TO_R3_VM_V        (10);
1190sw_r11_vm:      SWREG_TO_R3_VM_V        (11);
1191sw_r12_vm:      SWREG_TO_R3_VM_V        (12);
1192sw_r13_vm:      SWREG_TO_R3_VM_V        (13);
1193sw_r14_vm:      SWREG_TO_R3_VM_V        (14);
1194sw_r15_vm:      SWREG_TO_R3_VM_V        (15);
1195sw_r16_vm:      SWREG_TO_R3_VM_V        (16);
1196sw_r17_vm:      SWREG_TO_R3_VM_V        (17);
1197sw_r18_vm:      SWREG_TO_R3_VM_V        (18);
1198sw_r19_vm:      SWREG_TO_R3_VM_V        (19);
1199sw_r20_vm:      SWREG_TO_R3_VM_V        (20);
1200sw_r21_vm:      SWREG_TO_R3_VM_V        (21);
1201sw_r22_vm:      SWREG_TO_R3_VM_V        (22);
1202sw_r23_vm:      SWREG_TO_R3_VM_V        (23);
1203sw_r24_vm:      SWREG_TO_R3_VM_V        (24);
1204sw_r25_vm:      SWREG_TO_R3_VM_V        (25);
1205sw_r26_vm:      SWREG_TO_R3_VM_V        (26);
1206sw_r27_vm:      SWREG_TO_R3_VM_V        (27);
1207sw_r28_vm:      SWREG_TO_R3_VM_V        (28);
1208sw_r29_vm:      SWREG_TO_R3_VM_V        (29);
1209sw_r30_vm:      SWREG_TO_R3_VM_V        (30);
1210sw_r31_vm:      SWREG_TO_R3_VM_V        (31);
1211#endif /* CONFIG_MMU */
1212
1213/* Temporary data structures used in the handler */
1214.section .data
1215.align 4
1216ex_tmp_data_loc_0:
1217        .byte 0
1218ex_tmp_data_loc_1:
1219        .byte 0
1220ex_tmp_data_loc_2:
1221        .byte 0
1222ex_tmp_data_loc_3:
1223        .byte 0
1224ex_reg_op:
1225        .byte 0
1226