1/* $Id: rtrap.S,v 1.57 2001/07/17 16:17:33 anton 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 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 C_LABEL(ret_trap_lockless_ipi) 50ret_trap_entry: 51C_LABEL(ret_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 + AOFF_task_need_resched], %g2 62 orcc %g2, %g0, %g0 63 be signal_p 64 ld [%curptr + AOFF_task_sigpending], %g2 65 66 call C_LABEL(schedule) 67 nop 68 69 ld [%curptr + AOFF_task_sigpending], %g2 70signal_p: 71 cmp %g2, 0 72 bz,a ret_trap_continue 73 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr 74 75 clr %o0 76 mov %l5, %o2 77 mov %l6, %o3 78 call C_LABEL(do_signal) 79 add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr 80 81 /* Fall through. */ 82 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr 83 clr %l6 84ret_trap_continue: 85 wr %t_psr, 0x0, %psr 86 WRITE_PAUSE 87 88 ld [%curptr + AOFF_task_thread + AOFF_thread_w_saved], %twin_tmp1 89 orcc %g0, %twin_tmp1, %g0 90 be ret_trap_nobufwins 91 nop 92 93 wr %t_psr, PSR_ET, %psr 94 WRITE_PAUSE 95 96 mov 1, %o1 97 call C_LABEL(try_to_clear_window_buffer) 98 add %sp, STACKFRAME_SZ, %o0 99 100 b signal_p 101 ld [%curptr + AOFF_task_sigpending], %g2 102 103ret_trap_nobufwins: 104 /* Load up the user's out registers so we can pull 105 * a window from the stack, if necessary. 106 */ 107 LOAD_PT_INS(sp) 108 109 /* If there are already live user windows in the 110 * set we can return from trap safely. 111 */ 112 ld [%curptr + AOFF_task_thread + AOFF_thread_uwinmask], %twin_tmp1 113 orcc %g0, %twin_tmp1, %g0 114 bne ret_trap_userwins_ok 115 nop 116 117 /* Calculate new %wim, we have to pull a register 118 * window from the users stack. 119 */ 120ret_trap_pull_one_window: 121 rd %wim, %t_wim 122 sll %t_wim, 0x1, %twin_tmp1 123rtrap_patch1: srl %t_wim, 0x7, %glob_tmp 124 or %glob_tmp, %twin_tmp1, %glob_tmp 125rtrap_patch2: and %glob_tmp, 0xff, %glob_tmp 126 127 wr %glob_tmp, 0x0, %wim 128 129 /* Here comes the architecture specific 130 * branch to the user stack checking routine 131 * for return from traps. 132 */ 133 .globl C_LABEL(rtrap_mmu_patchme) 134C_LABEL(rtrap_mmu_patchme): b C_LABEL(sun4c_rett_stackchk) 135 andcc %fp, 0x7, %g0 136 137ret_trap_userwins_ok: 138 LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc) 139 or %t_pc, %t_npc, %g2 140 andcc %g2, 0x3, %g0 141 be 1f 142 nop 143 144 b ret_trap_unaligned_pc 145 add %sp, STACKFRAME_SZ, %o0 146 1471: 148 LOAD_PT_YREG(sp, g1) 149 LOAD_PT_GLOBALS(sp) 150 151 wr %t_psr, 0x0, %psr 152 WRITE_PAUSE 153 154 jmp %t_pc 155 rett %t_npc 156 157ret_trap_unaligned_pc: 158 ld [%sp + STACKFRAME_SZ + PT_PC], %o1 159 ld [%sp + STACKFRAME_SZ + PT_NPC], %o2 160 ld [%sp + STACKFRAME_SZ + PT_PSR], %o3 161 162 wr %t_wim, 0x0, %wim ! or else... 163 164 wr %t_psr, PSR_ET, %psr 165 WRITE_PAUSE 166 167 call C_LABEL(do_memaccess_unaligned) 168 nop 169 170 b signal_p 171 ld [%curptr + AOFF_task_sigpending], %g2 172 173ret_trap_kernel: 174 /* Will the rett land us in the invalid window? */ 175 mov 2, %g1 176 sll %g1, %t_psr, %g1 177rtrap_patch3: srl %g1, 8, %g2 178 or %g1, %g2, %g1 179 rd %wim, %g2 180 andcc %g2, %g1, %g0 181 be 1f ! Nope, just return from the trap 182 sll %g2, 0x1, %g1 183 184 /* We have to grab a window before returning. */ 185rtrap_patch4: srl %g2, 7, %g2 186 or %g1, %g2, %g1 187rtrap_patch5: and %g1, 0xff, %g1 188 189 wr %g1, 0x0, %wim 190 191 /* Grrr, make sure we load from the right %sp... */ 192 LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1) 193 194 restore %g0, %g0, %g0 195 LOAD_WINDOW(sp) 196 b 2f 197 save %g0, %g0, %g0 198 199 /* Reload the entire frame in case this is from a 200 * kernel system call or whatever... 201 */ 2021: 203 LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1) 2042: 205 wr %t_psr, 0x0, %psr 206 WRITE_PAUSE 207 208 jmp %t_pc 209 rett %t_npc 210 211ret_trap_user_stack_is_bolixed: 212 wr %t_wim, 0x0, %wim 213 214 wr %t_psr, PSR_ET, %psr 215 WRITE_PAUSE 216 217 call C_LABEL(window_ret_fault) 218 add %sp, STACKFRAME_SZ, %o0 219 220 b signal_p 221 ld [%curptr + AOFF_task_sigpending], %g2 222 223 .globl C_LABEL(sun4c_rett_stackchk) 224C_LABEL(sun4c_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 C_LABEL(srmmu_rett_stackchk) 288C_LABEL(srmmu_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