restore sparc comments
de-linting of .s files
1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/asm_linkage.h>
27 #include <sys/intreg.h>
28 #include <sys/ivintr.h>
29 #include <sys/mmu.h>
30 #include <sys/machpcb.h>
31 #include <sys/machtrap.h>
32 #include <sys/machlock.h>
33 #include <sys/fdreg.h>
34 #include <sys/vis.h>
35 #include <sys/traptrace.h>
36 #include <sys/panic.h>
37 #include <sys/machasi.h>
38 #include <sys/privregs.h>
39 #include <sys/hypervisor_api.h>
40 #include <sys/clock.h>
41
42 #include "assym.h"
43
44
45 !
46 ! REGOFF must add up to allow double word access to r_tstate.
47 ! PCB_WBUF must also be aligned.
48 !
49 #if (REGOFF & 7) != 0
50 #error "struct regs not aligned"
51 #endif
52
53 /*
54 * Absolute external symbols.
55 * On the sun4u we put the panic buffer in the third and fourth pages.
56 * We set things up so that the first 2 pages of KERNELBASE is illegal
57 * to act as a redzone during copyin/copyout type operations. One of
58 * the reasons the panic buffer is allocated in low memory to
59 * prevent being overwritten during booting operations (besides
60 * the fact that it is small enough to share pages with others).
61 */
62
63 .seg ".data"
64 .global panicbuf
65
66 PROM = 0xFFE00000 ! address of prom virtual area
67 panicbuf = SYSBASE32 + PAGESIZE ! address of panic buffer
68
69 .type panicbuf, #object
70 .size panicbuf, PANICBUFSIZE
71
72 /*
73 * Absolute external symbol - intr_vec_table.
74 *
75 * With new bus structures supporting a larger number of interrupt
76 * numbers, the interrupt vector table, intr_vec_table[] has been
77 * moved out of kernel nucleus and allocated after panicbuf.
78 */
79 .global intr_vec_table
80
81 intr_vec_table = SYSBASE32 + PAGESIZE + PANICBUFSIZE ! address of interrupt table
82
83 .type intr_vec_table, #object
84 .size intr_vec_table, MAXIVNUM * CPTRSIZE + MAX_RSVD_IV * IV_SIZE + MAX_RSVD_IVX * (IV_SIZE + CPTRSIZE * (NCPU - 1))
85
86 /*
87 * The thread 0 stack. This must be the first thing in the data
88 * segment (other than an sccs string) so that we don't stomp
89 * on anything important if the stack overflows. We get a
90 * red zone below this stack for free when the kernel text is
91 * write protected.
92 */
93
94 .global t0stack
95 .align 16
96 .type t0stack, #object
97 t0stack:
98 .skip T0STKSZ ! thread 0 stack
99 t0stacktop:
100 .size t0stack, T0STKSZ
101
102 /*
103 * cpu0 and its ptl1_panic stack. The cpu structure must be allocated
104 * on a single page for ptl1_panic's physical address accesses.
105 */
106 .global cpu0
107 .align MMU_PAGESIZE
108 cpu0:
109 .type cpu0, #object
110 .skip CPU_ALLOC_SIZE
111 .size cpu0, CPU_ALLOC_SIZE
112
113 .global t0
114 .align PTR24_ALIGN ! alignment for mutex.
115 .type t0, #object
116 t0:
117 .skip THREAD_SIZE ! thread 0
118 .size t0, THREAD_SIZE
119
120 .global trap_trace_ctl
121 .global htrap_tr0
122 .global htrap_trace_bufsize
123
124 .align 64
125 trap_trace_ctl:
126 .skip NCPU * TRAPTR_SIZE ! NCPU control headers
127 htrap_tr0:
128 .skip HTRAP_TSIZE ! one buffer for the boot cpu
129 .align 4
130 htrap_trace_bufsize:
131 .word HTRAP_TSIZE ! default hv trap buffer size
132
133 #ifdef TRAPTRACE
134 .global trap_tr0
135 .global trap_trace_bufsize
136 .global trap_freeze
137 .global trap_freeze_pc
138
139 .align 4
140 trap_trace_bufsize:
141 .word TRAP_TSIZE ! default trap buffer size
142 trap_freeze:
143 .word 0
144
145 .align 16
146 trap_tr0:
147 .skip TRAP_TSIZE ! one buffer for the boot cpu
148
149 /*
150 * When an assertion in TRACE_PTR was failed, %pc is saved in trap_freeze_pc to
151 * show in which TRACE_PTR the assertion failure happened.
152 */
153 .align 8
154 trap_freeze_pc:
155 .nword 0
156 #endif /* TRAPTRACE */
157
158 .align 4
159 .seg ".text"
160
161 #ifdef NOPROM
162 .global availmem
163 availmem:
164 .word 0
165 #endif /* NOPROM */
166
167 .align 8
168 _local_p1275cis:
169 .nword 0
170
171 .seg ".data"
172
173 .global nwindows, nwin_minus_one, winmask
174 nwindows:
175 .word 8
176 nwin_minus_one:
177 .word 7
178 winmask:
179 .word 8
180
181 .global afsrbuf
182 afsrbuf:
183 .word 0,0,0,0
184
185 /*
186 * System initialization
187 *
188 * Our contract with the boot prom specifies that the MMU is on and the
189 * first 16 meg of memory is mapped with a level-1 pte. We are called
190 * with p1275cis ptr in %o0 and kdi_dvec in %o1; we start execution
191 * directly from physical memory, so we need to get up into our proper
192 * addresses quickly: all code before we do this must be position
193 * independent.
194 *
195 * NB: Above is not true for boot/stick kernel, the only thing mapped is
196 * the text+data+bss. The kernel is loaded directly into KERNELBASE.
197 *
198 * entry, the romvec pointer (romp) is the first argument;
199 * i.e., %o0.
200 * the bootops vector is in the third argument (%o1)
201 *
202 * Our tasks are:
203 * save parameters
204 * construct mappings for KERNELBASE (not needed for boot/stick kernel)
205 * hop up into high memory (not needed for boot/stick kernel)
206 * initialize stack pointer
207 * initialize trap base register
208 * initialize window invalid mask
209 * initialize psr (with traps enabled)
210 * figure out all the module type stuff
211 * tear down the 1-1 mappings
212 * dive into main()
213 */
214 ENTRY_NP(_start)
215 !
216 ! Stash away our arguments in memory.
217 !
218 sethi %hi(_local_p1275cis), %g1
219 stn %o4, [%g1 + %lo(_local_p1275cis)]
220
221 !
222 ! Initialize CPU state registers
223 !
224 wrpr %g0, PSTATE_KERN, %pstate
225 wr %g0, %g0, %fprs
226
227 !
228 ! call krtld to link the world together
229 !
230 call kobj_start
231 mov %o4, %o0
232
233 ! Write 0x1f (MAX_REG_WINDOWS) to %cwp and read back to get
234 ! the actual implemented nwin - 1 value
235 rdpr %cwp, %g2 ! save current %cwp
236 wrpr %g0, 0x1f, %cwp
237 rdpr %cwp, %g1 ! %g1 = nwin - 1
238 wrpr %g0, %g2, %cwp ! restore current %cwp
239
240 !
241 ! Stuff some memory cells related to numbers of windows.
242 !
243 sethi %hi(nwin_minus_one), %g2
244 st %g1, [%g2 + %lo(nwin_minus_one)]
245 inc %g1
246 sethi %hi(nwindows), %g2
247 st %g1, [%g2 + %lo(nwindows)]
248 dec %g1
249 mov -2, %g2
250 sll %g2, %g1, %g2
251 sethi %hi(winmask), %g4
252 st %g2, [%g4 + %lo(winmask)]
253
254 !
255 ! save a pointer to obp's tba for later use by kmdb
256 !
257 rdpr %tba, %g1
258 set boot_tba, %g2
259 stx %g1, [%g2]
260
261 !
262 ! copy obp's breakpoint trap entry to obp_bpt
263 !
264 rdpr %tba, %g1
265 set T_SOFTWARE_TRAP | ST_MON_BREAKPOINT, %g2
266 sll %g2, 5, %g2
267 or %g1, %g2, %g1
268 set obp_bpt, %g2
269 ldx [%g1], %g3
270 stx %g3, [%g2]
271 flush %g2
272 ldx [%g1 + 8], %g3
273 stx %g3, [%g2 + 8]
274 flush %g2 + 8
275 ldx [%g1 + 16], %g3
276 stx %g3, [%g2 + 16]
277 flush %g2 + 16
278 ldx [%g1 + 24], %g3
279 stx %g3, [%g2 + 24]
280 flush %g2 + 24
281
282 !
283 ! Initialize thread 0's stack.
284 !
285 set t0stacktop, %g1 ! setup kernel stack pointer
286 sub %g1, SA(KFPUSIZE+GSR_SIZE), %g2
287 and %g2, 0x3f, %g3
288 sub %g2, %g3, %o1
289 sub %o1, SA(MPCBSIZE) + STACK_BIAS, %sp
290
291 !
292 ! Initialize global thread register.
293 !
294 set t0, THREAD_REG
295
296 !
297 ! Fill in enough of the cpu structure so that
298 ! the wbuf management code works. Make sure the
299 ! boot cpu is inserted in cpu[] based on cpuid.
300 !
301 CPU_INDEX(%g2, %g1)
302 sll %g2, CPTRSHIFT, %g2 ! convert cpuid to cpu[] offset
303 set cpu0, %o0 ! &cpu0
304 set cpu, %g1 ! &cpu[]
305 stn %o0, [%g1 + %g2] ! cpu[cpuid] = &cpu0
306
307 stn %o0, [THREAD_REG + T_CPU] ! threadp()->t_cpu = cpu[cpuid]
308 stn THREAD_REG, [%o0 + CPU_THREAD] ! cpu[cpuid]->cpu_thread = threadp()
309
310
311 ! We do NOT need to bzero our BSS...boot has already done it for us.
312 ! Just need to reference edata so that we don't break /dev/ksyms
313 set edata, %g0
314
315 !
316 ! Call mlsetup with address of prototype user registers.
317 !
318 call mlsetup
319 add %sp, REGOFF + STACK_BIAS, %o0
320
321 #if (REGOFF != MPCB_REGS)
322 #error "hole in struct machpcb between frame and regs?"
323 #endif
324
325 !
326 ! Now call main. We will return as process 1 (init).
327 !
328 call main
329 nop
330
331 !
332 ! Main should never return.
333 !
334 set .mainretmsg, %o0
335 call panic
336 nop
337 SET_SIZE(_start)
338
339 .mainretmsg:
340 .asciz "main returned"
341 .align 4
342
343
344 /*
345 * Generic system trap handler.
346 *
347 * Some kernel trap handlers save themselves from buying a window by
348 * borrowing some of sys_trap's unused locals. %l0 thru %l3 may be used
349 * for this purpose, as user_rtt and priv_rtt do not depend on them.
350 * %l4 thru %l7 should NOT be used this way.
351 *
352 * Entry Conditions:
353 * %pstate am:0 priv:1 ie:0
354 * %gl global level 1
355 *
356 * Register Inputs:
357 * %g1 pc of trap handler
358 * %g2, %g3 args for handler
359 * %g4 desired %pil (-1 means current %pil)
360 * %g5, %g6 destroyed
361 * %g7 saved
362 *
363 * Register Usage:
364 * %l0, %l1 temps
365 * %l3 saved %g1
366 * %l6 curthread for user traps, %pil for priv traps
367 * %l7 regs
368 *
369 * Called function prototype variants:
370 *
371 * func(struct regs *rp);
372 * func(struct regs *rp, uintptr_t arg1 [%g2], uintptr_t arg2 [%g3])
373 * func(struct regs *rp, uintptr_t arg1 [%g2],
374 * uint32_t arg2 [%g3.l], uint32_t arg3 [%g3.h])
375 * func(struct regs *rp, uint32_t arg1 [%g2.l],
376 * uint32_t arg2 [%g3.l], uint32_t arg3 [%g3.h], uint32_t [%g2.h])
377 */
378
379 ENTRY_NP(sys_trap)
380 #ifdef DEBUG
381 ! Assert gl == 1
382 rdpr %gl, %g5
383 cmp %g5, 1
384 bne,a,pn %xcc, ptl1_panic
385 mov PTL1_BAD_GL, %g1
386 #endif
387
388 !
389 ! force tl=1, update %cwp, branch to correct handler
390 !
391
392 wrpr %g0, 1, %tl
393 rdpr %tstate, %g5
394 btst TSTATE_PRIV, %g5
395 and %g5, TSTATE_CWP, %g6
396 bnz,pn %xcc, priv_trap
397 wrpr %g0, %g6, %cwp
398
399 ALTENTRY(user_trap)
400 !
401 ! user trap
402 !
403 ! make all windows clean for kernel
404 ! buy a window using the current thread's stack
405 !
406 #ifdef DEBUG
407 ! Assert gl == 1
408 rdpr %gl, %g5
409 cmp %g5, 1
410 bne,a,pn %xcc, ptl1_panic
411 mov PTL1_BAD_GL, %g1
412 #endif
413 sethi %hi(nwin_minus_one), %g5
414 ld [%g5 + %lo(nwin_minus_one)], %g5
415 wrpr %g0, %g5, %cleanwin
416 CPU_ADDR(%g5, %g6)
417 ldn [%g5 + CPU_THREAD], %g5
418 ldn [%g5 + T_STACK], %g6
419 sub %g6, STACK_BIAS, %g6
420 save %g6, 0, %sp
421 !
422 ! set window registers so that current windows are "other" windows
423 !
424 rdpr %canrestore, %l0
425 rdpr %wstate, %l1
426 wrpr %g0, 0, %canrestore
427 sllx %l1, WSTATE_SHIFT, %l1
428 wrpr %l1, WSTATE_K64, %wstate
429 wrpr %g0, %l0, %otherwin
430 !
431 ! set pcontext to run kernel
432 !
433 mov KCONTEXT, %l0
434 mov MMU_PCONTEXT, %l1
435 stxa %l0, [%l1]ASI_MMU_CTX
436 ! Ensure new ctx takes effect by the time the "done" (below) completes
437 membar #Sync
438
439 set utl0, %g6 ! bounce to utl0
440 have_win:
441 #ifdef DEBUG
442 CPU_ADDR(%o1, %o2)
443 add %o1, CPU_MCPU, %o1
444 ld [%o1 + MCPU_KWBUF_FULL], %o2
445 tst %o2
446 bnz,a,pn %icc, ptl1_panic
447 mov PTL1_BAD_WTRAP, %g1
448 #endif /* DEBUG */
449 SYSTRAP_TRACE(%o1, %o2, %o3)
450
451
452 !
453 ! at this point we have a new window we can play in,
454 ! and %g6 is the label we want done to bounce to
455 !
456 ! save needed current globals
457 !
458 mov %g1, %l3 ! pc
459 mov %g2, %o1 ! arg #1
460 mov %g3, %o2 ! arg #2
461 srlx %g3, 32, %o3 ! pseudo arg #3
462 srlx %g2, 32, %o4 ! pseudo arg #4
463 mov %g5, %l6 ! curthread if user trap, %pil if priv trap
464 !
465 ! save trap state on stack
466 !
467 add %sp, REGOFF + STACK_BIAS, %l7
468 rdpr %tpc, %l0
469 rdpr %tnpc, %l1
470 rdpr %tstate, %l2
471 stn %l0, [%l7 + PC_OFF]
472 stn %l1, [%l7 + nPC_OFF]
473 stx %l2, [%l7 + TSTATE_OFF]
474 !
475 ! setup pil
476 !
477 brlz,pt %g4, 1f
478 nop
479 #ifdef DEBUG
480 !
481 ! ASSERT(%g4 >= %pil).
482 !
483 rdpr %pil, %l0
484 cmp %g4, %l0
485 bge,pt %xcc, 0f
486 nop ! yes, nop; to avoid anull
487 set bad_g4_called, %l3
488 mov 1, %o1
489 st %o1, [%l3]
490 set bad_g4, %l3 ! pc
491 set sys_trap_wrong_pil, %o1 ! arg #1
492 mov %g4, %o2 ! arg #2
493 ba 1f ! stay at the current %pil
494 mov %l0, %o3 ! arg #3
495 0:
496 #endif /* DEBUG */
497 wrpr %g0, %g4, %pil
498 1:
499 !
500 ! set trap regs to execute in kernel at %g6
501 ! done resumes execution there
502 !
503 wrpr %g0, %g6, %tnpc
504 rdpr %cwp, %l0
505 set TSTATE_KERN, %l1
506 wrpr %l1, %l0, %tstate
507 done
508 /* NOTREACHED */
509 SET_SIZE(user_trap)
510 SET_SIZE(sys_trap)
511
512 #define KWBUF64_TO_STACK(SBP,SPP,TMP) \
513 ldx [SBP + (0*8)], TMP; \
514 stx TMP, [SPP + V9BIAS64 + 0]; \
515 ldx [SBP + (1*8)], TMP; \
516 stx TMP, [SPP + V9BIAS64 + 8]; \
517 ldx [SBP + (2*8)], TMP; \
518 stx TMP, [SPP + V9BIAS64 + 16]; \
519 ldx [SBP + (3*8)], TMP; \
520 stx TMP, [SPP + V9BIAS64 + 24]; \
521 ldx [SBP + (4*8)], TMP; \
522 stx TMP, [SPP + V9BIAS64 + 32]; \
523 ldx [SBP + (5*8)], TMP; \
524 stx TMP, [SPP + V9BIAS64 + 40]; \
525 ldx [SBP + (6*8)], TMP; \
526 stx TMP, [SPP + V9BIAS64 + 48]; \
527 ldx [SBP + (7*8)], TMP; \
528 stx TMP, [SPP + V9BIAS64 + 56]; \
529 ldx [SBP + (8*8)], TMP; \
530 stx TMP, [SPP + V9BIAS64 + 64]; \
531 ldx [SBP + (9*8)], TMP; \
532 stx TMP, [SPP + V9BIAS64 + 72]; \
533 ldx [SBP + (10*8)], TMP; \
534 stx TMP, [SPP + V9BIAS64 + 80]; \
535 ldx [SBP + (11*8)], TMP; \
536 stx TMP, [SPP + V9BIAS64 + 88]; \
537 ldx [SBP + (12*8)], TMP; \
538 stx TMP, [SPP + V9BIAS64 + 96]; \
539 ldx [SBP + (13*8)], TMP; \
540 stx TMP, [SPP + V9BIAS64 + 104]; \
541 ldx [SBP + (14*8)], TMP; \
542 stx TMP, [SPP + V9BIAS64 + 112]; \
543 ldx [SBP + (15*8)], TMP; \
544 stx TMP, [SPP + V9BIAS64 + 120];
545
546 #define KWBUF32_TO_STACK(SBP,SPP,TMP) \
547 lduw [SBP + (0 * 4)], TMP; \
548 stw TMP, [SPP + 0]; \
549 lduw [SBP + (1 * 4)], TMP; \
550 stw TMP, [SPP + (1 * 4)]; \
551 lduw [SBP + (2 * 4)], TMP; \
552 stw TMP, [SPP + (2 * 4)]; \
553 lduw [SBP + (3 * 4)], TMP; \
554 stw TMP, [SPP + (3 * 4)]; \
555 lduw [SBP + (4 * 4)], TMP; \
556 stw TMP, [SPP + (4 * 4)]; \
557 lduw [SBP + (5 * 4)], TMP; \
558 stw TMP, [SPP + (5 * 4)]; \
559 lduw [SBP + (6 * 4)], TMP; \
560 stw TMP, [SPP + (6 * 4)]; \
561 lduw [SBP + (7 * 4)], TMP; \
562 stw TMP, [SPP + (7 * 4)]; \
563 lduw [SBP + (8 * 4)], TMP; \
564 stw TMP, [SPP + (8 * 4)]; \
565 lduw [SBP + (9 * 4)], TMP; \
566 stw TMP, [SPP + (9 * 4)]; \
567 lduw [SBP + (10 * 4)], TMP; \
568 stw TMP, [SPP + (10 * 4)]; \
569 lduw [SBP + (11 * 4)], TMP; \
570 stw TMP, [SPP + (11 * 4)]; \
571 lduw [SBP + (12 * 4)], TMP; \
572 stw TMP, [SPP + (12 * 4)]; \
573 lduw [SBP + (13 * 4)], TMP; \
574 stw TMP, [SPP + (13 * 4)]; \
575 lduw [SBP + (14 * 4)], TMP; \
576 stw TMP, [SPP + (14 * 4)]; \
577 lduw [SBP + (15 * 4)], TMP; \
578 stw TMP, [SPP + (15 * 4)];
579
580 #define COPY_KWBUF_TO_STACK(TMP1,TMP2,TMP3) \
581 CPU_ADDR(TMP2, TMP3) ;\
582 add TMP2, CPU_MCPU, TMP2 ;\
583 ld [TMP2 + MCPU_KWBUF_FULL], TMP3 ;\
584 brz,pt TMP3, 2f ;\
585 nop ;\
586 st %g0, [TMP2 + MCPU_KWBUF_FULL] ;\
587 set MCPU_KWBUF_SP, TMP3 ;\
588 ldn [TMP2 + TMP3], TMP3 ;\
589 set MCPU_KWBUF, TMP1 ;\
590 btst 1, TMP3 ;\
591 bz,pn %xcc, 3f ;\
592 add TMP2, TMP1, TMP2 ;\
593 KWBUF64_TO_STACK(TMP2, TMP3, TMP1) ;\
594 ba,a 2f ;\
595 3: ;\
596 KWBUF32_TO_STACK(TMP2, TMP3, TMP1) ;\
597 2:
598
599 ENTRY_NP(prom_trap)
600 !
601 ! prom trap switches the stack to 32-bit
602 ! if we took a trap from a 64-bit window
603 ! Then buys a window on the current stack.
604 !
605 save %sp, -SA64(REGOFF + REGSIZE), %sp
606 /* 32 bit frame, 64 bit sized */
607 COPY_KWBUF_TO_STACK(%o1, %o2, %o3)
608 set ptl0, %g6
609 ba,a,pt %xcc, have_win
610 SET_SIZE(prom_trap)
611
612 ENTRY_NP(priv_trap)
613 !
614 ! kernel trap
615 ! buy a window on the current stack
616 !
617 ! is the trap PC in the range allocated to Open Firmware?
618 rdpr %tpc, %g5
619 set OFW_END_ADDR, %g6
620 cmp %g5, %g6
621 bgu,a,pn %xcc, 1f
622 rdpr %pil, %g5
623 set OFW_START_ADDR, %g6
624 cmp %g5, %g6
625 bgeu,pn %xcc, prom_trap
626 rdpr %pil, %g5
627 1:
628 set ktl0, %g6
629 save %sp, -SA(REGOFF + REGSIZE), %sp
630 COPY_KWBUF_TO_STACK(%o1, %o2, %o3)
631 ba,a,pt %xcc, have_win
632 SET_SIZE(priv_trap)
633
634 /*
635 * FILL_32bit_rtt/FILL_64bit_rtt fills a 32/64-bit-wide register window
636 * from a 32/64-bit * wide address space via the designated asi.
637 * It is used to fill windows in user_rtt to avoid going above TL 2.
638 */
639 /* TODO: Use the faster FILL based on FILL_32bit_asi/FILL_64bit_asi */
640 #define FILL_32bit_rtt(asi_num) \
641 mov asi_num, %asi ;\
642 rdpr %cwp, %g1 ;\
643 dec %g1 ;\
644 wrpr %g1, %cwp ;\
645 srl %sp, 0, %sp ;\
646 lda [%sp + 0]%asi, %l0 ;\
647 lda [%sp + 4]%asi, %l1 ;\
648 lda [%sp + 8]%asi, %l2 ;\
649 lda [%sp + 12]%asi, %l3 ;\
650 lda [%sp + 16]%asi, %l4 ;\
651 lda [%sp + 20]%asi, %l5 ;\
652 lda [%sp + 24]%asi, %l6 ;\
653 lda [%sp + 28]%asi, %l7 ;\
654 lda [%sp + 32]%asi, %i0 ;\
655 lda [%sp + 36]%asi, %i1 ;\
656 lda [%sp + 40]%asi, %i2 ;\
657 lda [%sp + 44]%asi, %i3 ;\
658 lda [%sp + 48]%asi, %i4 ;\
659 lda [%sp + 52]%asi, %i5 ;\
660 lda [%sp + 56]%asi, %i6 ;\
661 lda [%sp + 60]%asi, %i7 ;\
662 restored ;\
663 add %g1, 1, %g1 ;\
664 wrpr %g1, %cwp
665
666 #define FILL_64bit_rtt(asi_num) \
667 mov asi_num, %asi ;\
668 rdpr %cwp, %g1 ;\
669 sub %g1, 1, %g1 ;\
670 wrpr %g1, %cwp ;\
671 ldxa [%sp + V9BIAS64 + 0]%asi, %l0 ;\
672 ldxa [%sp + V9BIAS64 + 8]%asi, %l1 ;\
673 ldxa [%sp + V9BIAS64 + 16]%asi, %l2 ;\
674 ldxa [%sp + V9BIAS64 + 24]%asi, %l3 ;\
675 ldxa [%sp + V9BIAS64 + 32]%asi, %l4 ;\
676 ldxa [%sp + V9BIAS64 + 40]%asi, %l5 ;\
677 ldxa [%sp + V9BIAS64 + 48]%asi, %l6 ;\
678 ldxa [%sp + V9BIAS64 + 56]%asi, %l7 ;\
679 ldxa [%sp + V9BIAS64 + 64]%asi, %i0 ;\
680 ldxa [%sp + V9BIAS64 + 72]%asi, %i1 ;\
681 ldxa [%sp + V9BIAS64 + 80]%asi, %i2 ;\
682 ldxa [%sp + V9BIAS64 + 88]%asi, %i3 ;\
683 ldxa [%sp + V9BIAS64 + 96]%asi, %i4 ;\
684 ldxa [%sp + V9BIAS64 + 104]%asi, %i5 ;\
685 ldxa [%sp + V9BIAS64 + 112]%asi, %i6 ;\
686 ldxa [%sp + V9BIAS64 + 120]%asi, %i7 ;\
687 restored ;\
688 add %g1, 1, %g1 ;\
689 wrpr %g1, %cwp
690
691 ENTRY_NP(utl0)
692 SAVE_GLOBALS(%l7)
693 SAVE_OUTS(%l7)
694 mov %l6, THREAD_REG
695 wrpr %g0, PSTATE_KERN, %pstate ! enable ints
696 jmpl %l3, %o7 ! call trap handler
697 mov %l7, %o0
698 !
699 ALTENTRY(user_rtt)
700 !
701 ! Register inputs
702 ! %l7 - regs
703 !
704 ! disable interrupts and check for ASTs and wbuf restores
705 ! keep cpu_base_spl in %l4
706 !
707 wrpr %g0, PIL_MAX, %pil
708 ldn [THREAD_REG + T_CPU], %l0
709 ld [%l0 + CPU_BASE_SPL], %l4
710
711 ldub [THREAD_REG + T_ASTFLAG], %l2
712 brz,pt %l2, 1f
713 ld [%sp + STACK_BIAS + MPCB_WBCNT], %l3
714 !
715 ! call trap to do ast processing
716 !
717 wrpr %g0, %l4, %pil ! pil = cpu_base_spl
718 mov %l7, %o0
719 call trap
720 mov T_AST, %o2
721 ba,a,pt %xcc, user_rtt
722 1:
723 brz,pt %l3, 2f
724 mov THREAD_REG, %l6
725 !
726 ! call restore_wbuf to push wbuf windows to stack
727 !
728 wrpr %g0, %l4, %pil ! pil = cpu_base_spl
729 mov %l7, %o0
730 call trap
731 mov T_FLUSH_PCB, %o2
732 ba,a,pt %xcc, user_rtt
733 2:
734 #ifdef TRAPTRACE
735 TRACE_RTT(TT_SYS_RTT_USER, %l0, %l1, %l2, %l3)
736 #endif /* TRAPTRACE */
737 ld [%sp + STACK_BIAS + MPCB_WSTATE], %l3 ! get wstate
738
739 !
740 ! restore user globals and outs
741 !
742 rdpr %pstate, %l1
743 wrpr %l1, PSTATE_IE, %pstate
744 RESTORE_GLOBALS(%l7)
745 ! switch to global set 1, saving THREAD_REG in %l6
746 wrpr %g0, 1, %gl
747 mov %sp, %g6 ! remember the mpcb pointer in %g6
748 RESTORE_OUTS(%l7)
749 !
750 ! set %pil from cpu_base_spl
751 !
752 wrpr %g0, %l4, %pil
753 !
754 ! raise tl (now using nucleus context)
755 ! set pcontext to scontext for user execution
756 !
757 wrpr %g0, 1, %tl
758
759 mov MMU_SCONTEXT, %g1
760 ldxa [%g1]ASI_MMU_CTX, %g2
761 mov MMU_PCONTEXT, %g1
762 stxa %g2, [%g1]ASI_MMU_CTX
763 !
764 ! If shared context support is not enabled, then the next six
765 ! instructions will be patched with nop instructions.
766 !
767 .global sfmmu_shctx_user_rtt_patch
768 sfmmu_shctx_user_rtt_patch:
769 !
770 ! On processors which support multiple contexts, writing to
771 ! pcontext0 automatically updates pcontext1 for backwards
772 ! compatibility. So, if scontext0 & scontext1 are the same
773 ! a write to pcontext0 is sufficient.
774 !
775 mov MMU_SCONTEXT1, %g1
776 ldxa [%g1]ASI_MMU_CTX, %g3
777 cmp %g2, %g3
778 beq,pt %xcc, no_pctx1_update
779 mov MMU_PCONTEXT1, %g1
780 stxa %g3, [%g1]ASI_MMU_CTX
781
782 no_pctx1_update:
783 ! Ensure new ctxs take effect by the time the "retry" (below) completes
784 membar #Sync
785
786 !
787 ! setup trap regs
788 !
789 ldn [%l7 + PC_OFF], %g1
790 ldn [%l7 + nPC_OFF], %g2
791 ldx [%l7 + TSTATE_OFF], %l0
792 andn %l0, TSTATE_CWP, %g7
793 wrpr %g1, %tpc
794 wrpr %g2, %tnpc
795 !
796 ! switch "other" windows back to "normal" windows and
797 ! restore to window we originally trapped in
798 !
799 rdpr %otherwin, %g1
800 wrpr %g0, 0, %otherwin
801 add %l3, WSTATE_CLEAN_OFFSET, %l3 ! convert to "clean" wstate
802 wrpr %g0, %l3, %wstate
803 wrpr %g0, %g1, %canrestore
804 !
805 ! First attempt to restore from the watchpoint saved register window
806 tst %g1
807 bne,a 1f
808 clrn [%g6 + STACK_BIAS + MPCB_RSP0]
809 tst %fp
810 be,a 1f
811 clrn [%g6 + STACK_BIAS + MPCB_RSP0]
812 ! test for user return window in pcb
813 ldn [%g6 + STACK_BIAS + MPCB_RSP0], %g1
814 cmp %fp, %g1
815 bne 1f
816 clrn [%g6 + STACK_BIAS + MPCB_RSP0]
817 restored
818 restore
819 ! restore from user return window
820 RESTORE_V9WINDOW(%g6 + STACK_BIAS + MPCB_RWIN0)
821 !
822 ! Attempt to restore from the scond watchpoint saved register window
823 tst %fp
824 be,a 2f
825 clrn [%g6 + STACK_BIAS + MPCB_RSP1]
826 ldn [%g6 + STACK_BIAS + MPCB_RSP1], %g1
827 cmp %fp, %g1
828 bne 2f
829 clrn [%g6 + STACK_BIAS + MPCB_RSP1]
830 restored
831 restore
832 RESTORE_V9WINDOW(%g6 + STACK_BIAS + MPCB_RWIN1)
833 save
834 b,a 2f
835 1:
836 rdpr %canrestore, %g1
837 brnz %g1, 3f
838 nop ! no trap, use restore directly
839 rdpr %cwp, %g1
840 wrpr %g1, %g7, %tstate ! needed by wbuf recovery code
841 ! hand craft the restore to avoid getting to TL > 2
842 rdpr %wstate, %g1
843 btst 1, %g1
844 beq 4f
845 nop
846 .global rtt_fill_start
847 rtt_fill_start:
848 FILL_32bit_rtt(ASI_AIUP)
849 ba,a 3f
850 4:
851 FILL_64bit_rtt(ASI_AIUP)
852 .global rtt_fill_end
853 rtt_fill_end:
854 3:
855 restore ! should not trap
856 2:
857 !
858 ! set %cleanwin to %canrestore
859 ! set %tstate to the correct %cwp
860 ! retry resumes user execution
861 !
862 rdpr %canrestore, %g1
863 wrpr %g0, %g1, %cleanwin
864 rdpr %cwp, %g1
865 wrpr %g1, %g7, %tstate
866 retry
867 /* NOTREACHED */
868 SET_SIZE(user_rtt)
869 SET_SIZE(utl0)
870
871 ENTRY_NP(ptl0)
872 SAVE_GLOBALS(%l7)
873 SAVE_OUTS(%l7)
874 CPU_ADDR(%g5, %g6)
875 ldn [%g5 + CPU_THREAD], THREAD_REG
876 wrpr %g0, PSTATE_KERN, %pstate ! enable ints
877 jmpl %l3, %o7 ! call trap handler
878 mov %l7, %o0
879 !
880 ALTENTRY(prom_rtt)
881 #ifdef TRAPTRACE
882 TRACE_RTT(TT_SYS_RTT_PROM, %l0, %l1, %l2, %l3)
883 #endif /* TRAPTRACE */
884 ba,pt %xcc, common_rtt
885 mov THREAD_REG, %l0
886 SET_SIZE(prom_rtt)
887 SET_SIZE(ptl0)
888
889 ENTRY_NP(ktl0)
890 /*
891 * THREAD_REG cannot be restored in fault_32bit_fn1 since
892 * sun4v cannot safely lower %gl then raise it again.
893 */
894 CPU_ADDR(%l0, %l1)
895 ldn [%l0 + CPU_THREAD], THREAD_REG
896 SAVE_GLOBALS(%l7)
897 SAVE_OUTS(%l7) ! for the call bug workaround
898 wrpr %g0, PSTATE_KERN, %pstate ! enable ints
899 jmpl %l3, %o7 ! call trap handler
900 mov %l7, %o0
901 !
902 ALTENTRY(priv_rtt)
903 #ifdef TRAPTRACE
904 TRACE_RTT(TT_SYS_RTT_PRIV, %l0, %l1, %l2, %l3)
905 #endif /* TRAPTRACE */
906 !
907 ! Register inputs
908 ! %l7 - regs
909 ! %l6 - trap %pil
910 !
911 ! Check for a kernel preemption request
912 !
913 ldn [THREAD_REG + T_CPU], %l0
914 ldub [%l0 + CPU_KPRUNRUN], %l0
915 brz,pt %l0, 1f
916 nop
917
918 !
919 ! Attempt to preempt
920 !
921 ldstub [THREAD_REG + T_PREEMPT_LK], %l0 ! load preempt lock
922 brnz,pn %l0, 1f ! can't call kpreempt if this thread is
923 nop ! already in it...
924
925 call kpreempt
926 mov %l6, %o0 ! pass original interrupt level
927
928 stub %g0, [THREAD_REG + T_PREEMPT_LK] ! nuke the lock
929
930 rdpr %pil, %o0 ! compare old pil level
931 cmp %l6, %o0 ! with current pil level
932 movg %xcc, %o0, %l6 ! if current is lower, drop old pil
933 1:
934 !
935 ! If we interrupted the mutex_owner_running() critical region we
936 ! must reset ! the PC and nPC back to the beginning to prevent missed
937 ! wakeups. ! See the comments in mutex_exit() for details.
938 !
939 ldn [%l7 + PC_OFF], %l0
940 set mutex_owner_running_critical_start, %l1
941 sub %l0, %l1, %l0
942 cmp %l0, mutex_owner_running_critical_size
943 bgeu,pt %xcc, 2f
944 mov THREAD_REG, %l0
945 stn %l1, [%l7 + PC_OFF] ! restart mutex_owner_running()
946 add %l1, 4, %l1
947 ba,pt %xcc, common_rtt
948 stn %l1, [%l7 + nPC_OFF]
949
950 2:
951 !
952 ! If we interrupted the mutex_exit() critical region we must reset
953 ! the PC and nPC back to the beginning to prevent missed wakeups.
954 ! See the comments in mutex_exit() for details.
955 !
956 ldn [%l7 + PC_OFF], %l0
957 set mutex_exit_critical_start, %l1
958 sub %l0, %l1, %l0
959 cmp %l0, mutex_exit_critical_size
960 bgeu,pt %xcc, common_rtt
961 mov THREAD_REG, %l0
962 stn %l1, [%l7 + PC_OFF] ! restart mutex_exit()
963 add %l1, 4, %l1
964 stn %l1, [%l7 + nPC_OFF]
965
966 common_rtt:
967 !
968 ! restore globals and outs
969 !
970 rdpr %pstate, %l1
971 wrpr %l1, PSTATE_IE, %pstate
972 RESTORE_GLOBALS(%l7)
973 ! switch to global set 1
974 wrpr %g0, 1, %gl
975 RESTORE_OUTS(%l7)
976 !
977 ! set %pil from max(old pil, cpu_base_spl)
978 !
979 ldn [%l0 + T_CPU], %l0
980 ld [%l0 + CPU_BASE_SPL], %l0
981 cmp %l6, %l0
982 movg %xcc, %l6, %l0
983 wrpr %g0, %l0, %pil
984 !
985 ! raise tl
986 ! setup trap regs
987 ! restore to window we originally trapped in
988 !
989 wrpr %g0, 1, %tl
990 ldn [%l7 + PC_OFF], %g1
991 ldn [%l7 + nPC_OFF], %g2
992 ldx [%l7 + TSTATE_OFF], %l0
993 andn %l0, TSTATE_CWP, %g7
994 wrpr %g1, %tpc
995 wrpr %g2, %tnpc
996 rdpr %canrestore, %g1
997 brnz %g1, 3f
998 nop ! no trap, use restore directly
999 rdpr %cwp, %g1
1000 wrpr %g1, %g7, %tstate ! needed by wbuf recovery code
1001 ! hand craft the restore to avoid getting to TL > 2
1002 FILL_64bit_rtt(ASI_N)
1003 3:
1004 restore
1005 !
1006 ! set %tstate to the correct %cwp
1007 ! retry resumes prom execution
1008 !
1009 rdpr %cwp, %g1
1010 wrpr %g1, %g7, %tstate
1011 retry
1012 /* NOTREACHED */
1013 SET_SIZE(priv_rtt)
1014 SET_SIZE(ktl0)
1015
1016 #ifdef DEBUG
1017 .seg ".data"
1018 .align 4
1019
1020 .global bad_g4_called
1021 bad_g4_called:
1022 .word 0
1023
1024 sys_trap_wrong_pil:
1025 .asciz "sys_trap: %g4(%d) is lower than %pil(%d)"
1026 .align 4
1027 .seg ".text"
1028
1029 ENTRY_NP(bad_g4)
1030 mov %o1, %o0
1031 mov %o2, %o1
1032 call panic
1033 mov %o3, %o2
1034 SET_SIZE(bad_g4)
1035 #endif /* DEBUG */
1036
1037 /*
1038 * sys_tl1_panic can be called by traps at tl1 which
1039 * really want to panic, but need the rearrangement of
1040 * the args as provided by this wrapper routine.
1041 */
1042 ENTRY_NP(sys_tl1_panic)
1043 mov %o1, %o0
1044 mov %o2, %o1
1045 call panic
1046 mov %o3, %o2
1047 SET_SIZE(sys_tl1_panic)
1048
1049
1050 /*
1051 * Flush all windows to memory, except for the one we entered in.
1052 * We do this by doing NWINDOW-2 saves then the same number of restores.
1053 * This leaves the WIM immediately before window entered in.
1054 * This is used for context switching.
1055 */
1056
1057 ENTRY_NP(flush_windows)
1058 retl
1059 flushw
1060 SET_SIZE(flush_windows)
1061
1062 ENTRY_NP(debug_flush_windows)
1063 set nwindows, %g1
1064 ld [%g1], %g1
1065 mov %g1, %g2
1066
1067 1:
1068 save %sp, -WINDOWSIZE, %sp
1069 brnz %g2, 1b
1070 dec %g2
1071
1072 mov %g1, %g2
1073 2:
1074 restore
1075 brnz %g2, 2b
1076 dec %g2
1077
1078 retl
1079 nop
1080
1081 SET_SIZE(debug_flush_windows)
1082
1083 /*
1084 * flush user windows to memory.
1085 */
1086
1087 ENTRY_NP(flush_user_windows)
1088 rdpr %otherwin, %g1
1089 brz %g1, 3f
1090 clr %g2
1091 1:
1092 save %sp, -WINDOWSIZE, %sp
1093 rdpr %otherwin, %g1
1094 brnz %g1, 1b
1095 add %g2, 1, %g2
1096 2:
1097 sub %g2, 1, %g2 ! restore back to orig window
1098 brnz %g2, 2b
1099 restore
1100 3:
1101 retl
1102 nop
1103 SET_SIZE(flush_user_windows)
1104
1105 /*
1106 * Throw out any user windows in the register file.
1107 * Used by setregs (exec) to clean out old user.
1108 * Used by sigcleanup to remove extraneous windows when returning from a
1109 * signal.
1110 */
1111
1112 ENTRY_NP(trash_user_windows)
1113 rdpr %otherwin, %g1
1114 brz %g1, 3f ! no user windows?
1115 ldn [THREAD_REG + T_STACK], %g5
1116
1117 !
1118 ! There are old user windows in the register file. We disable ints
1119 ! and increment cansave so that we don't overflow on these windows.
1120 ! Also, this sets up a nice underflow when first returning to the
1121 ! new user.
1122 !
1123 rdpr %pstate, %g2
1124 wrpr %g2, PSTATE_IE, %pstate
1125 rdpr %cansave, %g3
1126 rdpr %otherwin, %g1 ! re-read in case of interrupt
1127 add %g3, %g1, %g3
1128 wrpr %g0, 0, %otherwin
1129 wrpr %g0, %g3, %cansave
1130 wrpr %g0, %g2, %pstate
1131 3:
1132 retl
1133 clr [%g5 + MPCB_WBCNT] ! zero window buffer cnt
1134 SET_SIZE(trash_user_windows)
1135
1136
1137 /*
1138 * Setup g7 via the CPU data structure.
1139 */
1140
1141 ENTRY_NP(set_tbr)
1142 retl
1143 ta 72 ! no tbr, stop simulation
1144 SET_SIZE(set_tbr)
1145
1146
1147 #define PTL1_SAVE_WINDOW(RP) \
1148 stxa %l0, [RP + RW64_LOCAL + (0 * RW64_LOCAL_INCR)] %asi; \
1149 stxa %l1, [RP + RW64_LOCAL + (1 * RW64_LOCAL_INCR)] %asi; \
1150 stxa %l2, [RP + RW64_LOCAL + (2 * RW64_LOCAL_INCR)] %asi; \
1151 stxa %l3, [RP + RW64_LOCAL + (3 * RW64_LOCAL_INCR)] %asi; \
1152 stxa %l4, [RP + RW64_LOCAL + (4 * RW64_LOCAL_INCR)] %asi; \
1153 stxa %l5, [RP + RW64_LOCAL + (5 * RW64_LOCAL_INCR)] %asi; \
1154 stxa %l6, [RP + RW64_LOCAL + (6 * RW64_LOCAL_INCR)] %asi; \
1155 stxa %l7, [RP + RW64_LOCAL + (7 * RW64_LOCAL_INCR)] %asi; \
1156 stxa %i0, [RP + RW64_IN + (0 * RW64_IN_INCR)] %asi; \
1157 stxa %i1, [RP + RW64_IN + (1 * RW64_IN_INCR)] %asi; \
1158 stxa %i2, [RP + RW64_IN + (2 * RW64_IN_INCR)] %asi; \
1159 stxa %i3, [RP + RW64_IN + (3 * RW64_IN_INCR)] %asi; \
1160 stxa %i4, [RP + RW64_IN + (4 * RW64_IN_INCR)] %asi; \
1161 stxa %i5, [RP + RW64_IN + (5 * RW64_IN_INCR)] %asi; \
1162 stxa %i6, [RP + RW64_IN + (6 * RW64_IN_INCR)] %asi; \
1163 stxa %i7, [RP + RW64_IN + (7 * RW64_IN_INCR)] %asi
1164 #define PTL1_NEXT_WINDOW(scr) \
1165 add scr, RWIN64SIZE, scr
1166
1167 #define PTL1_RESET_RWINDOWS(scr) \
1168 sethi %hi(nwin_minus_one), scr; \
1169 ld [scr + %lo(nwin_minus_one)], scr; \
1170 wrpr scr, %cleanwin; \
1171 dec scr; \
1172 wrpr scr, %cansave; \
1173 wrpr %g0, %canrestore; \
1174 wrpr %g0, %otherwin
1175
1176 #define PTL1_DCACHE_LINE_SIZE 4 /* small enough for all CPUs */
1177
1178 /*
1179 * ptl1_panic is called when the kernel detects that it is in an invalid state
1180 * and the trap level is greater than 0. ptl1_panic is responsible to save the
1181 * current CPU state, to restore the CPU state to normal, and to call panic.
1182 * The CPU state must be saved reliably without causing traps. ptl1_panic saves
1183 * it in the ptl1_state structure, which is a member of the machcpu structure.
1184 * In order to access the ptl1_state structure without causing traps, physical
1185 * addresses are used so that we can avoid MMU miss traps. The restriction of
1186 * physical memory accesses is that the ptl1_state structure must be on a single
1187 * physical page. This is because (1) a single physical address for each
1188 * ptl1_state structure is needed and (2) it simplifies physical address
1189 * calculation for each member of the structure.
1190 * ptl1_panic is a likely spot for stack overflows to wind up; thus, the current
1191 * stack may not be usable. In order to call panic reliably in such a state,
1192 * each CPU needs a dedicated ptl1 panic stack.
1193 * CPU_ALLOC_SIZE, which is defined to be MMU_PAGESIZE, is used to allocate the
1194 * cpu structure and a ptl1 panic stack. They are put together on the same page
1195 * for memory space efficiency. The low address part is used for the cpu
1196 * structure, and the high address part is for a ptl1 panic stack.
1197 * The cpu_pa array holds the physical addresses of the allocated cpu structures,
1198 * as the cpu array holds their virtual addresses.
1199 *
1200 * %g1 reason to be called
1201 * %g2 broken
1202 * %g3 broken
1203 */
1204 ENTRY_NP(ptl1_panic)
1205 !
1206 ! increment the entry counter.
1207 ! save CPU state if this is the first entry.
1208 !
1209 CPU_PADDR(%g2, %g3);
1210 add %g2, CPU_PTL1, %g2 ! pstate = &CPU->mcpu.ptl1_state
1211 wr %g0, ASI_MEM, %asi ! physical address access
1212 !
1213 ! pstate->ptl1_entry_count++
1214 !
1215 lduwa [%g2 + PTL1_ENTRY_COUNT] %asi, %g3
1216 add %g3, 1, %g3
1217 stuwa %g3, [%g2 + PTL1_ENTRY_COUNT] %asi
1218 !
1219 ! CPU state saving is skipped from the 2nd entry to ptl1_panic since we
1220 ! do not want to clobber the state from the original failure. panic()
1221 ! is responsible for handling multiple or recursive panics.
1222 !
1223 cmp %g3, 2 ! if (ptl1_entry_count >= 2)
1224 bge,pn %icc, state_saved ! goto state_saved
1225 add %g2, PTL1_REGS, %g3 ! %g3 = &pstate->ptl1_regs[0]
1226 !
1227 ! save CPU state
1228 !
1229 save_cpu_state:
1230 ! save current global registers
1231 ! so that all them become available for use
1232 !
1233 stxa %o1, [%g3 + PTL1_RWINDOW] %asi ! save %o1
1234 stxa %o2, [%g3 + PTL1_RWINDOW + 8] %asi ! save %o2
1235 stxa %o3, [%g3 + PTL1_RWINDOW + 16] %asi ! save %o3
1236 rdpr %gl, %o1
1237 add %g3, PTL1_GREGS, %o2 ! %o4 = &ptl1_gregs[0]
1238 mov %g3, %o3
1239 6:
1240 stxa %o1, [%o2 + PTL1_GL] %asi
1241 stxa %g1, [%o2 + PTL1_G1] %asi
1242 stxa %g2, [%o2 + PTL1_G2] %asi
1243 stxa %g3, [%o2 + PTL1_G3] %asi
1244 stxa %g4, [%o2 + PTL1_G4] %asi
1245 stxa %g5, [%o2 + PTL1_G5] %asi
1246 stxa %g6, [%o2 + PTL1_G6] %asi
1247 stxa %g7, [%o2 + PTL1_G7] %asi
1248 add %o2, PTL1_GREGS_INCR, %o2
1249 deccc %o1
1250 brgez,a,pt %o1, 6b
1251 wrpr %o1, %gl
1252 !
1253 ! restore %g3, %o1, %o2 and %o3
1254 !
1255 mov %o3, %g3
1256 ldxa [%g3 + PTL1_RWINDOW] %asi, %o1
1257 ldxa [%g3 + PTL1_RWINDOW + 8] %asi, %o2
1258 ldxa [%g3 + PTL1_RWINDOW + 16] %asi, %o3
1259 !
1260 ! %tl, %tt, %tstate, %tpc, %tnpc for each TL
1261 !
1262 rdpr %tl, %g1
1263 brz %g1, 1f ! if(trap_level == 0) -------+
1264 add %g3, PTL1_TRAP_REGS, %g4 ! %g4 = &ptl1_trap_regs[0]; !
1265 0: ! -----------<----------+ !
1266 stwa %g1, [%g4 + PTL1_TL] %asi ! !
1267 rdpr %tt, %g5 ! !
1268 stwa %g5, [%g4 + PTL1_TT] %asi ! !
1269 rdpr %tstate, %g5 ! !
1270 stxa %g5, [%g4 + PTL1_TSTATE] %asi ! !
1271 rdpr %tpc, %g5 ! !
1272 stxa %g5, [%g4 + PTL1_TPC] %asi ! !
1273 rdpr %tnpc, %g5 ! !
1274 stxa %g5, [%g4 + PTL1_TNPC] %asi ! !
1275 add %g4, PTL1_TRAP_REGS_INCR, %g4 ! !
1276 deccc %g1 ! !
1277 bnz,a,pt %icc, 0b ! if(trap_level != 0) --+ !
1278 wrpr %g1, %tl !
1279 1: ! ----------<----------------+
1280 !
1281 ! %pstate, %pil, SOFTINT, (S)TICK
1282 ! Pending interrupts is also cleared in order to avoid a recursive call
1283 ! to ptl1_panic in case the interrupt handler causes a panic.
1284 !
1285 rdpr %pil, %g1
1286 stba %g1, [%g3 + PTL1_PIL] %asi
1287 rdpr %pstate, %g1
1288 stha %g1, [%g3 + PTL1_PSTATE] %asi
1289 rd SOFTINT, %g1
1290 sta %g1, [%g3 + PTL1_SOFTINT] %asi
1291 wr %g1, CLEAR_SOFTINT
1292 RD_TICKSTICK_FLAG(%g1, %g4, traptrace_use_stick)
1293 stxa %g1, [%g3 + PTL1_TICK] %asi
1294
1295 MMU_FAULT_STATUS_AREA(%g1)
1296 ldx [%g1 + MMFSA_D_TYPE], %g4
1297 stxa %g4, [%g3 + PTL1_DMMU_TYPE] %asi
1298 ldx [%g1 + MMFSA_D_ADDR], %g4
1299 stxa %g4, [%g3 + PTL1_DMMU_ADDR] %asi
1300 ldx [%g1 + MMFSA_D_CTX], %g4
1301 stxa %g4, [%g3 + PTL1_DMMU_CTX] %asi
1302 ldx [%g1 + MMFSA_I_TYPE], %g4
1303 stxa %g4, [%g3 + PTL1_IMMU_TYPE] %asi
1304 ldx [%g1 + MMFSA_I_ADDR], %g4
1305 stxa %g4, [%g3 + PTL1_IMMU_ADDR] %asi
1306 ldx [%g1 + MMFSA_I_CTX], %g4
1307 stxa %g4, [%g3 + PTL1_IMMU_CTX] %asi
1308
1309 !
1310 ! Save register window state and register windows.
1311 !
1312 rdpr %cwp, %g1
1313 stba %g1, [%g3 + PTL1_CWP] %asi
1314 rdpr %wstate, %g1
1315 stba %g1, [%g3 + PTL1_WSTATE] %asi
1316 rdpr %otherwin, %g1
1317 stba %g1, [%g3 + PTL1_OTHERWIN] %asi
1318 rdpr %cleanwin, %g1
1319 stba %g1, [%g3 + PTL1_CLEANWIN] %asi
1320 rdpr %cansave, %g1
1321 stba %g1, [%g3 + PTL1_CANSAVE] %asi
1322 rdpr %canrestore, %g1
1323 stba %g1, [%g3 + PTL1_CANRESTORE] %asi
1324
1325 PTL1_RESET_RWINDOWS(%g1)
1326 clr %g1
1327 wrpr %g1, %cwp
1328 add %g3, PTL1_RWINDOW, %g4 ! %g4 = &ptl1_rwindow[0];
1329
1330 3: PTL1_SAVE_WINDOW(%g4) ! <-------------+
1331 inc %g1 !
1332 cmp %g1, MAXWIN !
1333 bgeu,pn %icc, 5f !
1334 wrpr %g1, %cwp !
1335 rdpr %cwp, %g2 !
1336 cmp %g1, %g2 ! saturation check
1337 be,pt %icc, 3b !
1338 PTL1_NEXT_WINDOW(%g4) ! ------+
1339 5:
1340 !
1341 ! most crucial CPU state was saved.
1342 ! Proceed to go back to TL = 0.
1343 !
1344 state_saved:
1345 wrpr %g0, 1, %tl
1346 wrpr %g0, 1, %gl
1347 wrpr %g0, PIL_MAX, %pil
1348 !
1349 PTL1_RESET_RWINDOWS(%g1)
1350 wrpr %g0, %cwp
1351 wrpr %g0, %cleanwin
1352 wrpr %g0, WSTATE_KERN, %wstate
1353 !
1354 ! Set pcontext to run kernel.
1355 !
1356 set MMU_PCONTEXT, %g1
1357 stxa %g0, [%g1]ASI_MMU_CTX
1358 membar #Sync
1359
1360 rdpr %cwp, %g1
1361 set TSTATE_KERN, %g3
1362 wrpr %g3, %g1, %tstate
1363 set ptl1_panic_tl0, %g3
1364 wrpr %g0, %g3, %tnpc
1365 done ! go to -->-+ TL:1
1366 !
1367 ptl1_panic_tl0: ! ----<-----+ TL:0
1368 CPU_ADDR(%l0, %l1) ! %l0 = cpu[cpuid]
1369 add %l0, CPU_PTL1, %l1 ! %l1 = &CPU->mcpu.ptl1_state
1370 !
1371 ! prepare to call panic()
1372 !
1373 ldn [%l0 + CPU_THREAD], THREAD_REG ! restore %g7
1374 ldn [%l1 + PTL1_STKTOP], %l2 ! %sp = ptl1_stktop
1375 sub %l2, SA(MINFRAME) + STACK_BIAS, %sp
1376 clr %fp ! no frame below this window
1377 clr %i7
1378 !
1379 ! enable limited interrupts
1380 !
1381 wrpr %g0, CLOCK_LEVEL, %pil
1382 wrpr %g0, PSTATE_KERN, %pstate
1383 !
1384 ba,pt %xcc, ptl1_panic_handler
1385 mov %l1, %o0
1386 /*NOTREACHED*/
1387 SET_SIZE(ptl1_panic)
1388
1389 #ifdef PTL1_PANIC_DEBUG
1390
1391 /*
1392 * ptl1_recurse() calls itself a number of times to either set up a known
1393 * stack or to cause a kernel stack overflow. It decrements the arguments
1394 * on each recursion.
1395 * It's called by #ifdef PTL1_PANIC_DEBUG code in startup.c to set the
1396 * registers to a known state to facilitate debugging.
1397 */
1398 ENTRY_NP(ptl1_recurse)
1399 save %sp, -SA(MINFRAME), %sp
1400
1401 set ptl1_recurse_call, %o7
1402 cmp %o7, %i7 ! if ptl1_recurse is called
1403 be,pt %icc, 0f ! by itself, then skip
1404 nop ! register initialization
1405
1406 /*
1407 * Initialize Out Registers to Known Values
1408 */
1409 set 0x01000, %l0 ! %i0 is the ...
1410 ! recursion_depth_count
1411 sub %i0, 1, %o0;
1412 sub %i1, 1, %o1;
1413 add %l0, %o0, %o2;
1414 add %l0, %o2, %o3;
1415 add %l0, %o3, %o4;
1416 add %l0, %o4, %o5;
1417 ba,a 1f
1418 nop
1419
1420 0: /* Outs = Ins - 1 */
1421 sub %i0, 1, %o0;
1422 sub %i1, 1, %o1;
1423 sub %i2, 1, %o2;
1424 sub %i3, 1, %o3;
1425 sub %i4, 1, %o4;
1426 sub %i5, 1, %o5;
1427
1428 /* Locals = Ins + 1 */
1429 1: add %i0, 1, %l0;
1430 add %i1, 1, %l1;
1431 add %i2, 1, %l2;
1432 add %i3, 1, %l3;
1433 add %i4, 1, %l4;
1434 add %i5, 1, %l5;
1435
1436 set 0x0100000, %g5
1437 add %g5, %g0, %g1
1438 add %g5, %g1, %g2
1439 add %g5, %g2, %g3
1440 add %g5, %g3, %g4
1441 add %g5, %g4, %g5
1442
1443 brz,pn %i1, ptl1_recurse_trap ! if trpp_count == 0) {
1444 nop ! trap to ptl1_panic
1445 !
1446 brz,pn %i0, ptl1_recure_exit ! if(depth_count == 0) {
1447 nop ! skip recursive call
1448 ! }
1449 ptl1_recurse_call:
1450 call ptl1_recurse
1451 nop
1452
1453 ptl1_recure_exit:
1454 ret
1455 restore
1456
1457 ptl1_recurse_trap:
1458 ta PTL1_DEBUG_TRAP; ! Trap Always to ptl1_panic()
1459 nop ! NOTREACHED
1460 SET_SIZE(ptl1_recurse)
1461
1462 /*
1463 * Asm function to handle a cross trap to call ptl1_panic()
1464 */
1465 ENTRY_NP(ptl1_panic_xt)
1466 ba ptl1_panic
1467 mov PTL1_BAD_DEBUG, %g1
1468 SET_SIZE(ptl1_panic_xt)
1469
1470 #endif /* PTL1_PANIC_DEBUG */
1471
1472 #ifdef TRAPTRACE
1473
1474 ENTRY_NP(trace_ptr_panic)
1475 !
1476 ! freeze the trap trace to disable the assertions. Otherwise,
1477 ! ptl1_panic is likely to be repeatedly called from there.
1478 ! %g2 and %g3 are used as scratch registers in ptl1_panic.
1479 !
1480 mov 1, %g3
1481 sethi %hi(trap_freeze), %g2
1482 st %g3, [%g2 + %lo(trap_freeze)]
1483 !
1484 ! %g1 contains the %pc address where an assertion was failed.
1485 ! save it in trap_freeze_pc for a debugging hint if there is
1486 ! no value saved in it.
1487 !
1488 set trap_freeze_pc, %g2
1489 casn [%g2], %g0, %g1
1490
1491 ba ptl1_panic
1492 mov PTL1_BAD_TRACE_PTR, %g1
1493 SET_SIZE(trace_ptr_panic)
1494
1495 #endif /* TRAPTRACE */
1496
1497 /*
1498 * The interface for a 32-bit client program that takes over the TBA
1499 * calling the 64-bit romvec OBP.
1500 */
1501
1502 ENTRY(client_handler)
1503 save %sp, -SA64(MINFRAME64), %sp ! 32 bit frame, 64 bit sized
1504 sethi %hi(tba_taken_over), %l2
1505 ld [%l2+%lo(tba_taken_over)], %l3
1506 brz %l3, 1f ! is the tba_taken_over = 1 ?
1507 rdpr %wstate, %l5 ! save %wstate
1508 andn %l5, WSTATE_MASK, %l6
1509 wrpr %l6, WSTATE_KMIX, %wstate
1510 1: mov %i1, %o0
1511 1: rdpr %pstate, %l4 ! Get the present pstate value
1512 andn %l4, PSTATE_AM, %l6
1513 wrpr %l6, 0, %pstate ! Set PSTATE_AM = 0
1514 jmpl %i0, %o7 ! Call cif handler
1515 nop
1516 wrpr %l4, 0, %pstate ! restore pstate
1517 brz %l3, 1f ! is the tba_taken_over = 1
1518 nop
1519 wrpr %g0, %l5, %wstate ! restore wstate
1520 1: ret ! Return result ...
1521 restore %o0, %g0, %o0 ! delay; result in %o0
1522 SET_SIZE(client_handler)
1523
1524 .seg ".text"
1525 bad_hcall_error:
1526 .asciz "hypervisor call 0x%x returned an unexpected error %d"
1527
1528 /*
1529 * panic_bad_hcall is called when a hcall returns
1530 * unexpected error
1531 * %o0 error number
1532 * %o1 hcall number
1533 */
1534
1535 ENTRY(panic_bad_hcall)
1536 mov %o0, %o2
1537 sethi %hi(bad_hcall_error), %o0
1538 or %o0, %lo(bad_hcall_error), %o0
1539 mov %o7, %o3
1540 call panic
1541 mov %o3, %o7
1542 SET_SIZE(panic_bad_hcall)
1543
--- EOF ---