Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / arch / sparc / kernel / rtrap.S
blobb4b0b5f7b45fb0ed5ceed07e249bb1866e3f32d0
1 /* $Id: rtrap.S,v 1.55 2000/08/05 10:48:40 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  */
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>
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
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, %glob_tmp
29 rtrap_7win_patch2:      and     %glob_tmp, 0x7f, %glob_tmp
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 */
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          */
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)
50 ret_trap_entry:
51         ld      [%curptr + AOFF_task_processor], %l3
52         sll     %l3, 5, %l3
53         sethi   %hi(C_LABEL(irq_stat)), %l4             ! &softirq_active
54         add     %l4, %l3, %l4
55         ld      [%l4 + %lo(C_LABEL(irq_stat))], %g5     ! softirq_active
56         ld      [%l4 + %lo(C_LABEL(irq_stat) + 4)], %g4 ! softirq_mask
57         andcc   %g4, %g5, %g0
58         be      C_LABEL(ret_trap_lockless_ipi)
59          nop
60         call    C_LABEL(do_softirq)
61          nop
62         
63 C_LABEL(ret_trap_lockless_ipi):
64         andcc   %t_psr, PSR_PS, %g0
65         be      1f
66          nop
68         wr      %t_psr, 0x0, %psr
69         b       ret_trap_kernel
70          nop
73         ld      [%curptr + AOFF_task_need_resched], %g2
74         orcc    %g2, %g0, %g0
75         be      signal_p
76          ld     [%curptr + AOFF_task_sigpending], %g2
78         call    C_LABEL(schedule)
79          nop
81         ld      [%curptr + AOFF_task_sigpending], %g2
82 signal_p:
83         cmp     %g2, 0
84         bz,a    ret_trap_continue
85          ld     [%sp + REGWIN_SZ + PT_PSR], %t_psr
87         clr     %o0
88         mov     %l5, %o2
89         mov     %l6, %o3
90         call    C_LABEL(do_signal)
91          add    %sp, REGWIN_SZ, %o1     ! pt_regs ptr
93         /* Fall through. */
94         ld      [%sp + REGWIN_SZ + PT_PSR], %t_psr
95         clr     %l6
96 ret_trap_continue:
97         wr      %t_psr, 0x0, %psr
98         WRITE_PAUSE
100         ld      [%curptr + AOFF_task_thread + AOFF_thread_w_saved], %twin_tmp1
101         orcc    %g0, %twin_tmp1, %g0
102         be      ret_trap_nobufwins
103          nop
105         wr      %t_psr, PSR_ET, %psr
106         WRITE_PAUSE
108         mov     1, %o1
109         call    C_LABEL(try_to_clear_window_buffer)
110          add    %sp, REGWIN_SZ, %o0
112         b       signal_p
113          ld     [%curptr + AOFF_task_sigpending], %g2
115 ret_trap_nobufwins:
116         /* Load up the user's out registers so we can pull
117          * a window from the stack, if necessary.
118          */
119         LOAD_PT_INS(sp)
121         /* If there are already live user windows in the
122          * set we can return from trap safely.
123          */
124         ld      [%curptr + AOFF_task_thread + AOFF_thread_uwinmask], %twin_tmp1
125         orcc    %g0, %twin_tmp1, %g0
126         bne     ret_trap_userwins_ok
127          nop
128         
129                 /* Calculate new %wim, we have to pull a register
130                  * window from the users stack.
131                  */
132 ret_trap_pull_one_window:
133                 rd      %wim, %t_wim
134                 sll     %t_wim, 0x1, %twin_tmp1
135 rtrap_patch1:   srl     %t_wim, 0x7, %glob_tmp
136                 or      %glob_tmp, %twin_tmp1, %glob_tmp
137 rtrap_patch2:   and     %glob_tmp, 0xff, %glob_tmp
139                 wr      %glob_tmp, 0x0, %wim
141                                 /* Here comes the architecture specific 
142                                  * branch to the user stack checking routine
143                                  * for return from traps.
144                                  */
145                                 .globl  C_LABEL(rtrap_mmu_patchme)
146 C_LABEL(rtrap_mmu_patchme):     b       C_LABEL(sun4c_rett_stackchk)
147                                  andcc  %fp, 0x7, %g0   
149 ret_trap_userwins_ok:
150         LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
151         or      %t_pc, %t_npc, %g2
152         andcc   %g2, 0x3, %g0
153         be      1f
154          nop
156         b       ret_trap_unaligned_pc
157          add    %sp, REGWIN_SZ, %o0
160         LOAD_PT_YREG(sp, g1)
161         LOAD_PT_GLOBALS(sp)
163         wr      %t_psr, 0x0, %psr
164         WRITE_PAUSE
166         jmp     %t_pc
167         rett    %t_npc
168         
169 ret_trap_unaligned_pc:
170         ld      [%sp + REGWIN_SZ + PT_PC], %o1
171         ld      [%sp + REGWIN_SZ + PT_NPC], %o2
172         ld      [%sp + REGWIN_SZ + PT_PSR], %o3
174         wr      %t_wim, 0x0, %wim               ! or else...
176         wr      %t_psr, PSR_ET, %psr
177         WRITE_PAUSE
179         call    C_LABEL(do_memaccess_unaligned)
180          nop
182         b       signal_p
183          ld     [%curptr + AOFF_task_sigpending], %g2
185 ret_trap_kernel:
186                 /* Will the rett land us in the invalid window? */
187                 mov     2, %g1
188                 sll     %g1, %t_psr, %g1
189 rtrap_patch3:   srl     %g1, 8, %g2
190                 or      %g1, %g2, %g1
191                 rd      %wim, %g2
192                 andcc   %g2, %g1, %g0
193                 be      1f              ! Nope, just return from the trap
194                  sll    %g2, 0x1, %g1
196                 /* We have to grab a window before returning. */
197 rtrap_patch4:   srl     %g2, 7,  %g2
198                 or      %g1, %g2, %g1
199 rtrap_patch5:   and     %g1, 0xff, %g1
201         wr      %g1, 0x0, %wim
203         /* Grrr, make sure we load from the right %sp... */
204         LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
206         restore %g0, %g0, %g0
207         LOAD_WINDOW(sp)
208         b       2f
209          save   %g0, %g0, %g0
211         /* Reload the entire frame in case this is from a
212          * kernel system call or whatever...
213          */
215         LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
217         wr      %t_psr, 0x0, %psr
218         WRITE_PAUSE
220         jmp     %t_pc
221         rett    %t_npc
223 ret_trap_user_stack_is_bolixed:
224         wr      %t_wim, 0x0, %wim
226         wr      %t_psr, PSR_ET, %psr
227         WRITE_PAUSE
229         call    C_LABEL(window_ret_fault)
230          add    %sp, REGWIN_SZ, %o0
232         b       signal_p
233          ld     [%curptr + AOFF_task_sigpending], %g2
235         .globl  C_LABEL(sun4c_rett_stackchk)
236 C_LABEL(sun4c_rett_stackchk):
237         be      1f
238          and    %fp, 0xfff, %g1         ! delay slot
240         b       ret_trap_user_stack_is_bolixed + 0x4
241          wr     %t_wim, 0x0, %wim
243         /* See if we have to check the sanity of one page or two */
245         add     %g1, 0x38, %g1
246         sra     %fp, 29, %g2
247         add     %g2, 0x1, %g2
248         andncc  %g2, 0x1, %g0
249         be      1f
250          andncc %g1, 0xff8, %g0
252         /* %sp is in vma hole, yuck */
253         b       ret_trap_user_stack_is_bolixed + 0x4
254          wr     %t_wim, 0x0, %wim
257         be      sun4c_rett_onepage      /* Only one page to check */
258          lda    [%fp] ASI_PTE, %g2
260 sun4c_rett_twopages:
261         add     %fp, 0x38, %g1
262         sra     %g1, 29, %g2
263         add     %g2, 0x1, %g2
264         andncc  %g2, 0x1, %g0
265         be      1f
266          lda    [%g1] ASI_PTE, %g2
268         /* Second page is in vma hole */
269         b       ret_trap_user_stack_is_bolixed + 0x4
270          wr     %t_wim, 0x0, %wim
273         srl     %g2, 29, %g2
274         andcc   %g2, 0x4, %g0
275         bne     sun4c_rett_onepage
276          lda    [%fp] ASI_PTE, %g2
278         /* Second page has bad perms */
279         b       ret_trap_user_stack_is_bolixed + 0x4
280          wr     %t_wim, 0x0, %wim
282 sun4c_rett_onepage:
283         srl     %g2, 29, %g2
284         andcc   %g2, 0x4, %g0
285         bne,a   1f
286          restore %g0, %g0, %g0
288         /* A page had bad page permissions, losing... */
289         b       ret_trap_user_stack_is_bolixed + 0x4
290          wr     %t_wim, 0x0, %wim
292         /* Whee, things are ok, load the window and continue. */
294         LOAD_WINDOW(sp)
296         b       ret_trap_userwins_ok
297          save   %g0, %g0, %g0
299         .globl  C_LABEL(srmmu_rett_stackchk)
300 C_LABEL(srmmu_rett_stackchk):
301         bne     ret_trap_user_stack_is_bolixed
302          sethi   %hi(PAGE_OFFSET), %g1
303         cmp     %g1, %fp
304         bleu    ret_trap_user_stack_is_bolixed
305          mov    AC_M_SFSR, %g1
306         lda     [%g1] ASI_M_MMUREGS, %g0
308         lda     [%g0] ASI_M_MMUREGS, %g1
309         or      %g1, 0x2, %g1
310         sta     %g1, [%g0] ASI_M_MMUREGS
312         restore %g0, %g0, %g0
314         LOAD_WINDOW(sp)
316         save    %g0, %g0, %g0
318         andn    %g1, 0x2, %g1
319         sta     %g1, [%g0] ASI_M_MMUREGS
321         mov     AC_M_SFAR, %g2
322         lda     [%g2] ASI_M_MMUREGS, %g2
324         mov     AC_M_SFSR, %g1
325         lda     [%g1] ASI_M_MMUREGS, %g1
326         andcc   %g1, 0x2, %g0
327         be      ret_trap_userwins_ok
328          nop
330         b,a     ret_trap_user_stack_is_bolixed