root/arch/sparc/kernel/rtrap.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /* $Id: rtrap.S,v 1.21 1996/02/20 07:45:11 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 + REGWIN_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 
  56         cmp     %twin_tmp2, 0
  57         be      signal_p
  58          nop
  59 
  60         call    C_LABEL(schedule)
  61          nop
  62 
  63         /* Try to return again... We are a different process,
  64          * most likely so load and then check if going back
  65          * to user or kernel this time.
  66          */
  67         b       ret_trap_entry
  68          nop
  69 
  70 signal_p:
  71         /* No signals for swapper. */
  72         LOAD_CURRENT(twin_tmp1, twin_tmp3)
  73         set     C_LABEL(init_task), %twin_tmp3
  74         cmp     %twin_tmp3, %twin_tmp1
  75         be      ret_trap_continue
  76          nop
  77 
  78         ld      [%twin_tmp1 + TASK_SIGNAL], %twin_tmp2
  79         ld      [%twin_tmp1 + TASK_BLOCKED], %o0
  80         andncc  %twin_tmp2, %o0, %g0
  81         be      ret_trap_continue
  82          nop
  83 
  84         call    C_LABEL(do_signal)
  85          add    %sp, REGWIN_SZ, %o1     ! pt_regs ptr
  86 
  87         /* Fall through... */
  88 ret_trap_continue:
  89         ld      [%sp + REGWIN_SZ + PT_PSR], %t_psr
  90         wr      %t_psr, 0x0, %psr
  91         WRITE_PAUSE
  92 
  93         /* If not current fpu proc, disable fp-ops */
  94         LOAD_CURRENT(twin_tmp2, twin_tmp1)
  95         set     C_LABEL(last_task_used_math), %twin_tmp1
  96         ld      [%twin_tmp1], %twin_tmp1
  97         cmp     %twin_tmp2, %twin_tmp1
  98         be      1f
  99          nop
 100 
 101         set     PSR_EF, %twin_tmp1
 102         andn    %t_psr, %twin_tmp1, %t_psr
 103         st      %t_psr, [%sp + REGWIN_SZ + PT_PSR]
 104 
 105 1:
 106         ld      [%twin_tmp2 + THREAD_W_SAVED], %twin_tmp1
 107         orcc    %g0, %twin_tmp1, %g0
 108         be      ret_trap_nobufwins
 109          nop
 110 
 111         wr      %t_psr, PSR_ET, %psr
 112         WRITE_PAUSE
 113 
 114         mov     1, %o1
 115         call    C_LABEL(try_to_clear_window_buffer)
 116          add    %sp, REGWIN_SZ, %o0
 117 
 118         b       ret_trap_entry
 119          nop
 120 
 121 ret_trap_nobufwins:
 122         /* Load up the user's out registers so we can pull
 123          * a window from the stack, if necessary.
 124          */
 125         LOAD_PT_INS(sp)
 126 
 127         /* If there are already live user windows in the
 128          * set we can return from trap safely.
 129          */
 130         ld      [%twin_tmp2 + THREAD_UMASK], %twin_tmp1
 131         orcc    %g0, %twin_tmp1, %g0
 132         bne     ret_trap_userwins_ok
 133          nop
 134         
 135                 /* Calculate new %wim, we have to pull a register
 136                  * window from the users stack.
 137                  */
 138 ret_trap_pull_one_window:
 139                 rd      %wim, %t_wim
 140                 sll     %t_wim, 0x1, %twin_tmp1
 141 rtrap_patch1:   srl     %t_wim, 0x7, %twin_tmp2
 142                 or      %twin_tmp2, %twin_tmp1, %twin_tmp2
 143 rtrap_patch2:   and     %twin_tmp2, 0xff, %twin_tmp2
 144 
 145                 wr      %twin_tmp2, 0x0, %wim
 146                 WRITE_PAUSE
 147 
 148                                 /* Here comes the architecture specific 
 149                                  * branch to the user stack checking routine
 150                                  * for return from traps.
 151                                  */
 152                                 .globl  C_LABEL(rtrap_mmu_patchme)
 153 C_LABEL(rtrap_mmu_patchme):     b       C_LABEL(sun4c_rett_stackchk)
 154                                  andcc  %fp, 0x7, %g0   
 155 
 156 ret_trap_userwins_ok:
 157         LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
 158         or      %t_pc, %t_npc, %g2
 159         andcc   %g2, 0x3, %g0
 160         bne     ret_trap_unaligned_pc
 161          nop
 162 
 163         LOAD_PT_YREG(sp, g1)
 164         LOAD_PT_GLOBALS(sp)
 165 
 166         wr      %t_psr, 0x0, %psr
 167         WRITE_PAUSE
 168 
 169         jmp     %t_pc
 170         rett    %t_npc
 171         
 172         /* HyperSparc special nop patching, if we are on a hypersparc
 173          * we nop the top two instructions and the first nop coming
 174          * up to be:
 175          * rd   %iccr, %g0  <-- flush on-chip instruction cache
 176          * jmp  %t_pc
 177          * rett %t_npc
 178          */
 179         nop
 180         nop
 181 
 182 ret_trap_unaligned_pc:
 183         add     %sp, REGWIN_SZ, %o0
 184         ld      [%sp + REGWIN_SZ + PT_PC], %o1
 185         ld      [%sp + REGWIN_SZ + PT_NPC], %o2
 186         ld      [%sp + REGWIN_SZ + PT_PSR], %o3
 187 
 188         wr      %t_wim, 0x0, %wim               ! or else...
 189         WRITE_PAUSE
 190 
 191         wr      %t_psr, PSR_ET, %psr
 192         WRITE_PAUSE
 193 
 194         call    C_LABEL(do_memaccess_unaligned)
 195          nop
 196 
 197         b       ret_trap_entry                  ! maybe signal posted
 198          nop
 199 
 200 ret_trap_kernel:
 201         ld      [%sp + REGWIN_SZ + PT_PSR], %t_psr
 202         wr      %t_psr, 0x0, %psr
 203         WRITE_PAUSE
 204 
 205                 /* Will the rett land us in the invalid window? */
 206                 mov     2, %g1
 207                 sll     %g1, %t_psr, %g1
 208 rtrap_patch3:   srl     %g1, 8, %g2
 209                 or      %g1, %g2, %g1
 210                 rd      %wim, %g2
 211                 andcc   %g2, %g1, %g0
 212                 be      1f              ! Nope, just return from the trap
 213                  nop
 214 
 215                 /* We have to grab a window before returning. */
 216                 sll     %g2, 0x1, %g1
 217 rtrap_patch4:   srl     %g2, 7,  %g2
 218                 or      %g1, %g2, %g1
 219 rtrap_patch5:   and     %g1, 0xff, %g1
 220 
 221         wr      %g1, 0x0, %wim
 222         WRITE_PAUSE
 223 
 224         restore %g0, %g0, %g0
 225         LOAD_WINDOW(sp)
 226         save    %g0, %g0, %g0
 227 
 228         /* Reload the entire frame in case this is from a
 229          * kernel system call or whatever...
 230          */
 231 1:
 232         LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
 233 
 234         wr      %t_psr, 0x0, %psr
 235         WRITE_PAUSE
 236 
 237         jmp     %t_pc
 238         rett    %t_npc
 239 
 240 ret_trap_user_stack_is_bolixed:
 241         wr      %t_wim, 0x0, %wim
 242         WRITE_PAUSE
 243 
 244         wr      %t_psr, PSR_ET, %psr
 245         WRITE_PAUSE
 246 
 247         call    C_LABEL(window_ret_fault)
 248          add    %sp, REGWIN_SZ, %o0
 249 
 250         b       ret_trap_entry
 251          nop
 252 
 253         .globl  C_LABEL(sun4c_rett_stackchk)
 254 C_LABEL(sun4c_rett_stackchk):
 255         be      1f
 256          and    %fp, 0xfff, %g1         ! delay slot
 257 
 258         b       ret_trap_user_stack_is_bolixed
 259          nop
 260 
 261         /* See if we have to check the sanity of one page or two */
 262 1:
 263         add     %g1, 0x38, %g1
 264         sra     %fp, 29, %g2
 265         add     %g2, 0x1, %g2
 266         andncc  %g2, 0x1, %g0
 267         be      1f
 268          andncc %g1, 0xff8, %g0
 269 
 270         /* %sp is in vma hole, yuck */
 271         b       ret_trap_user_stack_is_bolixed
 272          nop
 273 
 274 1:
 275         be      sun4c_rett_onepage      /* Only one page to check */
 276          lda    [%fp] ASI_PTE, %g2
 277 
 278 sun4c_rett_twopages:
 279         add     %fp, 0x38, %g1
 280         sra     %g1, 29, %g2
 281         add     %g2, 0x1, %g2
 282         andncc  %g2, 0x1, %g0
 283         be      1f
 284          lda    [%g1] ASI_PTE, %g2
 285 
 286         /* Second page is in vma hole */
 287         b       ret_trap_user_stack_is_bolixed
 288          nop
 289 
 290 1:
 291         srl     %g2, 29, %g2
 292         andcc   %g2, 0x4, %g0
 293         bne     sun4c_rett_onepage
 294          lda    [%fp] ASI_PTE, %g2
 295 
 296         /* Second page has bad perms */
 297         b       ret_trap_user_stack_is_bolixed
 298          nop
 299 
 300 sun4c_rett_onepage:
 301         srl     %g2, 29, %g2
 302         andcc   %g2, 0x4, %g0
 303         bne     1f
 304          nop
 305 
 306         /* A page had bad page permissions, losing... */
 307         b       ret_trap_user_stack_is_bolixed
 308          nop
 309 
 310         /* Whee, things are ok, load the window and continue. */
 311 1:
 312         restore %g0, %g0, %g0
 313 
 314         LOAD_WINDOW(sp)
 315 
 316         save    %g0, %g0, %g0
 317         b       ret_trap_userwins_ok
 318          nop
 319 
 320         .globl  C_LABEL(srmmu_rett_stackchk)
 321 C_LABEL(srmmu_rett_stackchk):
 322         bne     ret_trap_user_stack_is_bolixed
 323          sethi  %hi(KERNBASE), %g1
 324         cmp     %g1, %fp
 325         bleu    ret_trap_user_stack_is_bolixed
 326          mov    AC_M_SFSR, %g1
 327         lda     [%g1] ASI_M_MMUREGS, %g0
 328 
 329         lda     [%g0] ASI_M_MMUREGS, %g1
 330         or      %g1, 0x2, %g1
 331         sta     %g1, [%g0] ASI_M_MMUREGS
 332 
 333         restore %g0, %g0, %g0
 334 
 335         LOAD_WINDOW(sp)
 336 
 337         save    %g0, %g0, %g0
 338 
 339         andn    %g1, 0x2, %g1
 340         sta     %g1, [%g0] ASI_M_MMUREGS
 341 
 342         mov     AC_M_SFAR, %g2
 343         lda     [%g2] ASI_M_MMUREGS, %g2
 344 
 345         mov     AC_M_SFSR, %g1
 346         lda     [%g1] ASI_M_MMUREGS, %g1
 347         andcc   %g1, 0x2, %g0
 348         bne     ret_trap_user_stack_is_bolixed
 349          nop
 350 
 351         b       ret_trap_userwins_ok
 352          nop

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