linux/arch/sh/kernel/cpu/sh5/entry.S
<<
>>
Prefs
   1/*
   2 * arch/sh/kernel/cpu/sh5/entry.S
   3 *
   4 * Copyright (C) 2000, 2001  Paolo Alberelli
   5 * Copyright (C) 2004 - 2008  Paul Mundt
   6 * Copyright (C) 2003, 2004  Richard Curnow
   7 *
   8 * This file is subject to the terms and conditions of the GNU General Public
   9 * License.  See the file "COPYING" in the main directory of this archive
  10 * for more details.
  11 */
  12#include <linux/errno.h>
  13#include <linux/init.h>
  14#include <linux/sys.h>
  15#include <cpu/registers.h>
  16#include <asm/processor.h>
  17#include <asm/unistd.h>
  18#include <asm/thread_info.h>
  19#include <asm/asm-offsets.h>
  20
  21/*
  22 * SR fields.
  23 */
  24#define SR_ASID_MASK    0x00ff0000
  25#define SR_FD_MASK      0x00008000
  26#define SR_SS           0x08000000
  27#define SR_BL           0x10000000
  28#define SR_MD           0x40000000
  29
  30/*
  31 * Event code.
  32 */
  33#define EVENT_INTERRUPT         0
  34#define EVENT_FAULT_TLB         1
  35#define EVENT_FAULT_NOT_TLB     2
  36#define EVENT_DEBUG             3
  37
  38/* EXPEVT values */
  39#define RESET_CAUSE             0x20
  40#define DEBUGSS_CAUSE           0x980
  41
  42/*
  43 * Frame layout. Quad index.
  44 */
  45#define FRAME_T(x)      FRAME_TBASE+(x*8)
  46#define FRAME_R(x)      FRAME_RBASE+(x*8)
  47#define FRAME_S(x)      FRAME_SBASE+(x*8)
  48#define FSPC            0
  49#define FSSR            1
  50#define FSYSCALL_ID     2
  51
  52/* Arrange the save frame to be a multiple of 32 bytes long */
  53#define FRAME_SBASE     0
  54#define FRAME_RBASE     (FRAME_SBASE+(3*8))     /* SYSCALL_ID - SSR - SPC */
  55#define FRAME_TBASE     (FRAME_RBASE+(63*8))    /* r0 - r62 */
  56#define FRAME_PBASE     (FRAME_TBASE+(8*8))     /* tr0 -tr7 */
  57#define FRAME_SIZE      (FRAME_PBASE+(2*8))     /* pad0-pad1 */
  58
  59#define FP_FRAME_SIZE   FP_FRAME_BASE+(33*8)    /* dr0 - dr31 + fpscr */
  60#define FP_FRAME_BASE   0
  61
  62#define SAVED_R2        0*8
  63#define SAVED_R3        1*8
  64#define SAVED_R4        2*8
  65#define SAVED_R5        3*8
  66#define SAVED_R18       4*8
  67#define SAVED_R6        5*8
  68#define SAVED_TR0       6*8
  69
  70/* These are the registers saved in the TLB path that aren't saved in the first
  71   level of the normal one. */
  72#define TLB_SAVED_R25   7*8
  73#define TLB_SAVED_TR1   8*8
  74#define TLB_SAVED_TR2   9*8
  75#define TLB_SAVED_TR3   10*8
  76#define TLB_SAVED_TR4   11*8
  77/* Save R0/R1 : PT-migrating compiler currently dishounours -ffixed-r0 and -ffixed-r1 causing
  78   breakage otherwise. */
  79#define TLB_SAVED_R0    12*8
  80#define TLB_SAVED_R1    13*8
  81
  82#define CLI()                           \
  83        getcon  SR, r6;                 \
  84        ori     r6, 0xf0, r6;           \
  85        putcon  r6, SR;
  86
  87#define STI()                           \
  88        getcon  SR, r6;                 \
  89        andi    r6, ~0xf0, r6;          \
  90        putcon  r6, SR;
  91
  92#ifdef CONFIG_PREEMPT
  93#  define preempt_stop()        CLI()
  94#else
  95#  define preempt_stop()
  96#  define resume_kernel         restore_all
  97#endif
  98
  99        .section        .data, "aw"
 100
 101#define FAST_TLBMISS_STACK_CACHELINES 4
 102#define FAST_TLBMISS_STACK_QUADWORDS (4*FAST_TLBMISS_STACK_CACHELINES)
 103
 104/* Register back-up area for all exceptions */
 105        .balign 32
 106        /* Allow for 16 quadwords to be pushed by fast tlbmiss handling
 107         * register saves etc. */
 108        .fill FAST_TLBMISS_STACK_QUADWORDS, 8, 0x0
 109/* This is 32 byte aligned by construction */
 110/* Register back-up area for all exceptions */
 111reg_save_area:
 112        .quad   0
 113        .quad   0
 114        .quad   0
 115        .quad   0
 116
 117        .quad   0
 118        .quad   0
 119        .quad   0
 120        .quad   0
 121
 122        .quad   0
 123        .quad   0
 124        .quad   0
 125        .quad   0
 126
 127        .quad   0
 128        .quad   0
 129
 130/* Save area for RESVEC exceptions. We cannot use reg_save_area because of
 131 * reentrancy. Note this area may be accessed via physical address.
 132 * Align so this fits a whole single cache line, for ease of purging.
 133 */
 134        .balign 32,0,32
 135resvec_save_area:
 136        .quad   0
 137        .quad   0
 138        .quad   0
 139        .quad   0
 140        .quad   0
 141        .balign 32,0,32
 142
 143/* Jump table of 3rd level handlers  */
 144trap_jtable:
 145        .long   do_exception_error              /* 0x000 */
 146        .long   do_exception_error              /* 0x020 */
 147#ifdef CONFIG_MMU
 148        .long   tlb_miss_load                           /* 0x040 */
 149        .long   tlb_miss_store                          /* 0x060 */
 150#else
 151        .long   do_exception_error
 152        .long   do_exception_error
 153#endif
 154        ! ARTIFICIAL pseudo-EXPEVT setting
 155        .long   do_debug_interrupt              /* 0x080 */
 156#ifdef CONFIG_MMU
 157        .long   tlb_miss_load                           /* 0x0A0 */
 158        .long   tlb_miss_store                          /* 0x0C0 */
 159#else
 160        .long   do_exception_error
 161        .long   do_exception_error
 162#endif
 163        .long   do_address_error_load   /* 0x0E0 */
 164        .long   do_address_error_store  /* 0x100 */
 165#ifdef CONFIG_SH_FPU
 166        .long   do_fpu_error            /* 0x120 */
 167#else
 168        .long   do_exception_error              /* 0x120 */
 169#endif
 170        .long   do_exception_error              /* 0x140 */
 171        .long   system_call                             /* 0x160 */
 172        .long   do_reserved_inst                /* 0x180 */
 173        .long   do_illegal_slot_inst    /* 0x1A0 */
 174        .long   do_exception_error              /* 0x1C0 - NMI */
 175        .long   do_exception_error              /* 0x1E0 */
 176        .rept 15
 177                .long do_IRQ            /* 0x200 - 0x3C0 */
 178        .endr
 179        .long   do_exception_error              /* 0x3E0 */
 180        .rept 32
 181                .long do_IRQ            /* 0x400 - 0x7E0 */
 182        .endr
 183        .long   fpu_error_or_IRQA                       /* 0x800 */
 184        .long   fpu_error_or_IRQB                       /* 0x820 */
 185        .long   do_IRQ                  /* 0x840 */
 186        .long   do_IRQ                  /* 0x860 */
 187        .rept 6
 188                .long do_exception_error        /* 0x880 - 0x920 */
 189        .endr
 190        .long   breakpoint_trap_handler /* 0x940 */
 191        .long   do_exception_error              /* 0x960 */
 192        .long   do_single_step          /* 0x980 */
 193
 194        .rept 3
 195                .long do_exception_error        /* 0x9A0 - 0x9E0 */
 196        .endr
 197        .long   do_IRQ                  /* 0xA00 */
 198        .long   do_IRQ                  /* 0xA20 */
 199#ifdef CONFIG_MMU
 200        .long   itlb_miss_or_IRQ                        /* 0xA40 */
 201#else
 202        .long   do_IRQ
 203#endif
 204        .long   do_IRQ                  /* 0xA60 */
 205        .long   do_IRQ                  /* 0xA80 */
 206#ifdef CONFIG_MMU
 207        .long   itlb_miss_or_IRQ                        /* 0xAA0 */
 208#else
 209        .long   do_IRQ
 210#endif
 211        .long   do_exception_error              /* 0xAC0 */
 212        .long   do_address_error_exec   /* 0xAE0 */
 213        .rept 8
 214                .long do_exception_error        /* 0xB00 - 0xBE0 */
 215        .endr
 216        .rept 18
 217                .long do_IRQ            /* 0xC00 - 0xE20 */
 218        .endr
 219
 220        .section        .text64, "ax"
 221
 222/*
 223 * --- Exception/Interrupt/Event Handling Section
 224 */
 225
 226/*
 227 * VBR and RESVEC blocks.
 228 *
 229 * First level handler for VBR-based exceptions.
 230 *
 231 * To avoid waste of space, align to the maximum text block size.
 232 * This is assumed to be at most 128 bytes or 32 instructions.
 233 * DO NOT EXCEED 32 instructions on the first level handlers !
 234 *
 235 * Also note that RESVEC is contained within the VBR block
 236 * where the room left (1KB - TEXT_SIZE) allows placing
 237 * the RESVEC block (at most 512B + TEXT_SIZE).
 238 *
 239 * So first (and only) level handler for RESVEC-based exceptions.
 240 *
 241 * Where the fault/interrupt is handled (not_a_tlb_miss, tlb_miss
 242 * and interrupt) we are a lot tight with register space until
 243 * saving onto the stack frame, which is done in handle_exception().
 244 *
 245 */
 246
 247#define TEXT_SIZE       128
 248#define BLOCK_SIZE      1664            /* Dynamic check, 13*128 */
 249
 250        .balign TEXT_SIZE
 251LVBR_block:
 252        .space  256, 0                  /* Power-on class handler, */
 253                                        /* not required here       */
 254not_a_tlb_miss:
 255        synco   /* TAKum03020 (but probably a good idea anyway.) */
 256        /* Save original stack pointer into KCR1 */
 257        putcon  SP, KCR1
 258
 259        /* Save other original registers into reg_save_area */
 260        movi  reg_save_area, SP
 261        st.q    SP, SAVED_R2, r2
 262        st.q    SP, SAVED_R3, r3
 263        st.q    SP, SAVED_R4, r4
 264        st.q    SP, SAVED_R5, r5
 265        st.q    SP, SAVED_R6, r6
 266        st.q    SP, SAVED_R18, r18
 267        gettr   tr0, r3
 268        st.q    SP, SAVED_TR0, r3
 269
 270        /* Set args for Non-debug, Not a TLB miss class handler */
 271        getcon  EXPEVT, r2
 272        movi    ret_from_exception, r3
 273        ori     r3, 1, r3
 274        movi    EVENT_FAULT_NOT_TLB, r4
 275        or      SP, ZERO, r5
 276        getcon  KCR1, SP
 277        pta     handle_exception, tr0
 278        blink   tr0, ZERO
 279
 280        .balign 256
 281        ! VBR+0x200
 282        nop
 283        .balign 256
 284        ! VBR+0x300
 285        nop
 286        .balign 256
 287        /*
 288         * Instead of the natural .balign 1024 place RESVEC here
 289         * respecting the final 1KB alignment.
 290         */
 291        .balign TEXT_SIZE
 292        /*
 293         * Instead of '.space 1024-TEXT_SIZE' place the RESVEC
 294         * block making sure the final alignment is correct.
 295         */
 296#ifdef CONFIG_MMU
 297tlb_miss:
 298        synco   /* TAKum03020 (but probably a good idea anyway.) */
 299        putcon  SP, KCR1
 300        movi    reg_save_area, SP
 301        /* SP is guaranteed 32-byte aligned. */
 302        st.q    SP, TLB_SAVED_R0 , r0
 303        st.q    SP, TLB_SAVED_R1 , r1
 304        st.q    SP, SAVED_R2 , r2
 305        st.q    SP, SAVED_R3 , r3
 306        st.q    SP, SAVED_R4 , r4
 307        st.q    SP, SAVED_R5 , r5
 308        st.q    SP, SAVED_R6 , r6
 309        st.q    SP, SAVED_R18, r18
 310
 311        /* Save R25 for safety; as/ld may want to use it to achieve the call to
 312         * the code in mm/tlbmiss.c */
 313        st.q    SP, TLB_SAVED_R25, r25
 314        gettr   tr0, r2
 315        gettr   tr1, r3
 316        gettr   tr2, r4
 317        gettr   tr3, r5
 318        gettr   tr4, r18
 319        st.q    SP, SAVED_TR0 , r2
 320        st.q    SP, TLB_SAVED_TR1 , r3
 321        st.q    SP, TLB_SAVED_TR2 , r4
 322        st.q    SP, TLB_SAVED_TR3 , r5
 323        st.q    SP, TLB_SAVED_TR4 , r18
 324
 325        pt      do_fast_page_fault, tr0
 326        getcon  SSR, r2
 327        getcon  EXPEVT, r3
 328        getcon  TEA, r4
 329        shlri   r2, 30, r2
 330        andi    r2, 1, r2       /* r2 = SSR.MD */
 331        blink   tr0, LINK
 332
 333        pt      fixup_to_invoke_general_handler, tr1
 334
 335        /* If the fast path handler fixed the fault, just drop through quickly
 336           to the restore code right away to return to the excepting context.
 337           */
 338        bnei/u  r2, 0, tr1
 339
 340fast_tlb_miss_restore:
 341        ld.q    SP, SAVED_TR0, r2
 342        ld.q    SP, TLB_SAVED_TR1, r3
 343        ld.q    SP, TLB_SAVED_TR2, r4
 344
 345        ld.q    SP, TLB_SAVED_TR3, r5
 346        ld.q    SP, TLB_SAVED_TR4, r18
 347
 348        ptabs   r2, tr0
 349        ptabs   r3, tr1
 350        ptabs   r4, tr2
 351        ptabs   r5, tr3
 352        ptabs   r18, tr4
 353
 354        ld.q    SP, TLB_SAVED_R0, r0
 355        ld.q    SP, TLB_SAVED_R1, r1
 356        ld.q    SP, SAVED_R2, r2
 357        ld.q    SP, SAVED_R3, r3
 358        ld.q    SP, SAVED_R4, r4
 359        ld.q    SP, SAVED_R5, r5
 360        ld.q    SP, SAVED_R6, r6
 361        ld.q    SP, SAVED_R18, r18
 362        ld.q    SP, TLB_SAVED_R25, r25
 363
 364        getcon  KCR1, SP
 365        rte
 366        nop /* for safety, in case the code is run on sh5-101 cut1.x */
 367
 368fixup_to_invoke_general_handler:
 369
 370        /* OK, new method.  Restore stuff that's not expected to get saved into
 371           the 'first-level' reg save area, then just fall through to setting
 372           up the registers and calling the second-level handler. */
 373
 374        /* 2nd level expects r2,3,4,5,6,18,tr0 to be saved.  So we must restore
 375           r25,tr1-4 and save r6 to get into the right state.  */
 376
 377        ld.q    SP, TLB_SAVED_TR1, r3
 378        ld.q    SP, TLB_SAVED_TR2, r4
 379        ld.q    SP, TLB_SAVED_TR3, r5
 380        ld.q    SP, TLB_SAVED_TR4, r18
 381        ld.q    SP, TLB_SAVED_R25, r25
 382
 383        ld.q    SP, TLB_SAVED_R0, r0
 384        ld.q    SP, TLB_SAVED_R1, r1
 385
 386        ptabs/u r3, tr1
 387        ptabs/u r4, tr2
 388        ptabs/u r5, tr3
 389        ptabs/u r18, tr4
 390
 391        /* Set args for Non-debug, TLB miss class handler */
 392        getcon  EXPEVT, r2
 393        movi    ret_from_exception, r3
 394        ori     r3, 1, r3
 395        movi    EVENT_FAULT_TLB, r4
 396        or      SP, ZERO, r5
 397        getcon  KCR1, SP
 398        pta     handle_exception, tr0
 399        blink   tr0, ZERO
 400#else /* CONFIG_MMU */
 401        .balign 256
 402#endif
 403
 404/* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE
 405   DOES END UP AT VBR+0x600 */
 406        nop
 407        nop
 408        nop
 409        nop
 410        nop
 411        nop
 412
 413        .balign 256
 414        /* VBR + 0x600 */
 415
 416interrupt:
 417        synco   /* TAKum03020 (but probably a good idea anyway.) */
 418        /* Save original stack pointer into KCR1 */
 419        putcon  SP, KCR1
 420
 421        /* Save other original registers into reg_save_area */
 422        movi  reg_save_area, SP
 423        st.q    SP, SAVED_R2, r2
 424        st.q    SP, SAVED_R3, r3
 425        st.q    SP, SAVED_R4, r4
 426        st.q    SP, SAVED_R5, r5
 427        st.q    SP, SAVED_R6, r6
 428        st.q    SP, SAVED_R18, r18
 429        gettr   tr0, r3
 430        st.q    SP, SAVED_TR0, r3
 431
 432        /* Set args for interrupt class handler */
 433        getcon  INTEVT, r2
 434        movi    ret_from_irq, r3
 435        ori     r3, 1, r3
 436        movi    EVENT_INTERRUPT, r4
 437        or      SP, ZERO, r5
 438        getcon  KCR1, SP
 439        pta     handle_exception, tr0
 440        blink   tr0, ZERO
 441        .balign TEXT_SIZE               /* let's waste the bare minimum */
 442
 443LVBR_block_end:                         /* Marker. Used for total checking */
 444
 445        .balign 256
 446LRESVEC_block:
 447        /* Panic handler. Called with MMU off. Possible causes/actions:
 448         * - Reset:             Jump to program start.
 449         * - Single Step:       Turn off Single Step & return.
 450         * - Others:            Call panic handler, passing PC as arg.
 451         *                      (this may need to be extended...)
 452         */
 453reset_or_panic:
 454        synco   /* TAKum03020 (but probably a good idea anyway.) */
 455        putcon  SP, DCR
 456        /* First save r0-1 and tr0, as we need to use these */
 457        movi    resvec_save_area-CONFIG_PAGE_OFFSET, SP
 458        st.q    SP, 0, r0
 459        st.q    SP, 8, r1
 460        gettr   tr0, r0
 461        st.q    SP, 32, r0
 462
 463        /* Check cause */
 464        getcon  EXPEVT, r0
 465        movi    RESET_CAUSE, r1
 466        sub     r1, r0, r1              /* r1=0 if reset */
 467        movi    _stext-CONFIG_PAGE_OFFSET, r0
 468        ori     r0, 1, r0
 469        ptabs   r0, tr0
 470        beqi    r1, 0, tr0              /* Jump to start address if reset */
 471
 472        getcon  EXPEVT, r0
 473        movi    DEBUGSS_CAUSE, r1
 474        sub     r1, r0, r1              /* r1=0 if single step */
 475        pta     single_step_panic, tr0
 476        beqi    r1, 0, tr0              /* jump if single step */
 477
 478        /* Now jump to where we save the registers. */
 479        movi    panic_stash_regs-CONFIG_PAGE_OFFSET, r1
 480        ptabs   r1, tr0
 481        blink   tr0, r63
 482
 483single_step_panic:
 484        /* We are in a handler with Single Step set. We need to resume the
 485         * handler, by turning on MMU & turning off Single Step. */
 486        getcon  SSR, r0
 487        movi    SR_MMU, r1
 488        or      r0, r1, r0
 489        movi    ~SR_SS, r1
 490        and     r0, r1, r0
 491        putcon  r0, SSR
 492        /* Restore EXPEVT, as the rte won't do this */
 493        getcon  PEXPEVT, r0
 494        putcon  r0, EXPEVT
 495        /* Restore regs */
 496        ld.q    SP, 32, r0
 497        ptabs   r0, tr0
 498        ld.q    SP, 0, r0
 499        ld.q    SP, 8, r1
 500        getcon  DCR, SP
 501        synco
 502        rte
 503
 504
 505        .balign 256
 506debug_exception:
 507        synco   /* TAKum03020 (but probably a good idea anyway.) */
 508        /*
 509         * Single step/software_break_point first level handler.
 510         * Called with MMU off, so the first thing we do is enable it
 511         * by doing an rte with appropriate SSR.
 512         */
 513        putcon  SP, DCR
 514        /* Save SSR & SPC, together with R0 & R1, as we need to use 2 regs. */
 515        movi    resvec_save_area-CONFIG_PAGE_OFFSET, SP
 516
 517        /* With the MMU off, we are bypassing the cache, so purge any
 518         * data that will be made stale by the following stores.
 519         */
 520        ocbp    SP, 0
 521        synco
 522
 523        st.q    SP, 0, r0
 524        st.q    SP, 8, r1
 525        getcon  SPC, r0
 526        st.q    SP, 16, r0
 527        getcon  SSR, r0
 528        st.q    SP, 24, r0
 529
 530        /* Enable MMU, block exceptions, set priv mode, disable single step */
 531        movi    SR_MMU | SR_BL | SR_MD, r1
 532        or      r0, r1, r0
 533        movi    ~SR_SS, r1
 534        and     r0, r1, r0
 535        putcon  r0, SSR
 536        /* Force control to debug_exception_2 when rte is executed */
 537        movi    debug_exeception_2, r0
 538        ori     r0, 1, r0      /* force SHmedia, just in case */
 539        putcon  r0, SPC
 540        getcon  DCR, SP
 541        synco
 542        rte
 543debug_exeception_2:
 544        /* Restore saved regs */
 545        putcon  SP, KCR1
 546        movi    resvec_save_area, SP
 547        ld.q    SP, 24, r0
 548        putcon  r0, SSR
 549        ld.q    SP, 16, r0
 550        putcon  r0, SPC
 551        ld.q    SP, 0, r0
 552        ld.q    SP, 8, r1
 553
 554        /* Save other original registers into reg_save_area */
 555        movi  reg_save_area, SP
 556        st.q    SP, SAVED_R2, r2
 557        st.q    SP, SAVED_R3, r3
 558        st.q    SP, SAVED_R4, r4
 559        st.q    SP, SAVED_R5, r5
 560        st.q    SP, SAVED_R6, r6
 561        st.q    SP, SAVED_R18, r18
 562        gettr   tr0, r3
 563        st.q    SP, SAVED_TR0, r3
 564
 565        /* Set args for debug class handler */
 566        getcon  EXPEVT, r2
 567        movi    ret_from_exception, r3
 568        ori     r3, 1, r3
 569        movi    EVENT_DEBUG, r4
 570        or      SP, ZERO, r5
 571        getcon  KCR1, SP
 572        pta     handle_exception, tr0
 573        blink   tr0, ZERO
 574
 575        .balign 256
 576debug_interrupt:
 577        /* !!! WE COME HERE IN REAL MODE !!! */
 578        /* Hook-up debug interrupt to allow various debugging options to be
 579         * hooked into its handler. */
 580        /* Save original stack pointer into KCR1 */
 581        synco
 582        putcon  SP, KCR1
 583        movi    resvec_save_area-CONFIG_PAGE_OFFSET, SP
 584        ocbp    SP, 0
 585        ocbp    SP, 32
 586        synco
 587
 588        /* Save other original registers into reg_save_area thru real addresses */
 589        st.q    SP, SAVED_R2, r2
 590        st.q    SP, SAVED_R3, r3
 591        st.q    SP, SAVED_R4, r4
 592        st.q    SP, SAVED_R5, r5
 593        st.q    SP, SAVED_R6, r6
 594        st.q    SP, SAVED_R18, r18
 595        gettr   tr0, r3
 596        st.q    SP, SAVED_TR0, r3
 597
 598        /* move (spc,ssr)->(pspc,pssr).  The rte will shift
 599           them back again, so that they look like the originals
 600           as far as the real handler code is concerned. */
 601        getcon  spc, r6
 602        putcon  r6, pspc
 603        getcon  ssr, r6
 604        putcon  r6, pssr
 605
 606        ! construct useful SR for handle_exception
 607        movi    3, r6
 608        shlli   r6, 30, r6
 609        getcon  sr, r18
 610        or      r18, r6, r6
 611        putcon  r6, ssr
 612
 613        ! SSR is now the current SR with the MD and MMU bits set
 614        ! i.e. the rte will switch back to priv mode and put
 615        ! the mmu back on
 616
 617        ! construct spc
 618        movi    handle_exception, r18
 619        ori     r18, 1, r18             ! for safety (do we need this?)
 620        putcon  r18, spc
 621
 622        /* Set args for Non-debug, Not a TLB miss class handler */
 623
 624        ! EXPEVT==0x80 is unused, so 'steal' this value to put the
 625        ! debug interrupt handler in the vectoring table
 626        movi    0x80, r2
 627        movi    ret_from_exception, r3
 628        ori     r3, 1, r3
 629        movi    EVENT_FAULT_NOT_TLB, r4
 630
 631        or      SP, ZERO, r5
 632        movi    CONFIG_PAGE_OFFSET, r6
 633        add     r6, r5, r5
 634        getcon  KCR1, SP
 635
 636        synco   ! for safety
 637        rte     ! -> handle_exception, switch back to priv mode again
 638
 639LRESVEC_block_end:                      /* Marker. Unused. */
 640
 641        .balign TEXT_SIZE
 642
 643/*
 644 * Second level handler for VBR-based exceptions. Pre-handler.
 645 * In common to all stack-frame sensitive handlers.
 646 *
 647 * Inputs:
 648 * (KCR0) Current [current task union]
 649 * (KCR1) Original SP
 650 * (r2)   INTEVT/EXPEVT
 651 * (r3)   appropriate return address
 652 * (r4)   Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault, 3=debug)
 653 * (r5)   Pointer to reg_save_area
 654 * (SP)   Original SP
 655 *
 656 * Available registers:
 657 * (r6)
 658 * (r18)
 659 * (tr0)
 660 *
 661 */
 662handle_exception:
 663        /* Common 2nd level handler. */
 664
 665        /* First thing we need an appropriate stack pointer */
 666        getcon  SSR, r6
 667        shlri   r6, 30, r6
 668        andi    r6, 1, r6
 669        pta     stack_ok, tr0
 670        bne     r6, ZERO, tr0           /* Original stack pointer is fine */
 671
 672        /* Set stack pointer for user fault */
 673        getcon  KCR0, SP
 674        movi    THREAD_SIZE, r6         /* Point to the end */
 675        add     SP, r6, SP
 676
 677stack_ok:
 678
 679/* DEBUG : check for underflow/overflow of the kernel stack */
 680        pta     no_underflow, tr0
 681        getcon  KCR0, r6
 682        movi    1024, r18
 683        add     r6, r18, r6
 684        bge     SP, r6, tr0     ! ? below 1k from bottom of stack : danger zone
 685
 686/* Just panic to cause a crash. */
 687bad_sp:
 688        ld.b    r63, 0, r6
 689        nop
 690
 691no_underflow:
 692        pta     bad_sp, tr0
 693        getcon  kcr0, r6
 694        movi    THREAD_SIZE, r18
 695        add     r18, r6, r6
 696        bgt     SP, r6, tr0     ! sp above the stack
 697
 698        /* Make some room for the BASIC frame. */
 699        movi    -(FRAME_SIZE), r6
 700        add     SP, r6, SP
 701
 702/* Could do this with no stalling if we had another spare register, but the
 703   code below will be OK. */
 704        ld.q    r5, SAVED_R2, r6
 705        ld.q    r5, SAVED_R3, r18
 706        st.q    SP, FRAME_R(2), r6
 707        ld.q    r5, SAVED_R4, r6
 708        st.q    SP, FRAME_R(3), r18
 709        ld.q    r5, SAVED_R5, r18
 710        st.q    SP, FRAME_R(4), r6
 711        ld.q    r5, SAVED_R6, r6
 712        st.q    SP, FRAME_R(5), r18
 713        ld.q    r5, SAVED_R18, r18
 714        st.q    SP, FRAME_R(6), r6
 715        ld.q    r5, SAVED_TR0, r6
 716        st.q    SP, FRAME_R(18), r18
 717        st.q    SP, FRAME_T(0), r6
 718
 719        /* Keep old SP around */
 720        getcon  KCR1, r6
 721
 722        /* Save the rest of the general purpose registers */
 723        st.q    SP, FRAME_R(0), r0
 724        st.q    SP, FRAME_R(1), r1
 725        st.q    SP, FRAME_R(7), r7
 726        st.q    SP, FRAME_R(8), r8
 727        st.q    SP, FRAME_R(9), r9
 728        st.q    SP, FRAME_R(10), r10
 729        st.q    SP, FRAME_R(11), r11
 730        st.q    SP, FRAME_R(12), r12
 731        st.q    SP, FRAME_R(13), r13
 732        st.q    SP, FRAME_R(14), r14
 733
 734        /* SP is somewhere else */
 735        st.q    SP, FRAME_R(15), r6
 736
 737        st.q    SP, FRAME_R(16), r16
 738        st.q    SP, FRAME_R(17), r17
 739        /* r18 is saved earlier. */
 740        st.q    SP, FRAME_R(19), r19
 741        st.q    SP, FRAME_R(20), r20
 742        st.q    SP, FRAME_R(21), r21
 743        st.q    SP, FRAME_R(22), r22
 744        st.q    SP, FRAME_R(23), r23
 745        st.q    SP, FRAME_R(24), r24
 746        st.q    SP, FRAME_R(25), r25
 747        st.q    SP, FRAME_R(26), r26
 748        st.q    SP, FRAME_R(27), r27
 749        st.q    SP, FRAME_R(28), r28
 750        st.q    SP, FRAME_R(29), r29
 751        st.q    SP, FRAME_R(30), r30
 752        st.q    SP, FRAME_R(31), r31
 753        st.q    SP, FRAME_R(32), r32
 754        st.q    SP, FRAME_R(33), r33
 755        st.q    SP, FRAME_R(34), r34
 756        st.q    SP, FRAME_R(35), r35
 757        st.q    SP, FRAME_R(36), r36
 758        st.q    SP, FRAME_R(37), r37
 759        st.q    SP, FRAME_R(38), r38
 760        st.q    SP, FRAME_R(39), r39
 761        st.q    SP, FRAME_R(40), r40
 762        st.q    SP, FRAME_R(41), r41
 763        st.q    SP, FRAME_R(42), r42
 764        st.q    SP, FRAME_R(43), r43
 765        st.q    SP, FRAME_R(44), r44
 766        st.q    SP, FRAME_R(45), r45
 767        st.q    SP, FRAME_R(46), r46
 768        st.q    SP, FRAME_R(47), r47
 769        st.q    SP, FRAME_R(48), r48
 770        st.q    SP, FRAME_R(49), r49
 771        st.q    SP, FRAME_R(50), r50
 772        st.q    SP, FRAME_R(51), r51
 773        st.q    SP, FRAME_R(52), r52
 774        st.q    SP, FRAME_R(53), r53
 775        st.q    SP, FRAME_R(54), r54
 776        st.q    SP, FRAME_R(55), r55
 777        st.q    SP, FRAME_R(56), r56
 778        st.q    SP, FRAME_R(57), r57
 779        st.q    SP, FRAME_R(58), r58
 780        st.q    SP, FRAME_R(59), r59
 781        st.q    SP, FRAME_R(60), r60
 782        st.q    SP, FRAME_R(61), r61
 783        st.q    SP, FRAME_R(62), r62
 784
 785        /*
 786         * Save the S* registers.
 787         */
 788        getcon  SSR, r61
 789        st.q    SP, FRAME_S(FSSR), r61
 790        getcon  SPC, r62
 791        st.q    SP, FRAME_S(FSPC), r62
 792        movi    -1, r62                 /* Reset syscall_nr */
 793        st.q    SP, FRAME_S(FSYSCALL_ID), r62
 794
 795        /* Save the rest of the target registers */
 796        gettr   tr1, r6
 797        st.q    SP, FRAME_T(1), r6
 798        gettr   tr2, r6
 799        st.q    SP, FRAME_T(2), r6
 800        gettr   tr3, r6
 801        st.q    SP, FRAME_T(3), r6
 802        gettr   tr4, r6
 803        st.q    SP, FRAME_T(4), r6
 804        gettr   tr5, r6
 805        st.q    SP, FRAME_T(5), r6
 806        gettr   tr6, r6
 807        st.q    SP, FRAME_T(6), r6
 808        gettr   tr7, r6
 809        st.q    SP, FRAME_T(7), r6
 810
 811        ! setup FP so that unwinder can wind back through nested kernel mode
 812        ! exceptions
 813        add     SP, ZERO, r14
 814
 815        /* For syscall and debug race condition, get TRA now */
 816        getcon  TRA, r5
 817
 818        /* We are in a safe position to turn SR.BL off, but set IMASK=0xf
 819         * Also set FD, to catch FPU usage in the kernel.
 820         *
 821         * benedict.gaster@superh.com 29/07/2002
 822         *
 823         * On all SH5-101 revisions it is unsafe to raise the IMASK and at the
 824         * same time change BL from 1->0, as any pending interrupt of a level
 825         * higher than he previous value of IMASK will leak through and be
 826         * taken unexpectedly.
 827         *
 828         * To avoid this we raise the IMASK and then issue another PUTCON to
 829         * enable interrupts.
 830         */
 831        getcon  SR, r6
 832        movi    SR_IMASK | SR_FD, r7
 833        or      r6, r7, r6
 834        putcon  r6, SR
 835        movi    SR_UNBLOCK_EXC, r7
 836        and     r6, r7, r6
 837        putcon  r6, SR
 838
 839
 840        /* Now call the appropriate 3rd level handler */
 841        or      r3, ZERO, LINK
 842        movi    trap_jtable, r3
 843        shlri   r2, 3, r2
 844        ldx.l   r2, r3, r3
 845        shlri   r2, 2, r2
 846        ptabs   r3, tr0
 847        or      SP, ZERO, r3
 848        blink   tr0, ZERO
 849
 850/*
 851 * Second level handler for VBR-based exceptions. Post-handlers.
 852 *
 853 * Post-handlers for interrupts (ret_from_irq), exceptions
 854 * (ret_from_exception) and common reentrance doors (restore_all
 855 * to get back to the original context, ret_from_syscall loop to
 856 * check kernel exiting).
 857 *
 858 * ret_with_reschedule and work_notifysig are an inner lables of
 859 * the ret_from_syscall loop.
 860 *
 861 * In common to all stack-frame sensitive handlers.
 862 *
 863 * Inputs:
 864 * (SP)   struct pt_regs *, original register's frame pointer (basic)
 865 *
 866 */
 867        .global ret_from_irq
 868ret_from_irq:
 869        ld.q    SP, FRAME_S(FSSR), r6
 870        shlri   r6, 30, r6
 871        andi    r6, 1, r6
 872        pta     resume_kernel, tr0
 873        bne     r6, ZERO, tr0           /* no further checks */
 874        STI()
 875        pta     ret_with_reschedule, tr0
 876        blink   tr0, ZERO               /* Do not check softirqs */
 877
 878        .global ret_from_exception
 879ret_from_exception:
 880        preempt_stop()
 881
 882        ld.q    SP, FRAME_S(FSSR), r6
 883        shlri   r6, 30, r6
 884        andi    r6, 1, r6
 885        pta     resume_kernel, tr0
 886        bne     r6, ZERO, tr0           /* no further checks */
 887
 888        /* Check softirqs */
 889
 890#ifdef CONFIG_PREEMPT
 891        pta   ret_from_syscall, tr0
 892        blink   tr0, ZERO
 893
 894resume_kernel:
 895        CLI()
 896
 897        pta     restore_all, tr0
 898
 899        getcon  KCR0, r6
 900        ld.l    r6, TI_PRE_COUNT, r7
 901        beq/u   r7, ZERO, tr0
 902
 903need_resched:
 904        ld.l    r6, TI_FLAGS, r7
 905        movi    (1 << TIF_NEED_RESCHED), r8
 906        and     r8, r7, r8
 907        bne     r8, ZERO, tr0
 908
 909        getcon  SR, r7
 910        andi    r7, 0xf0, r7
 911        bne     r7, ZERO, tr0
 912
 913        movi    preempt_schedule_irq, r7
 914        ori     r7, 1, r7
 915        ptabs   r7, tr1
 916        blink   tr1, LINK
 917
 918        pta     need_resched, tr1
 919        blink   tr1, ZERO
 920#endif
 921
 922        .global ret_from_syscall
 923ret_from_syscall:
 924
 925ret_with_reschedule:
 926        getcon  KCR0, r6                ! r6 contains current_thread_info
 927        ld.l    r6, TI_FLAGS, r7        ! r7 contains current_thread_info->flags
 928
 929        movi    _TIF_NEED_RESCHED, r8
 930        and     r8, r7, r8
 931        pta     work_resched, tr0
 932        bne     r8, ZERO, tr0
 933
 934        pta     restore_all, tr1
 935
 936        movi    (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), r8
 937        and     r8, r7, r8
 938        pta     work_notifysig, tr0
 939        bne     r8, ZERO, tr0
 940
 941        blink   tr1, ZERO
 942
 943work_resched:
 944        pta     ret_from_syscall, tr0
 945        gettr   tr0, LINK
 946        movi    schedule, r6
 947        ptabs   r6, tr0
 948        blink   tr0, ZERO               /* Call schedule(), return on top */
 949
 950work_notifysig:
 951        gettr   tr1, LINK
 952
 953        movi    do_notify_resume, r6
 954        ptabs   r6, tr0
 955        or      SP, ZERO, r2
 956        or      r7, ZERO, r3
 957        blink   tr0, LINK           /* Call do_notify_resume(regs, current_thread_info->flags), return here */
 958
 959restore_all:
 960        /* Do prefetches */
 961
 962        ld.q    SP, FRAME_T(0), r6
 963        ld.q    SP, FRAME_T(1), r7
 964        ld.q    SP, FRAME_T(2), r8
 965        ld.q    SP, FRAME_T(3), r9
 966        ptabs   r6, tr0
 967        ptabs   r7, tr1
 968        ptabs   r8, tr2
 969        ptabs   r9, tr3
 970        ld.q    SP, FRAME_T(4), r6
 971        ld.q    SP, FRAME_T(5), r7
 972        ld.q    SP, FRAME_T(6), r8
 973        ld.q    SP, FRAME_T(7), r9
 974        ptabs   r6, tr4
 975        ptabs   r7, tr5
 976        ptabs   r8, tr6
 977        ptabs   r9, tr7
 978
 979        ld.q    SP, FRAME_R(0), r0
 980        ld.q    SP, FRAME_R(1), r1
 981        ld.q    SP, FRAME_R(2), r2
 982        ld.q    SP, FRAME_R(3), r3
 983        ld.q    SP, FRAME_R(4), r4
 984        ld.q    SP, FRAME_R(5), r5
 985        ld.q    SP, FRAME_R(6), r6
 986        ld.q    SP, FRAME_R(7), r7
 987        ld.q    SP, FRAME_R(8), r8
 988        ld.q    SP, FRAME_R(9), r9
 989        ld.q    SP, FRAME_R(10), r10
 990        ld.q    SP, FRAME_R(11), r11
 991        ld.q    SP, FRAME_R(12), r12
 992        ld.q    SP, FRAME_R(13), r13
 993        ld.q    SP, FRAME_R(14), r14
 994
 995        ld.q    SP, FRAME_R(16), r16
 996        ld.q    SP, FRAME_R(17), r17
 997        ld.q    SP, FRAME_R(18), r18
 998        ld.q    SP, FRAME_R(19), r19
 999        ld.q    SP, FRAME_R(20), r20
1000        ld.q    SP, FRAME_R(21), r21
1001        ld.q    SP, FRAME_R(22), r22
1002        ld.q    SP, FRAME_R(23), r23
1003        ld.q    SP, FRAME_R(24), r24
1004        ld.q    SP, FRAME_R(25), r25
1005        ld.q    SP, FRAME_R(26), r26
1006        ld.q    SP, FRAME_R(27), r27
1007        ld.q    SP, FRAME_R(28), r28
1008        ld.q    SP, FRAME_R(29), r29
1009        ld.q    SP, FRAME_R(30), r30
1010        ld.q    SP, FRAME_R(31), r31
1011        ld.q    SP, FRAME_R(32), r32
1012        ld.q    SP, FRAME_R(33), r33
1013        ld.q    SP, FRAME_R(34), r34
1014        ld.q    SP, FRAME_R(35), r35
1015        ld.q    SP, FRAME_R(36), r36
1016        ld.q    SP, FRAME_R(37), r37
1017        ld.q    SP, FRAME_R(38), r38
1018        ld.q    SP, FRAME_R(39), r39
1019        ld.q    SP, FRAME_R(40), r40
1020        ld.q    SP, FRAME_R(41), r41
1021        ld.q    SP, FRAME_R(42), r42
1022        ld.q    SP, FRAME_R(43), r43
1023        ld.q    SP, FRAME_R(44), r44
1024        ld.q    SP, FRAME_R(45), r45
1025        ld.q    SP, FRAME_R(46), r46
1026        ld.q    SP, FRAME_R(47), r47
1027        ld.q    SP, FRAME_R(48), r48
1028        ld.q    SP, FRAME_R(49), r49
1029        ld.q    SP, FRAME_R(50), r50
1030        ld.q    SP, FRAME_R(51), r51
1031        ld.q    SP, FRAME_R(52), r52
1032        ld.q    SP, FRAME_R(53), r53
1033        ld.q    SP, FRAME_R(54), r54
1034        ld.q    SP, FRAME_R(55), r55
1035        ld.q    SP, FRAME_R(56), r56
1036        ld.q    SP, FRAME_R(57), r57
1037        ld.q    SP, FRAME_R(58), r58
1038
1039        getcon  SR, r59
1040        movi    SR_BLOCK_EXC, r60
1041        or      r59, r60, r59
1042        putcon  r59, SR                 /* SR.BL = 1, keep nesting out */
1043        ld.q    SP, FRAME_S(FSSR), r61
1044        ld.q    SP, FRAME_S(FSPC), r62
1045        movi    SR_ASID_MASK, r60
1046        and     r59, r60, r59
1047        andc    r61, r60, r61           /* Clear out older ASID */
1048        or      r59, r61, r61           /* Retain current ASID */
1049        putcon  r61, SSR
1050        putcon  r62, SPC
1051
1052        /* Ignore FSYSCALL_ID */
1053
1054        ld.q    SP, FRAME_R(59), r59
1055        ld.q    SP, FRAME_R(60), r60
1056        ld.q    SP, FRAME_R(61), r61
1057        ld.q    SP, FRAME_R(62), r62
1058
1059        /* Last touch */
1060        ld.q    SP, FRAME_R(15), SP
1061        rte
1062        nop
1063
1064/*
1065 * Third level handlers for VBR-based exceptions. Adapting args to
1066 * and/or deflecting to fourth level handlers.
1067 *
1068 * Fourth level handlers interface.
1069 * Most are C-coded handlers directly pointed by the trap_jtable.
1070 * (Third = Fourth level)
1071 * Inputs:
1072 * (r2)   fault/interrupt code, entry number (e.g. NMI = 14,
1073 *        IRL0-3 (0000) = 16, RTLBMISS = 2, SYSCALL = 11, etc ...)
1074 * (r3)   struct pt_regs *, original register's frame pointer
1075 * (r4)   Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault)
1076 * (r5)   TRA control register (for syscall/debug benefit only)
1077 * (LINK) return address
1078 * (SP)   = r3
1079 *
1080 * Kernel TLB fault handlers will get a slightly different interface.
1081 * (r2)   struct pt_regs *, original register's frame pointer
1082 * (r3)   page fault error code (see asm/thread_info.h)
1083 * (r4)   Effective Address of fault
1084 * (LINK) return address
1085 * (SP)   = r2
1086 *
1087 * fpu_error_or_IRQ? is a helper to deflect to the right cause.
1088 *
1089 */
1090#ifdef CONFIG_MMU
1091tlb_miss_load:
1092        or      SP, ZERO, r2
1093        or      ZERO, ZERO, r3          /* Read */
1094        getcon  TEA, r4
1095        pta     call_do_page_fault, tr0
1096        beq     ZERO, ZERO, tr0
1097
1098tlb_miss_store:
1099        or      SP, ZERO, r2
1100        movi    FAULT_CODE_WRITE, r3            /* Write */
1101        getcon  TEA, r4
1102        pta     call_do_page_fault, tr0
1103        beq     ZERO, ZERO, tr0
1104
1105itlb_miss_or_IRQ:
1106        pta     its_IRQ, tr0
1107        beqi/u  r4, EVENT_INTERRUPT, tr0
1108
1109        /* ITLB miss */
1110        or      SP, ZERO, r2
1111        movi    FAULT_CODE_ITLB, r3
1112        getcon  TEA, r4
1113        /* Fall through */
1114
1115call_do_page_fault:
1116        movi    do_page_fault, r6
1117        ptabs   r6, tr0
1118        blink   tr0, ZERO
1119#endif /* CONFIG_MMU */
1120
1121fpu_error_or_IRQA:
1122        pta     its_IRQ, tr0
1123        beqi/l  r4, EVENT_INTERRUPT, tr0
1124#ifdef CONFIG_SH_FPU
1125        movi    fpu_state_restore_trap_handler, r6
1126#else
1127        movi    do_exception_error, r6
1128#endif
1129        ptabs   r6, tr0
1130        blink   tr0, ZERO
1131
1132fpu_error_or_IRQB:
1133        pta     its_IRQ, tr0
1134        beqi/l  r4, EVENT_INTERRUPT, tr0
1135#ifdef CONFIG_SH_FPU
1136        movi    fpu_state_restore_trap_handler, r6
1137#else
1138        movi    do_exception_error, r6
1139#endif
1140        ptabs   r6, tr0
1141        blink   tr0, ZERO
1142
1143its_IRQ:
1144        movi    do_IRQ, r6
1145        ptabs   r6, tr0
1146        blink   tr0, ZERO
1147
1148/*
1149 * system_call/unknown_trap third level handler:
1150 *
1151 * Inputs:
1152 * (r2)   fault/interrupt code, entry number (TRAP = 11)
1153 * (r3)   struct pt_regs *, original register's frame pointer
1154 * (r4)   Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault)
1155 * (r5)   TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr)
1156 * (SP)   = r3
1157 * (LINK) return address: ret_from_exception
1158 * (*r3)  Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7)
1159 *
1160 * Outputs:
1161 * (*r3)  Syscall reply (Saved r2)
1162 * (LINK) In case of syscall only it can be scrapped.
1163 *        Common second level post handler will be ret_from_syscall.
1164 *        Common (non-trace) exit point to that is syscall_ret (saving
1165 *        result to r2). Common bad exit point is syscall_bad (returning
1166 *        ENOSYS then saved to r2).
1167 *
1168 */
1169
1170unknown_trap:
1171        /* Unknown Trap or User Trace */
1172        movi    do_unknown_trapa, r6
1173        ptabs   r6, tr0
1174        ld.q    r3, FRAME_R(9), r2      /* r2 = #arg << 16 | syscall # */
1175        andi    r2, 0x1ff, r2           /* r2 = syscall # */
1176        blink   tr0, LINK
1177
1178        pta     syscall_ret, tr0
1179        blink   tr0, ZERO
1180
1181        /* New syscall implementation*/
1182system_call:
1183        pta     unknown_trap, tr0
1184        or      r5, ZERO, r4            /* TRA (=r5) -> r4 */
1185        shlri   r4, 20, r4
1186        bnei    r4, 1, tr0              /* unknown_trap if not 0x1yzzzz */
1187
1188        /* It's a system call */
1189        st.q    r3, FRAME_S(FSYSCALL_ID), r5    /* ID (0x1yzzzz) -> stack */
1190        andi    r5, 0x1ff, r5                   /* syscall # -> r5        */
1191
1192        STI()
1193
1194        pta     syscall_allowed, tr0
1195        movi    NR_syscalls - 1, r4     /* Last valid */
1196        bgeu/l  r4, r5, tr0
1197
1198syscall_bad:
1199        /* Return ENOSYS ! */
1200        movi    -(ENOSYS), r2           /* Fall-through */
1201
1202        .global syscall_ret
1203syscall_ret:
1204        st.q    SP, FRAME_R(9), r2      /* Expecting SP back to BASIC frame */
1205        ld.q    SP, FRAME_S(FSPC), r2
1206        addi    r2, 4, r2               /* Move PC, being pre-execution event */
1207        st.q    SP, FRAME_S(FSPC), r2
1208        pta     ret_from_syscall, tr0
1209        blink   tr0, ZERO
1210
1211
1212/*  A different return path for ret_from_fork, because we now need
1213 *  to call schedule_tail with the later kernels. Because prev is
1214 *  loaded into r2 by switch_to() means we can just call it straight  away
1215 */
1216
1217.global ret_from_fork
1218ret_from_fork:
1219
1220        movi    schedule_tail,r5
1221        ori     r5, 1, r5
1222        ptabs   r5, tr0
1223        blink   tr0, LINK
1224
1225        ld.q    SP, FRAME_S(FSPC), r2
1226        addi    r2, 4, r2               /* Move PC, being pre-execution event */
1227        st.q    SP, FRAME_S(FSPC), r2
1228        pta     ret_from_syscall, tr0
1229        blink   tr0, ZERO
1230
1231.global ret_from_kernel_thread
1232ret_from_kernel_thread:
1233
1234        movi    schedule_tail,r5
1235        ori     r5, 1, r5
1236        ptabs   r5, tr0
1237        blink   tr0, LINK
1238
1239        ld.q    SP, FRAME_R(2), r2
1240        ld.q    SP, FRAME_R(3), r3
1241        ptabs   r3, tr0
1242        blink   tr0, LINK
1243
1244        ld.q    SP, FRAME_S(FSPC), r2
1245        addi    r2, 4, r2               /* Move PC, being pre-execution event */
1246        st.q    SP, FRAME_S(FSPC), r2
1247        pta     ret_from_syscall, tr0
1248        blink   tr0, ZERO
1249
1250syscall_allowed:
1251        /* Use LINK to deflect the exit point, default is syscall_ret */
1252        pta     syscall_ret, tr0
1253        gettr   tr0, LINK
1254        pta     syscall_notrace, tr0
1255
1256        getcon  KCR0, r2
1257        ld.l    r2, TI_FLAGS, r4
1258        movi    _TIF_WORK_SYSCALL_MASK, r6
1259        and     r6, r4, r6
1260        beq/l   r6, ZERO, tr0
1261
1262        /* Trace it by calling syscall_trace before and after */
1263        movi    do_syscall_trace_enter, r4
1264        or      SP, ZERO, r2
1265        ptabs   r4, tr0
1266        blink   tr0, LINK
1267
1268        /* Save the retval */
1269        st.q    SP, FRAME_R(2), r2
1270
1271        /* Reload syscall number as r5 is trashed by do_syscall_trace_enter */
1272        ld.q    SP, FRAME_S(FSYSCALL_ID), r5
1273        andi    r5, 0x1ff, r5
1274
1275        pta     syscall_ret_trace, tr0
1276        gettr   tr0, LINK
1277
1278syscall_notrace:
1279        /* Now point to the appropriate 4th level syscall handler */
1280        movi    sys_call_table, r4
1281        shlli   r5, 2, r5
1282        ldx.l   r4, r5, r5
1283        ptabs   r5, tr0
1284
1285        /* Prepare original args */
1286        ld.q    SP, FRAME_R(2), r2
1287        ld.q    SP, FRAME_R(3), r3
1288        ld.q    SP, FRAME_R(4), r4
1289        ld.q    SP, FRAME_R(5), r5
1290        ld.q    SP, FRAME_R(6), r6
1291        ld.q    SP, FRAME_R(7), r7
1292
1293        /* And now the trick for those syscalls requiring regs * ! */
1294        or      SP, ZERO, r8
1295
1296        /* Call it */
1297        blink   tr0, ZERO       /* LINK is already properly set */
1298
1299syscall_ret_trace:
1300        /* We get back here only if under trace */
1301        st.q    SP, FRAME_R(9), r2      /* Save return value */
1302
1303        movi    do_syscall_trace_leave, LINK
1304        or      SP, ZERO, r2
1305        ptabs   LINK, tr0
1306        blink   tr0, LINK
1307
1308        /* This needs to be done after any syscall tracing */
1309        ld.q    SP, FRAME_S(FSPC), r2
1310        addi    r2, 4, r2       /* Move PC, being pre-execution event */
1311        st.q    SP, FRAME_S(FSPC), r2
1312
1313        pta     ret_from_syscall, tr0
1314        blink   tr0, ZERO               /* Resume normal return sequence */
1315
1316/*
1317 * --- Switch to running under a particular ASID and return the previous ASID value
1318 * --- The caller is assumed to have done a cli before calling this.
1319 *
1320 * Input r2 : new ASID
1321 * Output r2 : old ASID
1322 */
1323
1324        .global switch_and_save_asid
1325switch_and_save_asid:
1326        getcon  sr, r0
1327        movi    255, r4
1328        shlli   r4, 16, r4      /* r4 = mask to select ASID */
1329        and     r0, r4, r3      /* r3 = shifted old ASID */
1330        andi    r2, 255, r2     /* mask down new ASID */
1331        shlli   r2, 16, r2      /* align new ASID against SR.ASID */
1332        andc    r0, r4, r0      /* efface old ASID from SR */
1333        or      r0, r2, r0      /* insert the new ASID */
1334        putcon  r0, ssr
1335        movi    1f, r0
1336        putcon  r0, spc
1337        rte
1338        nop
13391:
1340        ptabs   LINK, tr0
1341        shlri   r3, 16, r2      /* r2 = old ASID */
1342        blink tr0, r63
1343
1344        .global route_to_panic_handler
1345route_to_panic_handler:
1346        /* Switch to real mode, goto panic_handler, don't return.  Useful for
1347           last-chance debugging, e.g. if no output wants to go to the console.
1348           */
1349
1350        movi    panic_handler - CONFIG_PAGE_OFFSET, r1
1351        ptabs   r1, tr0
1352        pta     1f, tr1
1353        gettr   tr1, r0
1354        putcon  r0, spc
1355        getcon  sr, r0
1356        movi    1, r1
1357        shlli   r1, 31, r1
1358        andc    r0, r1, r0
1359        putcon  r0, ssr
1360        rte
1361        nop
13621:      /* Now in real mode */
1363        blink tr0, r63
1364        nop
1365
1366        .global peek_real_address_q
1367peek_real_address_q:
1368        /* Two args:
1369           r2 : real mode address to peek
1370           r2(out) : result quadword
1371
1372           This is provided as a cheapskate way of manipulating device
1373           registers for debugging (to avoid the need to ioremap the debug
1374           module, and to avoid the need to ioremap the watchpoint
1375           controller in a way that identity maps sufficient bits to avoid the
1376           SH5-101 cut2 silicon defect).
1377
1378           This code is not performance critical
1379        */
1380
1381        add.l   r2, r63, r2     /* sign extend address */
1382        getcon  sr, r0          /* r0 = saved original SR */
1383        movi    1, r1
1384        shlli   r1, 28, r1
1385        or      r0, r1, r1      /* r0 with block bit set */
1386        putcon  r1, sr          /* now in critical section */
1387        movi    1, r36
1388        shlli   r36, 31, r36
1389        andc    r1, r36, r1     /* turn sr.mmu off in real mode section */
1390
1391        putcon  r1, ssr
1392        movi    .peek0 - CONFIG_PAGE_OFFSET, r36 /* real mode target address */
1393        movi    1f, r37         /* virtual mode return addr */
1394        putcon  r36, spc
1395
1396        synco
1397        rte
1398        nop
1399
1400.peek0: /* come here in real mode, don't touch caches!!
1401           still in critical section (sr.bl==1) */
1402        putcon  r0, ssr
1403        putcon  r37, spc
1404        /* Here's the actual peek.  If the address is bad, all bets are now off
1405         * what will happen (handlers invoked in real-mode = bad news) */
1406        ld.q    r2, 0, r2
1407        synco
1408        rte     /* Back to virtual mode */
1409        nop
1410
14111:
1412        ptabs   LINK, tr0
1413        blink   tr0, r63
1414
1415        .global poke_real_address_q
1416poke_real_address_q:
1417        /* Two args:
1418           r2 : real mode address to poke
1419           r3 : quadword value to write.
1420
1421           This is provided as a cheapskate way of manipulating device
1422           registers for debugging (to avoid the need to ioremap the debug
1423           module, and to avoid the need to ioremap the watchpoint
1424           controller in a way that identity maps sufficient bits to avoid the
1425           SH5-101 cut2 silicon defect).
1426
1427           This code is not performance critical
1428        */
1429
1430        add.l   r2, r63, r2     /* sign extend address */
1431        getcon  sr, r0          /* r0 = saved original SR */
1432        movi    1, r1
1433        shlli   r1, 28, r1
1434        or      r0, r1, r1      /* r0 with block bit set */
1435        putcon  r1, sr          /* now in critical section */
1436        movi    1, r36
1437        shlli   r36, 31, r36
1438        andc    r1, r36, r1     /* turn sr.mmu off in real mode section */
1439
1440        putcon  r1, ssr
1441        movi    .poke0-CONFIG_PAGE_OFFSET, r36 /* real mode target address */
1442        movi    1f, r37         /* virtual mode return addr */
1443        putcon  r36, spc
1444
1445        synco
1446        rte
1447        nop
1448
1449.poke0: /* come here in real mode, don't touch caches!!
1450           still in critical section (sr.bl==1) */
1451        putcon  r0, ssr
1452        putcon  r37, spc
1453        /* Here's the actual poke.  If the address is bad, all bets are now off
1454         * what will happen (handlers invoked in real-mode = bad news) */
1455        st.q    r2, 0, r3
1456        synco
1457        rte     /* Back to virtual mode */
1458        nop
1459
14601:
1461        ptabs   LINK, tr0
1462        blink   tr0, r63
1463
1464#ifdef CONFIG_MMU
1465/*
1466 * --- User Access Handling Section
1467 */
1468
1469/*
1470 * User Access support. It all moved to non inlined Assembler
1471 * functions in here.
1472 *
1473 * __kernel_size_t __copy_user(void *__to, const void *__from,
1474 *                             __kernel_size_t __n)
1475 *
1476 * Inputs:
1477 * (r2)  target address
1478 * (r3)  source address
1479 * (r4)  size in bytes
1480 *
1481 * Ouputs:
1482 * (*r2) target data
1483 * (r2)  non-copied bytes
1484 *
1485 * If a fault occurs on the user pointer, bail out early and return the
1486 * number of bytes not copied in r2.
1487 * Strategy : for large blocks, call a real memcpy function which can
1488 * move >1 byte at a time using unaligned ld/st instructions, and can
1489 * manipulate the cache using prefetch + alloco to improve the speed
1490 * further.  If a fault occurs in that function, just revert to the
1491 * byte-by-byte approach used for small blocks; this is rare so the
1492 * performance hit for that case does not matter.
1493 *
1494 * For small blocks it's not worth the overhead of setting up and calling
1495 * the memcpy routine; do the copy a byte at a time.
1496 *
1497 */
1498        .global __copy_user
1499__copy_user:
1500        pta     __copy_user_byte_by_byte, tr1
1501        movi    16, r0 ! this value is a best guess, should tune it by benchmarking
1502        bge/u   r0, r4, tr1
1503        pta copy_user_memcpy, tr0
1504        addi    SP, -32, SP
1505        /* Save arguments in case we have to fix-up unhandled page fault */
1506        st.q    SP, 0, r2
1507        st.q    SP, 8, r3
1508        st.q    SP, 16, r4
1509        st.q    SP, 24, r35 ! r35 is callee-save
1510        /* Save LINK in a register to reduce RTS time later (otherwise
1511           ld SP,*,LINK;ptabs LINK;trn;blink trn,r63 becomes a critical path) */
1512        ori     LINK, 0, r35
1513        blink   tr0, LINK
1514
1515        /* Copy completed normally if we get back here */
1516        ptabs   r35, tr0
1517        ld.q    SP, 24, r35
1518        /* don't restore r2-r4, pointless */
1519        /* set result=r2 to zero as the copy must have succeeded. */
1520        or      r63, r63, r2
1521        addi    SP, 32, SP
1522        blink   tr0, r63 ! RTS
1523
1524        .global __copy_user_fixup
1525__copy_user_fixup:
1526        /* Restore stack frame */
1527        ori     r35, 0, LINK
1528        ld.q    SP, 24, r35
1529        ld.q    SP, 16, r4
1530        ld.q    SP,  8, r3
1531        ld.q    SP,  0, r2
1532        addi    SP, 32, SP
1533        /* Fall through to original code, in the 'same' state we entered with */
1534
1535/* The slow byte-by-byte method is used if the fast copy traps due to a bad
1536   user address.  In that rare case, the speed drop can be tolerated. */
1537__copy_user_byte_by_byte:
1538        pta     ___copy_user_exit, tr1
1539        pta     ___copy_user1, tr0
1540        beq/u   r4, r63, tr1    /* early exit for zero length copy */
1541        sub     r2, r3, r0
1542        addi    r0, -1, r0
1543
1544___copy_user1:
1545        ld.b    r3, 0, r5               /* Fault address 1 */
1546
1547        /* Could rewrite this to use just 1 add, but the second comes 'free'
1548           due to load latency */
1549        addi    r3, 1, r3
1550        addi    r4, -1, r4              /* No real fixup required */
1551___copy_user2:
1552        stx.b   r3, r0, r5              /* Fault address 2 */
1553        bne     r4, ZERO, tr0
1554
1555___copy_user_exit:
1556        or      r4, ZERO, r2
1557        ptabs   LINK, tr0
1558        blink   tr0, ZERO
1559
1560/*
1561 * __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
1562 *
1563 * Inputs:
1564 * (r2)  target address
1565 * (r3)  size in bytes
1566 *
1567 * Ouputs:
1568 * (*r2) zero-ed target data
1569 * (r2)  non-zero-ed bytes
1570 */
1571        .global __clear_user
1572__clear_user:
1573        pta     ___clear_user_exit, tr1
1574        pta     ___clear_user1, tr0
1575        beq/u   r3, r63, tr1
1576
1577___clear_user1:
1578        st.b    r2, 0, ZERO             /* Fault address */
1579        addi    r2, 1, r2
1580        addi    r3, -1, r3              /* No real fixup required */
1581        bne     r3, ZERO, tr0
1582
1583___clear_user_exit:
1584        or      r3, ZERO, r2
1585        ptabs   LINK, tr0
1586        blink   tr0, ZERO
1587
1588#endif /* CONFIG_MMU */
1589
1590/*
1591 * extern long __get_user_asm_?(void *val, long addr)
1592 *
1593 * Inputs:
1594 * (r2)  dest address
1595 * (r3)  source address (in User Space)
1596 *
1597 * Ouputs:
1598 * (r2)  -EFAULT (faulting)
1599 *       0       (not faulting)
1600 */
1601        .global __get_user_asm_b
1602__get_user_asm_b:
1603        or      r2, ZERO, r4
1604        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1605
1606___get_user_asm_b1:
1607        ld.b    r3, 0, r5               /* r5 = data */
1608        st.b    r4, 0, r5
1609        or      ZERO, ZERO, r2
1610
1611___get_user_asm_b_exit:
1612        ptabs   LINK, tr0
1613        blink   tr0, ZERO
1614
1615
1616        .global __get_user_asm_w
1617__get_user_asm_w:
1618        or      r2, ZERO, r4
1619        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1620
1621___get_user_asm_w1:
1622        ld.w    r3, 0, r5               /* r5 = data */
1623        st.w    r4, 0, r5
1624        or      ZERO, ZERO, r2
1625
1626___get_user_asm_w_exit:
1627        ptabs   LINK, tr0
1628        blink   tr0, ZERO
1629
1630
1631        .global __get_user_asm_l
1632__get_user_asm_l:
1633        or      r2, ZERO, r4
1634        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1635
1636___get_user_asm_l1:
1637        ld.l    r3, 0, r5               /* r5 = data */
1638        st.l    r4, 0, r5
1639        or      ZERO, ZERO, r2
1640
1641___get_user_asm_l_exit:
1642        ptabs   LINK, tr0
1643        blink   tr0, ZERO
1644
1645
1646        .global __get_user_asm_q
1647__get_user_asm_q:
1648        or      r2, ZERO, r4
1649        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1650
1651___get_user_asm_q1:
1652        ld.q    r3, 0, r5               /* r5 = data */
1653        st.q    r4, 0, r5
1654        or      ZERO, ZERO, r2
1655
1656___get_user_asm_q_exit:
1657        ptabs   LINK, tr0
1658        blink   tr0, ZERO
1659
1660/*
1661 * extern long __put_user_asm_?(void *pval, long addr)
1662 *
1663 * Inputs:
1664 * (r2)  kernel pointer to value
1665 * (r3)  dest address (in User Space)
1666 *
1667 * Ouputs:
1668 * (r2)  -EFAULT (faulting)
1669 *       0       (not faulting)
1670 */
1671        .global __put_user_asm_b
1672__put_user_asm_b:
1673        ld.b    r2, 0, r4               /* r4 = data */
1674        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1675
1676___put_user_asm_b1:
1677        st.b    r3, 0, r4
1678        or      ZERO, ZERO, r2
1679
1680___put_user_asm_b_exit:
1681        ptabs   LINK, tr0
1682        blink   tr0, ZERO
1683
1684
1685        .global __put_user_asm_w
1686__put_user_asm_w:
1687        ld.w    r2, 0, r4               /* r4 = data */
1688        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1689
1690___put_user_asm_w1:
1691        st.w    r3, 0, r4
1692        or      ZERO, ZERO, r2
1693
1694___put_user_asm_w_exit:
1695        ptabs   LINK, tr0
1696        blink   tr0, ZERO
1697
1698
1699        .global __put_user_asm_l
1700__put_user_asm_l:
1701        ld.l    r2, 0, r4               /* r4 = data */
1702        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1703
1704___put_user_asm_l1:
1705        st.l    r3, 0, r4
1706        or      ZERO, ZERO, r2
1707
1708___put_user_asm_l_exit:
1709        ptabs   LINK, tr0
1710        blink   tr0, ZERO
1711
1712
1713        .global __put_user_asm_q
1714__put_user_asm_q:
1715        ld.q    r2, 0, r4               /* r4 = data */
1716        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1717
1718___put_user_asm_q1:
1719        st.q    r3, 0, r4
1720        or      ZERO, ZERO, r2
1721
1722___put_user_asm_q_exit:
1723        ptabs   LINK, tr0
1724        blink   tr0, ZERO
1725
1726panic_stash_regs:
1727        /* The idea is : when we get an unhandled panic, we dump the registers
1728           to a known memory location, the just sit in a tight loop.
1729           This allows the human to look at the memory region through the GDB
1730           session (assuming the debug module's SHwy initiator isn't locked up
1731           or anything), to hopefully analyze the cause of the panic. */
1732
1733        /* On entry, former r15 (SP) is in DCR
1734           former r0  is at resvec_saved_area + 0
1735           former r1  is at resvec_saved_area + 8
1736           former tr0 is at resvec_saved_area + 32
1737           DCR is the only register whose value is lost altogether.
1738        */
1739
1740        movi    0xffffffff80000000, r0 ! phy of dump area
1741        ld.q    SP, 0x000, r1   ! former r0
1742        st.q    r0,  0x000, r1
1743        ld.q    SP, 0x008, r1   ! former r1
1744        st.q    r0,  0x008, r1
1745        st.q    r0,  0x010, r2
1746        st.q    r0,  0x018, r3
1747        st.q    r0,  0x020, r4
1748        st.q    r0,  0x028, r5
1749        st.q    r0,  0x030, r6
1750        st.q    r0,  0x038, r7
1751        st.q    r0,  0x040, r8
1752        st.q    r0,  0x048, r9
1753        st.q    r0,  0x050, r10
1754        st.q    r0,  0x058, r11
1755        st.q    r0,  0x060, r12
1756        st.q    r0,  0x068, r13
1757        st.q    r0,  0x070, r14
1758        getcon  dcr, r14
1759        st.q    r0,  0x078, r14
1760        st.q    r0,  0x080, r16
1761        st.q    r0,  0x088, r17
1762        st.q    r0,  0x090, r18
1763        st.q    r0,  0x098, r19
1764        st.q    r0,  0x0a0, r20
1765        st.q    r0,  0x0a8, r21
1766        st.q    r0,  0x0b0, r22
1767        st.q    r0,  0x0b8, r23
1768        st.q    r0,  0x0c0, r24
1769        st.q    r0,  0x0c8, r25
1770        st.q    r0,  0x0d0, r26
1771        st.q    r0,  0x0d8, r27
1772        st.q    r0,  0x0e0, r28
1773        st.q    r0,  0x0e8, r29
1774        st.q    r0,  0x0f0, r30
1775        st.q    r0,  0x0f8, r31
1776        st.q    r0,  0x100, r32
1777        st.q    r0,  0x108, r33
1778        st.q    r0,  0x110, r34
1779        st.q    r0,  0x118, r35
1780        st.q    r0,  0x120, r36
1781        st.q    r0,  0x128, r37
1782        st.q    r0,  0x130, r38
1783        st.q    r0,  0x138, r39
1784        st.q    r0,  0x140, r40
1785        st.q    r0,  0x148, r41
1786        st.q    r0,  0x150, r42
1787        st.q    r0,  0x158, r43
1788        st.q    r0,  0x160, r44
1789        st.q    r0,  0x168, r45
1790        st.q    r0,  0x170, r46
1791        st.q    r0,  0x178, r47
1792        st.q    r0,  0x180, r48
1793        st.q    r0,  0x188, r49
1794        st.q    r0,  0x190, r50
1795        st.q    r0,  0x198, r51
1796        st.q    r0,  0x1a0, r52
1797        st.q    r0,  0x1a8, r53
1798        st.q    r0,  0x1b0, r54
1799        st.q    r0,  0x1b8, r55
1800        st.q    r0,  0x1c0, r56
1801        st.q    r0,  0x1c8, r57
1802        st.q    r0,  0x1d0, r58
1803        st.q    r0,  0x1d8, r59
1804        st.q    r0,  0x1e0, r60
1805        st.q    r0,  0x1e8, r61
1806        st.q    r0,  0x1f0, r62
1807        st.q    r0,  0x1f8, r63 ! bogus, but for consistency's sake...
1808
1809        ld.q    SP, 0x020, r1  ! former tr0
1810        st.q    r0,  0x200, r1
1811        gettr   tr1, r1
1812        st.q    r0,  0x208, r1
1813        gettr   tr2, r1
1814        st.q    r0,  0x210, r1
1815        gettr   tr3, r1
1816        st.q    r0,  0x218, r1
1817        gettr   tr4, r1
1818        st.q    r0,  0x220, r1
1819        gettr   tr5, r1
1820        st.q    r0,  0x228, r1
1821        gettr   tr6, r1
1822        st.q    r0,  0x230, r1
1823        gettr   tr7, r1
1824        st.q    r0,  0x238, r1
1825
1826        getcon  sr,  r1
1827        getcon  ssr,  r2
1828        getcon  pssr,  r3
1829        getcon  spc,  r4
1830        getcon  pspc,  r5
1831        getcon  intevt,  r6
1832        getcon  expevt,  r7
1833        getcon  pexpevt,  r8
1834        getcon  tra,  r9
1835        getcon  tea,  r10
1836        getcon  kcr0, r11
1837        getcon  kcr1, r12
1838        getcon  vbr,  r13
1839        getcon  resvec,  r14
1840
1841        st.q    r0,  0x240, r1
1842        st.q    r0,  0x248, r2
1843        st.q    r0,  0x250, r3
1844        st.q    r0,  0x258, r4
1845        st.q    r0,  0x260, r5
1846        st.q    r0,  0x268, r6
1847        st.q    r0,  0x270, r7
1848        st.q    r0,  0x278, r8
1849        st.q    r0,  0x280, r9
1850        st.q    r0,  0x288, r10
1851        st.q    r0,  0x290, r11
1852        st.q    r0,  0x298, r12
1853        st.q    r0,  0x2a0, r13
1854        st.q    r0,  0x2a8, r14
1855
1856        getcon  SPC,r2
1857        getcon  SSR,r3
1858        getcon  EXPEVT,r4
1859        /* Prepare to jump to C - physical address */
1860        movi    panic_handler-CONFIG_PAGE_OFFSET, r1
1861        ori     r1, 1, r1
1862        ptabs   r1, tr0
1863        getcon  DCR, SP
1864        blink   tr0, ZERO
1865        nop
1866        nop
1867        nop
1868        nop
1869
1870
1871
1872
1873/*
1874 * --- Signal Handling Section
1875 */
1876
1877/*
1878 * extern long long _sa_default_rt_restorer
1879 * extern long long _sa_default_restorer
1880 *
1881 *               or, better,
1882 *
1883 * extern void _sa_default_rt_restorer(void)
1884 * extern void _sa_default_restorer(void)
1885 *
1886 * Code prototypes to do a sys_rt_sigreturn() or sys_sysreturn()
1887 * from user space. Copied into user space by signal management.
1888 * Both must be quad aligned and 2 quad long (4 instructions).
1889 *
1890 */
1891        .balign 8
1892        .global sa_default_rt_restorer
1893sa_default_rt_restorer:
1894        movi    0x10, r9
1895        shori   __NR_rt_sigreturn, r9
1896        trapa   r9
1897        nop
1898
1899        .balign 8
1900        .global sa_default_restorer
1901sa_default_restorer:
1902        movi    0x10, r9
1903        shori   __NR_sigreturn, r9
1904        trapa   r9
1905        nop
1906
1907/*
1908 * --- __ex_table Section
1909 */
1910
1911/*
1912 * User Access Exception Table.
1913 */
1914        .section        __ex_table,  "a"
1915
1916        .global asm_uaccess_start       /* Just a marker */
1917asm_uaccess_start:
1918
1919#ifdef CONFIG_MMU
1920        .long   ___copy_user1, ___copy_user_exit
1921        .long   ___copy_user2, ___copy_user_exit
1922        .long   ___clear_user1, ___clear_user_exit
1923#endif
1924        .long   ___get_user_asm_b1, ___get_user_asm_b_exit
1925        .long   ___get_user_asm_w1, ___get_user_asm_w_exit
1926        .long   ___get_user_asm_l1, ___get_user_asm_l_exit
1927        .long   ___get_user_asm_q1, ___get_user_asm_q_exit
1928        .long   ___put_user_asm_b1, ___put_user_asm_b_exit
1929        .long   ___put_user_asm_w1, ___put_user_asm_w_exit
1930        .long   ___put_user_asm_l1, ___put_user_asm_l_exit
1931        .long   ___put_user_asm_q1, ___put_user_asm_q_exit
1932
1933        .global asm_uaccess_end         /* Just a marker */
1934asm_uaccess_end:
1935
1936
1937
1938
1939/*
1940 * --- .init.text Section
1941 */
1942
1943        __INIT
1944
1945/*
1946 * void trap_init (void)
1947 *
1948 */
1949        .global trap_init
1950trap_init:
1951        addi    SP, -24, SP                     /* Room to save r28/r29/r30 */
1952        st.q    SP, 0, r28
1953        st.q    SP, 8, r29
1954        st.q    SP, 16, r30
1955
1956        /* Set VBR and RESVEC */
1957        movi    LVBR_block, r19
1958        andi    r19, -4, r19                    /* reset MMUOFF + reserved */
1959        /* For RESVEC exceptions we force the MMU off, which means we need the
1960           physical address. */
1961        movi    LRESVEC_block-CONFIG_PAGE_OFFSET, r20
1962        andi    r20, -4, r20                    /* reset reserved */
1963        ori     r20, 1, r20                     /* set MMUOFF */
1964        putcon  r19, VBR
1965        putcon  r20, RESVEC
1966
1967        /* Sanity check */
1968        movi    LVBR_block_end, r21
1969        andi    r21, -4, r21
1970        movi    BLOCK_SIZE, r29                 /* r29 = expected size */
1971        or      r19, ZERO, r30
1972        add     r19, r29, r19
1973
1974        /*
1975         * Ugly, but better loop forever now than crash afterwards.
1976         * We should print a message, but if we touch LVBR or
1977         * LRESVEC blocks we should not be surprised if we get stuck
1978         * in trap_init().
1979         */
1980        pta     trap_init_loop, tr1
1981        gettr   tr1, r28                        /* r28 = trap_init_loop */
1982        sub     r21, r30, r30                   /* r30 = actual size */
1983
1984        /*
1985         * VBR/RESVEC handlers overlap by being bigger than
1986         * allowed. Very bad. Just loop forever.
1987         * (r28) panic/loop address
1988         * (r29) expected size
1989         * (r30) actual size
1990         */
1991trap_init_loop:
1992        bne     r19, r21, tr1
1993
1994        /* Now that exception vectors are set up reset SR.BL */
1995        getcon  SR, r22
1996        movi    SR_UNBLOCK_EXC, r23
1997        and     r22, r23, r22
1998        putcon  r22, SR
1999
2000        addi    SP, 24, SP
2001        ptabs   LINK, tr0
2002        blink   tr0, ZERO
2003
2004