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