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