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 #ifndef _SYS_TRAPTRACE_H 27 #define _SYS_TRAPTRACE_H 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 /* 34 * Trap tracing. If TRAPTRACE is defined, every trap records info 35 * in a circular buffer. Define TRAPTRACE in Makefile.$ARCH. 36 * 37 * Trap trace records are TRAP_ENT_SIZE bytes, consisting of the 38 * %tick, %tl, %tt, %tpc, %tstate, %sp, and a few other words: 39 * 40 * struct trap_trace_record { 41 * ushort_t tl, tt; 42 * long pc; 43 * int64_t tstate, tick; 44 * long sp, tr, f1, f2, f3, f4; 45 * }; 46 * 47 * Note that for UltraSparc III and beyond %stick is used in place of %tick 48 * unless compiled with TRAPTRACE_FORCE_TICK. 49 * 50 * Auxilliary entries (not of just a trap), have obvious non-%tt values in 51 * the TRAP_ENT_TT field 52 */ 53 54 #define TRAP_TPGS (2 * PAGESIZE) /* default size is two pages */ 55 56 #ifndef _ASM 57 58 struct trap_trace_record { 59 uint16_t tt_tl; 60 uint16_t tt_tt; 61 uintptr_t tt_tpc; 62 uint64_t tt_tstate; 63 uint64_t tt_tick; 64 uintptr_t tt_sp; 65 uintptr_t tt_tr; 66 uintptr_t tt_f1; 67 uintptr_t tt_f2; 68 uintptr_t tt_f3; 69 uintptr_t tt_f4; 70 }; 71 72 #define TRAP_TSIZE ((TRAP_TPGS / sizeof (struct trap_trace_record)) * \ 73 sizeof (struct trap_trace_record)) 74 75 #else 76 77 #define TRAP_TSIZE ((TRAP_TPGS / TRAP_ENT_SIZE) * TRAP_ENT_SIZE) 78 79 #endif 80 81 #define HTRAP_TSIZE 0 82 83 /* 84 * Trap tracing buffer header. 85 */ 86 87 #ifndef _ASM 88 89 /* 90 * Example buffer header stored in locore.s: 91 * 92 * (the actual implementation could be .skip TRAPTR_SIZE*NCPU) 93 */ 94 typedef union { 95 struct { 96 caddr_t vaddr_base; /* virtual address of top of buffer */ 97 uint64_t paddr_base; /* physical address of buffer */ 98 uint_t last_offset; /* to "know" what trace completed */ 99 uint_t offset; /* current index into buffer (bytes) */ 100 uint_t limit; /* upper limit on index */ 101 uchar_t asi; /* cache for real asi */ 102 } d; 103 char cache_linesize[64]; 104 } TRAP_TRACE_CTL; 105 106 #ifdef _KERNEL 107 108 extern TRAP_TRACE_CTL trap_trace_ctl[]; /* allocated in locore.s */ 109 extern int trap_trace_bufsize; /* default buffer size */ 110 extern char trap_tr0[]; /* prealloc buf for boot cpu */ 111 extern int trap_freeze; /* freeze the trap trace */ 112 extern caddr_t ttrace_buf; /* kmem64 buffer */ 113 extern int ttrace_index; /* index used */ 114 extern size_t calc_traptrace_sz(void); 115 extern void mach_htraptrace_setup(int); 116 extern void mach_htraptrace_configure(int); 117 extern void mach_htraptrace_cleanup(int); 118 119 #endif 120 121 /* 122 * freeze the trap trace 123 */ 124 #define TRAPTRACE_FREEZE trap_freeze = 1; 125 #define TRAPTRACE_UNFREEZE trap_freeze = 0; 126 127 #else /* _ASM */ 128 129 #include <sys/machthread.h> 130 131 /* 132 * Offsets of words in trap_trace_ctl: 133 */ 134 /* 135 * XXX This should be done with genassym 136 */ 137 #define TRAPTR_VBASE 0 /* virtual address of buffer */ 138 #define TRAPTR_LAST_OFFSET 16 /* last completed trace entry */ 139 #define TRAPTR_OFFSET 20 /* next trace entry pointer */ 140 #define TRAPTR_LIMIT 24 /* pointer past end of buffer */ 141 #define TRAPTR_PBASE 8 /* start of buffer */ 142 #define TRAPTR_ASIBUF 28 /* cache of current asi */ 143 #define TRAPTR_SIZE_SHIFT 6 /* shift count -- per CPU indexing */ 144 #define TRAPTR_SIZE (1<<TRAPTR_SIZE_SHIFT) 145 146 #define TRAPTR_ASI ASI_MEM /* ASI to use for TRAPTR access */ 147 148 /* 149 * Use new %stick register for UltraSparc III and beyond for 150 * sane debugging of mixed speed CPU systems. Use TRAPTRACE_FORCE_TICK 151 * for finer granularity on same speed systems. 152 * 153 * Note the label-less branches used due to contraints of where 154 * and when trap trace macros are used. 155 */ 156 #ifdef TRAPTRACE_FORCE_TICK 157 #define GET_TRACE_TICK(reg, scr) \ 158 rdpr %tick, reg; 159 #else 160 #define GET_TRACE_TICK(reg, scr) \ 161 sethi %hi(traptrace_use_stick), reg; \ 162 lduw [reg + %lo(traptrace_use_stick)], reg; \ 163 /* CSTYLED */ \ 164 brz,a reg, .+12; \ 165 rdpr %tick, reg; \ 166 rd %asr24, reg; 167 #endif 168 169 /* 170 * TRACE_PTR(ptr, scr1) - get trap trace entry physical pointer. 171 * ptr is the register to receive the trace pointer. 172 * scr1 is a different register to be used as scratch. 173 * TRACING now needs a known processor state. Hence the assertion. 174 * NOTE: this caches and resets %asi 175 */ 176 #define TRACE_PTR(ptr, scr1) \ 177 sethi %hi(trap_freeze), ptr; \ 178 ld [ptr + %lo(trap_freeze)], ptr; \ 179 /* CSTYLED */ \ 180 brnz,pn ptr, .+20; /* skip assertion */ \ 181 rdpr %pstate, scr1; \ 182 andcc scr1, PSTATE_IE | PSTATE_AM, scr1; \ 183 /* CSTYLED */ \ 184 bne,a,pn %icc, trace_ptr_panic; \ 185 rd %pc, %g1; \ 186 CPU_INDEX(scr1, ptr); \ 187 sll scr1, TRAPTR_SIZE_SHIFT, scr1; \ 188 set trap_trace_ctl, ptr; \ 189 add ptr, scr1, scr1; \ 190 rd %asi, ptr; \ 191 stb ptr, [scr1 + TRAPTR_ASIBUF]; \ 192 sethi %hi(trap_freeze), ptr; \ 193 ld [ptr + %lo(trap_freeze)], ptr; \ 194 /* CSTYLED */ \ 195 brnz,pn ptr, .+20; /* skip assertion */ \ 196 ld [scr1 + TRAPTR_LIMIT], ptr; \ 197 tst ptr; \ 198 /* CSTYLED */ \ 199 be,a,pn %icc, trace_ptr_panic; \ 200 rd %pc, %g1; \ 201 ldx [scr1 + TRAPTR_PBASE], ptr; \ 202 ld [scr1 + TRAPTR_OFFSET], scr1; \ 203 wr %g0, TRAPTR_ASI, %asi; \ 204 add ptr, scr1, ptr; 205 206 /* 207 * TRACE_NEXT(scr1, scr2, scr3) - advance the trap trace pointer. 208 * scr1, scr2, scr3 are scratch registers. 209 * This routine will skip updating the trap pointers if the 210 * global freeze register is set (e.g. in panic). 211 * (we also restore the asi register) 212 */ 213 #define TRACE_NEXT(scr1, scr2, scr3) \ 214 CPU_INDEX(scr2, scr1); \ 215 sll scr2, TRAPTR_SIZE_SHIFT, scr2; \ 216 set trap_trace_ctl, scr1; \ 217 add scr1, scr2, scr2; \ 218 ldub [scr2 + TRAPTR_ASIBUF], scr1; \ 219 wr %g0, scr1, %asi; \ 220 sethi %hi(trap_freeze), scr1; \ 221 ld [scr1 + %lo(trap_freeze)], scr1; \ 222 /* CSTYLED */ \ 223 brnz scr1, .+36; /* skip update on freeze */ \ 224 ld [scr2 + TRAPTR_OFFSET], scr1; \ 225 ld [scr2 + TRAPTR_LIMIT], scr3; \ 226 st scr1, [scr2 + TRAPTR_LAST_OFFSET]; \ 227 add scr1, TRAP_ENT_SIZE, scr1; \ 228 sub scr3, TRAP_ENT_SIZE, scr3; \ 229 cmp scr1, scr3; \ 230 movge %icc, 0, scr1; \ 231 st scr1, [scr2 + TRAPTR_OFFSET]; 232 233 /* 234 * macro to save %tl to trap trace record at addr 235 */ 236 #define TRACE_SAVE_TL_GL_REGS(addr, scr1) \ 237 rdpr %tl, scr1; \ 238 stha scr1, [addr + TRAP_ENT_TL]%asi 239 240 /* 241 * macro to save tl to trap trace record at addr 242 */ 243 #define TRACE_SAVE_TL_VAL(addr, tl) \ 244 stha tl, [addr + TRAP_ENT_TL]%asi 245 246 /* 247 * dummy macro 248 */ 249 #define TRACE_SAVE_GL_VAL(addr, gl) 250 251 252 /* 253 * Trace macro for sys_trap return entries: 254 * prom_rtt, priv_rtt, and user_rtt 255 * %l7 - regs 256 * %l6 - trap %pil for prom_rtt and priv_rtt; THREAD_REG for user_rtt 257 */ 258 #define TRACE_RTT(code, scr1, scr2, scr3, scr4) \ 259 rdpr %pstate, scr4; \ 260 andn scr4, PSTATE_IE | PSTATE_AM, scr3; \ 261 wrpr %g0, scr3, %pstate; \ 262 TRACE_PTR(scr1, scr2); \ 263 GET_TRACE_TICK(scr2, scr3); \ 264 stxa scr2, [scr1 + TRAP_ENT_TICK]%asi; \ 265 rdpr %tl, scr2; \ 266 stha scr2, [scr1 + TRAP_ENT_TL]%asi; \ 267 set code, scr2; \ 268 stha scr2, [scr1 + TRAP_ENT_TT]%asi; \ 269 ldn [%l7 + PC_OFF], scr2; \ 270 stna scr2, [scr1 + TRAP_ENT_TPC]%asi; \ 271 ldx [%l7 + TSTATE_OFF], scr2; \ 272 stxa scr2, [scr1 + TRAP_ENT_TSTATE]%asi; \ 273 stna %sp, [scr1 + TRAP_ENT_SP]%asi; \ 274 stna %l6, [scr1 + TRAP_ENT_TR]%asi; \ 275 stna %l7, [scr1 + TRAP_ENT_F1]%asi; \ 276 ldn [THREAD_REG + T_CPU], scr2; \ 277 ld [scr2 + CPU_BASE_SPL], scr2; \ 278 stna scr2, [scr1 + TRAP_ENT_F2]%asi; \ 279 mov MMU_SCONTEXT, scr2; \ 280 ldxa [scr2]ASI_DMMU, scr2; \ 281 stna scr2, [scr1 + TRAP_ENT_F3]%asi; \ 282 rdpr %cwp, scr2; \ 283 stna scr2, [scr1 + TRAP_ENT_F4]%asi; \ 284 TRACE_NEXT(scr1, scr2, scr3); \ 285 wrpr %g0, scr4, %pstate 286 287 /* 288 * Trace macro for spill and fill trap handlers 289 * tl and tt fields indicate which spill handler is entered 290 */ 291 #define TRACE_WIN_INFO(code, scr1, scr2, scr3) \ 292 TRACE_PTR(scr1, scr2); \ 293 GET_TRACE_TICK(scr2, scr3); \ 294 stxa scr2, [scr1 + TRAP_ENT_TICK]%asi; \ 295 rdpr %tl, scr2; \ 296 stha scr2, [scr1 + TRAP_ENT_TL]%asi; \ 297 rdpr %tt, scr2; \ 298 set code, scr3; \ 299 or scr2, scr3, scr2; \ 300 stha scr2, [scr1 + TRAP_ENT_TT]%asi; \ 301 rdpr %tstate, scr2; \ 302 stxa scr2, [scr1 + TRAP_ENT_TSTATE]%asi; \ 303 stna %sp, [scr1 + TRAP_ENT_SP]%asi; \ 304 rdpr %tpc, scr2; \ 305 stna scr2, [scr1 + TRAP_ENT_TPC]%asi; \ 306 set TT_FSPILL_DEBUG, scr2; \ 307 stna scr2, [scr1 + TRAP_ENT_TR]%asi; \ 308 rdpr %pstate, scr2; \ 309 stna scr2, [scr1 + TRAP_ENT_F1]%asi; \ 310 rdpr %cwp, scr2; \ 311 sll scr2, 24, scr2; \ 312 rdpr %cansave, scr3; \ 313 sll scr3, 16, scr3; \ 314 or scr2, scr3, scr2; \ 315 rdpr %canrestore, scr3; \ 316 or scr2, scr3, scr2; \ 317 stna scr2, [scr1 + TRAP_ENT_F2]%asi; \ 318 rdpr %otherwin, scr2; \ 319 sll scr2, 24, scr2; \ 320 rdpr %cleanwin, scr3; \ 321 sll scr3, 16, scr3; \ 322 or scr2, scr3, scr2; \ 323 rdpr %wstate, scr3; \ 324 or scr2, scr3, scr2; \ 325 stna scr2, [scr1 + TRAP_ENT_F3]%asi; \ 326 stna %o7, [scr1 + TRAP_ENT_F4]%asi; \ 327 TRACE_NEXT(scr1, scr2, scr3) 328 329 #ifdef TRAPTRACE 330 331 #define FAULT_WINTRACE(scr1, scr2, scr3, type) \ 332 TRACE_PTR(scr1, scr2); \ 333 GET_TRACE_TICK(scr2, scr3); \ 334 stxa scr2, [scr1 + TRAP_ENT_TICK]%asi; \ 335 rdpr %tl, scr2; \ 336 stha scr2, [scr1 + TRAP_ENT_TL]%asi; \ 337 set type, scr2; \ 338 stha scr2, [scr1 + TRAP_ENT_TT]%asi; \ 339 rdpr %tpc, scr2; \ 340 stna scr2, [scr1 + TRAP_ENT_TPC]%asi; \ 341 rdpr %tstate, scr2; \ 342 stxa scr2, [scr1 + TRAP_ENT_TSTATE]%asi; \ 343 stna %sp, [scr1 + TRAP_ENT_SP]%asi; \ 344 stna %g0, [scr1 + TRAP_ENT_TR]%asi; \ 345 stna %g0, [scr1 + TRAP_ENT_F1]%asi; \ 346 stna %g4, [scr1 + TRAP_ENT_F2]%asi; \ 347 rdpr %pil, scr2; \ 348 stna scr2, [scr1 + TRAP_ENT_F3]%asi; \ 349 stna %g0, [scr1 + TRAP_ENT_F4]%asi; \ 350 TRACE_NEXT(scr1, scr2, scr3) 351 352 #define SYSTRAP_TT 0x1300 353 354 #define SYSTRAP_TRACE(scr1, scr2, scr3) \ 355 TRACE_PTR(scr1, scr2); \ 356 GET_TRACE_TICK(scr2, scr3); \ 357 stxa scr2, [scr1 + TRAP_ENT_TICK]%asi; \ 358 rdpr %tl, scr2; \ 359 stha scr2, [scr1 + TRAP_ENT_TL]%asi; \ 360 set SYSTRAP_TT, scr3; \ 361 rdpr %tt, scr2; \ 362 or scr3, scr2, scr2; \ 363 stha scr2, [scr1 + TRAP_ENT_TT]%asi; \ 364 rdpr %tpc, scr2; \ 365 stna scr2, [scr1 + TRAP_ENT_TPC]%asi; \ 366 rdpr %tstate, scr2; \ 367 stxa scr2, [scr1 + TRAP_ENT_TSTATE]%asi; \ 368 stna %g1, [scr1 + TRAP_ENT_SP]%asi; \ 369 stna %g2, [scr1 + TRAP_ENT_TR]%asi; \ 370 stna %g3, [scr1 + TRAP_ENT_F1]%asi; \ 371 stna %g4, [scr1 + TRAP_ENT_F2]%asi; \ 372 rdpr %pil, scr2; \ 373 stna scr2, [scr1 + TRAP_ENT_F3]%asi; \ 374 rdpr %cwp, scr2; \ 375 stna scr2, [scr1 + TRAP_ENT_F4]%asi; \ 376 TRACE_NEXT(scr1, scr2, scr3) 377 378 #else /* TRAPTRACE */ 379 380 #define FAULT_WINTRACE(scr1, scr2, scr3, type) 381 #define SYSTRAP_TRACE(scr1, scr2, scr3) 382 383 #endif /* TRAPTRACE */ 384 385 #endif /* _ASM */ 386 387 /* 388 * Trap trace codes used in place of a %tbr value when more than one 389 * entry is made by a trap. The general scheme is that the trap-type is 390 * in the same position as in the TT, and the low-order bits indicate 391 * which precise entry is being made. 392 */ 393 394 #define TT_F32_SN0 0x1084 395 #define TT_F64_SN0 0x1088 396 #define TT_F32_NT0 0x1094 397 #define TT_F64_NT0 0x1098 398 #define TT_F32_SO0 0x10A4 399 #define TT_F64_SO0 0x10A8 400 #define TT_F32_FN0 0x10C4 401 #define TT_F64_FN0 0x10C8 402 #define TT_F32_SN1 0x1284 403 #define TT_F64_SN1 0x1288 404 #define TT_F32_NT1 0x1294 405 #define TT_F64_NT1 0x1298 406 #define TT_F32_SO1 0x12A4 407 #define TT_F64_SO1 0x12A8 408 #define TT_F32_FN1 0x12C4 409 #define TT_F64_FN1 0x12C8 410 411 #define TT_SC_ENTR 0x880 /* enter system call */ 412 #define TT_SC_RET 0x881 /* system call normal return */ 413 414 #define TT_SYS_RTT_PROM 0x5555 /* return from trap to prom */ 415 #define TT_SYS_RTT_PRIV 0x6666 /* return from trap to privilege */ 416 #define TT_SYS_RTT_USER 0x7777 /* return from trap to user */ 417 418 #define TT_INTR_EXIT 0x8888 /* interrupt thread exit (no pinned thread) */ 419 #define TT_FSPILL_DEBUG 0x9999 /* fill/spill debugging */ 420 421 #define TT_SERVE_INTR 0x6000 /* SERVE_INTR */ 422 #define TT_XCALL 0xd000 /* xcall/xtrap */ 423 #define TT_XCALL_CONT 0xdc00 /* continuation of an xcall/xtrap record */ 424 425 #define TT_MMU_MISS 0x200 /* or'd into %tt to indicate a miss */ 426 #define TT_SPURIOUS_INT 0x400 /* or'd into %tt for spurious intr. */ 427 428 429 #ifdef __cplusplus 430 } 431 #endif 432 433 #endif /* _SYS_TRAPTRACE_H */ 434