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 default:
71 printf(" Unknown error");
72 break;
73 }
74
75 printf(" context 0x%x", X_FAULT_CTX(sfsr));
76 printf("\n");
77 }
78
79 /*
80 * Print out debugging info.
81 */
82 /*ARGSUSED*/
83 void
showregs(uint_t type,struct regs * rp,caddr_t addr,uint_t mmu_fsr)84 showregs(uint_t type, struct regs *rp, caddr_t addr, uint_t mmu_fsr)
85 {
86 int s;
87
88 s = spl7();
89 type &= ~T_USER;
90 printf("%s: ", PTOU(curproc)->u_comm);
91
92 switch (type) {
93 case T_SYS_RTT_ALIGN:
94 case T_ALIGNMENT:
95 printf("alignment error:\n");
96 break;
97 case T_INSTR_EXCEPTION:
98 printf("text access exception:\n");
99 break;
100 case T_DATA_EXCEPTION:
101 printf("data access exception:\n");
102 break;
103 case T_PRIV_INSTR:
104 printf("privileged instruction fault:\n");
105 break;
106 case T_UNIMP_INSTR:
107 printf("illegal instruction fault:\n");
108 break;
109 case T_IDIV0:
110 printf("integer divide zero trap:\n");
111 break;
112 case T_DIV0:
113 printf("zero divide trap:\n");
114 break;
115 case T_INT_OVERFLOW:
116 printf("integer overflow:\n");
117 break;
118 case T_BREAKPOINT:
119 printf("breakpoint trap:\n");
120 break;
121 case T_TAG_OVERFLOW:
122 printf("tag overflow:\n");
123 break;
124 default:
125 if (type >= T_SOFTWARE_TRAP && type <= T_ESOFTWARE_TRAP)
126 printf("software trap 0x%x\n", type - T_SOFTWARE_TRAP);
127 else
128 printf("trap type = 0x%x\n", type);
129 break;
130 }
131 if (type == T_DATA_EXCEPTION || type == T_INSTR_EXCEPTION) {
132 mmu_print_sfsr(mmu_fsr);
133 } else if (addr) {
134 printf("addr=0x%p\n", (void *)addr);
135 }
136
137 printf("pid=%d, pc=0x%lx, sp=0x%llx, tstate=0x%llx, context=0x%x\n",
138 (ttoproc(curthread) && ttoproc(curthread)->p_pidp) ?
139 (ttoproc(curthread)->p_pid) : 0, rp->r_pc, rp->r_sp,
140 rp->r_tstate, sfmmu_getctx_sec());
141 if (USERMODE(rp->r_tstate)) {
142 printf("o0-o7: %llx, %llx, %llx, %llx, %llx, %llx, "
143 "%llx, %llx\n", rp->r_o0, rp->r_o1, rp->r_o2, rp->r_o3,
144 rp->r_o4, rp->r_o5, rp->r_o6, rp->r_o7);
145 }
146 printf("g1-g7: %llx, %llx, %llx, %llx, %llx, %llx, %llx\n",
147 rp->r_g1, rp->r_g2, rp->r_g3,
148 rp->r_g4, rp->r_g5, rp->r_g6, rp->r_g7);
149
150 if (tudebug > 1 && (boothowto & RB_DEBUG)) {
151 debug_enter((char *)NULL);
152 }
153 splx(s);
154 }
155
156 static void
ptl1_showtrap(ptl1_state_t * pstate)157 ptl1_showtrap(ptl1_state_t *pstate)
158 {
159 ptl1_regs_t *rp = &pstate->ptl1_regs;
160 short i, j, maxtl = rp->ptl1_trap_regs[0].ptl1_tl;
161 short curgl = rp->ptl1_gregs[0].ptl1_gl;
162
163 printf("%%tl %%tpc %%tnpc %%tstate"
164 " %%tt\n");
165
166 for (i = maxtl - 1; i >= 0; i--) {
167 ptl1_trapregs_t *ptp = &rp->ptl1_trap_regs[i];
168 uint64_t tstate = ptp->ptl1_tstate;
169 uint32_t gl, ccr, asi, cwp, pstate;
170
171 cwp = (tstate >> TSTATE_CWP_SHIFT) & TSTATE_CWP_MASK;
172 pstate = (tstate >> TSTATE_PSTATE_SHIFT) & TSTATE_PSTATE_MASK;
173 asi = (tstate >> TSTATE_ASI_SHIFT) & TSTATE_ASI_MASK;
174 ccr = (tstate >> TSTATE_CCR_SHIFT) & TSTATE_CCR_MASK;
175 gl = (tstate >> TSTATE_GL_SHIFT) & TSTATE_GL_MASK;
176
177 printf(" %d %016" PRIx64 " %016" PRIx64 " %010" PRIx64
178 " %03x\n", ptp->ptl1_tl, ptp->ptl1_tpc,
179 ptp->ptl1_tnpc, tstate, ptp->ptl1_tt);
180 printf(" %%gl: %02x %%ccr: %02x %%asi: %02x %%cwp: %x "
181 "%%pstate: %b\n", gl, ccr, asi, cwp, pstate, PSTATE_BITS);
182 }
183
184 /*
185 * ptl1_gregs[] array holds global registers for GL 0 through
186 * current GL. Note that the current GL global registers are
187 * always stored at index 0 in the ptl1_gregs[] array.
188 */
189 for (i = 0; i <= curgl; i++) {
190 ptl1_gregs_t *pgp = &rp->ptl1_gregs[i];
191
192 printf(" %%gl: %02" PRIx64 "\n", pgp->ptl1_gl);
193 printf("%%g0-3: %016x %016" PRIx64 " %016" PRIx64 " %016"
194 PRIx64 "\n", 0, pgp->ptl1_g1, pgp->ptl1_g2, pgp->ptl1_g3);
195 printf("%%g4-7: %016" PRIx64 " %016" PRIx64 " %016"
196 PRIx64 " %016" PRIx64 "\n", pgp->ptl1_g4, pgp->ptl1_g5,
197 pgp->ptl1_g6, pgp->ptl1_g7);
198 }
199
200 i = rp->ptl1_cwp;
201 j = rp->ptl1_canrestore;
202 for (; j >= 0; i--, j--) {
203 struct rwindow *wp;
204 ulong_t off;
205 char *sym;
206
207 if (i < 0)
208 i += MAXWIN;
209
210 wp = &rp->ptl1_rwindow[i];
211
212 if ((sym = kobj_getsymname(wp->rw_in[7], &off)) != NULL) {
213 printf("Register window %d, caller %s+%lx\n",
214 i, sym, off);
215 } else {
216 printf("Register window %d, caller %lx\n",
217 i, wp->rw_in[7]);
218 }
219
220 if (i == rp->ptl1_cwp) {
221 struct rwindow *nwp;
222
223 if (i == MAXWIN - 1)
224 nwp = &rp->ptl1_rwindow[0];
225 else
226 nwp = &rp->ptl1_rwindow[i+1];
227 printf("%%o0-3: %016lx %016lx %016lx %016lx\n"
228 "%%o4-7: %016lx %016lx %016lx %016lx\n",
229 nwp->rw_in[0], nwp->rw_in[1], nwp->rw_in[2],
230 nwp->rw_in[3], nwp->rw_in[4], nwp->rw_in[5],
231 nwp->rw_in[6], nwp->rw_in[7]);
232 }
233 printf("%%l0-3: %016lx %016lx %016lx %016lx\n"
234 "%%l4-7: %016lx %016lx %016lx %016lx\n",
235 wp->rw_local[0], wp->rw_local[1], wp->rw_local[2],
236 wp->rw_local[3], wp->rw_local[4], wp->rw_local[5],
237 wp->rw_local[6], wp->rw_local[7]);
238
239 printf("%%i0-3: %016lx %016lx %016lx %016lx\n"
240 "%%i4-7: %016lx %016lx %016lx %016lx\n",
241 wp->rw_in[0], wp->rw_in[1], wp->rw_in[2], wp->rw_in[3],
242 wp->rw_in[4], wp->rw_in[5], wp->rw_in[6], wp->rw_in[7]);
243 }
244 }
245
246 void
panic_showtrap(struct panic_trap_info * tip)247 panic_showtrap(struct panic_trap_info *tip)
248 {
249 ptl1_state_t *pstate = &CPU->cpu_m.ptl1_state;
250 /*
251 * If ptl1_panic() was called, print out the information
252 * saved in the ptl1_state struture.
253 */
254 if (pstate->ptl1_entry_count) {
255 ptl1_showtrap(pstate);
256 return;
257 }
258
259 showregs(tip->trap_type, tip->trap_regs, tip->trap_addr,
260 tip->trap_mmu_fsr);
261 }
262
263 static void
ptl1_savetrap(panic_data_t * pdp,ptl1_state_t * pstate)264 ptl1_savetrap(panic_data_t *pdp, ptl1_state_t *pstate)
265 {
266 ptl1_regs_t *rp = &pstate->ptl1_regs;
267 short i, maxtl = rp->ptl1_trap_regs[0].ptl1_tl;
268 panic_nv_t *pnv = PANICNVGET(pdp);
269 char name[PANICNVNAMELEN];
270
271 for (i = maxtl - 1; i >= 0; i--) {
272 ptl1_trapregs_t *ptp = &rp->ptl1_trap_regs[i];
273
274 (void) snprintf(name, sizeof (name), "tl[%d]", i);
275 PANICNVADD(pnv, name, ptp->ptl1_tl);
276 (void) snprintf(name, sizeof (name), "tt[%d]", i);
277 PANICNVADD(pnv, name, ptp->ptl1_tt);
278 (void) snprintf(name, sizeof (name), "tpc[%d]", i);
279 PANICNVADD(pnv, name, ptp->ptl1_tpc);
280 (void) snprintf(name, sizeof (name), "tnpc[%d]", i);
281 PANICNVADD(pnv, name, ptp->ptl1_tnpc);
282 (void) snprintf(name, sizeof (name), "tstate[%d]", i);
283 PANICNVADD(pnv, name, ptp->ptl1_tstate);
284 }
285
286 PANICNVSET(pdp, pnv);
287 }
288
289 void
panic_savetrap(panic_data_t * pdp,struct panic_trap_info * tip)290 panic_savetrap(panic_data_t *pdp, struct panic_trap_info *tip)
291 {
292 panic_nv_t *pnv;
293 ptl1_state_t *pstate = &CPU->cpu_m.ptl1_state;
294 /*
295 * If ptl1_panic() was called, save the trap registers
296 * stored in the ptl1_state struture.
297 */
298 if (pstate->ptl1_entry_count) {
299 ptl1_savetrap(pdp, pstate);
300 return;
301 }
302
303 panic_saveregs(pdp, tip->trap_regs);
304 pnv = PANICNVGET(pdp);
305
306 PANICNVADD(pnv, "sfsr", tip->trap_mmu_fsr);
307 PANICNVADD(pnv, "sfar", tip->trap_addr);
308 PANICNVADD(pnv, "tt", tip->trap_type);
309
310 PANICNVSET(pdp, pnv);
311 }
312