1 /* $Id: winfixup.S,v 1.30 2002/02/09 19:49:30 davem Exp $
3 * winfixup.S: Handle cases where user stack pointer is found to be bogus.
5 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
11 #include <asm/ptrace.h>
12 #include <asm/processor.h>
13 #include <asm/spitfire.h>
14 #include <asm/thread_info.h>
19 cplus_winfixup_insn_1:
21 mov PRIMARY_CONTEXT, %g1
23 cplus_winfixup_insn_2:
26 stxa %l1, [%g1] ASI_DMMU
32 sethi %uhi(CTX_CHEETAH_PLUS_NUC), %l1
34 sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2
38 /* Here are the rules, pay attention.
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.
46 * These are layed out in a special way for cache reasons,
49 .globl fill_fixup, spill_fixup
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
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.
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.
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.
74 * First, get into the window where the original restore was executed.
77 rdpr %wstate, %g2 ! Grab user mode wstate.
78 wrpr %g1, %cwp ! Get into the right window.
79 sll %g2, 3, %g2 ! NORMAL-->OTHER
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...
86 rdpr %pstate, %l1 ! Prepare to change globals.
87 mov %g6, %o7 ! Get current.
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
95 ldx [%g6 + TI_TASK], %g4
98 ldxa [%g1] ASI_IMMU, %g5
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.
104 call do_sparc64_fault
105 add %sp, PTREGS_OFF, %o0
107 nop ! yes, nop is correct
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.
118 ldx [%g6 + TI_FLAGS], %g1
119 andcc %g1, _TIF_32BIT, %g0
120 ldub [%g6 + TI_WSAVED], %g1
124 stx %sp, [%g3 + TI_RWIN_SPTRS]
128 stx %l0, [%g3 + TI_REG_WINDOW + 0x00]
129 stx %l1, [%g3 + TI_REG_WINDOW + 0x08]
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]
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]
146 stx %i7, [%g3 + TI_REG_WINDOW + 0x78]
147 1: stw %l0, [%g3 + TI_REG_WINDOW + 0x00]
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]
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]
167 stb %g1, [%g6 + TI_WSAVED]
169 andcc %g1, TSTATE_PRIV, %g0
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
176 window_scheisse_from_user_common:
177 stb %g4, [%g6 + TI_FAULT_CODE]
178 stx %g5, [%g6 + TI_FAULT_ADDR]
182 call do_sparc64_fault
183 add %sp, PTREGS_OFF, %o0
184 ba,a,pt %xcc, rtrap_clr_l6
186 .globl winfix_mna, fill_fixup_mna, spill_fixup_mna
194 andcc %g1, TSTATE_PRIV, %g0
195 be,pt %xcc, window_mna_from_user_common
196 and %g1, TSTATE_CWP, %g1
198 /* Please, see fill_fixup commentary about why we must preserve
199 * %l5 and %l6 to preserve absolute correct semantics.
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.
206 wrpr %g2, 0x0, %wstate ! This must be consistent.
207 wrpr %g0, 0x0, %otherwin ! We know this.
208 call set_pcontext ! Change contexts...
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
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.
222 ldxa [%g1] ASI_IMMU, %g5
224 call mem_address_unaligned
225 add %sp, PTREGS_OFF, %o0
228 nop ! yes, the nop is correct
230 ldx [%g6 + TI_FLAGS], %g1
231 andcc %g1, _TIF_32BIT, %g0
232 ldub [%g6 + TI_WSAVED], %g1
235 stx %sp, [%g3 + TI_RWIN_SPTRS]
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]
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]
255 stx %i5, [%g3 + TI_REG_WINDOW + 0x68]
256 stx %i6, [%g3 + TI_REG_WINDOW + 0x70]
257 stx %i7, [%g3 + TI_REG_WINDOW + 0x78]
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]
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]
270 2: stb %g1, [%g6 + TI_WSAVED]
273 andcc %g1, TSTATE_PRIV, %g0
275 be,pn %xcc, window_mna_from_user_common
276 and %g1, TSTATE_CWP, %g1
278 window_mna_from_user_common:
282 109: or %g7, %lo(109b), %g7
285 call mem_address_unaligned
286 add %sp, PTREGS_OFF, %o0
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.
295 .globl winfix_dax, fill_fixup_dax, spill_fixup_dax
303 andcc %g1, TSTATE_PRIV, %g0
304 be,pt %xcc, window_dax_from_user_common
305 and %g1, TSTATE_CWP, %g1
307 /* Please, see fill_fixup commentary about why we must preserve
308 * %l5 and %l6 to preserve absolute correct semantics.
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.
315 wrpr %g2, 0x0, %wstate ! This must be consistent.
316 wrpr %g0, 0x0, %otherwin ! We know this.
317 call set_pcontext ! Change contexts...
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
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.
331 ldxa [%g1] ASI_IMMU, %g5
333 call data_access_exception
334 add %sp, PTREGS_OFF, %o0
337 nop ! yes, the nop is correct
339 ldx [%g6 + TI_FLAGS], %g1
340 andcc %g1, _TIF_32BIT, %g0
341 ldub [%g6 + TI_WSAVED], %g1
344 stx %sp, [%g3 + TI_RWIN_SPTRS]
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]
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]
364 stx %i5, [%g3 + TI_REG_WINDOW + 0x68]
365 stx %i6, [%g3 + TI_REG_WINDOW + 0x70]
366 stx %i7, [%g3 + TI_REG_WINDOW + 0x78]
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]
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]
379 2: stb %g1, [%g6 + TI_WSAVED]
382 andcc %g1, TSTATE_PRIV, %g0
384 be,pn %xcc, window_dax_from_user_common
385 and %g1, TSTATE_CWP, %g1
387 window_dax_from_user_common:
391 109: or %g7, %lo(109b), %g7
394 call data_access_exception
395 add %sp, PTREGS_OFF, %o0
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
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