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 _IA32_SYS_TRAPTRACE_H 27 #define _IA32_SYS_TRAPTRACE_H 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 #include <sys/privregs.h> 36 37 /* 38 * Trap tracing. If TRAPTRACE is defined, an entry is recorded every time 39 * the CPU jumps through the Interrupt Descriptor Table (IDT). One exception 40 * is the Double Fault handler, which does not record a traptrace entry. 41 * 42 * There are facilities to (conditionally) interleave tracing of related 43 * facilities e.h. x-calls. 44 */ 45 46 /* 47 * Note: non-assembler files that include this file must include 48 * <sys/systm.h> before it, for the typedef of pc_t to be visible. 49 */ 50 51 #define TTR_STACK_DEPTH 10 52 53 #ifndef _ASM 54 55 #define TTR_PAD1_SIZE (sizeof (long) - 1) 56 57 typedef struct { 58 uintptr_t ttc_next; 59 uintptr_t ttc_first; 60 uintptr_t ttc_limit; 61 uintptr_t ttc_current; 62 } trap_trace_ctl_t; 63 64 typedef struct { 65 struct regs ttr_regs; 66 greg_t ttr_cr2; 67 union _ttr_info { 68 struct _idt_entry { 69 short vector; 70 uchar_t ipl; 71 uchar_t spl; 72 uchar_t pri; 73 } idt_entry; 74 struct _gate_entry { 75 int sysnum; 76 } gate_entry; 77 struct _xc_entry { 78 ulong_t xce_arg; 79 ulong_t xce_func; 80 int8_t xce_pri; 81 uint8_t xce_marker, 82 xce_pend, 83 xce_wait, 84 xce_ack, 85 xce_state; 86 uint_t xce_retval; 87 } xc_entry; 88 } ttr_info; 89 uintptr_t ttr_curthread; 90 uchar_t ttr_pad[TTR_PAD1_SIZE]; 91 uchar_t ttr_marker; 92 hrtime_t ttr_stamp; 93 int ttr_sdepth; 94 pc_t ttr_stack[TTR_STACK_DEPTH]; 95 } trap_trace_rec_t; 96 97 #define ttr_vector ttr_info.idt_entry.vector 98 #define ttr_ipl ttr_info.idt_entry.ipl 99 #define ttr_spl ttr_info.idt_entry.spl 100 #define ttr_pri ttr_info.idt_entry.pri 101 #define ttr_sysnum ttr_info.gate_entry.sysnum 102 103 #define TRAPTR_NENT 128 104 105 extern trap_trace_ctl_t trap_trace_ctl[NCPU]; /* Allocated in locore.s */ 106 extern size_t trap_trace_bufsize; 107 extern int trap_trace_freeze; 108 extern trap_trace_rec_t trap_trace_postmort; /* Entry used after death */ 109 110 extern trap_trace_rec_t *trap_trace_get_traceptr(uint8_t, ulong_t, ulong_t); 111 112 #define TRAPTRACE_FREEZE trap_trace_freeze = 1; 113 #define TRAPTRACE_UNFREEZE trap_trace_freeze = 0; 114 115 #else /* _ASM */ 116 117 /* 118 * ptr -- will be set to a TRAPTRACE entry. 119 * scr1 -- scratch 120 * scr1_32 -- 32-bit version of scr1 121 * scr2 -- scratch 122 * marker -- register containing byte to store in marker field of entry 123 * 124 * Note that this macro defines labels "8" and "9". 125 */ 126 #ifdef TRAPTRACE 127 128 #if defined(__amd64) 129 130 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker) \ 131 leaq trap_trace_postmort(%rip), ptr; \ 132 cmpl $0, trap_trace_freeze(%rip); \ 133 jne 9f; \ 134 LOADCPU(ptr); \ 135 movl CPU_ID(ptr), scr1_32; \ 136 shlq $TRAPTR_SIZE_SHIFT, scr1; \ 137 leaq trap_trace_ctl(%rip), scr2; \ 138 addq scr2, scr1; \ 139 movq TRAPTR_NEXT(scr1), ptr; \ 140 leaq TRAP_ENT_SIZE(ptr), scr2; \ 141 cmpq TRAPTR_LIMIT(scr1), scr2; \ 142 jl 8f; \ 143 movq TRAPTR_FIRST(scr1), scr2; \ 144 8: movq scr2, TRAPTR_NEXT(scr1); \ 145 9: movb marker, TTR_MARKER(ptr); 146 147 #elif defined(__i386) 148 149 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker) \ 150 movl $trap_trace_postmort, ptr; \ 151 cmpl $0, trap_trace_freeze; \ 152 jne 9f; \ 153 LOADCPU(ptr); \ 154 movl CPU_ID(ptr), scr1_32; \ 155 shll $TRAPTR_SIZE_SHIFT, scr1; \ 156 addl $trap_trace_ctl, scr1; \ 157 movl TRAPTR_NEXT(scr1), ptr; \ 158 leal TRAP_ENT_SIZE(ptr), scr2; \ 159 cmpl TRAPTR_LIMIT(scr1), scr2; \ 160 jl 8f; \ 161 movl TRAPTR_FIRST(scr1), scr2; \ 162 8: movl scr2, TRAPTR_NEXT(scr1); \ 163 9: movb marker, TTR_MARKER(ptr); 164 165 #endif /* __i386 */ 166 167 /* 168 * ptr -- pointer to the current TRAPTRACE entry. 169 * reg -- pointer to the stored registers; must be on the stack 170 * scr1 -- scratch used as array index 171 * scr2 -- scratch used as temporary 172 * 173 * Note that this macro defines label "9". 174 * Also captures curthread on exit of loop. 175 */ 176 #define __GETCR2(_mov, reg) \ 177 _mov %cr2, reg 178 179 #if defined(__amd64) 180 181 #define TRACE_REGS(ptr, reg, scr1, scr2) \ 182 xorq scr1, scr1; \ 183 /*CSTYLED*/ \ 184 9: movq (reg, scr1, 1), scr2; \ 185 movq scr2, (ptr, scr1, 1); \ 186 addq $CLONGSIZE, scr1; \ 187 cmpq $REGSIZE, scr1; \ 188 jl 9b; \ 189 movq %gs:CPU_THREAD, scr2; \ 190 movq scr2, TTR_CURTHREAD(ptr); \ 191 __GETCR2(movq, scr2); \ 192 movq scr2, TTR_CR2(ptr) 193 194 #elif defined(__i386) 195 196 #define TRACE_REGS(ptr, reg, scr1, scr2) \ 197 xorl scr1, scr1; \ 198 /*CSTYLED*/ \ 199 9: movl (reg, scr1, 1), scr2; \ 200 movl scr2, (ptr, scr1, 1); \ 201 addl $CLONGSIZE, scr1; \ 202 cmpl $REGSIZE, scr1; \ 203 jl 9b; \ 204 movl %gs:CPU_THREAD, scr2; \ 205 movl scr2, TTR_CURTHREAD(ptr); \ 206 __GETCR2(movl, scr2); \ 207 movl scr2, TTR_CR2(ptr) 208 209 #endif /* __i386 */ 210 211 /* 212 * The time stamp macro records a high-resolution time stamp for the 213 * given TRAPTRACE entry. Note that %eax and %edx are plowed by this 214 * macro; if they are to be preserved, it's up to the caller of the macro. 215 */ 216 217 #if defined(__amd64) 218 219 #define TRACE_STAMP(reg) \ 220 rdtsc; \ 221 movl %eax, TTR_STAMP(reg); \ 222 movl %edx, TTR_STAMP+4(reg) 223 224 /* 225 * %rbp should be set before invoking this macro. 226 */ 227 228 #define TRACE_STACK(tt) \ 229 pushq %rdi; \ 230 pushq %rsi; \ 231 pushq %rdx; \ 232 pushq %rcx; \ 233 pushq %r8; \ 234 pushq %r9; \ 235 pushq %rax; \ 236 pushq %r12; \ 237 movq tt, %r12; \ 238 leaq TTR_STACK(%r12), %rdi; \ 239 movl $TTR_STACK_DEPTH, %esi; \ 240 call getpcstack; \ 241 movl %eax, TTR_SDEPTH(%r12); \ 242 popq %r12; \ 243 popq %rax; \ 244 popq %r9; \ 245 popq %r8; \ 246 popq %rcx; \ 247 popq %rdx; \ 248 popq %rsi; \ 249 popq %rdi 250 251 #elif defined(__i386) 252 253 #define TRACE_STAMP(reg) \ 254 xorl %eax, %eax; \ 255 xorl %edx, %edx; \ 256 testl $X86_TSC, x86_feature; \ 257 jz 9f; \ 258 rdtsc; \ 259 9: movl %eax, TTR_STAMP(reg); \ 260 movl %edx, TTR_STAMP+4(reg) 261 262 #define TRACE_STACK(tt) \ 263 pushl %eax; \ 264 pushl %ecx; \ 265 pushl %edx; \ 266 pushl %ebx; \ 267 pushl $TTR_STACK_DEPTH; \ 268 movl tt, %ebx; \ 269 leal TTR_STACK(%ebx), %eax; \ 270 pushl %eax; \ 271 call getpcstack; \ 272 addl $8, %esp; \ 273 movl %eax, TTR_SDEPTH(%ebx); \ 274 popl %ebx; \ 275 popl %edx; \ 276 popl %ecx; \ 277 popl %eax 278 279 #endif /* __i386 */ 280 281 #else 282 283 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker) 284 #define TRACE_REGS(ptr, reg, scr1, scr2) 285 #define TRACE_STAMP(reg) 286 #define TRACE_STACK(reg) 287 288 #endif /* TRAPTRACE */ 289 290 #endif /* _ASM */ 291 292 #define TT_SYSCALL 0xaa /* system call via lcall */ 293 #define TT_SYSENTER 0xab /* system call via sysenter */ 294 #define TT_SYSC 0xad /* system call via syscall (32-bit) */ 295 #define TT_SYSC64 0xae /* system call via syscall (64-bit) */ 296 #define TT_INTERRUPT 0xbb 297 #define TT_TRAP 0xcc 298 #define TT_INTTRAP 0xdd 299 #define TT_EVENT 0xee /* hypervisor event */ 300 #define TT_XCALL 0xf0 /* x-call handling */ 301 302 /* 303 * TT_XCALL subcodes: 304 */ 305 #define TT_XC_SVC_BEGIN 0 /* xc_serv() entry */ 306 #define TT_XC_SVC_END 1 /* xc_serv() return */ 307 #define TT_XC_START 2 /* xc_common() - pre-dirint */ 308 #define TT_XC_WAIT 3 /* xc_common() - wait for completion */ 309 #define TT_XC_ACK 4 /* xc_common() - ack completion */ 310 #define TT_XC_CAPTURE 5 /* xc_capture() */ 311 #define TT_XC_RELEASE 6 /* xc_release() */ 312 #define TT_XC_POKE_CPU 7 /* poke_cpu() */ 313 #define TT_XC_CBE_FIRE 8 /* cbe_fire() */ 314 #define TT_XC_CBE_XCALL 9 /* cbe_xcall() */ 315 316 #ifdef __cplusplus 317 } 318 #endif 319 320 #endif /* _IA32_SYS_TRAPTRACE_H */ 321