linux/arch/sparc/kernel/rtrap.S
<<
>>
Prefs
   1/* $Id: rtrap.S,v 1.58 2002/01/31 03:30:05 davem Exp $
   2 * rtrap.S: Return from Sparc trap low-level code.
   3 *
   4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   5 */
   6
   7#include <asm/page.h>
   8#include <asm/ptrace.h>
   9#include <asm/psr.h>
  10#include <asm/asi.h>
  11#include <asm/smp.h>
  12#include <asm/contregs.h>
  13#include <asm/winmacro.h>
  14#include <asm/asmmacro.h>
  15#include <asm/thread_info.h>
  16
  17#define t_psr     l0
  18#define t_pc      l1
  19#define t_npc     l2
  20#define t_wim     l3
  21#define twin_tmp1 l4
  22#define glob_tmp  g4
  23#define curptr    g6
  24
  25        /* 7 WINDOW SPARC PATCH INSTRUCTIONS */
  26        .globl  rtrap_7win_patch1, rtrap_7win_patch2, rtrap_7win_patch3
  27        .globl  rtrap_7win_patch4, rtrap_7win_patch5
  28rtrap_7win_patch1:      srl     %t_wim, 0x6, %glob_tmp
  29rtrap_7win_patch2:      and     %glob_tmp, 0x7f, %glob_tmp
  30rtrap_7win_patch3:      srl     %g1, 7, %g2
  31rtrap_7win_patch4:      srl     %g2, 6, %g2
  32rtrap_7win_patch5:      and     %g1, 0x7f, %g1
  33        /* END OF PATCH INSTRUCTIONS */
  34
  35        /* We need to check for a few things which are:
  36         * 1) The need to call schedule() because this
  37         *    processes quantum is up.
  38         * 2) Pending signals for this process, if any
  39         *    exist we need to call do_signal() to do
  40         *    the needy.
  41         *
  42         * Else we just check if the rett would land us
  43         * in an invalid window, if so we need to grab
  44         * it off the user/kernel stack first.
  45         */
  46
  47        .globl  ret_trap_entry, rtrap_patch1, rtrap_patch2
  48        .globl  rtrap_patch3, rtrap_patch4, rtrap_patch5
  49        .globl  ret_trap_lockless_ipi
  50ret_trap_entry:
  51ret_trap_lockless_ipi:
  52        andcc   %t_psr, PSR_PS, %g0
  53        be      1f
  54         nop
  55
  56        wr      %t_psr, 0x0, %psr
  57        b       ret_trap_kernel
  58         nop
  59
  601:
  61        ld      [%curptr + TI_FLAGS], %g2
  62        andcc   %g2, (_TIF_NEED_RESCHED), %g0
  63        be      signal_p
  64         nop
  65
  66        call    schedule
  67         nop
  68
  69        ld      [%curptr + TI_FLAGS], %g2
  70signal_p:
  71        andcc   %g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0
  72        bz,a    ret_trap_continue
  73         ld     [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
  74
  75        mov     %l5, %o1
  76        mov     %l6, %o2
  77        call    do_signal
  78         add    %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr
  79
  80        /* Fall through. */
  81        ld      [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
  82        clr     %l6
  83ret_trap_continue:
  84        wr      %t_psr, 0x0, %psr
  85        WRITE_PAUSE
  86
  87        ld      [%curptr + TI_W_SAVED], %twin_tmp1
  88        orcc    %g0, %twin_tmp1, %g0
  89        be      ret_trap_nobufwins
  90         nop
  91
  92        wr      %t_psr, PSR_ET, %psr
  93        WRITE_PAUSE
  94
  95        mov     1, %o1
  96        call    try_to_clear_window_buffer
  97         add    %sp, STACKFRAME_SZ, %o0
  98
  99        b       signal_p
 100         ld     [%curptr + TI_FLAGS], %g2
 101
 102ret_trap_nobufwins:
 103        /* Load up the user's out registers so we can pull
 104         * a window from the stack, if necessary.
 105         */
 106        LOAD_PT_INS(sp)
 107
 108        /* If there are already live user windows in the
 109         * set we can return from trap safely.
 110         */
 111        ld      [%curptr + TI_UWINMASK], %twin_tmp1
 112        orcc    %g0, %twin_tmp1, %g0
 113        bne     ret_trap_userwins_ok
 114         nop
 115
 116                /* Calculate new %wim, we have to pull a register
 117                 * window from the users stack.
 118                 */
 119ret_trap_pull_one_window:
 120                rd      %wim, %t_wim
 121                sll     %t_wim, 0x1, %twin_tmp1
 122rtrap_patch1:   srl     %t_wim, 0x7, %glob_tmp
 123                or      %glob_tmp, %twin_tmp1, %glob_tmp
 124rtrap_patch2:   and     %glob_tmp, 0xff, %glob_tmp
 125
 126                wr      %glob_tmp, 0x0, %wim
 127
 128                                /* Here comes the architecture specific 
 129                                 * branch to the user stack checking routine
 130                                 * for return from traps.
 131                                 */
 132                                .globl  rtrap_mmu_patchme
 133rtrap_mmu_patchme:      b       sun4c_rett_stackchk
 134                                 andcc  %fp, 0x7, %g0   
 135
 136ret_trap_userwins_ok:
 137        LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
 138        or      %t_pc, %t_npc, %g2
 139        andcc   %g2, 0x3, %g0
 140        be      1f
 141         nop
 142
 143        b       ret_trap_unaligned_pc
 144         add    %sp, STACKFRAME_SZ, %o0
 145
 1461:
 147        LOAD_PT_YREG(sp, g1)
 148        LOAD_PT_GLOBALS(sp)
 149
 150        wr      %t_psr, 0x0, %psr
 151        WRITE_PAUSE
 152
 153        jmp     %t_pc
 154        rett    %t_npc
 155        
 156ret_trap_unaligned_pc:
 157        ld      [%sp + STACKFRAME_SZ + PT_PC], %o1
 158        ld      [%sp + STACKFRAME_SZ + PT_NPC], %o2
 159        ld      [%sp + STACKFRAME_SZ + PT_PSR], %o3
 160
 161        wr      %t_wim, 0x0, %wim               ! or else...
 162
 163        wr      %t_psr, PSR_ET, %psr
 164        WRITE_PAUSE
 165
 166        call    do_memaccess_unaligned
 167         nop
 168
 169        b       signal_p
 170         ld     [%curptr + TI_FLAGS], %g2
 171
 172ret_trap_kernel:
 173                /* Will the rett land us in the invalid window? */
 174                mov     2, %g1
 175                sll     %g1, %t_psr, %g1
 176rtrap_patch3:   srl     %g1, 8, %g2
 177                or      %g1, %g2, %g1
 178                rd      %wim, %g2
 179                andcc   %g2, %g1, %g0
 180                be      1f              ! Nope, just return from the trap
 181                 sll    %g2, 0x1, %g1
 182
 183                /* We have to grab a window before returning. */
 184rtrap_patch4:   srl     %g2, 7,  %g2
 185                or      %g1, %g2, %g1
 186rtrap_patch5:   and     %g1, 0xff, %g1
 187
 188        wr      %g1, 0x0, %wim
 189
 190        /* Grrr, make sure we load from the right %sp... */
 191        LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
 192
 193        restore %g0, %g0, %g0
 194        LOAD_WINDOW(sp)
 195        b       2f
 196         save   %g0, %g0, %g0
 197
 198        /* Reload the entire frame in case this is from a
 199         * kernel system call or whatever...
 200         */
 2011:
 202        LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
 2032:
 204        wr      %t_psr, 0x0, %psr
 205        WRITE_PAUSE
 206
 207        jmp     %t_pc
 208        rett    %t_npc
 209
 210ret_trap_user_stack_is_bolixed:
 211        wr      %t_wim, 0x0, %wim
 212
 213        wr      %t_psr, PSR_ET, %psr
 214        WRITE_PAUSE
 215
 216        call    window_ret_fault
 217         add    %sp, STACKFRAME_SZ, %o0
 218
 219        b       signal_p
 220         ld     [%curptr + TI_FLAGS], %g2
 221
 222
 223        .globl  sun4c_rett_stackchk
 224sun4c_rett_stackchk:
 225        be      1f
 226         and    %fp, 0xfff, %g1         ! delay slot
 227
 228        b       ret_trap_user_stack_is_bolixed + 0x4
 229         wr     %t_wim, 0x0, %wim
 230
 231        /* See if we have to check the sanity of one page or two */
 2321:
 233        add     %g1, 0x38, %g1
 234        sra     %fp, 29, %g2
 235        add     %g2, 0x1, %g2
 236        andncc  %g2, 0x1, %g0
 237        be      1f
 238         andncc %g1, 0xff8, %g0
 239
 240        /* %sp is in vma hole, yuck */
 241        b       ret_trap_user_stack_is_bolixed + 0x4
 242         wr     %t_wim, 0x0, %wim
 243
 2441:
 245        be      sun4c_rett_onepage      /* Only one page to check */
 246         lda    [%fp] ASI_PTE, %g2
 247
 248sun4c_rett_twopages:
 249        add     %fp, 0x38, %g1
 250        sra     %g1, 29, %g2
 251        add     %g2, 0x1, %g2
 252        andncc  %g2, 0x1, %g0
 253        be      1f
 254         lda    [%g1] ASI_PTE, %g2
 255
 256        /* Second page is in vma hole */
 257        b       ret_trap_user_stack_is_bolixed + 0x4
 258         wr     %t_wim, 0x0, %wim
 259
 2601:
 261        srl     %g2, 29, %g2
 262        andcc   %g2, 0x4, %g0
 263        bne     sun4c_rett_onepage
 264         lda    [%fp] ASI_PTE, %g2
 265
 266        /* Second page has bad perms */
 267        b       ret_trap_user_stack_is_bolixed + 0x4
 268         wr     %t_wim, 0x0, %wim
 269
 270sun4c_rett_onepage:
 271        srl     %g2, 29, %g2
 272        andcc   %g2, 0x4, %g0
 273        bne,a   1f
 274         restore %g0, %g0, %g0
 275
 276        /* A page had bad page permissions, losing... */
 277        b       ret_trap_user_stack_is_bolixed + 0x4
 278         wr     %t_wim, 0x0, %wim
 279
 280        /* Whee, things are ok, load the window and continue. */
 2811:
 282        LOAD_WINDOW(sp)
 283
 284        b       ret_trap_userwins_ok
 285         save   %g0, %g0, %g0
 286
 287        .globl  srmmu_rett_stackchk
 288srmmu_rett_stackchk:
 289        bne     ret_trap_user_stack_is_bolixed
 290         sethi   %hi(PAGE_OFFSET), %g1
 291        cmp     %g1, %fp
 292        bleu    ret_trap_user_stack_is_bolixed
 293         mov    AC_M_SFSR, %g1
 294        lda     [%g1] ASI_M_MMUREGS, %g0
 295
 296        lda     [%g0] ASI_M_MMUREGS, %g1
 297        or      %g1, 0x2, %g1
 298        sta     %g1, [%g0] ASI_M_MMUREGS
 299
 300        restore %g0, %g0, %g0
 301
 302        LOAD_WINDOW(sp)
 303
 304        save    %g0, %g0, %g0
 305
 306        andn    %g1, 0x2, %g1
 307        sta     %g1, [%g0] ASI_M_MMUREGS
 308
 309        mov     AC_M_SFAR, %g2
 310        lda     [%g2] ASI_M_MMUREGS, %g2
 311
 312        mov     AC_M_SFSR, %g1
 313        lda     [%g1] ASI_M_MMUREGS, %g1
 314        andcc   %g1, 0x2, %g0
 315        be      ret_trap_userwins_ok
 316         nop
 317
 318        b,a     ret_trap_user_stack_is_bolixed
 319