xref: /illumos-gate/usr/src/uts/sun4u/os/mach_trap.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
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
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
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
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
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
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
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