Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * rtrap.S: Return from Sparc trap low-level code.
0004  *
0005  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
0006  */
0007 
0008 #include <asm/page.h>
0009 #include <asm/ptrace.h>
0010 #include <asm/psr.h>
0011 #include <asm/asi.h>
0012 #include <asm/smp.h>
0013 #include <asm/contregs.h>
0014 #include <asm/winmacro.h>
0015 #include <asm/asmmacro.h>
0016 #include <asm/thread_info.h>
0017 
0018 #define t_psr     l0
0019 #define t_pc      l1
0020 #define t_npc     l2
0021 #define t_wim     l3
0022 #define twin_tmp1 l4
0023 #define glob_tmp  g4
0024 #define curptr    g6
0025 
0026     /* 7 WINDOW SPARC PATCH INSTRUCTIONS */
0027     .globl  rtrap_7win_patch1, rtrap_7win_patch2, rtrap_7win_patch3
0028     .globl  rtrap_7win_patch4, rtrap_7win_patch5
0029 rtrap_7win_patch1:  srl %t_wim, 0x6, %glob_tmp
0030 rtrap_7win_patch2:  and %glob_tmp, 0x7f, %glob_tmp
0031 rtrap_7win_patch3:  srl %g1, 7, %g2
0032 rtrap_7win_patch4:  srl %g2, 6, %g2
0033 rtrap_7win_patch5:  and %g1, 0x7f, %g1
0034     /* END OF PATCH INSTRUCTIONS */
0035 
0036     /* We need to check for a few things which are:
0037      * 1) The need to call schedule() because this
0038      *    processes quantum is up.
0039      * 2) Pending signals for this process, if any
0040      *    exist we need to call do_signal() to do
0041      *    the needy.
0042      *
0043      * Else we just check if the rett would land us
0044      * in an invalid window, if so we need to grab
0045      * it off the user/kernel stack first.
0046      */
0047 
0048     .globl  ret_trap_entry, rtrap_patch1, rtrap_patch2
0049     .globl  rtrap_patch3, rtrap_patch4, rtrap_patch5
0050     .globl  ret_trap_lockless_ipi
0051 ret_trap_entry:
0052 ret_trap_lockless_ipi:
0053     andcc   %t_psr, PSR_PS, %g0
0054     sethi   %hi(PSR_SYSCALL), %g1
0055     be  1f
0056      andn   %t_psr, %g1, %t_psr
0057 
0058     wr  %t_psr, 0x0, %psr
0059     b   ret_trap_kernel
0060      nop
0061 
0062 1:
0063     ld  [%curptr + TI_FLAGS], %g2
0064     andcc   %g2, (_TIF_NEED_RESCHED), %g0
0065     be  signal_p
0066      nop
0067 
0068     call    schedule
0069      nop
0070 
0071     ld  [%curptr + TI_FLAGS], %g2
0072 signal_p:
0073     andcc   %g2, _TIF_DO_NOTIFY_RESUME_MASK, %g0
0074     bz,a    ret_trap_continue
0075      ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
0076 
0077     mov %g2, %o2
0078     mov %l6, %o1
0079     call    do_notify_resume
0080      add    %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr
0081 
0082     b   signal_p
0083      ld [%curptr + TI_FLAGS], %g2
0084 
0085 ret_trap_continue:
0086     sethi   %hi(PSR_SYSCALL), %g1
0087     andn    %t_psr, %g1, %t_psr
0088     wr  %t_psr, 0x0, %psr
0089     WRITE_PAUSE
0090 
0091     ld  [%curptr + TI_W_SAVED], %twin_tmp1
0092     orcc    %g0, %twin_tmp1, %g0
0093     be  ret_trap_nobufwins
0094      nop
0095 
0096     wr  %t_psr, PSR_ET, %psr
0097     WRITE_PAUSE
0098 
0099     mov 1, %o1
0100     call    try_to_clear_window_buffer
0101      add    %sp, STACKFRAME_SZ, %o0
0102 
0103     b   signal_p
0104      ld [%curptr + TI_FLAGS], %g2
0105 
0106 ret_trap_nobufwins:
0107     /* Load up the user's out registers so we can pull
0108      * a window from the stack, if necessary.
0109      */
0110     LOAD_PT_INS(sp)
0111 
0112     /* If there are already live user windows in the
0113      * set we can return from trap safely.
0114      */
0115     ld  [%curptr + TI_UWINMASK], %twin_tmp1
0116     orcc    %g0, %twin_tmp1, %g0
0117     bne ret_trap_userwins_ok
0118      nop
0119 
0120         /* Calculate new %wim, we have to pull a register
0121          * window from the users stack.
0122          */
0123 ret_trap_pull_one_window:
0124         rd  %wim, %t_wim
0125         sll %t_wim, 0x1, %twin_tmp1
0126 rtrap_patch1:   srl %t_wim, 0x7, %glob_tmp
0127         or  %glob_tmp, %twin_tmp1, %glob_tmp
0128 rtrap_patch2:   and %glob_tmp, 0xff, %glob_tmp
0129 
0130         wr  %glob_tmp, 0x0, %wim
0131 
0132     /* Here comes the architecture specific
0133      * branch to the user stack checking routine
0134      * for return from traps.
0135      */
0136     b   srmmu_rett_stackchk
0137      andcc  %fp, 0x7, %g0
0138 
0139 ret_trap_userwins_ok:
0140     LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
0141     or  %t_pc, %t_npc, %g2
0142     andcc   %g2, 0x3, %g0
0143     sethi   %hi(PSR_SYSCALL), %g2
0144     be  1f
0145      andn   %t_psr, %g2, %t_psr
0146 
0147     b   ret_trap_unaligned_pc
0148      add    %sp, STACKFRAME_SZ, %o0
0149 
0150 1:
0151     LOAD_PT_YREG(sp, g1)
0152     LOAD_PT_GLOBALS(sp)
0153 
0154     wr  %t_psr, 0x0, %psr
0155     WRITE_PAUSE
0156 
0157     jmp %t_pc
0158     rett    %t_npc
0159     
0160 ret_trap_unaligned_pc:
0161     ld  [%sp + STACKFRAME_SZ + PT_PC], %o1
0162     ld  [%sp + STACKFRAME_SZ + PT_NPC], %o2
0163     ld  [%sp + STACKFRAME_SZ + PT_PSR], %o3
0164 
0165     wr  %t_wim, 0x0, %wim       ! or else...
0166 
0167     wr  %t_psr, PSR_ET, %psr
0168     WRITE_PAUSE
0169 
0170     call    do_memaccess_unaligned
0171      nop
0172 
0173     b   signal_p
0174      ld [%curptr + TI_FLAGS], %g2
0175 
0176 ret_trap_kernel:
0177         /* Will the rett land us in the invalid window? */
0178         mov 2, %g1
0179         sll %g1, %t_psr, %g1
0180 rtrap_patch3:   srl %g1, 8, %g2
0181         or  %g1, %g2, %g1
0182         rd  %wim, %g2
0183         andcc   %g2, %g1, %g0
0184         be  1f      ! Nope, just return from the trap
0185          sll    %g2, 0x1, %g1
0186 
0187         /* We have to grab a window before returning. */
0188 rtrap_patch4:   srl %g2, 7,  %g2
0189         or  %g1, %g2, %g1
0190 rtrap_patch5:   and %g1, 0xff, %g1
0191 
0192     wr  %g1, 0x0, %wim
0193 
0194     /* Grrr, make sure we load from the right %sp... */
0195     LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
0196 
0197     restore %g0, %g0, %g0
0198     LOAD_WINDOW(sp)
0199     b   2f
0200      save   %g0, %g0, %g0
0201 
0202     /* Reload the entire frame in case this is from a
0203      * kernel system call or whatever...
0204      */
0205 1:
0206     LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
0207 2:
0208     sethi   %hi(PSR_SYSCALL), %twin_tmp1
0209     andn    %t_psr, %twin_tmp1, %t_psr
0210     wr  %t_psr, 0x0, %psr
0211     WRITE_PAUSE
0212 
0213     jmp %t_pc
0214     rett    %t_npc
0215 
0216 ret_trap_user_stack_is_bolixed:
0217     wr  %t_wim, 0x0, %wim
0218 
0219     wr  %t_psr, PSR_ET, %psr
0220     WRITE_PAUSE
0221 
0222     call    window_ret_fault
0223      add    %sp, STACKFRAME_SZ, %o0
0224 
0225     b   signal_p
0226      ld [%curptr + TI_FLAGS], %g2
0227 
0228     .globl  srmmu_rett_stackchk
0229 srmmu_rett_stackchk:
0230     bne ret_trap_user_stack_is_bolixed
0231      sethi   %hi(PAGE_OFFSET), %g1
0232     cmp %g1, %fp
0233     bleu    ret_trap_user_stack_is_bolixed
0234      mov    AC_M_SFSR, %g1
0235 LEON_PI(lda [%g1] ASI_LEON_MMUREGS, %g0)
0236 SUN_PI_(lda [%g1] ASI_M_MMUREGS, %g0)
0237 
0238 LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %g1)
0239 SUN_PI_(lda [%g0] ASI_M_MMUREGS, %g1)
0240     or  %g1, 0x2, %g1
0241 LEON_PI(sta %g1, [%g0] ASI_LEON_MMUREGS)
0242 SUN_PI_(sta %g1, [%g0] ASI_M_MMUREGS)
0243 
0244     restore %g0, %g0, %g0
0245 
0246     LOAD_WINDOW(sp)
0247 
0248     save    %g0, %g0, %g0
0249 
0250     andn    %g1, 0x2, %g1
0251 LEON_PI(sta %g1, [%g0] ASI_LEON_MMUREGS)
0252 SUN_PI_(sta %g1, [%g0] ASI_M_MMUREGS)
0253 
0254     mov AC_M_SFAR, %g2
0255 LEON_PI(lda [%g2] ASI_LEON_MMUREGS, %g2)
0256 SUN_PI_(lda [%g2] ASI_M_MMUREGS, %g2)
0257 
0258     mov AC_M_SFSR, %g1
0259 LEON_PI(lda [%g1] ASI_LEON_MMUREGS, %g1)
0260 SUN_PI_(lda [%g1] ASI_M_MMUREGS, %g1)
0261     andcc   %g1, 0x2, %g0
0262     be  ret_trap_userwins_ok
0263      nop
0264 
0265     b,a ret_trap_user_stack_is_bolixed