ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / sparc64 / kernel / winfixup.S
1 /* $Id: winfixup.S,v 1.30 2002/02/09 19:49:30 davem Exp $
2  *
3  * winfixup.S: Handle cases where user stack pointer is found to be bogus.
4  *
5  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
6  */
7
8 #include <asm/asi.h>
9 #include <asm/head.h>
10 #include <asm/page.h>
11 #include <asm/ptrace.h>
12 #include <asm/processor.h>
13 #include <asm/spitfire.h>
14 #include <asm/thread_info.h>
15
16         .text
17         .align  32
18
19         /* Here are the rules, pay attention.
20          *
21          * The kernel is disallowed from touching user space while
22          * the trap level is greater than zero, except for from within
23          * the window spill/fill handlers.  This must be followed
24          * so that we can easily detect the case where we tried to
25          * spill/fill with a bogus (or unmapped) user stack pointer.
26          *
27          * These are layed out in a special way for cache reasons,
28          * don't touch...
29          */
30         .globl  fill_fixup, spill_fixup
31 fill_fixup:
32         rdpr            %tstate, %g1
33         andcc           %g1, TSTATE_PRIV, %g0
34         or              %g4, FAULT_CODE_WINFIXUP, %g4
35         be,pt           %xcc, window_scheisse_from_user_common
36          and            %g1, TSTATE_CWP, %g1
37
38         /* This is the extremely complex case, but it does happen from
39          * time to time if things are just right.  Essentially the restore
40          * done in rtrap right before going back to user mode, with tl=1
41          * and that levels trap stack registers all setup, took a fill trap,
42          * the user stack was not mapped in the tlb, and tlb miss occurred,
43          * the pte found was not valid, and a simple ref bit watch update
44          * could not satisfy the miss, so we got here.
45          *
46          * We must carefully unwind the state so we get back to tl=0, preserve
47          * all the register values we were going to give to the user.  Luckily
48          * most things are where they need to be, we also have the address
49          * which triggered the fault handy as well.
50          *
51          * Also note that we must preserve %l5 and %l6.  If the user was
52          * returning from a system call, we must make it look this way
53          * after we process the fill fault on the users stack.
54          *
55          * First, get into the window where the original restore was executed.
56          */
57
58         rdpr            %wstate, %g2                    ! Grab user mode wstate.
59         wrpr            %g1, %cwp                       ! Get into the right window.
60         sll             %g2, 3, %g2                     ! NORMAL-->OTHER
61
62         wrpr            %g0, 0x0, %canrestore           ! Standard etrap stuff.
63         wrpr            %g2, 0x0, %wstate               ! This must be consistent.
64         wrpr            %g0, 0x0, %otherwin             ! We know this.
65         mov             PRIMARY_CONTEXT, %g1            ! Change contexts...
66         stxa            %g0, [%g1] ASI_DMMU             ! Back into the nucleus.
67         flush           %g6                             ! Flush instruction buffers
68         rdpr            %pstate, %l1                    ! Prepare to change globals.
69         mov             %g6, %o7                        ! Get current.
70
71         andn            %l1, PSTATE_MM, %l1             ! We want to be in RMO
72         stb             %g4, [%g6 + TI_FAULT_CODE]
73         stx             %g5, [%g6 + TI_FAULT_ADDR]
74         wrpr            %g0, 0x0, %tl                   ! Out of trap levels.
75         wrpr            %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
76         mov             %o7, %g6
77         ldx             [%g6 + TI_TASK], %g4
78
79         /* This is the same as below, except we handle this a bit special
80          * since we must preserve %l5 and %l6, see comment above.
81          */
82         call            do_sparc64_fault
83          add            %sp, PTREGS_OFF, %o0
84         ba,pt           %xcc, rtrap
85          nop                                            ! yes, nop is correct
86
87         /* Be very careful about usage of the alternate globals here.
88          * You cannot touch %g4/%g5 as that has the fault information
89          * should this be from usermode.  Also be careful for the case
90          * where we get here from the save instruction in etrap.S when
91          * coming from either user or kernel (does not matter which, it
92          * is the same problem in both cases).  Essentially this means
93          * do not touch %g7 or %g2 so we handle the two cases fine.
94          */
95 spill_fixup:
96         ldx             [%g6 + TI_FLAGS], %g1
97         andcc           %g1, _TIF_32BIT, %g0
98         ldub            [%g6 + TI_WSAVED], %g1
99
100         sll             %g1, 3, %g3
101         add             %g6, %g3, %g3
102         stx             %sp, [%g3 + TI_RWIN_SPTRS]
103         sll             %g1, 7, %g3
104         bne,pt          %xcc, 1f
105          add            %g6, %g3, %g3
106         stx             %l0, [%g3 + TI_REG_WINDOW + 0x00]
107         stx             %l1, [%g3 + TI_REG_WINDOW + 0x08]
108
109         stx             %l2, [%g3 + TI_REG_WINDOW + 0x10]
110         stx             %l3, [%g3 + TI_REG_WINDOW + 0x18]
111         stx             %l4, [%g3 + TI_REG_WINDOW + 0x20]
112         stx             %l5, [%g3 + TI_REG_WINDOW + 0x28]
113         stx             %l6, [%g3 + TI_REG_WINDOW + 0x30]
114         stx             %l7, [%g3 + TI_REG_WINDOW + 0x38]
115         stx             %i0, [%g3 + TI_REG_WINDOW + 0x40]
116         stx             %i1, [%g3 + TI_REG_WINDOW + 0x48]
117
118         stx             %i2, [%g3 + TI_REG_WINDOW + 0x50]
119         stx             %i3, [%g3 + TI_REG_WINDOW + 0x58]
120         stx             %i4, [%g3 + TI_REG_WINDOW + 0x60]
121         stx             %i5, [%g3 + TI_REG_WINDOW + 0x68]
122         stx             %i6, [%g3 + TI_REG_WINDOW + 0x70]
123         b,pt            %xcc, 2f
124          stx            %i7, [%g3 + TI_REG_WINDOW + 0x78]
125 1:      stw             %l0, [%g3 + TI_REG_WINDOW + 0x00]
126
127         stw             %l1, [%g3 + TI_REG_WINDOW + 0x04]
128         stw             %l2, [%g3 + TI_REG_WINDOW + 0x08]
129         stw             %l3, [%g3 + TI_REG_WINDOW + 0x0c]
130         stw             %l4, [%g3 + TI_REG_WINDOW + 0x10]
131         stw             %l5, [%g3 + TI_REG_WINDOW + 0x14]
132         stw             %l6, [%g3 + TI_REG_WINDOW + 0x18]
133         stw             %l7, [%g3 + TI_REG_WINDOW + 0x1c]
134         stw             %i0, [%g3 + TI_REG_WINDOW + 0x20]
135
136         stw             %i1, [%g3 + TI_REG_WINDOW + 0x24]
137         stw             %i2, [%g3 + TI_REG_WINDOW + 0x28]
138         stw             %i3, [%g3 + TI_REG_WINDOW + 0x2c]
139         stw             %i4, [%g3 + TI_REG_WINDOW + 0x30]
140         stw             %i5, [%g3 + TI_REG_WINDOW + 0x34]
141         stw             %i6, [%g3 + TI_REG_WINDOW + 0x38]
142         stw             %i7, [%g3 + TI_REG_WINDOW + 0x3c]
143 2:      add             %g1, 1, %g1
144
145         stb             %g1, [%g6 + TI_WSAVED]
146         rdpr            %tstate, %g1
147         andcc           %g1, TSTATE_PRIV, %g0
148         saved
149         and             %g1, TSTATE_CWP, %g1
150         be,pn           %xcc, window_scheisse_from_user_common
151          mov            FAULT_CODE_WRITE | FAULT_CODE_DTLB | FAULT_CODE_WINFIXUP, %g4
152         retry
153
154 window_scheisse_from_user_common:
155         stb             %g4, [%g6 + TI_FAULT_CODE]
156         stx             %g5, [%g6 + TI_FAULT_ADDR]
157         wrpr            %g1, %cwp
158         ba,pt           %xcc, etrap
159          rd             %pc, %g7
160         call            do_sparc64_fault
161          add            %sp, PTREGS_OFF, %o0
162         ba,a,pt         %xcc, rtrap_clr_l6
163
164         .globl          winfix_mna, fill_fixup_mna, spill_fixup_mna
165 winfix_mna:
166         andn            %g3, 0x7f, %g3
167         add             %g3, 0x78, %g3
168         wrpr            %g3, %tnpc
169         done
170 fill_fixup_mna:
171         rdpr            %tstate, %g1
172         andcc           %g1, TSTATE_PRIV, %g0
173         be,pt           %xcc, window_mna_from_user_common
174          and            %g1, TSTATE_CWP, %g1
175
176         /* Please, see fill_fixup commentary about why we must preserve
177          * %l5 and %l6 to preserve absolute correct semantics.
178          */
179         rdpr            %wstate, %g2                    ! Grab user mode wstate.
180         wrpr            %g1, %cwp                       ! Get into the right window.
181         sll             %g2, 3, %g2                     ! NORMAL-->OTHER
182         wrpr            %g0, 0x0, %canrestore           ! Standard etrap stuff.
183
184         wrpr            %g2, 0x0, %wstate               ! This must be consistent.
185         wrpr            %g0, 0x0, %otherwin             ! We know this.
186         mov             PRIMARY_CONTEXT, %g1            ! Change contexts...
187         stxa            %g0, [%g1] ASI_DMMU             ! Back into the nucleus.
188         flush           %g6                             ! Flush instruction buffers
189         rdpr            %pstate, %l1                    ! Prepare to change globals.
190         mov             %g4, %o2                        ! Setup args for
191         mov             %g5, %o1                        ! final call to mem_address_unaligned.
192         andn            %l1, PSTATE_MM, %l1             ! We want to be in RMO
193
194         mov             %g6, %o7                        ! Stash away current.
195         wrpr            %g0, 0x0, %tl                   ! Out of trap levels.
196         wrpr            %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
197         mov             %o7, %g6                        ! Get current back.
198         ldx             [%g6 + TI_TASK], %g4            ! Finish it.
199         call            mem_address_unaligned
200          add            %sp, PTREGS_OFF, %o0
201
202         b,pt            %xcc, rtrap
203          nop                                            ! yes, the nop is correct
204 spill_fixup_mna:
205         ldx             [%g6 + TI_FLAGS], %g1
206         andcc           %g1, _TIF_32BIT, %g0
207         ldub            [%g6 + TI_WSAVED], %g1
208         sll             %g1, 3, %g3
209         add             %g6, %g3, %g3
210         stx             %sp, [%g3 + TI_RWIN_SPTRS]
211
212         sll             %g1, 7, %g3
213         bne,pt          %xcc, 1f
214          add            %g6, %g3, %g3
215         stx             %l0, [%g3 + TI_REG_WINDOW + 0x00]
216         stx             %l1, [%g3 + TI_REG_WINDOW + 0x08]
217         stx             %l2, [%g3 + TI_REG_WINDOW + 0x10]
218         stx             %l3, [%g3 + TI_REG_WINDOW + 0x18]
219         stx             %l4, [%g3 + TI_REG_WINDOW + 0x20]
220
221         stx             %l5, [%g3 + TI_REG_WINDOW + 0x28]
222         stx             %l6, [%g3 + TI_REG_WINDOW + 0x30]
223         stx             %l7, [%g3 + TI_REG_WINDOW + 0x38]
224         stx             %i0, [%g3 + TI_REG_WINDOW + 0x40]
225         stx             %i1, [%g3 + TI_REG_WINDOW + 0x48]
226         stx             %i2, [%g3 + TI_REG_WINDOW + 0x50]
227         stx             %i3, [%g3 + TI_REG_WINDOW + 0x58]
228         stx             %i4, [%g3 + TI_REG_WINDOW + 0x60]
229
230         stx             %i5, [%g3 + TI_REG_WINDOW + 0x68]
231         stx             %i6, [%g3 + TI_REG_WINDOW + 0x70]
232         stx             %i7, [%g3 + TI_REG_WINDOW + 0x78]
233         b,pt            %xcc, 2f
234          add            %g1, 1, %g1
235 1:      std             %l0, [%g3 + TI_REG_WINDOW + 0x00]
236         std             %l2, [%g3 + TI_REG_WINDOW + 0x08]
237         std             %l4, [%g3 + TI_REG_WINDOW + 0x10]
238
239         std             %l6, [%g3 + TI_REG_WINDOW + 0x18]
240         std             %i0, [%g3 + TI_REG_WINDOW + 0x20]
241         std             %i2, [%g3 + TI_REG_WINDOW + 0x28]
242         std             %i4, [%g3 + TI_REG_WINDOW + 0x30]
243         std             %i6, [%g3 + TI_REG_WINDOW + 0x38]
244         add             %g1, 1, %g1
245 2:      stb             %g1, [%g6 + TI_WSAVED]
246         rdpr            %tstate, %g1
247
248         andcc           %g1, TSTATE_PRIV, %g0
249         saved
250         be,pn           %xcc, window_mna_from_user_common
251          and            %g1, TSTATE_CWP, %g1
252         retry
253 window_mna_from_user_common:
254         wrpr            %g1, %cwp
255         sethi           %hi(109f), %g7
256         ba,pt           %xcc, etrap
257 109:     or             %g7, %lo(109b), %g7
258         mov             %l4, %o2
259         mov             %l5, %o1
260         call            mem_address_unaligned
261          add            %sp, PTREGS_OFF, %o0
262         ba,pt           %xcc, rtrap
263          clr            %l6
264         
265         /* These are only needed for 64-bit mode processes which
266          * put their stack pointer into the VPTE area and there
267          * happens to be a VPTE tlb entry mapped there during
268          * a spill/fill trap to that stack frame.
269          */
270         .globl          winfix_dax, fill_fixup_dax, spill_fixup_dax
271 winfix_dax:
272         andn            %g3, 0x7f, %g3
273         add             %g3, 0x74, %g3
274         wrpr            %g3, %tnpc
275         done
276 fill_fixup_dax:
277         rdpr            %tstate, %g1
278         andcc           %g1, TSTATE_PRIV, %g0
279         be,pt           %xcc, window_dax_from_user_common
280          and            %g1, TSTATE_CWP, %g1
281
282         /* Please, see fill_fixup commentary about why we must preserve
283          * %l5 and %l6 to preserve absolute correct semantics.
284          */
285         rdpr            %wstate, %g2                    ! Grab user mode wstate.
286         wrpr            %g1, %cwp                       ! Get into the right window.
287         sll             %g2, 3, %g2                     ! NORMAL-->OTHER
288         wrpr            %g0, 0x0, %canrestore           ! Standard etrap stuff.
289
290         wrpr            %g2, 0x0, %wstate               ! This must be consistent.
291         wrpr            %g0, 0x0, %otherwin             ! We know this.
292         mov             PRIMARY_CONTEXT, %g1            ! Change contexts...
293         stxa            %g0, [%g1] ASI_DMMU             ! Back into the nucleus.
294         flush           %g6                             ! Flush instruction buffers
295         rdpr            %pstate, %l1                    ! Prepare to change globals.
296         mov             %g4, %o1                        ! Setup args for
297         mov             %g5, %o2                        ! final call to data_access_exception.
298         andn            %l1, PSTATE_MM, %l1             ! We want to be in RMO
299
300         mov             %g6, %o7                        ! Stash away current.
301         wrpr            %g0, 0x0, %tl                   ! Out of trap levels.
302         wrpr            %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
303         mov             %o7, %g6                        ! Get current back.
304         ldx             [%g6 + TI_TASK], %g4            ! Finish it.
305         call            data_access_exception
306          add            %sp, PTREGS_OFF, %o0
307
308         b,pt            %xcc, rtrap
309          nop                                            ! yes, the nop is correct
310 spill_fixup_dax:
311         ldx             [%g6 + TI_FLAGS], %g1
312         andcc           %g1, _TIF_32BIT, %g0
313         ldub            [%g6 + TI_WSAVED], %g1
314         sll             %g1, 3, %g3
315         add             %g6, %g3, %g3
316         stx             %sp, [%g3 + TI_RWIN_SPTRS]
317
318         sll             %g1, 7, %g3
319         bne,pt          %xcc, 1f
320          add            %g6, %g3, %g3
321         stx             %l0, [%g3 + TI_REG_WINDOW + 0x00]
322         stx             %l1, [%g3 + TI_REG_WINDOW + 0x08]
323         stx             %l2, [%g3 + TI_REG_WINDOW + 0x10]
324         stx             %l3, [%g3 + TI_REG_WINDOW + 0x18]
325         stx             %l4, [%g3 + TI_REG_WINDOW + 0x20]
326
327         stx             %l5, [%g3 + TI_REG_WINDOW + 0x28]
328         stx             %l6, [%g3 + TI_REG_WINDOW + 0x30]
329         stx             %l7, [%g3 + TI_REG_WINDOW + 0x38]
330         stx             %i0, [%g3 + TI_REG_WINDOW + 0x40]
331         stx             %i1, [%g3 + TI_REG_WINDOW + 0x48]
332         stx             %i2, [%g3 + TI_REG_WINDOW + 0x50]
333         stx             %i3, [%g3 + TI_REG_WINDOW + 0x58]
334         stx             %i4, [%g3 + TI_REG_WINDOW + 0x60]
335
336         stx             %i5, [%g3 + TI_REG_WINDOW + 0x68]
337         stx             %i6, [%g3 + TI_REG_WINDOW + 0x70]
338         stx             %i7, [%g3 + TI_REG_WINDOW + 0x78]
339         b,pt            %xcc, 2f
340          add            %g1, 1, %g1
341 1:      std             %l0, [%g3 + TI_REG_WINDOW + 0x00]
342         std             %l2, [%g3 + TI_REG_WINDOW + 0x08]
343         std             %l4, [%g3 + TI_REG_WINDOW + 0x10]
344
345         std             %l6, [%g3 + TI_REG_WINDOW + 0x18]
346         std             %i0, [%g3 + TI_REG_WINDOW + 0x20]
347         std             %i2, [%g3 + TI_REG_WINDOW + 0x28]
348         std             %i4, [%g3 + TI_REG_WINDOW + 0x30]
349         std             %i6, [%g3 + TI_REG_WINDOW + 0x38]
350         add             %g1, 1, %g1
351 2:      stb             %g1, [%g6 + TI_WSAVED]
352         rdpr            %tstate, %g1
353
354         andcc           %g1, TSTATE_PRIV, %g0
355         saved
356         be,pn           %xcc, window_dax_from_user_common
357          and            %g1, TSTATE_CWP, %g1
358         retry
359 window_dax_from_user_common:
360         wrpr            %g1, %cwp
361         sethi           %hi(109f), %g7
362         ba,pt           %xcc, etrap
363 109:     or             %g7, %lo(109b), %g7
364         mov             %l4, %o1
365         mov             %l5, %o2
366         call            data_access_exception
367          add            %sp, PTREGS_OFF, %o0
368         ba,pt           %xcc, rtrap
369          clr            %l6
370