8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / uts / sun4u / ml / wbuf.s
blob9878e102f62adc4445a4e6d1dcf9c036deb185f2
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
32 #include <sys/trap.h>
33 #include <sys/mmu.h>
34 #include <sys/machparam.h>
35 #include <sys/machtrap.h>
36 #include <sys/traptrace.h>
38 #if !defined(lint)
39 #include "assym.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)
65 CPU_ADDR(%g4, %g1)
66 ldn [%g4 + CPU_MPCB], %g1
67 stn %sp, [%g1 + MPCB_SPBUF]
68 ldn [%g1 + MPCB_WBUF], %g2
69 SAVE_V8WINDOW(%g2)
70 mov 1, %g2
71 st %g2, [%g1 + MPCB_WBCNT]
72 saved
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
79 cmp %g5, T_ALIGNMENT
80 bne %icc, 1f
81 nop
82 set trap, %g1
83 mov T_ALIGNMENT, %g3
85 sub %g0, 1, %g4
87 ! spill traps increment %cwp by 2,
88 ! but user_trap wants the trap %cwp
90 rdpr %tstate, %g5
91 and %g5, TSTATE_CWP, %g5
92 ba,pt %xcc, user_trap
93 wrpr %g0, %g5, %cwp
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
100 ! sys_trap again.
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)
107 CPU_ADDR(%g5, %g6)
108 ldn [%g5 + CPU_MPCB], %g6
109 stn %sp, [%g6 + MPCB_SPBUF]
110 ldn [%g6 + MPCB_WBUF], %g5
111 SAVE_V8WINDOW(%g5)
112 mov 1, %g5
113 st %g5, [%g6 + MPCB_WBCNT]
114 saved
115 set sys_trap, %g5
116 wrpr %g5, %tnpc
117 done
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
131 CPU_ADDR(%g5, %g6)
132 ldn [%g5 + CPU_MPCB], %g1
133 ld [%g1 + MPCB_WBCNT], %g2
134 add %g2, 1, %g3
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
141 stn %sp, [%g3 + %g4]
142 sll %g2, RWIN32SHIFT, %g4
143 ldn [%g1 + MPCB_WBUF], %g3
144 add %g3, %g4, %g3
145 SAVE_V8WINDOW(%g3)
146 saved
147 retry
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
155 ! the save.
157 ENTRY_NP(fault_32bit_so1)
158 FAULT_WINTRACE(%g5, %g6, %g7, TT_F32_SO1)
159 CPU_ADDR(%g5, %g6)
161 ! find lwp & increment wbcnt
163 ldn [%g5 + CPU_MPCB], %g6
164 ld [%g6 + MPCB_WBCNT], %g5
165 add %g5, 1, %g7
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)
171 add %g6, %g7, %g7
172 stn %sp, [%g7 + MPCB_SPBUF]
173 sll %g5, RWIN32SHIFT, %g7
174 ldn [%g6 + MPCB_WBUF], %g5
175 add %g5, %g7, %g7
176 SAVE_V8WINDOW(%g7)
177 saved
178 set sys_trap, %g5
179 wrpr %g5, %tnpc
180 done
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)
199 CPU_ADDR(%g4, %g1)
200 ldn [%g4 + CPU_MPCB], %g1
201 stn %sp, [%g1 + MPCB_SPBUF]
202 ldn [%g1 + MPCB_WBUF], %g2
203 SAVE_V9WINDOW(%g2)
204 mov 1, %g2
205 st %g2, [%g1 + MPCB_WBCNT]
206 saved
208 ! setup user_trap args
210 set sfmmu_tsbmiss_exception, %g1
211 mov %g6, %g2 ! arg2 = tagaccess
212 mov %g5, %g3 ! arg3 = traptype
213 cmp %g5, T_ALIGNMENT
214 bne %icc, 1f
216 set trap, %g1
217 mov T_ALIGNMENT, %g3
219 sub %g0, 1, %g4
221 ! spill traps increment %cwp by 2,
222 ! but user_trap wants the trap %cwp
224 rdpr %tstate, %g5
225 and %g5, TSTATE_CWP, %g5
226 ba,pt %xcc, user_trap
227 wrpr %g0, %g5, %cwp
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
234 ! sys_trap again.
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)
241 CPU_ADDR(%g5, %g6)
242 ldn [%g5 + CPU_MPCB], %g6
243 stn %sp, [%g6 + MPCB_SPBUF]
244 ldn [%g6 + MPCB_WBUF], %g5
245 SAVE_V9WINDOW(%g5)
246 mov 1, %g5
247 st %g5, [%g6 + MPCB_WBCNT]
248 saved
249 set sys_trap, %g5
250 wrpr %g5, %tnpc
251 done
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
265 CPU_ADDR(%g5, %g6)
266 ldn [%g5 + CPU_MPCB], %g1
267 ld [%g1 + MPCB_WBCNT], %g2
268 add %g2, 1, %g3
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
275 stn %sp, [%g3 + %g4]
276 sll %g2, RWIN64SHIFT, %g4
277 ldn [%g1 + MPCB_WBUF], %g3
278 add %g3, %g4, %g3
279 SAVE_V9WINDOW(%g3)
280 saved
281 retry
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
289 ! the save.
291 ENTRY_NP(fault_64bit_so1)
292 FAULT_WINTRACE(%g5, %g6, %g7, TT_F64_SO1)
293 CPU_ADDR(%g5, %g6)
295 ! find lwp & increment wbcnt
297 ldn [%g5 + CPU_MPCB], %g6
298 ld [%g6 + MPCB_WBCNT], %g5
299 add %g5, 1, %g7
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)
305 add %g6, %g7, %g7
306 stn %sp, [%g7 + MPCB_SPBUF]
307 sll %g5, RWIN64SHIFT, %g7
308 ldn [%g6 + MPCB_WBUF], %g5
309 add %g5, %g7, %g7
310 SAVE_V9WINDOW(%g7)
311 saved
312 set sys_trap, %g5
313 wrpr %g5, %tnpc
314 done
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)
327 .fault_fn0_common:
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
343 cmp %g5, T_ALIGNMENT
344 bne %icc, 1f
346 set trap, %g1
347 mov T_ALIGNMENT, %g3
349 sub %g0, 1, %g4
351 ! sys_trap wants %cwp to be the same as when the trap occured,
352 ! so set it from %tstate
354 rdpr %tstate, %g5
355 and %g5, TSTATE_CWP, %g5
356 ba,pt %xcc, user_trap
357 wrpr %g0, %g5, %cwp
358 SET_SIZE(fault_32bit_fn0)
360 ENTRY_NP(fault_32bit_fn1)
362 FAULT_WINTRACE(%g1, %g2, %g3, TT_F32_FN1)
364 .fault_fn1_common:
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
374 rdpr %tstate, %g1
375 and %g1, TSTATE_CWP, %g1
376 wrpr %g0, %g1, %cwp
378 ! fake tl1 traps regs so that after pagefault runs, we
379 ! re-execute at user_rtt.
381 wrpr %g0, 1, %tl
382 set TSTATE_KERN | TSTATE_IE, %g1
383 wrpr %g0, %g1, %tstate
384 set user_rtt, %g1
385 wrpr %g0, %g1, %tpc
386 add %g1, 4, %g1
387 wrpr %g0, %g1, %tnpc
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
397 cmp %g5, T_ALIGNMENT
398 bne %icc, 1f
400 set trap, %g1
401 set T_USER | T_SYS_RTT_ALIGN, %g3
403 sub %g0, 1, %g4
405 ! setup to run kernel again by setting THREAD_REG, %wstate
406 ! and the mmu to their kernel values.
408 rdpr %pstate, %l1
409 wrpr %l1, PSTATE_AG, %pstate
410 mov %l6, THREAD_REG ! %l6 is user_rtt's thread
411 wrpr %g0, %l1, %pstate
412 rdpr %wstate, %l1
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
419 xor %g5, %g7, %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
429 flush %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)
437 b .fault_fn0_common
439 SET_SIZE(fault_64bit_fn0)
441 ENTRY_NP(fault_64bit_fn1)
442 FAULT_WINTRACE(%g1, %g2, %g3, TT_F64_FN1)
443 b .fault_fn1_common
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)
456 #endif /* !lint */