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