aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-04 03:10:01 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 04:11:36 -0500
commit314ef6859750b6539eac48d78059bb7986f29cb1 (patch)
tree26c7da386349c1cf377225356e1012ae62da6f07 /arch
parentffe483d55229fadbaf4cc7316d47024a24ecd1a2 (diff)
[SPARC64]: Refine register window trap handling.
When saving and restoing trap state, do the window spill/fill handling inline so that we never trap deeper than 2 trap levels. This is important for chips like Niagara. The window fixup code is massively simplified, and many more improvements are now possible. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/etrap.S104
-rw-r--r--arch/sparc64/kernel/process.c20
-rw-r--r--arch/sparc64/kernel/rtrap.S58
-rw-r--r--arch/sparc64/kernel/tsb.S1
-rw-r--r--arch/sparc64/kernel/ttable.S16
-rw-r--r--arch/sparc64/kernel/winfixup.S454
6 files changed, 214 insertions, 439 deletions
diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
index b5f6bc52d917..4a0e01b14044 100644
--- a/arch/sparc64/kernel/etrap.S
+++ b/arch/sparc64/kernel/etrap.S
@@ -55,7 +55,31 @@ etrap_irq:
55 rd %y, %g3 55 rd %y, %g3
56 stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC] 56 stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
57 st %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y] 57 st %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]
58 save %g2, -STACK_BIAS, %sp ! Ordering here is critical 58
59 rdpr %cansave, %g1
60 brnz,pt %g1, etrap_save
61 nop
62
63 rdpr %cwp, %g1
64 add %g1, 2, %g1
65 wrpr %g1, %cwp
66 be,pt %xcc, etrap_user_spill
67 mov ASI_AIUP, %g3
68
69 rdpr %otherwin, %g3
70 brz %g3, etrap_kernel_spill
71 mov ASI_AIUS, %g3
72
73etrap_user_spill:
74
75 wr %g3, 0x0, %asi
76 ldx [%g6 + TI_FLAGS], %g3
77 and %g3, _TIF_32BIT, %g3
78 brnz,pt %g3, etrap_user_spill_32bit
79 nop
80 ba,a,pt %xcc, etrap_user_spill_64bit
81
82etrap_save: save %g2, -STACK_BIAS, %sp
59 mov %g6, %l6 83 mov %g6, %l6
60 84
61 bne,pn %xcc, 3f 85 bne,pn %xcc, 3f
@@ -176,83 +200,5 @@ etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
176 ba,pt %xcc, 1b 200 ba,pt %xcc, 1b
177 andcc %g1, TSTATE_PRIV, %g0 201 andcc %g1, TSTATE_PRIV, %g0
178 202
179 .align 64
180 .globl scetrap
181scetrap:
182 TRAP_LOAD_THREAD_REG(%g6, %g1)
183 rdpr %pil, %g2
184 rdpr %tstate, %g1
185 sllx %g2, 20, %g3
186 andcc %g1, TSTATE_PRIV, %g0
187 or %g1, %g3, %g1
188 bne,pn %xcc, 1f
189 sub %sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2
190 wrpr %g0, 7, %cleanwin
191
192 sllx %g1, 51, %g3
193 sethi %hi(TASK_REGOFF), %g2
194 or %g2, %lo(TASK_REGOFF), %g2
195 brlz,pn %g3, 1f
196 add %g6, %g2, %g2
197 wr %g0, 0, %fprs
1981: rdpr %tpc, %g3
199 stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]
200
201 rdpr %tnpc, %g1
202 stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
203 stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
204 save %g2, -STACK_BIAS, %sp ! Ordering here is critical
205 mov %g6, %l6
206 bne,pn %xcc, 2f
207 mov ASI_P, %l7
208 rdpr %canrestore, %g3
209
210 rdpr %wstate, %g2
211 wrpr %g0, 0, %canrestore
212 sll %g2, 3, %g2
213 mov PRIMARY_CONTEXT, %l4
214 wrpr %g3, 0, %otherwin
215 wrpr %g2, 0, %wstate
216 sethi %hi(sparc64_kern_pri_context), %g2
217 ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3
218 stxa %g3, [%l4] ASI_DMMU
219 sethi %hi(KERNBASE), %l4
220 flush %l4
221
222 mov ASI_AIUS, %l7
2232: mov %g4, %l4
224 mov %g5, %l5
225 add %g7, 0x4, %l2
226 wrpr %g0, ETRAP_PSTATE1, %pstate
227 stx %g1, [%sp + PTREGS_OFF + PT_V9_G1]
228 stx %g2, [%sp + PTREGS_OFF + PT_V9_G2]
229 sllx %l7, 24, %l7
230
231 stx %g3, [%sp + PTREGS_OFF + PT_V9_G3]
232 rdpr %cwp, %l0
233 stx %g4, [%sp + PTREGS_OFF + PT_V9_G4]
234 stx %g5, [%sp + PTREGS_OFF + PT_V9_G5]
235 stx %g6, [%sp + PTREGS_OFF + PT_V9_G6]
236 stx %g7, [%sp + PTREGS_OFF + PT_V9_G7]
237 or %l7, %l0, %l7
238 sethi %hi(TSTATE_RMO | TSTATE_PEF), %l0
239
240 or %l7, %l0, %l7
241 wrpr %l2, %tnpc
242 wrpr %l7, (TSTATE_PRIV | TSTATE_IE), %tstate
243 stx %i0, [%sp + PTREGS_OFF + PT_V9_I0]
244 stx %i1, [%sp + PTREGS_OFF + PT_V9_I1]
245 stx %i2, [%sp + PTREGS_OFF + PT_V9_I2]
246 stx %i3, [%sp + PTREGS_OFF + PT_V9_I3]
247 stx %i4, [%sp + PTREGS_OFF + PT_V9_I4]
248
249 stx %i5, [%sp + PTREGS_OFF + PT_V9_I5]
250 stx %i6, [%sp + PTREGS_OFF + PT_V9_I6]
251 mov %l6, %g6
252 stx %i7, [%sp + PTREGS_OFF + PT_V9_I7]
253 LOAD_PER_CPU_BASE(%g5, %g6, %g4, %g3, %l1)
254 ldx [%g6 + TI_TASK], %g4
255 done
256
257#undef TASK_REGOFF 203#undef TASK_REGOFF
258#undef ETRAP_PSTATE1 204#undef ETRAP_PSTATE1
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 26548fc604b6..803eea4dc4ff 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -541,6 +541,18 @@ void synchronize_user_stack(void)
541 } 541 }
542} 542}
543 543
544static void stack_unaligned(unsigned long sp)
545{
546 siginfo_t info;
547
548 info.si_signo = SIGBUS;
549 info.si_errno = 0;
550 info.si_code = BUS_ADRALN;
551 info.si_addr = (void __user *) sp;
552 info.si_trapno = 0;
553 force_sig_info(SIGBUS, &info, current);
554}
555
544void fault_in_user_windows(void) 556void fault_in_user_windows(void)
545{ 557{
546 struct thread_info *t = current_thread_info(); 558 struct thread_info *t = current_thread_info();
@@ -556,13 +568,17 @@ void fault_in_user_windows(void)
556 flush_user_windows(); 568 flush_user_windows();
557 window = get_thread_wsaved(); 569 window = get_thread_wsaved();
558 570
559 if (window != 0) { 571 if (likely(window != 0)) {
560 window -= 1; 572 window -= 1;
561 do { 573 do {
562 unsigned long sp = (t->rwbuf_stkptrs[window] + bias); 574 unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
563 struct reg_window *rwin = &t->reg_window[window]; 575 struct reg_window *rwin = &t->reg_window[window];
564 576
565 if (copy_to_user((char __user *)sp, rwin, winsize)) 577 if (unlikely(sp & 0x7UL))
578 stack_unaligned(sp);
579
580 if (unlikely(copy_to_user((char __user *)sp,
581 rwin, winsize)))
566 goto barf; 582 goto barf;
567 } while (window--); 583 } while (window--);
568 } 584 }
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index 61bd45e7697e..ecfbbdc56125 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -267,15 +267,69 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
267 267
268 wrpr %l2, %g0, %canrestore 268 wrpr %l2, %g0, %canrestore
269 wrpr %l1, %g0, %wstate 269 wrpr %l1, %g0, %wstate
270 wrpr %g0, %g0, %otherwin 270 brnz,pt %l2, user_rtt_restore
271 wrpr %g0, %g0, %otherwin
272
273 ldx [%g6 + TI_FLAGS], %g3
274 wr %g0, ASI_AIUP, %asi
275 rdpr %cwp, %g1
276 andcc %g3, _TIF_32BIT, %g0
277 sub %g1, 1, %g1
278 bne,pt %xcc, user_rtt_fill_32bit
279 wrpr %g1, %cwp
280 ba,a,pt %xcc, user_rtt_fill_64bit
281
282user_rtt_fill_fixup:
283 rdpr %cwp, %g1
284 add %g1, 1, %g1
285 wrpr %g1, 0x0, %cwp
286
287 rdpr %wstate, %g2
288 sll %g2, 3, %g2
289 wrpr %g2, 0x0, %wstate
290
291 /* We know %canrestore and %otherwin are both zero. */
292
293 sethi %hi(sparc64_kern_pri_context), %g2
294 ldx [%g2 + %lo(sparc64_kern_pri_context)], %g2
295 mov PRIMARY_CONTEXT, %g1
296 stxa %g2, [%g1] ASI_DMMU
297 sethi %hi(KERNBASE), %g1
298 flush %g1
299
300 or %g4, FAULT_CODE_WINFIXUP, %g4
301 stb %g4, [%g6 + TI_FAULT_CODE]
302 stx %g5, [%g6 + TI_FAULT_ADDR]
303
304 mov %g6, %l1
305 wrpr %g0, 0x0, %tl
306 wrpr %g0, RTRAP_PSTATE, %pstate
307 mov %l1, %g6
308 ldx [%g6 + TI_TASK], %g4
309 LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
310 call do_sparc64_fault
311 add %sp, PTREGS_OFF, %o0
312 ba,pt %xcc, rtrap
313 nop
314
315user_rtt_pre_restore:
316 add %g1, 1, %g1
317 wrpr %g1, 0x0, %cwp
318
319user_rtt_restore:
271 restore 320 restore
272 rdpr %canrestore, %g1 321 rdpr %canrestore, %g1
273 wrpr %g1, 0x0, %cleanwin 322 wrpr %g1, 0x0, %cleanwin
274 retry 323 retry
275 nop 324 nop
276 325
277kern_rtt: restore 326kern_rtt: rdpr %canrestore, %g1
327 brz,pn %g1, kern_rtt_fill
328 nop
329kern_rtt_restore:
330 restore
278 retry 331 retry
332
279to_kernel: 333to_kernel:
280#ifdef CONFIG_PREEMPT 334#ifdef CONFIG_PREEMPT
281 ldsw [%g6 + TI_PRE_COUNT], %l5 335 ldsw [%g6 + TI_PRE_COUNT], %l5
diff --git a/arch/sparc64/kernel/tsb.S b/arch/sparc64/kernel/tsb.S
index 28e38b168dda..3b45db98005a 100644
--- a/arch/sparc64/kernel/tsb.S
+++ b/arch/sparc64/kernel/tsb.S
@@ -115,7 +115,6 @@ sparc64_realfault_common:
115 ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state 115 ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state
116 nop ! Delay slot (fill me) 116 nop ! Delay slot (fill me)
117 117
118 .globl winfix_trampoline
119winfix_trampoline: 118winfix_trampoline:
120 rdpr %tpc, %g3 ! Prepare winfixup TNPC 119 rdpr %tpc, %g3 ! Prepare winfixup TNPC
121 or %g3, 0x7c, %g3 ! Compute branch offset 120 or %g3, 0x7c, %g3 ! Compute branch offset
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 99531424c598..2679b6e253ae 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -92,11 +92,11 @@ tl0_resv07c: BTRAP(0x7c) BTRAP(0x7d) BTRAP(0x7e) BTRAP(0x7f)
92tl0_s0n: SPILL_0_NORMAL 92tl0_s0n: SPILL_0_NORMAL
93tl0_s1n: SPILL_1_NORMAL 93tl0_s1n: SPILL_1_NORMAL
94tl0_s2n: SPILL_2_NORMAL 94tl0_s2n: SPILL_2_NORMAL
95tl0_s3n: SPILL_3_NORMAL 95tl0_s3n: SPILL_0_NORMAL_ETRAP
96tl0_s4n: SPILL_4_NORMAL 96tl0_s4n: SPILL_1_GENERIC_ETRAP
97tl0_s5n: SPILL_5_NORMAL 97tl0_s5n: SPILL_1_GENERIC_ETRAP_FIXUP
98tl0_s6n: SPILL_6_NORMAL 98tl0_s6n: SPILL_2_GENERIC_ETRAP
99tl0_s7n: SPILL_7_NORMAL 99tl0_s7n: SPILL_2_GENERIC_ETRAP_FIXUP
100tl0_s0o: SPILL_0_OTHER 100tl0_s0o: SPILL_0_OTHER
101tl0_s1o: SPILL_1_OTHER 101tl0_s1o: SPILL_1_OTHER
102tl0_s2o: SPILL_2_OTHER 102tl0_s2o: SPILL_2_OTHER
@@ -110,9 +110,9 @@ tl0_f1n: FILL_1_NORMAL
110tl0_f2n: FILL_2_NORMAL 110tl0_f2n: FILL_2_NORMAL
111tl0_f3n: FILL_3_NORMAL 111tl0_f3n: FILL_3_NORMAL
112tl0_f4n: FILL_4_NORMAL 112tl0_f4n: FILL_4_NORMAL
113tl0_f5n: FILL_5_NORMAL 113tl0_f5n: FILL_0_NORMAL_RTRAP
114tl0_f6n: FILL_6_NORMAL 114tl0_f6n: FILL_1_GENERIC_RTRAP
115tl0_f7n: FILL_7_NORMAL 115tl0_f7n: FILL_2_GENERIC_RTRAP
116tl0_f0o: FILL_0_OTHER 116tl0_f0o: FILL_0_OTHER
117tl0_f1o: FILL_1_OTHER 117tl0_f1o: FILL_1_OTHER
118tl0_f2o: FILL_2_OTHER 118tl0_f2o: FILL_2_OTHER
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index 211021ae6e8a..efe2770e8f5d 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -1,8 +1,6 @@
1/* $Id: winfixup.S,v 1.30 2002/02/09 19:49:30 davem Exp $ 1/* winfixup.S: Handle cases where user stack pointer is found to be bogus.
2 * 2 *
3 * winfixup.S: Handle cases where user stack pointer is found to be bogus. 3 * Copyright (C) 1997, 2006 David S. Miller (davem@davemloft.net)
4 *
5 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
6 */ 4 */
7 5
8#include <asm/asi.h> 6#include <asm/asi.h>
@@ -15,367 +13,129 @@
15 13
16 .text 14 .text
17 15
18set_pcontext: 16 /* It used to be the case that these register window fault
19 sethi %hi(sparc64_kern_pri_context), %l1 17 * handlers could run via the save and restore instructions
20 ldx [%l1 + %lo(sparc64_kern_pri_context)], %l1 18 * done by the trap entry and exit code. They now do the
21 mov PRIMARY_CONTEXT, %g1 19 * window spill/fill by hand, so that case no longer can occur.
22 stxa %l1, [%g1] ASI_DMMU 20 */
23 sethi %hi(KERNBASE), %l1
24 flush %l1
25 retl
26 nop
27 21
28 .align 32 22 .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
42fill_fixup: 23fill_fixup:
43 TRAP_LOAD_THREAD_REG(%g6, %g1) 24 TRAP_LOAD_THREAD_REG(%g6, %g1)
44 rdpr %tstate, %g1 25 rdpr %tstate, %g1
45 andcc %g1, TSTATE_PRIV, %g0 26 and %g1, TSTATE_CWP, %g1
46 or %g4, FAULT_CODE_WINFIXUP, %g4 27 or %g4, FAULT_CODE_WINFIXUP, %g4
47 be,pt %xcc, window_scheisse_from_user_common 28 stb %g4, [%g6 + TI_FAULT_CODE]
48 and %g1, TSTATE_CWP, %g1 29 stx %g5, [%g6 + TI_FAULT_ADDR]
49 30 wrpr %g1, %cwp
50 /* This is the extremely complex case, but it does happen from 31 ba,pt %xcc, etrap
51 * time to time if things are just right. Essentially the restore 32 rd %pc, %g7
52 * done in rtrap right before going back to user mode, with tl=1 33 call do_sparc64_fault
53 * and that levels trap stack registers all setup, took a fill trap, 34 add %sp, PTREGS_OFF, %o0
54 * the user stack was not mapped in the tlb, and tlb miss occurred, 35 ba,pt %xcc, rtrap_clr_l6
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 36 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(%g5, %g6, %g1, %g2, %g3)
90 37
91 /* This is the same as below, except we handle this a bit special 38 /* Be very careful about usage of the trap globals here.
92 * since we must preserve %l5 and %l6, see comment above. 39 * You cannot touch %g5 as that has the fault information.
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 */ 40 */
107spill_fixup: 41spill_fixup:
42spill_fixup_mna:
43spill_fixup_dax:
108 TRAP_LOAD_THREAD_REG(%g6, %g1) 44 TRAP_LOAD_THREAD_REG(%g6, %g1)
109 ldx [%g6 + TI_FLAGS], %g1 45 ldx [%g6 + TI_FLAGS], %g1
110 andcc %g1, _TIF_32BIT, %g0 46 andcc %g1, _TIF_32BIT, %g0
111 ldub [%g6 + TI_WSAVED], %g1 47 ldub [%g6 + TI_WSAVED], %g1
112 48 sll %g1, 3, %g3
113 sll %g1, 3, %g3 49 add %g6, %g3, %g3
114 add %g6, %g3, %g3 50 stx %sp, [%g3 + TI_RWIN_SPTRS]
115 stx %sp, [%g3 + TI_RWIN_SPTRS] 51 sll %g1, 7, %g3
116 sll %g1, 7, %g3 52 bne,pt %xcc, 1f
117 bne,pt %xcc, 1f 53 add %g6, %g3, %g3
118 add %g6, %g3, %g3 54 stx %l0, [%g3 + TI_REG_WINDOW + 0x00]
119 stx %l0, [%g3 + TI_REG_WINDOW + 0x00] 55 stx %l1, [%g3 + TI_REG_WINDOW + 0x08]
120 stx %l1, [%g3 + TI_REG_WINDOW + 0x08] 56 stx %l2, [%g3 + TI_REG_WINDOW + 0x10]
121 57 stx %l3, [%g3 + TI_REG_WINDOW + 0x18]
122 stx %l2, [%g3 + TI_REG_WINDOW + 0x10] 58 stx %l4, [%g3 + TI_REG_WINDOW + 0x20]
123 stx %l3, [%g3 + TI_REG_WINDOW + 0x18] 59 stx %l5, [%g3 + TI_REG_WINDOW + 0x28]
124 stx %l4, [%g3 + TI_REG_WINDOW + 0x20] 60 stx %l6, [%g3 + TI_REG_WINDOW + 0x30]
125 stx %l5, [%g3 + TI_REG_WINDOW + 0x28] 61 stx %l7, [%g3 + TI_REG_WINDOW + 0x38]
126 stx %l6, [%g3 + TI_REG_WINDOW + 0x30] 62 stx %i0, [%g3 + TI_REG_WINDOW + 0x40]
127 stx %l7, [%g3 + TI_REG_WINDOW + 0x38] 63 stx %i1, [%g3 + TI_REG_WINDOW + 0x48]
128 stx %i0, [%g3 + TI_REG_WINDOW + 0x40] 64 stx %i2, [%g3 + TI_REG_WINDOW + 0x50]
129 stx %i1, [%g3 + TI_REG_WINDOW + 0x48] 65 stx %i3, [%g3 + TI_REG_WINDOW + 0x58]
130 66 stx %i4, [%g3 + TI_REG_WINDOW + 0x60]
131 stx %i2, [%g3 + TI_REG_WINDOW + 0x50] 67 stx %i5, [%g3 + TI_REG_WINDOW + 0x68]
132 stx %i3, [%g3 + TI_REG_WINDOW + 0x58] 68 stx %i6, [%g3 + TI_REG_WINDOW + 0x70]
133 stx %i4, [%g3 + TI_REG_WINDOW + 0x60] 69 ba,pt %xcc, 2f
134 stx %i5, [%g3 + TI_REG_WINDOW + 0x68] 70 stx %i7, [%g3 + TI_REG_WINDOW + 0x78]
135 stx %i6, [%g3 + TI_REG_WINDOW + 0x70] 711: stw %l0, [%g3 + TI_REG_WINDOW + 0x00]
136 b,pt %xcc, 2f 72 stw %l1, [%g3 + TI_REG_WINDOW + 0x04]
137 stx %i7, [%g3 + TI_REG_WINDOW + 0x78] 73 stw %l2, [%g3 + TI_REG_WINDOW + 0x08]
1381: stw %l0, [%g3 + TI_REG_WINDOW + 0x00] 74 stw %l3, [%g3 + TI_REG_WINDOW + 0x0c]
139 75 stw %l4, [%g3 + TI_REG_WINDOW + 0x10]
140 stw %l1, [%g3 + TI_REG_WINDOW + 0x04] 76 stw %l5, [%g3 + TI_REG_WINDOW + 0x14]
141 stw %l2, [%g3 + TI_REG_WINDOW + 0x08] 77 stw %l6, [%g3 + TI_REG_WINDOW + 0x18]
142 stw %l3, [%g3 + TI_REG_WINDOW + 0x0c] 78 stw %l7, [%g3 + TI_REG_WINDOW + 0x1c]
143 stw %l4, [%g3 + TI_REG_WINDOW + 0x10] 79 stw %i0, [%g3 + TI_REG_WINDOW + 0x20]
144 stw %l5, [%g3 + TI_REG_WINDOW + 0x14] 80 stw %i1, [%g3 + TI_REG_WINDOW + 0x24]
145 stw %l6, [%g3 + TI_REG_WINDOW + 0x18] 81 stw %i2, [%g3 + TI_REG_WINDOW + 0x28]
146 stw %l7, [%g3 + TI_REG_WINDOW + 0x1c] 82 stw %i3, [%g3 + TI_REG_WINDOW + 0x2c]
147 stw %i0, [%g3 + TI_REG_WINDOW + 0x20] 83 stw %i4, [%g3 + TI_REG_WINDOW + 0x30]
148 84 stw %i5, [%g3 + TI_REG_WINDOW + 0x34]
149 stw %i1, [%g3 + TI_REG_WINDOW + 0x24] 85 stw %i6, [%g3 + TI_REG_WINDOW + 0x38]
150 stw %i2, [%g3 + TI_REG_WINDOW + 0x28] 86 stw %i7, [%g3 + TI_REG_WINDOW + 0x3c]
151 stw %i3, [%g3 + TI_REG_WINDOW + 0x2c] 872: add %g1, 1, %g1
152 stw %i4, [%g3 + TI_REG_WINDOW + 0x30] 88 stb %g1, [%g6 + TI_WSAVED]
153 stw %i5, [%g3 + TI_REG_WINDOW + 0x34] 89 rdpr %tstate, %g1
154 stw %i6, [%g3 + TI_REG_WINDOW + 0x38] 90 andcc %g1, TSTATE_PRIV, %g0
155 stw %i7, [%g3 + TI_REG_WINDOW + 0x3c]
1562: add %g1, 1, %g1
157
158 stb %g1, [%g6 + TI_WSAVED]
159 rdpr %tstate, %g1
160 andcc %g1, TSTATE_PRIV, %g0
161 saved 91 saved
162 and %g1, TSTATE_CWP, %g1 92 be,pn %xcc, 1f
163 be,a,pn %xcc, window_scheisse_from_user_common 93 and %g1, TSTATE_CWP, %g1
164 mov FAULT_CODE_WRITE | FAULT_CODE_DTLB | FAULT_CODE_WINFIXUP, %g4
165 retry 94 retry
951: mov FAULT_CODE_WRITE | FAULT_CODE_DTLB | FAULT_CODE_WINFIXUP, %g4
96 stb %g4, [%g6 + TI_FAULT_CODE]
97 stx %g5, [%g6 + TI_FAULT_ADDR]
98 wrpr %g1, %cwp
99 ba,pt %xcc, etrap
100 rd %pc, %g7
101 call do_sparc64_fault
102 add %sp, PTREGS_OFF, %o0
103 ba,a,pt %xcc, rtrap_clr_l6
166 104
167window_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
178winfix_mna: 105winfix_mna:
179 andn %g3, 0x7f, %g3 106 andn %g3, 0x7f, %g3
180 add %g3, 0x78, %g3 107 add %g3, 0x78, %g3
181 wrpr %g3, %tnpc 108 wrpr %g3, %tnpc
182 done 109 done
183fill_fixup_mna:
184 TRAP_LOAD_THREAD_REG(%g6, %g1)
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(%g5, %g6, %g1, %g2, %g3)
213 call mem_address_unaligned
214 add %sp, PTREGS_OFF, %o0
215 110
216 b,pt %xcc, rtrap 111fill_fixup_mna:
217 nop ! yes, the nop is correct
218spill_fixup_mna:
219 TRAP_LOAD_THREAD_REG(%g6, %g1) 112 TRAP_LOAD_THREAD_REG(%g6, %g1)
220 ldx [%g6 + TI_FLAGS], %g1 113 rdpr %tstate, %g1
221 andcc %g1, _TIF_32BIT, %g0 114 and %g1, TSTATE_CWP, %g1
222 ldub [%g6 + TI_WSAVED], %g1 115 wrpr %g1, %cwp
223 sll %g1, 3, %g3 116 ba,pt %xcc, etrap
224 add %g6, %g3, %g3 117 rd %pc, %g7
225 stx %sp, [%g3 + TI_RWIN_SPTRS] 118 mov %l4, %o2
226 119 mov %l5, %o1
227 sll %g1, 7, %g3 120 call mem_address_unaligned
228 bne,pt %xcc, 1f 121 add %sp, PTREGS_OFF, %o0
229 add %g6, %g3, %g3 122 ba,a,pt %xcc, rtrap_clr_l6
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
2501: std %l0, [%g3 + TI_REG_WINDOW + 0x00]
251 std %l2, [%g3 + TI_REG_WINDOW + 0x08]
252 std %l4, [%g3 + TI_REG_WINDOW + 0x10]
253 123
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
2602: 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
268window_mna_from_user_common:
269 wrpr %g1, %cwp
270 sethi %hi(109f), %g7
271 ba,pt %xcc, etrap
272109: 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
281winfix_dax: 124winfix_dax:
282 andn %g3, 0x7f, %g3 125 andn %g3, 0x7f, %g3
283 add %g3, 0x74, %g3 126 add %g3, 0x74, %g3
284 wrpr %g3, %tnpc 127 wrpr %g3, %tnpc
285 done 128 done
286fill_fixup_dax:
287 TRAP_LOAD_THREAD_REG(%g6, %g1)
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(%g5, %g6, %g1, %g2, %g3)
316 call spitfire_data_access_exception
317 add %sp, PTREGS_OFF, %o0
318 129
319 b,pt %xcc, rtrap 130fill_fixup_dax:
320 nop ! yes, the nop is correct
321spill_fixup_dax:
322 TRAP_LOAD_THREAD_REG(%g6, %g1) 131 TRAP_LOAD_THREAD_REG(%g6, %g1)
323 ldx [%g6 + TI_FLAGS], %g1 132 rdpr %tstate, %g1
324 andcc %g1, _TIF_32BIT, %g0 133 and %g1, TSTATE_CWP, %g1
325 ldub [%g6 + TI_WSAVED], %g1 134 wrpr %g1, %cwp
326 sll %g1, 3, %g3 135 ba,pt %xcc, etrap
327 add %g6, %g3, %g3 136 rd %pc, %g7
328 stx %sp, [%g3 + TI_RWIN_SPTRS] 137 mov %l4, %o1
329 138 mov %l5, %o2
330 sll %g1, 7, %g3 139 call spitfire_data_access_exception
331 bne,pt %xcc, 1f 140 add %sp, PTREGS_OFF, %o0
332 add %g6, %g3, %g3 141 ba,a,pt %xcc, rtrap_clr_l6
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
3531: 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
3632: 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
371window_dax_from_user_common:
372 wrpr %g1, %cwp
373 sethi %hi(109f), %g7
374 ba,pt %xcc, etrap
375109: 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