diff options
Diffstat (limited to 'arch/sparc64/kernel/rtrap.S')
-rw-r--r-- | arch/sparc64/kernel/rtrap.S | 115 |
1 files changed, 105 insertions, 10 deletions
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index b80eba0081ca..7130e866f935 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S | |||
@@ -223,12 +223,26 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 | |||
223 | ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3 | 223 | ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3 |
224 | ldx [%sp + PTREGS_OFF + PT_V9_G4], %g4 | 224 | ldx [%sp + PTREGS_OFF + PT_V9_G4], %g4 |
225 | ldx [%sp + PTREGS_OFF + PT_V9_G5], %g5 | 225 | ldx [%sp + PTREGS_OFF + PT_V9_G5], %g5 |
226 | mov TSB_REG, %g6 | 226 | brz,pt %l3, 1f |
227 | brnz,a,pn %l3, 1f | 227 | mov %g6, %l2 |
228 | ldxa [%g6] ASI_IMMU, %g5 | 228 | |
229 | 1: ldx [%sp + PTREGS_OFF + PT_V9_G6], %g6 | 229 | /* Must do this before thread reg is clobbered below. */ |
230 | LOAD_PER_CPU_BASE(%g5, %g6, %i0, %i1, %i2) | ||
231 | 1: | ||
232 | ldx [%sp + PTREGS_OFF + PT_V9_G6], %g6 | ||
230 | ldx [%sp + PTREGS_OFF + PT_V9_G7], %g7 | 233 | ldx [%sp + PTREGS_OFF + PT_V9_G7], %g7 |
231 | wrpr %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate | 234 | |
235 | /* Normal globals are restored, go to trap globals. */ | ||
236 | 661: wrpr %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate | ||
237 | nop | ||
238 | .section .sun4v_2insn_patch, "ax" | ||
239 | .word 661b | ||
240 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate | ||
241 | SET_GL(1) | ||
242 | .previous | ||
243 | |||
244 | mov %l2, %g6 | ||
245 | |||
232 | ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 | 246 | ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 |
233 | ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 | 247 | ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 |
234 | 248 | ||
@@ -252,27 +266,108 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 | |||
252 | 266 | ||
253 | brnz,pn %l3, kern_rtt | 267 | brnz,pn %l3, kern_rtt |
254 | mov PRIMARY_CONTEXT, %l7 | 268 | mov PRIMARY_CONTEXT, %l7 |
255 | ldxa [%l7 + %l7] ASI_DMMU, %l0 | 269 | |
270 | 661: ldxa [%l7 + %l7] ASI_DMMU, %l0 | ||
271 | .section .sun4v_1insn_patch, "ax" | ||
272 | .word 661b | ||
273 | ldxa [%l7 + %l7] ASI_MMU, %l0 | ||
274 | .previous | ||
275 | |||
256 | sethi %hi(sparc64_kern_pri_nuc_bits), %l1 | 276 | sethi %hi(sparc64_kern_pri_nuc_bits), %l1 |
257 | ldx [%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1 | 277 | ldx [%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1 |
258 | or %l0, %l1, %l0 | 278 | or %l0, %l1, %l0 |
259 | stxa %l0, [%l7] ASI_DMMU | 279 | |
260 | flush %g6 | 280 | 661: stxa %l0, [%l7] ASI_DMMU |
281 | .section .sun4v_1insn_patch, "ax" | ||
282 | .word 661b | ||
283 | stxa %l0, [%l7] ASI_MMU | ||
284 | .previous | ||
285 | |||
286 | sethi %hi(KERNBASE), %l7 | ||
287 | flush %l7 | ||
261 | rdpr %wstate, %l1 | 288 | rdpr %wstate, %l1 |
262 | rdpr %otherwin, %l2 | 289 | rdpr %otherwin, %l2 |
263 | srl %l1, 3, %l1 | 290 | srl %l1, 3, %l1 |
264 | 291 | ||
265 | wrpr %l2, %g0, %canrestore | 292 | wrpr %l2, %g0, %canrestore |
266 | wrpr %l1, %g0, %wstate | 293 | wrpr %l1, %g0, %wstate |
267 | wrpr %g0, %g0, %otherwin | 294 | brnz,pt %l2, user_rtt_restore |
295 | wrpr %g0, %g0, %otherwin | ||
296 | |||
297 | ldx [%g6 + TI_FLAGS], %g3 | ||
298 | wr %g0, ASI_AIUP, %asi | ||
299 | rdpr %cwp, %g1 | ||
300 | andcc %g3, _TIF_32BIT, %g0 | ||
301 | sub %g1, 1, %g1 | ||
302 | bne,pt %xcc, user_rtt_fill_32bit | ||
303 | wrpr %g1, %cwp | ||
304 | ba,a,pt %xcc, user_rtt_fill_64bit | ||
305 | |||
306 | user_rtt_fill_fixup: | ||
307 | rdpr %cwp, %g1 | ||
308 | add %g1, 1, %g1 | ||
309 | wrpr %g1, 0x0, %cwp | ||
310 | |||
311 | rdpr %wstate, %g2 | ||
312 | sll %g2, 3, %g2 | ||
313 | wrpr %g2, 0x0, %wstate | ||
314 | |||
315 | /* We know %canrestore and %otherwin are both zero. */ | ||
316 | |||
317 | sethi %hi(sparc64_kern_pri_context), %g2 | ||
318 | ldx [%g2 + %lo(sparc64_kern_pri_context)], %g2 | ||
319 | mov PRIMARY_CONTEXT, %g1 | ||
320 | |||
321 | 661: stxa %g2, [%g1] ASI_DMMU | ||
322 | .section .sun4v_1insn_patch, "ax" | ||
323 | .word 661b | ||
324 | stxa %g2, [%g1] ASI_MMU | ||
325 | .previous | ||
326 | |||
327 | sethi %hi(KERNBASE), %g1 | ||
328 | flush %g1 | ||
329 | |||
330 | or %g4, FAULT_CODE_WINFIXUP, %g4 | ||
331 | stb %g4, [%g6 + TI_FAULT_CODE] | ||
332 | stx %g5, [%g6 + TI_FAULT_ADDR] | ||
333 | |||
334 | mov %g6, %l1 | ||
335 | wrpr %g0, 0x0, %tl | ||
336 | |||
337 | 661: nop | ||
338 | .section .sun4v_1insn_patch, "ax" | ||
339 | .word 661b | ||
340 | SET_GL(0) | ||
341 | .previous | ||
342 | |||
343 | wrpr %g0, RTRAP_PSTATE, %pstate | ||
344 | |||
345 | mov %l1, %g6 | ||
346 | ldx [%g6 + TI_TASK], %g4 | ||
347 | LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3) | ||
348 | call do_sparc64_fault | ||
349 | add %sp, PTREGS_OFF, %o0 | ||
350 | ba,pt %xcc, rtrap | ||
351 | nop | ||
352 | |||
353 | user_rtt_pre_restore: | ||
354 | add %g1, 1, %g1 | ||
355 | wrpr %g1, 0x0, %cwp | ||
356 | |||
357 | user_rtt_restore: | ||
268 | restore | 358 | restore |
269 | rdpr %canrestore, %g1 | 359 | rdpr %canrestore, %g1 |
270 | wrpr %g1, 0x0, %cleanwin | 360 | wrpr %g1, 0x0, %cleanwin |
271 | retry | 361 | retry |
272 | nop | 362 | nop |
273 | 363 | ||
274 | kern_rtt: restore | 364 | kern_rtt: rdpr %canrestore, %g1 |
365 | brz,pn %g1, kern_rtt_fill | ||
366 | nop | ||
367 | kern_rtt_restore: | ||
368 | restore | ||
275 | retry | 369 | retry |
370 | |||
276 | to_kernel: | 371 | to_kernel: |
277 | #ifdef CONFIG_PREEMPT | 372 | #ifdef CONFIG_PREEMPT |
278 | ldsw [%g6 + TI_PRE_COUNT], %l5 | 373 | ldsw [%g6 + TI_PRE_COUNT], %l5 |