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