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