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/trap.h>
27 #include <sys/machtrap.h>
28 #include <sys/machsystm.h>
29 #include <sys/cpu_module.h>
30 #include <sys/panic.h>
31 #include <sys/uadmin.h>
32 #include <sys/kobj.h>
33 #include <vm/hat_sfmmu.h>
34 #include <sys/reboot.h>
35
36 #ifdef TRAPTRACE
37 #include <sys/traptrace.h>
38 #endif
39
40 void showregs(unsigned, struct regs *, caddr_t, uint_t);
41
42 extern int tudebug;
43
44 void
mmu_print_sfsr(uint_t sfsr)45 mmu_print_sfsr(uint_t sfsr)
46 {
47 printf("MMU sfsr=%x:", sfsr);
48 switch (X_FAULT_TYPE(sfsr)) {
49 case FT_NONE:
50 printf(" No error");
51 break;
52 case FT_PRIV:
53 printf(" Privilege violation");
54 break;
55 case FT_SPEC_LD:
56 printf(" Speculative load on E-bit page");
57 break;
58 case FT_ATOMIC_NC:
59 printf(" Atomic to uncacheable page");
60 break;
61 case FT_ILL_ALT:
62 printf(" Illegal lda or sta");
63 break;
64 case FT_NFO:
65 printf(" Normal access to NFO page");
66 break;
67 case FT_RANGE:
68 printf(" Data or instruction address out of range");
69 break;
70 case FT_RANGE_REG:
71 printf(" Jump to register out of range");
72 break;
73 default:
74 printf(" Unknown error");
75 break;
76 }
77 if (sfsr) {
78 printf(" on ASI 0x%x E %d CID %d PRIV %d W %d OW %d FV %d",
79 (sfsr & SFSR_ASI) >> SFSR_ASI_SHIFT,
80 (sfsr & SFSR_E) != 0,
81 (sfsr & SFSR_CTX) >> SFSR_CT_SHIFT,
82 (sfsr & SFSR_PR) != 0,
83 (sfsr & SFSR_W) != 0,
84 (sfsr & SFSR_OW) != 0,
85 (sfsr & SFSR_FV) != 0);
86 }
87 printf("\n");
88 }
89
90 #ifdef TRAPWINDOW
91 long trap_window[25];
92 #endif /* TRAPWINDOW */
93
94 /*
95 * Print out debugging info.
96 */
97 /*ARGSUSED*/
98 void
showregs(uint_t type,struct regs * rp,caddr_t addr,uint_t mmu_fsr)99 showregs(uint_t type, struct regs *rp, caddr_t addr, uint_t mmu_fsr)
100 {
101 int s;
102
103 s = spl7();
104 type &= ~T_USER;
105 printf("%s: ", PTOU(curproc)->u_comm);
106
107 switch (type) {
108 case T_SYS_RTT_ALIGN:
109 case T_ALIGNMENT:
110 printf("alignment error:\n");
111 break;
112 case T_INSTR_EXCEPTION:
113 printf("text access exception:\n");
114 break;
115 case T_DATA_EXCEPTION:
116 printf("data access exception:\n");
117 break;
118 case T_PRIV_INSTR:
119 printf("privileged instruction fault:\n");
120 break;
121 case T_UNIMP_INSTR:
122 printf("illegal instruction fault:\n");
123 break;
124 case T_IDIV0:
125 printf("integer divide zero trap:\n");
126 break;
127 case T_DIV0:
128 printf("zero divide trap:\n");
129 break;
130 case T_INT_OVERFLOW:
131 printf("integer overflow:\n");
132 break;
133 case T_BREAKPOINT:
134 printf("breakpoint trap:\n");
135 break;
136 case T_TAG_OVERFLOW:
137 printf("tag overflow:\n");
138 break;
139 default:
140 if (type >= T_SOFTWARE_TRAP && type <= T_ESOFTWARE_TRAP)
141 printf("software trap 0x%x\n", type - T_SOFTWARE_TRAP);
142 else
143 printf("trap type = 0x%x\n", type);
144 break;
145 }
146 if (type == T_DATA_EXCEPTION || type == T_INSTR_EXCEPTION) {
147 mmu_print_sfsr(mmu_fsr);
148 } else if (addr) {
149 printf("addr=0x%p\n", (void *)addr);
150 }
151
152 printf("pid=%d, pc=0x%lx, sp=0x%llx, tstate=0x%llx, context=0x%x\n",
153 (ttoproc(curthread) && ttoproc(curthread)->p_pidp) ?
154 (ttoproc(curthread)->p_pid) : 0, rp->r_pc, rp->r_sp,
155 rp->r_tstate, sfmmu_getctx_sec());
156 if (USERMODE(rp->r_tstate)) {
157 printf("o0-o7: %llx, %llx, %llx, %llx, %llx, %llx, "
158 "%llx, %llx\n", rp->r_o0, rp->r_o1, rp->r_o2, rp->r_o3,
159 rp->r_o4, rp->r_o5, rp->r_o6, rp->r_o7);
160 }
161 printf("g1-g7: %llx, %llx, %llx, %llx, %llx, %llx, %llx\n",
162 rp->r_g1, rp->r_g2, rp->r_g3,
163 rp->r_g4, rp->r_g5, rp->r_g6, rp->r_g7);
164
165 #ifdef TRAPWINDOW
166 printf("trap_window: wim=%x\n", trap_window[24]);
167 printf("o0-o7: %x, %x, %x, %x, %x, %x, %x, %x\n",
168 trap_window[0], trap_window[1], trap_window[2], trap_window[3],
169 trap_window[4], trap_window[5], trap_window[6], trap_window[7]);
170 printf("l0-l7: %x, %x, %x, %x, %x, %x, %x, %x\n",
171 trap_window[8], trap_window[9], trap_window[10], trap_window[11],
172 trap_window[12], trap_window[13], trap_window[14], trap_window[15]);
173 printf("i0-i7: %x, %x, %x, %x, %x, %x, %x, %x\n",
174 trap_window[16], trap_window[17], trap_window[18], trap_window[19],
175 trap_window[20], trap_window[21], trap_window[22], trap_window[23]);
176 #endif /* TRAPWINDOW */
177 if (tudebug > 1 && (boothowto & RB_DEBUG)) {
178 debug_enter((char *)NULL);
179 }
180 splx(s);
181 }
182
183 static void
ptl1_showtrap(ptl1_state_t * pstate)184 ptl1_showtrap(ptl1_state_t *pstate)
185 {
186 ptl1_regs_t *rp = &pstate->ptl1_regs;
187 short i, j, maxtl = rp->ptl1_trap_regs[0].ptl1_tl;
188
189 printf("%%tl %%tpc %%tnpc %%tstate"
190 " %%tt\n");
191
192 for (i = maxtl - 1; i >= 0; i--) {
193 ptl1_trapregs_t *ptp = &rp->ptl1_trap_regs[i];
194 uint64_t tstate = ptp->ptl1_tstate;
195 uint32_t ccr, asi, cwp, pstate;
196
197 cwp = (tstate >> TSTATE_CWP_SHIFT) & TSTATE_CWP_MASK;
198 pstate = (tstate >> TSTATE_PSTATE_SHIFT) & TSTATE_PSTATE_MASK;
199 asi = (tstate >> TSTATE_ASI_SHIFT) & TSTATE_ASI_MASK;
200 ccr = (tstate >> TSTATE_CCR_SHIFT) & TSTATE_CCR_MASK;
201
202 printf(" %d %016" PRIx64 " %016" PRIx64 " %010" PRIx64
203 " %03x\n", ptp->ptl1_tl, ptp->ptl1_tpc,
204 ptp->ptl1_tnpc, tstate, ptp->ptl1_tt);
205 printf(" %%ccr: %02x %%asi: %02x %%cwp: %x "
206 "%%pstate: %b\n", ccr, asi, cwp, pstate, PSTATE_BITS);
207 }
208
209 printf("%%g0-3: %016x %016" PRIx64 " %016" PRIx64 " %016"
210 PRIx64 "\n", 0, rp->ptl1_g1, rp->ptl1_g2, rp->ptl1_g3);
211 printf("%%g4-7: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016"
212 PRIx64 "\n", rp->ptl1_g4, rp->ptl1_g5, rp->ptl1_g6, rp->ptl1_g7);
213
214 i = rp->ptl1_cwp;
215 j = rp->ptl1_canrestore;
216 for (; j >= 0; i--, j--) {
217 struct rwindow *wp;
218 ulong_t off;
219 char *sym;
220
221 if (i < 0)
222 i += MAXWIN;
223
224 wp = &rp->ptl1_rwindow[i];
225
226 if ((sym = kobj_getsymname(wp->rw_in[7], &off)) != NULL) {
227 printf("Register window %d, caller %s+%lx\n",
228 i, sym, off);
229 } else {
230 printf("Register window %d, caller %lx\n",
231 i, wp->rw_in[7]);
232 }
233
234 if (i == rp->ptl1_cwp) {
235 struct rwindow *nwp;
236
237 if (i == MAXWIN - 1)
238 nwp = &rp->ptl1_rwindow[0];
239 else
240 nwp = &rp->ptl1_rwindow[i+1];
241 printf("%%o0-3: %016lx %016lx %016lx %016lx\n"
242 "%%o4-7: %016lx %016lx %016lx %016lx\n",
243 nwp->rw_in[0], nwp->rw_in[1], nwp->rw_in[2],
244 nwp->rw_in[3], nwp->rw_in[4], nwp->rw_in[5],
245 nwp->rw_in[6], nwp->rw_in[7]);
246 }
247 printf("%%l0-3: %016lx %016lx %016lx %016lx\n"
248 "%%l4-7: %016lx %016lx %016lx %016lx\n",
249 wp->rw_local[0], wp->rw_local[1], wp->rw_local[2],
250 wp->rw_local[3], wp->rw_local[4], wp->rw_local[5],
251 wp->rw_local[6], wp->rw_local[7]);
252
253 printf("%%i0-3: %016lx %016lx %016lx %016lx\n"
254 "%%i4-7: %016lx %016lx %016lx %016lx\n",
255 wp->rw_in[0], wp->rw_in[1], wp->rw_in[2], wp->rw_in[3],
256 wp->rw_in[4], wp->rw_in[5], wp->rw_in[6], wp->rw_in[7]);
257 }
258 }
259
260 void
panic_showtrap(struct panic_trap_info * tip)261 panic_showtrap(struct panic_trap_info *tip)
262 {
263 ptl1_state_t *pstate = &CPU->cpu_m.ptl1_state;
264 /*
265 * If ptl1_panic() was called, print out the information
266 * saved in the ptl1_state struture.
267 */
268 if (pstate->ptl1_entry_count) {
269 ptl1_showtrap(pstate);
270 return;
271 }
272
273 showregs(tip->trap_type, tip->trap_regs, tip->trap_addr,
274 tip->trap_mmu_fsr);
275 }
276
277 static void
ptl1_savetrap(panic_data_t * pdp,ptl1_state_t * pstate)278 ptl1_savetrap(panic_data_t *pdp, ptl1_state_t *pstate)
279 {
280 ptl1_regs_t *rp = &pstate->ptl1_regs;
281 short i, maxtl = rp->ptl1_trap_regs[0].ptl1_tl;
282 panic_nv_t *pnv = PANICNVGET(pdp);
283 char name[PANICNVNAMELEN];
284
285 for (i = maxtl - 1; i >= 0; i--) {
286 ptl1_trapregs_t *ptp = &rp->ptl1_trap_regs[i];
287
288 (void) snprintf(name, sizeof (name), "tl[%d]", i);
289 PANICNVADD(pnv, name, ptp->ptl1_tl);
290 (void) snprintf(name, sizeof (name), "tt[%d]", i);
291 PANICNVADD(pnv, name, ptp->ptl1_tt);
292 (void) snprintf(name, sizeof (name), "tpc[%d]", i);
293 PANICNVADD(pnv, name, ptp->ptl1_tpc);
294 (void) snprintf(name, sizeof (name), "tnpc[%d]", i);
295 PANICNVADD(pnv, name, ptp->ptl1_tnpc);
296 (void) snprintf(name, sizeof (name), "tstate[%d]", i);
297 PANICNVADD(pnv, name, ptp->ptl1_tstate);
298 }
299
300 PANICNVSET(pdp, pnv);
301 }
302
303 void
panic_savetrap(panic_data_t * pdp,struct panic_trap_info * tip)304 panic_savetrap(panic_data_t *pdp, struct panic_trap_info *tip)
305 {
306 panic_nv_t *pnv;
307 ptl1_state_t *pstate = &CPU->cpu_m.ptl1_state;
308 /*
309 * If ptl1_panic() was called, save the trap registers
310 * stored in the ptl1_state struture.
311 */
312 if (pstate->ptl1_entry_count) {
313 ptl1_savetrap(pdp, pstate);
314 return;
315 }
316
317 panic_saveregs(pdp, tip->trap_regs);
318 pnv = PANICNVGET(pdp);
319
320 PANICNVADD(pnv, "sfsr", tip->trap_mmu_fsr);
321 PANICNVADD(pnv, "sfar", tip->trap_addr);
322 PANICNVADD(pnv, "tt", tip->trap_type);
323
324 PANICNVSET(pdp, pnv);
325 }
326