diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-02-04 03:10:01 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 04:11:36 -0500 |
commit | 314ef6859750b6539eac48d78059bb7986f29cb1 (patch) | |
tree | 26c7da386349c1cf377225356e1012ae62da6f07 /arch/sparc64/kernel/winfixup.S | |
parent | ffe483d55229fadbaf4cc7316d47024a24ecd1a2 (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/sparc64/kernel/winfixup.S')
-rw-r--r-- | arch/sparc64/kernel/winfixup.S | 454 |
1 files changed, 107 insertions, 347 deletions
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 | ||
18 | set_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 | ||
42 | fill_fixup: | 23 | fill_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 | */ |
107 | spill_fixup: | 41 | spill_fixup: |
42 | spill_fixup_mna: | ||
43 | spill_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] | 71 | 1: 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] |
138 | 1: 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] | 87 | 2: 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] | ||
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 | 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 |
95 | 1: 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 | ||
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: | 105 | winfix_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 |
183 | fill_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 | 111 | fill_fixup_mna: |
217 | nop ! yes, the nop is correct | ||
218 | spill_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 | ||
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 | 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 | ||
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: | 124 | winfix_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 |
286 | fill_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 | 130 | fill_fixup_dax: |
320 | nop ! yes, the nop is correct | ||
321 | spill_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 | ||
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 | ||