4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/asm_linkage.h>
29 #include <sys/machthread.h>
30 #include <sys/privregs.h>
31 #include <sys/machasi.h>
34 #include <sys/machparam.h>
35 #include <sys/machtrap.h>
36 #include <sys/traptrace.h>
42 * Spill fault handlers
43 * sn0 - spill normal tl 0
44 * sn1 - spill normal tl >0
45 * so0 - spill other tl 0
46 * so1 - spill other tl >0
49 ENTRY_NP
(fault_32bit_sn0
)
51 FAULT_WINTRACE
(%g1
, %g2
, %g3
, TT_F32_SN0
)
53 ! Spill normal tl0 fault.
54 ! This happens when
a user tries to spill to an unmapped
or
55 ! misaligned stack. We handle an unmapped stack by simulating
56 ! a pagefault at the
trap pc
and a misaligned stack by generating
57 ! a user alignment trap.
59 ! spill the window into wbuf slot
0
60 ! (we know wbuf is empty since we came from user mode
)
62 ! g5
= mmu
trap type
, g6
= tag access reg
(g5
!= T_ALIGNMENT
) or
63 ! sfar
(g5
== T_ALIGNMENT
)
66 ldn
[%g4
+ CPU_MPCB
], %g1
67 stn
%sp
, [%g1
+ MPCB_SPBUF
]
68 ldn
[%g1
+ MPCB_WBUF
], %g2
71 st %g2
, [%g1
+ MPCB_WBCNT
]
74 ! setup user_trap args
76 set sfmmu_tsbmiss_exception
, %g1
77 mov
%g6
, %g2
! arg2
= tagaccess
78 mov T_WIN_OVERFLOW
, %g3
! arg3
= traptype
87 ! spill traps increment
%cwp by
2,
88 ! but user_trap wants the
trap %cwp
91 and %g5
, TSTATE_CWP
, %g5
94 SET_SIZE
(fault_32bit_sn0
)
97 ! Spill normal tl1 fault.
98 ! This happens when sys_trap
's save spills to an unmapped stack.
99 ! We handle it by spilling the window to the wbuf and trying
102 ! spill the window into wbuf slot 0
103 ! (we know wbuf is empty since we came from user mode)
105 ENTRY_NP(fault_32bit_sn1)
106 FAULT_WINTRACE(%g5, %g6, %g7, TT_F32_SN1)
108 ldn [%g5 + CPU_MPCB], %g6
109 stn %sp, [%g6 + MPCB_SPBUF]
110 ldn [%g6 + MPCB_WBUF], %g5
113 st %g5, [%g6 + MPCB_WBCNT]
118 SET_SIZE(fault_32bit_sn1)
120 ENTRY_NP(fault_32bit_so0)
122 FAULT_WINTRACE(%g5, %g6, %g1, TT_F32_SO0)
124 ! Spill other tl0 fault.
125 ! This happens when the kernel spills a user window and that
126 ! user's stack has been unmapped.
127 ! We handle it by spilling the window into the user
's wbuf.
129 ! find lwp & increment wbcnt
132 ldn [%g5 + CPU_MPCB], %g1
133 ld [%g1 + MPCB_WBCNT], %g2
135 st %g3, [%g1 + MPCB_WBCNT]
137 ! use previous wbcnt to spill new spbuf & wbuf
139 sll %g2, CPTRSHIFT, %g4 ! spbuf size is sizeof (caddr_t)
140 add %g1, MPCB_SPBUF, %g3
142 sll %g2, RWIN32SHIFT, %g4
143 ldn [%g1 + MPCB_WBUF], %g3
148 SET_SIZE(fault_32bit_so0)
151 ! Spill other tl1 fault.
152 ! This happens when priv_trap spills a user window and that
153 ! user's stack has been unmapped.
154 ! We handle it by spilling the window to the wbuf
and retrying
157 ENTRY_NP
(fault_32bit_so1
)
158 FAULT_WINTRACE
(%g5
, %g6
, %g7
, TT_F32_SO1
)
161 ! find lwp
& increment wbcnt
163 ldn
[%g5
+ CPU_MPCB
], %g6
164 ld [%g6
+ MPCB_WBCNT
], %g5
166 st %g7
, [%g6
+ MPCB_WBCNT
]
168 ! use previous wbcnt to spill new spbuf
& wbuf
170 sll
%g5
, CPTRSHIFT
, %g7
! spbuf size is sizeof
(caddr_t
)
172 stn
%sp
, [%g7
+ MPCB_SPBUF
]
173 sll
%g5
, RWIN32SHIFT
, %g7
174 ldn
[%g6
+ MPCB_WBUF
], %g5
181 SET_SIZE
(fault_32bit_so1
)
183 ENTRY_NP
(fault_64bit_sn0
)
185 FAULT_WINTRACE
(%g1
, %g2
, %g3
, TT_F64_SN0
)
187 ! Spill normal tl0 fault.
188 ! This happens when
a user tries to spill to an unmapped
or
189 ! misaligned stack. We handle an unmapped stack by simulating
190 ! a pagefault at the
trap pc
and a misaligned stack by generating
191 ! a user alignment trap.
193 ! spill the window into wbuf slot
0
194 ! (we know wbuf is empty since we came from user mode
)
196 ! g5
= mmu
trap type
, g6
= tag access reg
(g5
!= T_ALIGNMENT
) or
197 ! sfar
(g5
== T_ALIGNMENT
)
200 ldn
[%g4
+ CPU_MPCB
], %g1
201 stn
%sp
, [%g1
+ MPCB_SPBUF
]
202 ldn
[%g1
+ MPCB_WBUF
], %g2
205 st %g2
, [%g1
+ MPCB_WBCNT
]
208 ! setup user_trap args
210 set sfmmu_tsbmiss_exception
, %g1
211 mov
%g6
, %g2
! arg2
= tagaccess
212 mov
%g5
, %g3
! arg3
= traptype
221 ! spill traps increment
%cwp by
2,
222 ! but user_trap wants the
trap %cwp
225 and %g5
, TSTATE_CWP
, %g5
226 ba,pt
%xcc
, user_trap
228 SET_SIZE
(fault_64bit_sn0
)
231 ! Spill normal tl1 fault.
232 ! This happens when sys_trap
's save spills to an unmapped stack.
233 ! We handle it by spilling the window to the wbuf and trying
236 ! spill the window into wbuf slot 0
237 ! (we know wbuf is empty since we came from user mode)
239 ENTRY_NP(fault_64bit_sn1)
240 FAULT_WINTRACE(%g5, %g6, %g7, TT_F64_SN1)
242 ldn [%g5 + CPU_MPCB], %g6
243 stn %sp, [%g6 + MPCB_SPBUF]
244 ldn [%g6 + MPCB_WBUF], %g5
247 st %g5, [%g6 + MPCB_WBCNT]
252 SET_SIZE(fault_64bit_sn1)
254 ENTRY_NP(fault_64bit_so0)
256 FAULT_WINTRACE(%g5, %g6, %g1, TT_F64_SO0)
258 ! Spill other tl0 fault.
259 ! This happens when the kernel spills a user window and that
260 ! user's stack has been unmapped.
261 ! We handle it by spilling the window into the user
's wbuf.
263 ! find lwp & increment wbcnt
266 ldn [%g5 + CPU_MPCB], %g1
267 ld [%g1 + MPCB_WBCNT], %g2
269 st %g3, [%g1 + MPCB_WBCNT]
271 ! use previous wbcnt to spill new spbuf & wbuf
273 sll %g2, CPTRSHIFT, %g4 ! spbuf size is sizeof (caddr_t)
274 add %g1, MPCB_SPBUF, %g3
276 sll %g2, RWIN64SHIFT, %g4
277 ldn [%g1 + MPCB_WBUF], %g3
282 SET_SIZE(fault_64bit_so0)
285 ! Spill other tl1 fault.
286 ! This happens when priv_trap spills a user window and that
287 ! user's stack has been unmapped.
288 ! We handle it by spilling the window to the wbuf
and retrying
291 ENTRY_NP
(fault_64bit_so1
)
292 FAULT_WINTRACE
(%g5
, %g6
, %g7
, TT_F64_SO1
)
295 ! find lwp
& increment wbcnt
297 ldn
[%g5
+ CPU_MPCB
], %g6
298 ld [%g6
+ MPCB_WBCNT
], %g5
300 st %g7
, [%g6
+ MPCB_WBCNT
]
302 ! use previous wbcnt to spill new spbuf
& wbuf
304 sll
%g5
, CPTRSHIFT
, %g7
! spbuf size is sizeof
(caddr_t
)
306 stn
%sp
, [%g7
+ MPCB_SPBUF
]
307 sll
%g5
, RWIN64SHIFT
, %g7
308 ldn
[%g6
+ MPCB_WBUF
], %g5
315 SET_SIZE
(fault_64bit_so1
)
318 * Fill fault handlers
319 * fn0 - fill normal tl 0
320 * fn1 - fill normal tl 1
323 ENTRY_NP
(fault_32bit_fn0
)
325 FAULT_WINTRACE
(%g1
, %g2
, %g3
, TT_F32_FN0
)
329 ! Fill normal tl0 fault.
330 ! This happens when
a user tries to fill to an unmapped
or
331 ! misaligned stack. We handle an unmapped stack by simulating
332 ! a pagefault at the
trap pc
and a misaligned stack by generating
333 ! a user alignment trap.
335 ! setup user_trap args
337 ! g5
= mmu
trap type
, g6
= tag access reg
(g5
!= T_ALIGNMENT
) or
338 ! sfar
(g5
== T_ALIGNMENT
)
340 set sfmmu_tsbmiss_exception
, %g1
341 mov
%g6
, %g2
! arg2
= tagaccess
342 mov T_WIN_UNDERFLOW
, %g3
351 ! sys_trap wants
%cwp to
be the same as when the
trap occured
,
352 ! so set it from
%tstate
355 and %g5
, TSTATE_CWP
, %g5
356 ba,pt
%xcc
, user_trap
358 SET_SIZE
(fault_32bit_fn0
)
360 ENTRY_NP
(fault_32bit_fn1
)
362 FAULT_WINTRACE
(%g1
, %g2
, %g3
, TT_F32_FN1
)
366 ! Fill normal tl1 fault.
367 ! This happens when user_rtt
's restore fills from an unmapped or
368 ! misaligned stack. We handle an unmapped stack by simulating
369 ! a pagefault at user_rtt and a misaligned stack by generating
370 ! a RTT alignment trap.
372 ! save fault addr & fix %cwp
375 and %g1, TSTATE_CWP, %g1
378 ! fake tl1 traps regs so that after pagefault runs, we
379 ! re-execute at user_rtt.
382 set TSTATE_KERN | TSTATE_IE, %g1
383 wrpr %g0, %g1, %tstate
389 ! setup sys_trap args
391 ! g5 = mmu trap type, g6 = tag access reg (g5 != T_ALIGNMENT) or
392 ! sfar (g5 == T_ALIGNMENT)
394 set sfmmu_tsbmiss_exception, %g1
395 mov %g6, %g2 ! arg2 = tagaccess
396 set T_USER | T_SYS_RTT_PAGE, %g3 ! arg3 = traptype
401 set T_USER | T_SYS_RTT_ALIGN, %g3
405 ! setup to run kernel again by setting THREAD_REG, %wstate
406 ! and the mmu to their kernel values.
409 wrpr %l1, PSTATE_AG, %pstate
410 mov %l6, THREAD_REG ! %l6 is user_rtt's thread
411 wrpr
%g0
, %l1
, %pstate
413 sllx
%l1
, WSTATE_SHIFT
, %l1
414 wrpr
%l1
, WSTATE_K64
, %wstate
415 sethi
%hi
(kcontextreg
), %g5
! mov KCONTEXT
, %g5
416 ldx [%g5
+ %lo
(kcontextreg
)], %g5
417 mov MMU_PCONTEXT
, %g6
418 ldxa
[%g6
]ASI_MMU_CTX
, %g7
420 srlx
%g7
, CTXREG_NEXT_SHIFT
, %g7
421 brz
%g7
, 1f
! if N_pgsz0
/1 changed
, need demap
423 mov DEMAP_ALL_TYPE
, %g7
424 stxa
%g0
, [%g7
]ASI_DTLB_DEMAP
425 stxa
%g0
, [%g7
]ASI_ITLB_DEMAP
427 stxa
%g5
, [%g6
]ASI_MMU_CTX
428 sethi
%hi
(FLUSH_ADDR
), %g5
431 ba,pt
%xcc
, priv_trap
433 SET_SIZE
(fault_32bit_fn1
)
435 ENTRY_NP
(fault_64bit_fn0
)
436 FAULT_WINTRACE
(%g1
, %g2
, %g3
, TT_F64_FN0
)
439 SET_SIZE
(fault_64bit_fn0
)
441 ENTRY_NP
(fault_64bit_fn1
)
442 FAULT_WINTRACE
(%g1
, %g2
, %g3
, TT_F64_FN1
)
445 SET_SIZE
(fault_64bit_fn1
)
448 * Kernel fault handlers
450 ENTRY_NP
(fault_32bit_not
)
451 ENTRY_NP
(fault_64bit_not
)
452 ba,pt
%xcc
, ptl1_panic
453 mov PTL1_BAD_WTRAP
, %g1
454 SET_SIZE
(fault_32bit_not
)
455 SET_SIZE
(fault_64bit_not
)