diff options
Diffstat (limited to 'arch/sparc64/kernel/rtrap.S')
-rw-r--r-- | arch/sparc64/kernel/rtrap.S | 63 |
1 files changed, 56 insertions, 7 deletions
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index 85732960f..a3137ee50 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.39 1998/07/26 03:02:49 davem Exp $ +/* $Id: rtrap.S,v 1.45 1998/11/09 15:33:29 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -46,13 +46,15 @@ rtrap: sethi %hi(bh_active), %l2 ldub [%l6 + %o0], %l2 sub %l5, 2, %l5 add %g6, AOFF_task_tss + AOFF_thread_gsr, %o1 - andcc %l2, FPRS_FEF, %g0 + andcc %l2, (FPRS_FEF|FPRS_DU), %g0 be,pt %icc, 2f and %l2, FPRS_DL, %l6 + andcc %l2, FPRS_FEF, %g0 + be,pn %icc, 5f + sll %o0, 3, %o5 rd %fprs, %g5 wr %g5, FPRS_FEF, %fprs ldub [%o1 + %o0], %g5 - sll %o0, 3, %o5 add %g6, AOFF_task_tss + AOFF_thread_xfsr, %o1 membar #StoreLoad | #LoadLoad sll %o0, 8, %o2 @@ -130,21 +132,56 @@ to_user: ldx [%g6 + AOFF_task_need_resched], %l0 nop lduw [%g6 + AOFF_task_sigpending], %l0 check_signal: brz,a,pt %l0, check_user_wins - lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 + nop clr %o0 mov %l5, %o2 mov %l6, %o3 call do_signal add %sp, STACK_BIAS + REGWIN_SZ, %o1 - lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 clr %l6 -check_user_wins:brz,pt %o2, 1f + + /* We must not take any traps between here and the actual + * return to user-space. If we do we risk having windows + * saved to the thread struct between the test and the + * actual return from trap. --DaveM + */ +check_user_wins: + wrpr %l7, 0x0, %pstate + lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 + brz,pt %o2, 1f sethi %hi(TSTATE_PEF), %l6 + wrpr %l7, PSTATE_IE, %pstate call fault_in_user_windows add %sp, STACK_BIAS + REGWIN_SZ, %o0 + /* It is OK to leave interrupts on now because if + * fault_in_user_windows has returned it has left us + * with a clean user stack state. + */ +1: +#if 0 + call rtrap_check + add %sp, STACK_BIAS + REGWIN_SZ, %o0 +#endif + lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %l5 + andcc %l5, 0x200, %g0 + be,pt %xcc, 1f + nop -1: andcc %l1, %l6, %g0 + /* Don't forget to preserve user window invariants. */ + wrpr %l7, PSTATE_IE, %pstate + call update_perfctrs + nop + wrpr %l7, 0x0, %pstate + lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 + brz,pt %o2, 1f + sethi %hi(TSTATE_PEF), %l6 + wrpr %l7, PSTATE_IE, %pstate + call fault_in_user_windows + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + +1: + andcc %l1, %l6, %g0 be,pt %xcc, rt_continue stb %g0, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only @@ -155,4 +192,16 @@ check_user_wins:brz,pt %o2, 1f ba,pt %xcc, rt_continue+4 lduh [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0 +5: wr %g0, FPRS_FEF, %fprs + membar #StoreLoad | #LoadLoad + sll %o0, 8, %o2 + add %g6, AOFF_task_fpregs+0x80, %o3 + add %g6, AOFF_task_fpregs+0xc0, %o4 + ldda [%o3 + %o2] ASI_BLK_P, %f32 + ldda [%o4 + %o2] ASI_BLK_P, %f48 +1: membar #Sync + wr %g0, FPRS_DU, %fprs + ba,pt %xcc, rt_continue + stb %l5, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth] + #undef PTREGS_OFF |