root/arch/sparc/kernel/rtrap.S

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

/* [previous][next][first][last][top][bottom][index][help] */