root/arch/sparc/kernel/rtrap.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /* $Id: rtrap.S,v 1.27 1996/04/03 02:14:41 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/smp.h>
  13 #include <asm/contregs.h>
  14 #include <asm/winmacro.h>
  15 #include <asm/asmmacro.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 twin_tmp2 l5
  23 #define twin_tmp3 l6
  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
  28 rtrap_7win_patch1:      srl     %t_wim, 0x6, %twin_tmp2
  29 rtrap_7win_patch2:      and     %twin_tmp2, 0x7f, %twin_tmp2
  30 rtrap_7win_patch3:      srl     %g1, 7, %g2
  31 rtrap_7win_patch4:      srl     %g2, 6, %g2
  32 rtrap_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 ret_trap_entry:
  50         ld      [%sp + REGWIN_SZ + PT_PSR], %t_psr
  51         andcc   %t_psr, PSR_PS, %g0
  52         bne     ret_trap_kernel
  53          nop
  54 
  55         sethi   %hi(C_LABEL(need_resched)), %twin_tmp1
  56         ld      [%twin_tmp1 + %lo(C_LABEL(need_resched))], %twin_tmp2
  57 
  58         cmp     %twin_tmp2, 0
  59         be      signal_p
  60          nop
  61 
  62         call    C_LABEL(schedule)
  63          nop
  64 
  65         /* Try to return again... We are a different process,
  66          * most likely so load and then check if going back
  67          * to user or kernel this time.
  68          */
  69         b       ret_trap_entry
  70          nop
  71 
  72 signal_p:
  73         /* No signals for swapper. */
  74         LOAD_CURRENT(twin_tmp1, twin_tmp3)
  75         set     C_LABEL(init_task), %twin_tmp3
  76         cmp     %twin_tmp3, %twin_tmp1
  77         be      ret_trap_continue
  78          nop
  79 
  80         ld      [%twin_tmp1 + TASK_SIGNAL], %twin_tmp2
  81         ld      [%twin_tmp1 + TASK_BLOCKED], %o0
  82         andncc  %twin_tmp2, %o0, %g0
  83         be      ret_trap_continue
  84          nop
  85 
  86         call    C_LABEL(do_signal)
  87          add    %sp, REGWIN_SZ, %o1     ! pt_regs ptr
  88 
  89         /* Fall through... */
  90 ret_trap_continue:
  91         ld      [%sp + REGWIN_SZ + PT_PSR], %t_psr
  92         wr      %t_psr, 0x0, %psr
  93         WRITE_PAUSE
  94 
  95         LOAD_CURRENT(twin_tmp2, twin_tmp1)
  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, PSR_ET, %psr
 102         WRITE_PAUSE
 103 
 104         mov     1, %o1
 105         call    C_LABEL(try_to_clear_window_buffer)
 106          add    %sp, REGWIN_SZ, %o0
 107 
 108         b       ret_trap_entry
 109          nop
 110 
 111 ret_trap_nobufwins:
 112         /* Load up the user's out registers so we can pull
 113          * a window from the stack, if necessary.
 114          */
 115         LOAD_PT_INS(sp)
 116 
 117         /* If there are already live user windows in the
 118          * set we can return from trap safely.
 119          */
 120         ld      [%twin_tmp2 + THREAD_UMASK], %twin_tmp1
 121         orcc    %g0, %twin_tmp1, %g0
 122         bne     ret_trap_userwins_ok
 123          nop
 124         
 125                 /* Calculate new %wim, we have to pull a register
 126                  * window from the users stack.
 127                  */
 128 ret_trap_pull_one_window:
 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         LEAVE_SYSCALL
 157 
 158         wr      %t_psr, 0x0, %psr
 159         WRITE_PAUSE
 160 
 161         jmp     %t_pc
 162         rett    %t_npc
 163         
 164 ret_trap_unaligned_pc:
 165         add     %sp, REGWIN_SZ, %o0
 166         ld      [%sp + REGWIN_SZ + PT_PC], %o1
 167         ld      [%sp + REGWIN_SZ + PT_NPC], %o2
 168         ld      [%sp + REGWIN_SZ + PT_PSR], %o3
 169 
 170         wr      %t_wim, 0x0, %wim               ! or else...
 171         WRITE_PAUSE
 172 
 173         wr      %t_psr, PSR_ET, %psr
 174         WRITE_PAUSE
 175 
 176         call    C_LABEL(do_memaccess_unaligned)
 177          nop
 178 
 179         b       ret_trap_entry                  ! maybe signal posted
 180          nop
 181 
 182 ret_trap_kernel:
 183         ld      [%sp + REGWIN_SZ + PT_PSR], %t_psr
 184         wr      %t_psr, 0x0, %psr
 185         WRITE_PAUSE
 186 
 187                 /* Will the rett land us in the invalid window? */
 188                 mov     2, %g1
 189                 sll     %g1, %t_psr, %g1
 190 rtrap_patch3:   srl     %g1, 8, %g2
 191                 or      %g1, %g2, %g1
 192                 rd      %wim, %g2
 193                 andcc   %g2, %g1, %g0
 194                 be      1f              ! Nope, just return from the trap
 195                  nop
 196 
 197                 /* We have to grab a window before returning. */
 198                 sll     %g2, 0x1, %g1
 199 rtrap_patch4:   srl     %g2, 7,  %g2
 200                 or      %g1, %g2, %g1
 201 rtrap_patch5:   and     %g1, 0xff, %g1
 202 
 203         wr      %g1, 0x0, %wim
 204         WRITE_PAUSE
 205 
 206         restore %g0, %g0, %g0
 207         LOAD_WINDOW(sp)
 208         save    %g0, %g0, %g0
 209 
 210         /* Reload the entire frame in case this is from a
 211          * kernel system call or whatever...
 212          */
 213 1:
 214         LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
 215 
 216         LEAVE_SYSCALL
 217 
 218         wr      %t_psr, 0x0, %psr
 219         WRITE_PAUSE
 220 
 221         jmp     %t_pc
 222         rett    %t_npc
 223 
 224 ret_trap_user_stack_is_bolixed:
 225         wr      %t_wim, 0x0, %wim
 226         WRITE_PAUSE
 227 
 228         wr      %t_psr, PSR_ET, %psr
 229         WRITE_PAUSE
 230 
 231         call    C_LABEL(window_ret_fault)
 232          add    %sp, REGWIN_SZ, %o0
 233 
 234         b       ret_trap_entry
 235          nop
 236 
 237         .globl  C_LABEL(sun4c_rett_stackchk)
 238 C_LABEL(sun4c_rett_stackchk):
 239         be      1f
 240          and    %fp, 0xfff, %g1         ! delay slot
 241 
 242         b       ret_trap_user_stack_is_bolixed
 243          nop
 244 
 245         /* See if we have to check the sanity of one page or two */
 246 1:
 247         add     %g1, 0x38, %g1
 248         sra     %fp, 29, %g2
 249         add     %g2, 0x1, %g2
 250         andncc  %g2, 0x1, %g0
 251         be      1f
 252          andncc %g1, 0xff8, %g0
 253 
 254         /* %sp is in vma hole, yuck */
 255         b       ret_trap_user_stack_is_bolixed
 256          nop
 257 
 258 1:
 259         be      sun4c_rett_onepage      /* Only one page to check */
 260          lda    [%fp] ASI_PTE, %g2
 261 
 262 sun4c_rett_twopages:
 263         add     %fp, 0x38, %g1
 264         sra     %g1, 29, %g2
 265         add     %g2, 0x1, %g2
 266         andncc  %g2, 0x1, %g0
 267         be      1f
 268          lda    [%g1] ASI_PTE, %g2
 269 
 270         /* Second page is in vma hole */
 271         b       ret_trap_user_stack_is_bolixed
 272          nop
 273 
 274 1:
 275         srl     %g2, 29, %g2
 276         andcc   %g2, 0x4, %g0
 277         bne     sun4c_rett_onepage
 278          lda    [%fp] ASI_PTE, %g2
 279 
 280         /* Second page has bad perms */
 281         b       ret_trap_user_stack_is_bolixed
 282          nop
 283 
 284 sun4c_rett_onepage:
 285         srl     %g2, 29, %g2
 286         andcc   %g2, 0x4, %g0
 287         bne     1f
 288          nop
 289 
 290         /* A page had bad page permissions, losing... */
 291         b       ret_trap_user_stack_is_bolixed
 292          nop
 293 
 294         /* Whee, things are ok, load the window and continue. */
 295 1:
 296         restore %g0, %g0, %g0
 297 
 298         LOAD_WINDOW(sp)
 299 
 300         save    %g0, %g0, %g0
 301         b       ret_trap_userwins_ok
 302          nop
 303 
 304         .globl  C_LABEL(srmmu_rett_stackchk)
 305 C_LABEL(srmmu_rett_stackchk):
 306         bne     ret_trap_user_stack_is_bolixed
 307          sethi  %hi(KERNBASE), %g1
 308         cmp     %g1, %fp
 309         bleu    ret_trap_user_stack_is_bolixed
 310          mov    AC_M_SFSR, %g1
 311         lda     [%g1] ASI_M_MMUREGS, %g0
 312 
 313         lda     [%g0] ASI_M_MMUREGS, %g1
 314         or      %g1, 0x2, %g1
 315         sta     %g1, [%g0] ASI_M_MMUREGS
 316 
 317         restore %g0, %g0, %g0
 318 
 319         LOAD_WINDOW(sp)
 320 
 321         save    %g0, %g0, %g0
 322 
 323         andn    %g1, 0x2, %g1
 324         sta     %g1, [%g0] ASI_M_MMUREGS
 325 
 326         mov     AC_M_SFAR, %g2
 327         lda     [%g2] ASI_M_MMUREGS, %g2
 328 
 329         mov     AC_M_SFSR, %g1
 330         lda     [%g1] ASI_M_MMUREGS, %g1
 331         andcc   %g1, 0x2, %g0
 332         bne     ret_trap_user_stack_is_bolixed
 333          nop
 334 
 335         b       ret_trap_userwins_ok
 336          nop

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