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 #if defined(lint)
27 #include <sys/types.h>
28 #include <sys/t_lock.h>
29 #include <sys/promif.h>
30 #include <sys/prom_isa.h>
31 #endif /* lint */
32
33 #include <sys/asm_linkage.h>
34 #include <sys/intreg.h>
35 #include <sys/ivintr.h>
36 #include <sys/mmu.h>
37 #include <sys/machpcb.h>
38 #include <sys/machtrap.h>
39 #include <sys/machlock.h>
40 #include <sys/fdreg.h>
41 #include <sys/vis.h>
42 #include <sys/traptrace.h>
43 #include <sys/panic.h>
44 #include <sys/machasi.h>
45 #include <sys/privregs.h>
46 #include <sys/hypervisor_api.h>
47 #include <sys/clock.h>
48
49 #if defined(lint)
50
51 #include <sys/thread.h>
52 #include <sys/time.h>
53
54 #else /* lint */
55
56 #include "assym.h"
57
58
59 !
60 ! REGOFF must add up to allow double word access to r_tstate.
61 ! PCB_WBUF must also be aligned.
62 !
63 #if (REGOFF & 7) != 0
64 #error "struct regs not aligned"
65 #endif
66
67 /*
68 * Absolute external symbols.
69 * On the sun4u we put the panic buffer in the third and fourth pages.
70 * We set things up so that the first 2 pages of KERNELBASE is illegal
71 * to act as a redzone during copyin/copyout type operations. One of
72 * the reasons the panic buffer is allocated in low memory to
73 * prevent being overwritten during booting operations (besides
74 * the fact that it is small enough to share pages with others).
75 */
165 * show in which TRACE_PTR the assertion failure happened.
166 */
167 .align 8
168 trap_freeze_pc:
169 .nword 0
170 #endif /* TRAPTRACE */
171
172 .align 4
173 .seg ".text"
174
175 #ifdef NOPROM
176 .global availmem
177 availmem:
178 .word 0
179 #endif /* NOPROM */
180
181 .align 8
182 _local_p1275cis:
183 .nword 0
184
185 #endif /* lint */
186
187 #if defined(lint)
188
189 void
190 _start(void)
191 {}
192
193 #else /* lint */
194
195 .seg ".data"
196
197 .global nwindows, nwin_minus_one, winmask
198 nwindows:
199 .word 8
200 nwin_minus_one:
201 .word 7
202 winmask:
203 .word 8
204
205 .global afsrbuf
206 afsrbuf:
207 .word 0,0,0,0
208
209 /*
210 * System initialization
211 *
212 * Our contract with the boot prom specifies that the MMU is on and the
213 * first 16 meg of memory is mapped with a level-1 pte. We are called
214 * with p1275cis ptr in %o0 and kdi_dvec in %o1; we start execution
347 #endif
348
349 !
350 ! Now call main. We will return as process 1 (init).
351 !
352 call main
353 nop
354
355 !
356 ! Main should never return.
357 !
358 set .mainretmsg, %o0
359 call panic
360 nop
361 SET_SIZE(_start)
362
363 .mainretmsg:
364 .asciz "main returned"
365 .align 4
366
367 #endif /* lint */
368
369
370 /*
371 * Generic system trap handler.
372 *
373 * Some kernel trap handlers save themselves from buying a window by
374 * borrowing some of sys_trap's unused locals. %l0 thru %l3 may be used
375 * for this purpose, as user_rtt and priv_rtt do not depend on them.
376 * %l4 thru %l7 should NOT be used this way.
377 *
378 * Entry Conditions:
379 * %pstate am:0 priv:1 ie:0
380 * %gl global level 1
381 *
382 * Register Inputs:
383 * %g1 pc of trap handler
384 * %g2, %g3 args for handler
385 * %g4 desired %pil (-1 means current %pil)
386 * %g5, %g6 destroyed
387 * %g7 saved
388 *
389 * Register Usage:
390 * %l0, %l1 temps
391 * %l3 saved %g1
392 * %l6 curthread for user traps, %pil for priv traps
393 * %l7 regs
394 *
395 * Called function prototype variants:
396 *
397 * func(struct regs *rp);
398 * func(struct regs *rp, uintptr_t arg1 [%g2], uintptr_t arg2 [%g3])
399 * func(struct regs *rp, uintptr_t arg1 [%g2],
400 * uint32_t arg2 [%g3.l], uint32_t arg3 [%g3.h])
401 * func(struct regs *rp, uint32_t arg1 [%g2.l],
402 * uint32_t arg2 [%g3.l], uint32_t arg3 [%g3.h], uint32_t [%g2.h])
403 */
404
405 #if defined(lint)
406
407 void
408 sys_trap(void)
409 {}
410
411 #else /* lint */
412
413 ENTRY_NP(sys_trap)
414 #ifdef DEBUG
415 ! Assert gl == 1
416 rdpr %gl, %g5
417 cmp %g5, 1
418 bne,a,pn %xcc, ptl1_panic
419 mov PTL1_BAD_GL, %g1
420 #endif
421
422 !
423 ! force tl=1, update %cwp, branch to correct handler
424 !
425
426 wrpr %g0, 1, %tl
427 rdpr %tstate, %g5
428 btst TSTATE_PRIV, %g5
429 and %g5, TSTATE_CWP, %g6
430 bnz,pn %xcc, priv_trap
431 wrpr %g0, %g6, %cwp
432
1030 rdpr %canrestore, %g1
1031 brnz %g1, 3f
1032 nop ! no trap, use restore directly
1033 rdpr %cwp, %g1
1034 wrpr %g1, %g7, %tstate ! needed by wbuf recovery code
1035 ! hand craft the restore to avoid getting to TL > 2
1036 FILL_64bit_rtt(ASI_N)
1037 3:
1038 restore
1039 !
1040 ! set %tstate to the correct %cwp
1041 ! retry resumes prom execution
1042 !
1043 rdpr %cwp, %g1
1044 wrpr %g1, %g7, %tstate
1045 retry
1046 /* NOTREACHED */
1047 SET_SIZE(priv_rtt)
1048 SET_SIZE(ktl0)
1049
1050 #endif /* lint */
1051
1052 #ifndef lint
1053
1054 #ifdef DEBUG
1055 .seg ".data"
1056 .align 4
1057
1058 .global bad_g4_called
1059 bad_g4_called:
1060 .word 0
1061
1062 sys_trap_wrong_pil:
1063 .asciz "sys_trap: %g4(%d) is lower than %pil(%d)"
1064 .align 4
1065 .seg ".text"
1066
1067 ENTRY_NP(bad_g4)
1068 mov %o1, %o0
1069 mov %o2, %o1
1070 call panic
1071 mov %o3, %o2
1072 SET_SIZE(bad_g4)
1073 #endif /* DEBUG */
1074 #endif /* lint */
1075
1076 /*
1077 * sys_tl1_panic can be called by traps at tl1 which
1078 * really want to panic, but need the rearrangement of
1079 * the args as provided by this wrapper routine.
1080 */
1081 #if defined(lint)
1082
1083 void
1084 sys_tl1_panic(void)
1085 {}
1086
1087 #else /* lint */
1088 ENTRY_NP(sys_tl1_panic)
1089 mov %o1, %o0
1090 mov %o2, %o1
1091 call panic
1092 mov %o3, %o2
1093 SET_SIZE(sys_tl1_panic)
1094 #endif /* lint */
1095
1096
1097 /*
1098 * Flush all windows to memory, except for the one we entered in.
1099 * We do this by doing NWINDOW-2 saves then the same number of restores.
1100 * This leaves the WIM immediately before window entered in.
1101 * This is used for context switching.
1102 */
1103
1104 #if defined(lint)
1105
1106 void
1107 flush_windows(void)
1108 {}
1109
1110 #else /* lint */
1111
1112 ENTRY_NP(flush_windows)
1113 retl
1114 flushw
1115 SET_SIZE(flush_windows)
1116
1117 #endif /* lint */
1118
1119 #if defined(lint)
1120
1121 void
1122 debug_flush_windows(void)
1123 {}
1124
1125 #else /* lint */
1126
1127 ENTRY_NP(debug_flush_windows)
1128 set nwindows, %g1
1129 ld [%g1], %g1
1130 mov %g1, %g2
1131
1132 1:
1133 save %sp, -WINDOWSIZE, %sp
1134 brnz %g2, 1b
1135 dec %g2
1136
1137 mov %g1, %g2
1138 2:
1139 restore
1140 brnz %g2, 2b
1141 dec %g2
1142
1143 retl
1144 nop
1145
1146 SET_SIZE(debug_flush_windows)
1147
1148 #endif /* lint */
1149
1150 /*
1151 * flush user windows to memory.
1152 */
1153
1154 #if defined(lint)
1155
1156 void
1157 flush_user_windows(void)
1158 {}
1159
1160 #else /* lint */
1161
1162 ENTRY_NP(flush_user_windows)
1163 rdpr %otherwin, %g1
1164 brz %g1, 3f
1165 clr %g2
1166 1:
1167 save %sp, -WINDOWSIZE, %sp
1168 rdpr %otherwin, %g1
1169 brnz %g1, 1b
1170 add %g2, 1, %g2
1171 2:
1172 sub %g2, 1, %g2 ! restore back to orig window
1173 brnz %g2, 2b
1174 restore
1175 3:
1176 retl
1177 nop
1178 SET_SIZE(flush_user_windows)
1179
1180 #endif /* lint */
1181
1182 /*
1183 * Throw out any user windows in the register file.
1184 * Used by setregs (exec) to clean out old user.
1185 * Used by sigcleanup to remove extraneous windows when returning from a
1186 * signal.
1187 */
1188
1189 #if defined(lint)
1190
1191 void
1192 trash_user_windows(void)
1193 {}
1194
1195 #else /* lint */
1196
1197 ENTRY_NP(trash_user_windows)
1198 rdpr %otherwin, %g1
1199 brz %g1, 3f ! no user windows?
1200 ldn [THREAD_REG + T_STACK], %g5
1201
1202 !
1203 ! There are old user windows in the register file. We disable ints
1204 ! and increment cansave so that we don't overflow on these windows.
1205 ! Also, this sets up a nice underflow when first returning to the
1206 ! new user.
1207 !
1208 rdpr %pstate, %g2
1209 wrpr %g2, PSTATE_IE, %pstate
1210 rdpr %cansave, %g3
1211 rdpr %otherwin, %g1 ! re-read in case of interrupt
1212 add %g3, %g1, %g3
1213 wrpr %g0, 0, %otherwin
1214 wrpr %g0, %g3, %cansave
1215 wrpr %g0, %g2, %pstate
1216 3:
1217 retl
1218 clr [%g5 + MPCB_WBCNT] ! zero window buffer cnt
1219 SET_SIZE(trash_user_windows)
1220
1221
1222 #endif /* lint */
1223
1224 /*
1225 * Setup g7 via the CPU data structure.
1226 */
1227 #if defined(lint)
1228
1229 struct scb *
1230 set_tbr(struct scb *s)
1231 { return (s); }
1232
1233 #else /* lint */
1234
1235 ENTRY_NP(set_tbr)
1236 retl
1237 ta 72 ! no tbr, stop simulation
1238 SET_SIZE(set_tbr)
1239
1240 #endif /* lint */
1241
1242
1243 #if defined(lint)
1244 /*
1245 * These need to be defined somewhere to lint and there is no "hicore.s"...
1246 */
1247 char etext[1], end[1];
1248 #endif /* lint*/
1249
1250 #if defined (lint)
1251
1252 /* ARGSUSED */
1253 void
1254 ptl1_panic(u_int reason)
1255 {}
1256
1257 #else /* lint */
1258
1259 #define PTL1_SAVE_WINDOW(RP) \
1260 stxa %l0, [RP + RW64_LOCAL + (0 * RW64_LOCAL_INCR)] %asi; \
1261 stxa %l1, [RP + RW64_LOCAL + (1 * RW64_LOCAL_INCR)] %asi; \
1262 stxa %l2, [RP + RW64_LOCAL + (2 * RW64_LOCAL_INCR)] %asi; \
1263 stxa %l3, [RP + RW64_LOCAL + (3 * RW64_LOCAL_INCR)] %asi; \
1264 stxa %l4, [RP + RW64_LOCAL + (4 * RW64_LOCAL_INCR)] %asi; \
1265 stxa %l5, [RP + RW64_LOCAL + (5 * RW64_LOCAL_INCR)] %asi; \
1266 stxa %l6, [RP + RW64_LOCAL + (6 * RW64_LOCAL_INCR)] %asi; \
1267 stxa %l7, [RP + RW64_LOCAL + (7 * RW64_LOCAL_INCR)] %asi; \
1268 stxa %i0, [RP + RW64_IN + (0 * RW64_IN_INCR)] %asi; \
1269 stxa %i1, [RP + RW64_IN + (1 * RW64_IN_INCR)] %asi; \
1270 stxa %i2, [RP + RW64_IN + (2 * RW64_IN_INCR)] %asi; \
1271 stxa %i3, [RP + RW64_IN + (3 * RW64_IN_INCR)] %asi; \
1272 stxa %i4, [RP + RW64_IN + (4 * RW64_IN_INCR)] %asi; \
1273 stxa %i5, [RP + RW64_IN + (5 * RW64_IN_INCR)] %asi; \
1274 stxa %i6, [RP + RW64_IN + (6 * RW64_IN_INCR)] %asi; \
1275 stxa %i7, [RP + RW64_IN + (7 * RW64_IN_INCR)] %asi
1276 #define PTL1_NEXT_WINDOW(scr) \
1277 add scr, RWIN64SIZE, scr
1278
1480 CPU_ADDR(%l0, %l1) ! %l0 = cpu[cpuid]
1481 add %l0, CPU_PTL1, %l1 ! %l1 = &CPU->mcpu.ptl1_state
1482 !
1483 ! prepare to call panic()
1484 !
1485 ldn [%l0 + CPU_THREAD], THREAD_REG ! restore %g7
1486 ldn [%l1 + PTL1_STKTOP], %l2 ! %sp = ptl1_stktop
1487 sub %l2, SA(MINFRAME) + STACK_BIAS, %sp
1488 clr %fp ! no frame below this window
1489 clr %i7
1490 !
1491 ! enable limited interrupts
1492 !
1493 wrpr %g0, CLOCK_LEVEL, %pil
1494 wrpr %g0, PSTATE_KERN, %pstate
1495 !
1496 ba,pt %xcc, ptl1_panic_handler
1497 mov %l1, %o0
1498 /*NOTREACHED*/
1499 SET_SIZE(ptl1_panic)
1500 #endif /* lint */
1501
1502 #ifdef PTL1_PANIC_DEBUG
1503 #if defined (lint)
1504 /*
1505 * ptl1_recurse() calls itself a number of times to either set up a known
1506 * stack or to cause a kernel stack overflow. It decrements the arguments
1507 * on each recursion.
1508 * It's called by #ifdef PTL1_PANIC_DEBUG code in startup.c to set the
1509 * registers to a known state to facilitate debugging.
1510 */
1511
1512 /* ARGSUSED */
1513 void
1514 ptl1_recurse(int count_threshold, int trap_threshold)
1515 {}
1516
1517 #else /* lint */
1518
1519 ENTRY_NP(ptl1_recurse)
1520 save %sp, -SA(MINFRAME), %sp
1521
1522 set ptl1_recurse_call, %o7
1523 cmp %o7, %i7 ! if ptl1_recurse is called
1524 be,pt %icc, 0f ! by itself, then skip
1525 nop ! register initialization
1526
1527 /*
1528 * Initialize Out Registers to Known Values
1529 */
1530 set 0x01000, %l0 ! %i0 is the ...
1531 ! recursion_depth_count
1532 sub %i0, 1, %o0;
1533 sub %i1, 1, %o1;
1534 add %l0, %o0, %o2;
1535 add %l0, %o2, %o3;
1536 add %l0, %o3, %o4;
1537 add %l0, %o4, %o5;
1538 ba,a 1f
1563
1564 brz,pn %i1, ptl1_recurse_trap ! if trpp_count == 0) {
1565 nop ! trap to ptl1_panic
1566 !
1567 brz,pn %i0, ptl1_recure_exit ! if(depth_count == 0) {
1568 nop ! skip recursive call
1569 ! }
1570 ptl1_recurse_call:
1571 call ptl1_recurse
1572 nop
1573
1574 ptl1_recure_exit:
1575 ret
1576 restore
1577
1578 ptl1_recurse_trap:
1579 ta PTL1_DEBUG_TRAP; ! Trap Always to ptl1_panic()
1580 nop ! NOTREACHED
1581 SET_SIZE(ptl1_recurse)
1582
1583 #endif /* lint */
1584
1585 #if defined (lint)
1586
1587 /* ARGSUSED */
1588 void
1589 ptl1_panic_xt(int arg1, int arg2)
1590 {}
1591
1592 #else /* lint */
1593 /*
1594 * Asm function to handle a cross trap to call ptl1_panic()
1595 */
1596 ENTRY_NP(ptl1_panic_xt)
1597 ba ptl1_panic
1598 mov PTL1_BAD_DEBUG, %g1
1599 SET_SIZE(ptl1_panic_xt)
1600
1601 #endif /* lint */
1602
1603 #endif /* PTL1_PANIC_DEBUG */
1604
1605 #ifdef TRAPTRACE
1606 #if defined (lint)
1607
1608 void
1609 trace_ptr_panic(void)
1610 {
1611 }
1612
1613 #else /* lint */
1614
1615 ENTRY_NP(trace_ptr_panic)
1616 !
1617 ! freeze the trap trace to disable the assertions. Otherwise,
1618 ! ptl1_panic is likely to be repeatedly called from there.
1619 ! %g2 and %g3 are used as scratch registers in ptl1_panic.
1620 !
1621 mov 1, %g3
1622 sethi %hi(trap_freeze), %g2
1623 st %g3, [%g2 + %lo(trap_freeze)]
1624 !
1625 ! %g1 contains the %pc address where an assertion was failed.
1626 ! save it in trap_freeze_pc for a debugging hint if there is
1627 ! no value saved in it.
1628 !
1629 set trap_freeze_pc, %g2
1630 casn [%g2], %g0, %g1
1631
1632 ba ptl1_panic
1633 mov PTL1_BAD_TRACE_PTR, %g1
1634 SET_SIZE(trace_ptr_panic)
1635
1636 #endif /* lint */
1637 #endif /* TRAPTRACE */
1638
1639 /*
1640 * The interface for a 32-bit client program that takes over the TBA
1641 * calling the 64-bit romvec OBP.
1642 */
1643
1644 #if defined(lint)
1645
1646 /* ARGSUSED */
1647 int
1648 client_handler(void *cif_handler, void *arg_array)
1649 { return 0; }
1650
1651 #else /* lint */
1652
1653 ENTRY(client_handler)
1654 save %sp, -SA64(MINFRAME64), %sp ! 32 bit frame, 64 bit sized
1655 sethi %hi(tba_taken_over), %l2
1656 ld [%l2+%lo(tba_taken_over)], %l3
1657 brz %l3, 1f ! is the tba_taken_over = 1 ?
1658 rdpr %wstate, %l5 ! save %wstate
1659 andn %l5, WSTATE_MASK, %l6
1660 wrpr %l6, WSTATE_KMIX, %wstate
1661 1: mov %i1, %o0
1662 1: rdpr %pstate, %l4 ! Get the present pstate value
1663 andn %l4, PSTATE_AM, %l6
1664 wrpr %l6, 0, %pstate ! Set PSTATE_AM = 0
1665 jmpl %i0, %o7 ! Call cif handler
1666 nop
1667 wrpr %l4, 0, %pstate ! restore pstate
1668 brz %l3, 1f ! is the tba_taken_over = 1
1669 nop
1670 wrpr %g0, %l5, %wstate ! restore wstate
1671 1: ret ! Return result ...
1672 restore %o0, %g0, %o0 ! delay; result in %o0
1673 SET_SIZE(client_handler)
1674
1675 #endif /* lint */
1676
1677 #if defined(lint)
1678
1679 /*ARGSUSED*/
1680 void
1681 panic_bad_hcall(uint64_t err, uint64_t hcall)
1682 {}
1683
1684 #else /* lint */
1685
1686 .seg ".text"
1687 bad_hcall_error:
1688 .asciz "hypervisor call 0x%x returned an unexpected error %d"
1689
1690 /*
1691 * panic_bad_hcall is called when a hcall returns
1692 * unexpected error
1693 * %o0 error number
1694 * %o1 hcall number
1695 */
1696
1697 ENTRY(panic_bad_hcall)
1698 mov %o0, %o2
1699 sethi %hi(bad_hcall_error), %o0
1700 or %o0, %lo(bad_hcall_error), %o0
1701 mov %o7, %o3
1702 call panic
1703 mov %o3, %o7
1704 SET_SIZE(panic_bad_hcall)
1705
1706 #endif /* lint */
|
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 */
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
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
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
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
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
|