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