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