1/* $Id: rtrap.S,v 1.1.1.1 2007-08-03 18:52:17 $ 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