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   do_software_break_point /* 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        beqi/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_RESTORE_SIGMASK), 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)   writeaccess, whether it's a store fault as opposed to load fault
1083 * (r4)   execaccess, whether it's a ITLB fault as opposed to DTLB fault
1084 * (r5)   Effective Address of fault
1085 * (LINK) return address
1086 * (SP)   = r2
1087 *
1088 * fpu_error_or_IRQ? is a helper to deflect to the right cause.
1089 *
1090 */
1091#ifdef CONFIG_MMU
1092tlb_miss_load:
1093        or      SP, ZERO, r2
1094        or      ZERO, ZERO, r3          /* Read */
1095        or      ZERO, ZERO, r4          /* Data */
1096        getcon  TEA, r5
1097        pta     call_do_page_fault, tr0
1098        beq     ZERO, ZERO, tr0
1099
1100tlb_miss_store:
1101        or      SP, ZERO, r2
1102        movi    1, r3                   /* Write */
1103        or      ZERO, ZERO, r4          /* Data */
1104        getcon  TEA, r5
1105        pta     call_do_page_fault, tr0
1106        beq     ZERO, ZERO, tr0
1107
1108itlb_miss_or_IRQ:
1109        pta     its_IRQ, tr0
1110        beqi/u  r4, EVENT_INTERRUPT, tr0
1111        or      SP, ZERO, r2
1112        or      ZERO, ZERO, r3          /* Read */
1113        movi    1, r4                   /* Text */
1114        getcon  TEA, r5
1115        /* Fall through */
1116
1117call_do_page_fault:
1118        movi    do_page_fault, r6
1119        ptabs   r6, tr0
1120        blink   tr0, ZERO
1121#endif /* CONFIG_MMU */
1122
1123fpu_error_or_IRQA:
1124        pta     its_IRQ, tr0
1125        beqi/l  r4, EVENT_INTERRUPT, tr0
1126#ifdef CONFIG_SH_FPU
1127        movi    do_fpu_state_restore, r6
1128#else
1129        movi    do_exception_error, r6
1130#endif
1131        ptabs   r6, tr0
1132        blink   tr0, ZERO
1133
1134fpu_error_or_IRQB:
1135        pta     its_IRQ, tr0
1136        beqi/l  r4, EVENT_INTERRUPT, tr0
1137#ifdef CONFIG_SH_FPU
1138        movi    do_fpu_state_restore, r6
1139#else
1140        movi    do_exception_error, r6
1141#endif
1142        ptabs   r6, tr0
1143        blink   tr0, ZERO
1144
1145its_IRQ:
1146        movi    do_IRQ, r6
1147        ptabs   r6, tr0
1148        blink   tr0, ZERO
1149
1150/*
1151 * system_call/unknown_trap third level handler:
1152 *
1153 * Inputs:
1154 * (r2)   fault/interrupt code, entry number (TRAP = 11)
1155 * (r3)   struct pt_regs *, original register's frame pointer
1156 * (r4)   Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault)
1157 * (r5)   TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr)
1158 * (SP)   = r3
1159 * (LINK) return address: ret_from_exception
1160 * (*r3)  Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7)
1161 *
1162 * Outputs:
1163 * (*r3)  Syscall reply (Saved r2)
1164 * (LINK) In case of syscall only it can be scrapped.
1165 *        Common second level post handler will be ret_from_syscall.
1166 *        Common (non-trace) exit point to that is syscall_ret (saving
1167 *        result to r2). Common bad exit point is syscall_bad (returning
1168 *        ENOSYS then saved to r2).
1169 *
1170 */
1171
1172unknown_trap:
1173        /* Unknown Trap or User Trace */
1174        movi    do_unknown_trapa, r6
1175        ptabs   r6, tr0
1176        ld.q    r3, FRAME_R(9), r2      /* r2 = #arg << 16 | syscall # */
1177        andi    r2, 0x1ff, r2           /* r2 = syscall # */
1178        blink   tr0, LINK
1179
1180        pta     syscall_ret, tr0
1181        blink   tr0, ZERO
1182
1183        /* New syscall implementation*/
1184system_call:
1185        pta     unknown_trap, tr0
1186        or      r5, ZERO, r4            /* TRA (=r5) -> r4 */
1187        shlri   r4, 20, r4
1188        bnei    r4, 1, tr0              /* unknown_trap if not 0x1yzzzz */
1189
1190        /* It's a system call */
1191        st.q    r3, FRAME_S(FSYSCALL_ID), r5    /* ID (0x1yzzzz) -> stack */
1192        andi    r5, 0x1ff, r5                   /* syscall # -> r5        */
1193
1194        STI()
1195
1196        pta     syscall_allowed, tr0
1197        movi    NR_syscalls - 1, r4     /* Last valid */
1198        bgeu/l  r4, r5, tr0
1199
1200syscall_bad:
1201        /* Return ENOSYS ! */
1202        movi    -(ENOSYS), r2           /* Fall-through */
1203
1204        .global syscall_ret
1205syscall_ret:
1206        st.q    SP, FRAME_R(9), r2      /* Expecting SP back to BASIC frame */
1207        ld.q    SP, FRAME_S(FSPC), r2
1208        addi    r2, 4, r2               /* Move PC, being pre-execution event */
1209        st.q    SP, FRAME_S(FSPC), r2
1210        pta     ret_from_syscall, tr0
1211        blink   tr0, ZERO
1212
1213
1214/*  A different return path for ret_from_fork, because we now need
1215 *  to call schedule_tail with the later kernels. Because prev is
1216 *  loaded into r2 by switch_to() means we can just call it straight  away
1217 */
1218
1219.global ret_from_fork
1220ret_from_fork:
1221
1222        movi    schedule_tail,r5
1223        ori     r5, 1, r5
1224        ptabs   r5, tr0
1225        blink   tr0, LINK
1226
1227        ld.q    SP, FRAME_S(FSPC), r2
1228        addi    r2, 4, r2               /* Move PC, being pre-execution event */
1229        st.q    SP, FRAME_S(FSPC), r2
1230        pta     ret_from_syscall, tr0
1231        blink   tr0, ZERO
1232
1233syscall_allowed:
1234        /* Use LINK to deflect the exit point, default is syscall_ret */
1235        pta     syscall_ret, tr0
1236        gettr   tr0, LINK
1237        pta     syscall_notrace, tr0
1238
1239        getcon  KCR0, r2
1240        ld.l    r2, TI_FLAGS, r4
1241        movi    _TIF_WORK_SYSCALL_MASK, r6
1242        and     r6, r4, r6
1243        beq/l   r6, ZERO, tr0
1244
1245        /* Trace it by calling syscall_trace before and after */
1246        movi    do_syscall_trace_enter, r4
1247        or      SP, ZERO, r2
1248        ptabs   r4, tr0
1249        blink   tr0, LINK
1250
1251        /* Save the retval */
1252        st.q    SP, FRAME_R(2), r2
1253
1254        /* Reload syscall number as r5 is trashed by do_syscall_trace_enter */
1255        ld.q    SP, FRAME_S(FSYSCALL_ID), r5
1256        andi    r5, 0x1ff, r5
1257
1258        pta     syscall_ret_trace, tr0
1259        gettr   tr0, LINK
1260
1261syscall_notrace:
1262        /* Now point to the appropriate 4th level syscall handler */
1263        movi    sys_call_table, r4
1264        shlli   r5, 2, r5
1265        ldx.l   r4, r5, r5
1266        ptabs   r5, tr0
1267
1268        /* Prepare original args */
1269        ld.q    SP, FRAME_R(2), r2
1270        ld.q    SP, FRAME_R(3), r3
1271        ld.q    SP, FRAME_R(4), r4
1272        ld.q    SP, FRAME_R(5), r5
1273        ld.q    SP, FRAME_R(6), r6
1274        ld.q    SP, FRAME_R(7), r7
1275
1276        /* And now the trick for those syscalls requiring regs * ! */
1277        or      SP, ZERO, r8
1278
1279        /* Call it */
1280        blink   tr0, ZERO       /* LINK is already properly set */
1281
1282syscall_ret_trace:
1283        /* We get back here only if under trace */
1284        st.q    SP, FRAME_R(9), r2      /* Save return value */
1285
1286        movi    do_syscall_trace_leave, LINK
1287        or      SP, ZERO, r2
1288        ptabs   LINK, tr0
1289        blink   tr0, LINK
1290
1291        /* This needs to be done after any syscall tracing */
1292        ld.q    SP, FRAME_S(FSPC), r2
1293        addi    r2, 4, r2       /* Move PC, being pre-execution event */
1294        st.q    SP, FRAME_S(FSPC), r2
1295
1296        pta     ret_from_syscall, tr0
1297        blink   tr0, ZERO               /* Resume normal return sequence */
1298
1299/*
1300 * --- Switch to running under a particular ASID and return the previous ASID value
1301 * --- The caller is assumed to have done a cli before calling this.
1302 *
1303 * Input r2 : new ASID
1304 * Output r2 : old ASID
1305 */
1306
1307        .global switch_and_save_asid
1308switch_and_save_asid:
1309        getcon  sr, r0
1310        movi    255, r4
1311        shlli   r4, 16, r4      /* r4 = mask to select ASID */
1312        and     r0, r4, r3      /* r3 = shifted old ASID */
1313        andi    r2, 255, r2     /* mask down new ASID */
1314        shlli   r2, 16, r2      /* align new ASID against SR.ASID */
1315        andc    r0, r4, r0      /* efface old ASID from SR */
1316        or      r0, r2, r0      /* insert the new ASID */
1317        putcon  r0, ssr
1318        movi    1f, r0
1319        putcon  r0, spc
1320        rte
1321        nop
13221:
1323        ptabs   LINK, tr0
1324        shlri   r3, 16, r2      /* r2 = old ASID */
1325        blink tr0, r63
1326
1327        .global route_to_panic_handler
1328route_to_panic_handler:
1329        /* Switch to real mode, goto panic_handler, don't return.  Useful for
1330           last-chance debugging, e.g. if no output wants to go to the console.
1331           */
1332
1333        movi    panic_handler - CONFIG_PAGE_OFFSET, r1
1334        ptabs   r1, tr0
1335        pta     1f, tr1
1336        gettr   tr1, r0
1337        putcon  r0, spc
1338        getcon  sr, r0
1339        movi    1, r1
1340        shlli   r1, 31, r1
1341        andc    r0, r1, r0
1342        putcon  r0, ssr
1343        rte
1344        nop
13451:      /* Now in real mode */
1346        blink tr0, r63
1347        nop
1348
1349        .global peek_real_address_q
1350peek_real_address_q:
1351        /* Two args:
1352           r2 : real mode address to peek
1353           r2(out) : result quadword
1354
1355           This is provided as a cheapskate way of manipulating device
1356           registers for debugging (to avoid the need to ioremap the debug
1357           module, and to avoid the need to ioremap the watchpoint
1358           controller in a way that identity maps sufficient bits to avoid the
1359           SH5-101 cut2 silicon defect).
1360
1361           This code is not performance critical
1362        */
1363
1364        add.l   r2, r63, r2     /* sign extend address */
1365        getcon  sr, r0          /* r0 = saved original SR */
1366        movi    1, r1
1367        shlli   r1, 28, r1
1368        or      r0, r1, r1      /* r0 with block bit set */
1369        putcon  r1, sr          /* now in critical section */
1370        movi    1, r36
1371        shlli   r36, 31, r36
1372        andc    r1, r36, r1     /* turn sr.mmu off in real mode section */
1373
1374        putcon  r1, ssr
1375        movi    .peek0 - CONFIG_PAGE_OFFSET, r36 /* real mode target address */
1376        movi    1f, r37         /* virtual mode return addr */
1377        putcon  r36, spc
1378
1379        synco
1380        rte
1381        nop
1382
1383.peek0: /* come here in real mode, don't touch caches!!
1384           still in critical section (sr.bl==1) */
1385        putcon  r0, ssr
1386        putcon  r37, spc
1387        /* Here's the actual peek.  If the address is bad, all bets are now off
1388         * what will happen (handlers invoked in real-mode = bad news) */
1389        ld.q    r2, 0, r2
1390        synco
1391        rte     /* Back to virtual mode */
1392        nop
1393
13941:
1395        ptabs   LINK, tr0
1396        blink   tr0, r63
1397
1398        .global poke_real_address_q
1399poke_real_address_q:
1400        /* Two args:
1401           r2 : real mode address to poke
1402           r3 : quadword value to write.
1403
1404           This is provided as a cheapskate way of manipulating device
1405           registers for debugging (to avoid the need to ioremap the debug
1406           module, and to avoid the need to ioremap the watchpoint
1407           controller in a way that identity maps sufficient bits to avoid the
1408           SH5-101 cut2 silicon defect).
1409
1410           This code is not performance critical
1411        */
1412
1413        add.l   r2, r63, r2     /* sign extend address */
1414        getcon  sr, r0          /* r0 = saved original SR */
1415        movi    1, r1
1416        shlli   r1, 28, r1
1417        or      r0, r1, r1      /* r0 with block bit set */
1418        putcon  r1, sr          /* now in critical section */
1419        movi    1, r36
1420        shlli   r36, 31, r36
1421        andc    r1, r36, r1     /* turn sr.mmu off in real mode section */
1422
1423        putcon  r1, ssr
1424        movi    .poke0-CONFIG_PAGE_OFFSET, r36 /* real mode target address */
1425        movi    1f, r37         /* virtual mode return addr */
1426        putcon  r36, spc
1427
1428        synco
1429        rte
1430        nop
1431
1432.poke0: /* come here in real mode, don't touch caches!!
1433           still in critical section (sr.bl==1) */
1434        putcon  r0, ssr
1435        putcon  r37, spc
1436        /* Here's the actual poke.  If the address is bad, all bets are now off
1437         * what will happen (handlers invoked in real-mode = bad news) */
1438        st.q    r2, 0, r3
1439        synco
1440        rte     /* Back to virtual mode */
1441        nop
1442
14431:
1444        ptabs   LINK, tr0
1445        blink   tr0, r63
1446
1447#ifdef CONFIG_MMU
1448/*
1449 * --- User Access Handling Section
1450 */
1451
1452/*
1453 * User Access support. It all moved to non inlined Assembler
1454 * functions in here.
1455 *
1456 * __kernel_size_t __copy_user(void *__to, const void *__from,
1457 *                             __kernel_size_t __n)
1458 *
1459 * Inputs:
1460 * (r2)  target address
1461 * (r3)  source address
1462 * (r4)  size in bytes
1463 *
1464 * Ouputs:
1465 * (*r2) target data
1466 * (r2)  non-copied bytes
1467 *
1468 * If a fault occurs on the user pointer, bail out early and return the
1469 * number of bytes not copied in r2.
1470 * Strategy : for large blocks, call a real memcpy function which can
1471 * move >1 byte at a time using unaligned ld/st instructions, and can
1472 * manipulate the cache using prefetch + alloco to improve the speed
1473 * further.  If a fault occurs in that function, just revert to the
1474 * byte-by-byte approach used for small blocks; this is rare so the
1475 * performance hit for that case does not matter.
1476 *
1477 * For small blocks it's not worth the overhead of setting up and calling
1478 * the memcpy routine; do the copy a byte at a time.
1479 *
1480 */
1481        .global __copy_user
1482__copy_user:
1483        pta     __copy_user_byte_by_byte, tr1
1484        movi    16, r0 ! this value is a best guess, should tune it by benchmarking
1485        bge/u   r0, r4, tr1
1486        pta copy_user_memcpy, tr0
1487        addi    SP, -32, SP
1488        /* Save arguments in case we have to fix-up unhandled page fault */
1489        st.q    SP, 0, r2
1490        st.q    SP, 8, r3
1491        st.q    SP, 16, r4
1492        st.q    SP, 24, r35 ! r35 is callee-save
1493        /* Save LINK in a register to reduce RTS time later (otherwise
1494           ld SP,*,LINK;ptabs LINK;trn;blink trn,r63 becomes a critical path) */
1495        ori     LINK, 0, r35
1496        blink   tr0, LINK
1497
1498        /* Copy completed normally if we get back here */
1499        ptabs   r35, tr0
1500        ld.q    SP, 24, r35
1501        /* don't restore r2-r4, pointless */
1502        /* set result=r2 to zero as the copy must have succeeded. */
1503        or      r63, r63, r2
1504        addi    SP, 32, SP
1505        blink   tr0, r63 ! RTS
1506
1507        .global __copy_user_fixup
1508__copy_user_fixup:
1509        /* Restore stack frame */
1510        ori     r35, 0, LINK
1511        ld.q    SP, 24, r35
1512        ld.q    SP, 16, r4
1513        ld.q    SP,  8, r3
1514        ld.q    SP,  0, r2
1515        addi    SP, 32, SP
1516        /* Fall through to original code, in the 'same' state we entered with */
1517
1518/* The slow byte-by-byte method is used if the fast copy traps due to a bad
1519   user address.  In that rare case, the speed drop can be tolerated. */
1520__copy_user_byte_by_byte:
1521        pta     ___copy_user_exit, tr1
1522        pta     ___copy_user1, tr0
1523        beq/u   r4, r63, tr1    /* early exit for zero length copy */
1524        sub     r2, r3, r0
1525        addi    r0, -1, r0
1526
1527___copy_user1:
1528        ld.b    r3, 0, r5               /* Fault address 1 */
1529
1530        /* Could rewrite this to use just 1 add, but the second comes 'free'
1531           due to load latency */
1532        addi    r3, 1, r3
1533        addi    r4, -1, r4              /* No real fixup required */
1534___copy_user2:
1535        stx.b   r3, r0, r5              /* Fault address 2 */
1536        bne     r4, ZERO, tr0
1537
1538___copy_user_exit:
1539        or      r4, ZERO, r2
1540        ptabs   LINK, tr0
1541        blink   tr0, ZERO
1542
1543/*
1544 * __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
1545 *
1546 * Inputs:
1547 * (r2)  target address
1548 * (r3)  size in bytes
1549 *
1550 * Ouputs:
1551 * (*r2) zero-ed target data
1552 * (r2)  non-zero-ed bytes
1553 */
1554        .global __clear_user
1555__clear_user:
1556        pta     ___clear_user_exit, tr1
1557        pta     ___clear_user1, tr0
1558        beq/u   r3, r63, tr1
1559
1560___clear_user1:
1561        st.b    r2, 0, ZERO             /* Fault address */
1562        addi    r2, 1, r2
1563        addi    r3, -1, r3              /* No real fixup required */
1564        bne     r3, ZERO, tr0
1565
1566___clear_user_exit:
1567        or      r3, ZERO, r2
1568        ptabs   LINK, tr0
1569        blink   tr0, ZERO
1570
1571#endif /* CONFIG_MMU */
1572
1573/*
1574 * int __strncpy_from_user(unsigned long __dest, unsigned long __src,
1575 *                         int __count)
1576 *
1577 * Inputs:
1578 * (r2)  target address
1579 * (r3)  source address
1580 * (r4)  maximum size in bytes
1581 *
1582 * Ouputs:
1583 * (*r2) copied data
1584 * (r2)  -EFAULT (in case of faulting)
1585 *       copied data (otherwise)
1586 */
1587        .global __strncpy_from_user
1588__strncpy_from_user:
1589        pta     ___strncpy_from_user1, tr0
1590        pta     ___strncpy_from_user_done, tr1
1591        or      r4, ZERO, r5            /* r5 = original count */
1592        beq/u   r4, r63, tr1            /* early exit if r4==0 */
1593        movi    -(EFAULT), r6           /* r6 = reply, no real fixup */
1594        or      ZERO, ZERO, r7          /* r7 = data, clear top byte of data */
1595
1596___strncpy_from_user1:
1597        ld.b    r3, 0, r7               /* Fault address: only in reading */
1598        st.b    r2, 0, r7
1599        addi    r2, 1, r2
1600        addi    r3, 1, r3
1601        beq/u   ZERO, r7, tr1
1602        addi    r4, -1, r4              /* return real number of copied bytes */
1603        bne/l   ZERO, r4, tr0
1604
1605___strncpy_from_user_done:
1606        sub     r5, r4, r6              /* If done, return copied */
1607
1608___strncpy_from_user_exit:
1609        or      r6, ZERO, r2
1610        ptabs   LINK, tr0
1611        blink   tr0, ZERO
1612
1613/*
1614 * extern long __strnlen_user(const char *__s, long __n)
1615 *
1616 * Inputs:
1617 * (r2)  source address
1618 * (r3)  source size in bytes
1619 *
1620 * Ouputs:
1621 * (r2)  -EFAULT (in case of faulting)
1622 *       string length (otherwise)
1623 */
1624        .global __strnlen_user
1625__strnlen_user:
1626        pta     ___strnlen_user_set_reply, tr0
1627        pta     ___strnlen_user1, tr1
1628        or      ZERO, ZERO, r5          /* r5 = counter */
1629        movi    -(EFAULT), r6           /* r6 = reply, no real fixup */
1630        or      ZERO, ZERO, r7          /* r7 = data, clear top byte of data */
1631        beq     r3, ZERO, tr0
1632
1633___strnlen_user1:
1634        ldx.b   r2, r5, r7              /* Fault address: only in reading */
1635        addi    r3, -1, r3              /* No real fixup */
1636        addi    r5, 1, r5
1637        beq     r3, ZERO, tr0
1638        bne     r7, ZERO, tr1
1639! The line below used to be active.  This meant led to a junk byte lying between each pair
1640! of entries in the argv & envp structures in memory.  Whilst the program saw the right data
1641! via the argv and envp arguments to main, it meant the 'flat' representation visible through
1642! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example.
1643!       addi    r5, 1, r5               /* Include '\0' */
1644
1645___strnlen_user_set_reply:
1646        or      r5, ZERO, r6            /* If done, return counter */
1647
1648___strnlen_user_exit:
1649        or      r6, ZERO, r2
1650        ptabs   LINK, tr0
1651        blink   tr0, ZERO
1652
1653/*
1654 * extern long __get_user_asm_?(void *val, long addr)
1655 *
1656 * Inputs:
1657 * (r2)  dest address
1658 * (r3)  source address (in User Space)
1659 *
1660 * Ouputs:
1661 * (r2)  -EFAULT (faulting)
1662 *       0       (not faulting)
1663 */
1664        .global __get_user_asm_b
1665__get_user_asm_b:
1666        or      r2, ZERO, r4
1667        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1668
1669___get_user_asm_b1:
1670        ld.b    r3, 0, r5               /* r5 = data */
1671        st.b    r4, 0, r5
1672        or      ZERO, ZERO, r2
1673
1674___get_user_asm_b_exit:
1675        ptabs   LINK, tr0
1676        blink   tr0, ZERO
1677
1678
1679        .global __get_user_asm_w
1680__get_user_asm_w:
1681        or      r2, ZERO, r4
1682        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1683
1684___get_user_asm_w1:
1685        ld.w    r3, 0, r5               /* r5 = data */
1686        st.w    r4, 0, r5
1687        or      ZERO, ZERO, r2
1688
1689___get_user_asm_w_exit:
1690        ptabs   LINK, tr0
1691        blink   tr0, ZERO
1692
1693
1694        .global __get_user_asm_l
1695__get_user_asm_l:
1696        or      r2, ZERO, r4
1697        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1698
1699___get_user_asm_l1:
1700        ld.l    r3, 0, r5               /* r5 = data */
1701        st.l    r4, 0, r5
1702        or      ZERO, ZERO, r2
1703
1704___get_user_asm_l_exit:
1705        ptabs   LINK, tr0
1706        blink   tr0, ZERO
1707
1708
1709        .global __get_user_asm_q
1710__get_user_asm_q:
1711        or      r2, ZERO, r4
1712        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1713
1714___get_user_asm_q1:
1715        ld.q    r3, 0, r5               /* r5 = data */
1716        st.q    r4, 0, r5
1717        or      ZERO, ZERO, r2
1718
1719___get_user_asm_q_exit:
1720        ptabs   LINK, tr0
1721        blink   tr0, ZERO
1722
1723/*
1724 * extern long __put_user_asm_?(void *pval, long addr)
1725 *
1726 * Inputs:
1727 * (r2)  kernel pointer to value
1728 * (r3)  dest address (in User Space)
1729 *
1730 * Ouputs:
1731 * (r2)  -EFAULT (faulting)
1732 *       0       (not faulting)
1733 */
1734        .global __put_user_asm_b
1735__put_user_asm_b:
1736        ld.b    r2, 0, r4               /* r4 = data */
1737        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1738
1739___put_user_asm_b1:
1740        st.b    r3, 0, r4
1741        or      ZERO, ZERO, r2
1742
1743___put_user_asm_b_exit:
1744        ptabs   LINK, tr0
1745        blink   tr0, ZERO
1746
1747
1748        .global __put_user_asm_w
1749__put_user_asm_w:
1750        ld.w    r2, 0, r4               /* r4 = data */
1751        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1752
1753___put_user_asm_w1:
1754        st.w    r3, 0, r4
1755        or      ZERO, ZERO, r2
1756
1757___put_user_asm_w_exit:
1758        ptabs   LINK, tr0
1759        blink   tr0, ZERO
1760
1761
1762        .global __put_user_asm_l
1763__put_user_asm_l:
1764        ld.l    r2, 0, r4               /* r4 = data */
1765        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1766
1767___put_user_asm_l1:
1768        st.l    r3, 0, r4
1769        or      ZERO, ZERO, r2
1770
1771___put_user_asm_l_exit:
1772        ptabs   LINK, tr0
1773        blink   tr0, ZERO
1774
1775
1776        .global __put_user_asm_q
1777__put_user_asm_q:
1778        ld.q    r2, 0, r4               /* r4 = data */
1779        movi    -(EFAULT), r2           /* r2 = reply, no real fixup */
1780
1781___put_user_asm_q1:
1782        st.q    r3, 0, r4
1783        or      ZERO, ZERO, r2
1784
1785___put_user_asm_q_exit:
1786        ptabs   LINK, tr0
1787        blink   tr0, ZERO
1788
1789panic_stash_regs:
1790        /* The idea is : when we get an unhandled panic, we dump the registers
1791           to a known memory location, the just sit in a tight loop.
1792           This allows the human to look at the memory region through the GDB
1793           session (assuming the debug module's SHwy initiator isn't locked up
1794           or anything), to hopefully analyze the cause of the panic. */
1795
1796        /* On entry, former r15 (SP) is in DCR
1797           former r0  is at resvec_saved_area + 0
1798           former r1  is at resvec_saved_area + 8
1799           former tr0 is at resvec_saved_area + 32
1800           DCR is the only register whose value is lost altogether.
1801        */
1802
1803        movi    0xffffffff80000000, r0 ! phy of dump area
1804        ld.q    SP, 0x000, r1   ! former r0
1805        st.q    r0,  0x000, r1
1806        ld.q    SP, 0x008, r1   ! former r1
1807        st.q    r0,  0x008, r1
1808        st.q    r0,  0x010, r2
1809        st.q    r0,  0x018, r3
1810        st.q    r0,  0x020, r4
1811        st.q    r0,  0x028, r5
1812        st.q    r0,  0x030, r6
1813        st.q    r0,  0x038, r7
1814        st.q    r0,  0x040, r8
1815        st.q    r0,  0x048, r9
1816        st.q    r0,  0x050, r10
1817        st.q    r0,  0x058, r11
1818        st.q    r0,  0x060, r12
1819        st.q    r0,  0x068, r13
1820        st.q    r0,  0x070, r14
1821        getcon  dcr, r14
1822        st.q    r0,  0x078, r14
1823        st.q    r0,  0x080, r16
1824        st.q    r0,  0x088, r17
1825        st.q    r0,  0x090, r18
1826        st.q    r0,  0x098, r19
1827        st.q    r0,  0x0a0, r20
1828        st.q    r0,  0x0a8, r21
1829        st.q    r0,  0x0b0, r22
1830        st.q    r0,  0x0b8, r23
1831        st.q    r0,  0x0c0, r24
1832        st.q    r0,  0x0c8, r25
1833        st.q    r0,  0x0d0, r26
1834        st.q    r0,  0x0d8, r27
1835        st.q    r0,  0x0e0, r28
1836        st.q    r0,  0x0e8, r29
1837        st.q    r0,  0x0f0, r30
1838        st.q    r0,  0x0f8, r31
1839        st.q    r0,  0x100, r32
1840        st.q    r0,  0x108, r33
1841        st.q    r0,  0x110, r34
1842        st.q    r0,  0x118, r35
1843        st.q    r0,  0x120, r36
1844        st.q    r0,  0x128, r37
1845        st.q    r0,  0x130, r38
1846        st.q    r0,  0x138, r39
1847        st.q    r0,  0x140, r40
1848        st.q    r0,  0x148, r41
1849        st.q    r0,  0x150, r42
1850        st.q    r0,  0x158, r43
1851        st.q    r0,  0x160, r44
1852        st.q    r0,  0x168, r45
1853        st.q    r0,  0x170, r46
1854        st.q    r0,  0x178, r47
1855        st.q    r0,  0x180, r48
1856        st.q    r0,  0x188, r49
1857        st.q    r0,  0x190, r50
1858        st.q    r0,  0x198, r51
1859        st.q    r0,  0x1a0, r52
1860        st.q    r0,  0x1a8, r53
1861        st.q    r0,  0x1b0, r54
1862        st.q    r0,  0x1b8, r55
1863        st.q    r0,  0x1c0, r56
1864        st.q    r0,  0x1c8, r57
1865        st.q    r0,  0x1d0, r58
1866        st.q    r0,  0x1d8, r59
1867        st.q    r0,  0x1e0, r60
1868        st.q    r0,  0x1e8, r61
1869        st.q    r0,  0x1f0, r62
1870        st.q    r0,  0x1f8, r63 ! bogus, but for consistency's sake...
1871
1872        ld.q    SP, 0x020, r1  ! former tr0
1873        st.q    r0,  0x200, r1
1874        gettr   tr1, r1
1875        st.q    r0,  0x208, r1
1876        gettr   tr2, r1
1877        st.q    r0,  0x210, r1
1878        gettr   tr3, r1
1879        st.q    r0,  0x218, r1
1880        gettr   tr4, r1
1881        st.q    r0,  0x220, r1
1882        gettr   tr5, r1
1883        st.q    r0,  0x228, r1
1884        gettr   tr6, r1
1885        st.q    r0,  0x230, r1
1886        gettr   tr7, r1
1887        st.q    r0,  0x238, r1
1888
1889        getcon  sr,  r1
1890        getcon  ssr,  r2
1891        getcon  pssr,  r3
1892        getcon  spc,  r4
1893        getcon  pspc,  r5
1894        getcon  intevt,  r6
1895        getcon  expevt,  r7
1896        getcon  pexpevt,  r8
1897        getcon  tra,  r9
1898        getcon  tea,  r10
1899        getcon  kcr0, r11
1900        getcon  kcr1, r12
1901        getcon  vbr,  r13
1902        getcon  resvec,  r14
1903
1904        st.q    r0,  0x240, r1
1905        st.q    r0,  0x248, r2
1906        st.q    r0,  0x250, r3
1907        st.q    r0,  0x258, r4
1908        st.q    r0,  0x260, r5
1909        st.q    r0,  0x268, r6
1910        st.q    r0,  0x270, r7
1911        st.q    r0,  0x278, r8
1912        st.q    r0,  0x280, r9
1913        st.q    r0,  0x288, r10
1914        st.q    r0,  0x290, r11
1915        st.q    r0,  0x298, r12
1916        st.q    r0,  0x2a0, r13
1917        st.q    r0,  0x2a8, r14
1918
1919        getcon  SPC,r2
1920        getcon  SSR,r3
1921        getcon  EXPEVT,r4
1922        /* Prepare to jump to C - physical address */
1923        movi    panic_handler-CONFIG_PAGE_OFFSET, r1
1924        ori     r1, 1, r1
1925        ptabs   r1, tr0
1926        getcon  DCR, SP
1927        blink   tr0, ZERO
1928        nop
1929        nop
1930        nop
1931        nop
1932
1933
1934
1935
1936/*
1937 * --- Signal Handling Section
1938 */
1939
1940/*
1941 * extern long long _sa_default_rt_restorer
1942 * extern long long _sa_default_restorer
1943 *
1944 *               or, better,
1945 *
1946 * extern void _sa_default_rt_restorer(void)
1947 * extern void _sa_default_restorer(void)
1948 *
1949 * Code prototypes to do a sys_rt_sigreturn() or sys_sysreturn()
1950 * from user space. Copied into user space by signal management.
1951 * Both must be quad aligned and 2 quad long (4 instructions).
1952 *
1953 */
1954        .balign 8
1955        .global sa_default_rt_restorer
1956sa_default_rt_restorer:
1957        movi    0x10, r9
1958        shori   __NR_rt_sigreturn, r9
1959        trapa   r9
1960        nop
1961
1962        .balign 8
1963        .global sa_default_restorer
1964sa_default_restorer:
1965        movi    0x10, r9
1966        shori   __NR_sigreturn, r9
1967        trapa   r9
1968        nop
1969
1970/*
1971 * --- __ex_table Section
1972 */
1973
1974/*
1975 * User Access Exception Table.
1976 */
1977        .section        __ex_table,  "a"
1978
1979        .global asm_uaccess_start       /* Just a marker */
1980asm_uaccess_start:
1981
1982#ifdef CONFIG_MMU
1983        .long   ___copy_user1, ___copy_user_exit
1984        .long   ___copy_user2, ___copy_user_exit
1985        .long   ___clear_user1, ___clear_user_exit
1986#endif
1987        .long   ___strncpy_from_user1, ___strncpy_from_user_exit
1988        .long   ___strnlen_user1, ___strnlen_user_exit
1989        .long   ___get_user_asm_b1, ___get_user_asm_b_exit
1990        .long   ___get_user_asm_w1, ___get_user_asm_w_exit
1991        .long   ___get_user_asm_l1, ___get_user_asm_l_exit
1992        .long   ___get_user_asm_q1, ___get_user_asm_q_exit
1993        .long   ___put_user_asm_b1, ___put_user_asm_b_exit
1994        .long   ___put_user_asm_w1, ___put_user_asm_w_exit
1995        .long   ___put_user_asm_l1, ___put_user_asm_l_exit
1996        .long   ___put_user_asm_q1, ___put_user_asm_q_exit
1997
1998        .global asm_uaccess_end         /* Just a marker */
1999asm_uaccess_end:
2000
2001
2002
2003
2004/*
2005 * --- .init.text Section
2006 */
2007
2008        __INIT
2009
2010/*
2011 * void trap_init (void)
2012 *
2013 */
2014        .global trap_init
2015trap_init:
2016        addi    SP, -24, SP                     /* Room to save r28/r29/r30 */
2017        st.q    SP, 0, r28
2018        st.q    SP, 8, r29
2019        st.q    SP, 16, r30
2020
2021        /* Set VBR and RESVEC */
2022        movi    LVBR_block, r19
2023        andi    r19, -4, r19                    /* reset MMUOFF + reserved */
2024        /* For RESVEC exceptions we force the MMU off, which means we need the
2025           physical address. */
2026        movi    LRESVEC_block-CONFIG_PAGE_OFFSET, r20
2027        andi    r20, -4, r20                    /* reset reserved */
2028        ori     r20, 1, r20                     /* set MMUOFF */
2029        putcon  r19, VBR
2030        putcon  r20, RESVEC
2031
2032        /* Sanity check */
2033        movi    LVBR_block_end, r21
2034        andi    r21, -4, r21
2035        movi    BLOCK_SIZE, r29                 /* r29 = expected size */
2036        or      r19, ZERO, r30
2037        add     r19, r29, r19
2038
2039        /*
2040         * Ugly, but better loop forever now than crash afterwards.
2041         * We should print a message, but if we touch LVBR or
2042         * LRESVEC blocks we should not be surprised if we get stuck
2043         * in trap_init().
2044         */
2045        pta     trap_init_loop, tr1
2046        gettr   tr1, r28                        /* r28 = trap_init_loop */
2047        sub     r21, r30, r30                   /* r30 = actual size */
2048
2049        /*
2050         * VBR/RESVEC handlers overlap by being bigger than
2051         * allowed. Very bad. Just loop forever.
2052         * (r28) panic/loop address
2053         * (r29) expected size
2054         * (r30) actual size
2055         */
2056trap_init_loop:
2057        bne     r19, r21, tr1
2058
2059        /* Now that exception vectors are set up reset SR.BL */
2060        getcon  SR, r22
2061        movi    SR_UNBLOCK_EXC, r23
2062        and     r22, r23, r22
2063        putcon  r22, SR
2064
2065        addi    SP, 24, SP
2066        ptabs   LINK, tr0
2067        blink   tr0, ZERO
2068
2069