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