xref: /illumos-gate/usr/src/uts/sun4v/os/mach_trap.c (revision 3299f39fdcbdab4be7a9c70daa3873f2b78a398d)
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 	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
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
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
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
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
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