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