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 #if defined(__xpv) 177 #define __GETCR2(_mov, reg) \ 178 _mov %gs:CPU_VCPU_INFO, reg; \ 179 _mov VCPU_INFO_ARCH_CR2(reg), reg 180 #else 181 #define __GETCR2(_mov, reg) \ 182 _mov %cr2, reg 183 #endif 184 185 #if defined(__amd64) 186 187 #define TRACE_REGS(ptr, reg, scr1, scr2) \ 188 xorq scr1, scr1; \ 189 /*CSTYLED*/ \ 190 9: movq (reg, scr1, 1), scr2; \ 191 movq scr2, (ptr, scr1, 1); \ 192 addq $CLONGSIZE, scr1; \ 193 cmpq $REGSIZE, scr1; \ 194 jl 9b; \ 195 movq %gs:CPU_THREAD, scr2; \ 196 movq scr2, TTR_CURTHREAD(ptr); \ 197 __GETCR2(movq, scr2); \ 198 movq scr2, TTR_CR2(ptr) 199 200 #elif defined(__i386) 201 202 #define TRACE_REGS(ptr, reg, scr1, scr2) \ 203 xorl scr1, scr1; \ 204 /*CSTYLED*/ \ 205 9: movl (reg, scr1, 1), scr2; \ 206 movl scr2, (ptr, scr1, 1); \ 207 addl $CLONGSIZE, scr1; \ 208 cmpl $REGSIZE, scr1; \ 209 jl 9b; \ 210 movl %gs:CPU_THREAD, scr2; \ 211 movl scr2, TTR_CURTHREAD(ptr); \ 212 __GETCR2(movl, scr2); \ 213 movl scr2, TTR_CR2(ptr) 214 215 #endif /* __i386 */ 216 217 /* 218 * The time stamp macro records a high-resolution time stamp for the 219 * given TRAPTRACE entry. Note that %eax and %edx are plowed by this 220 * macro; if they are to be preserved, it's up to the caller of the macro. 221 */ 222 223 #if defined(__amd64) 224 225 #define TRACE_STAMP(reg) \ 226 rdtsc; \ 227 movl %eax, TTR_STAMP(reg); \ 228 movl %edx, TTR_STAMP+4(reg) 229 230 /* 231 * %rbp should be set before invoking this macro. 232 */ 233 234 #define TRACE_STACK(tt) \ 235 pushq %rdi; \ 236 pushq %rsi; \ 237 pushq %rdx; \ 238 pushq %rcx; \ 239 pushq %r8; \ 240 pushq %r9; \ 241 pushq %rax; \ 242 pushq %r12; \ 243 movq tt, %r12; \ 244 leaq TTR_STACK(%r12), %rdi; \ 245 movl $TTR_STACK_DEPTH, %esi; \ 246 call getpcstack; \ 247 movl %eax, TTR_SDEPTH(%r12); \ 248 popq %r12; \ 249 popq %rax; \ 250 popq %r9; \ 251 popq %r8; \ 252 popq %rcx; \ 253 popq %rdx; \ 254 popq %rsi; \ 255 popq %rdi 256 257 #elif defined(__i386) 258 259 #define TRACE_STAMP(reg) \ 260 xorl %eax, %eax; \ 261 xorl %edx, %edx; \ 262 testl $X86_TSC, x86_feature; \ 263 jz 9f; \ 264 rdtsc; \ 265 9: movl %eax, TTR_STAMP(reg); \ 266 movl %edx, TTR_STAMP+4(reg) 267 268 #define TRACE_STACK(tt) \ 269 pushl %eax; \ 270 pushl %ecx; \ 271 pushl %edx; \ 272 pushl %ebx; \ 273 pushl $TTR_STACK_DEPTH; \ 274 movl tt, %ebx; \ 275 leal TTR_STACK(%ebx), %eax; \ 276 pushl %eax; \ 277 call getpcstack; \ 278 addl $8, %esp; \ 279 movl %eax, TTR_SDEPTH(%ebx); \ 280 popl %ebx; \ 281 popl %edx; \ 282 popl %ecx; \ 283 popl %eax 284 285 #endif /* __i386 */ 286 287 #else 288 289 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker) 290 #define TRACE_REGS(ptr, reg, scr1, scr2) 291 #define TRACE_STAMP(reg) 292 #define TRACE_STACK(reg) 293 294 #endif /* TRAPTRACE */ 295 296 #endif /* _ASM */ 297 298 #define TT_SYSCALL 0xaa /* system call via lcall */ 299 #define TT_SYSENTER 0xab /* system call via sysenter */ 300 #define TT_SYSC 0xad /* system call via syscall (32-bit) */ 301 #define TT_SYSC64 0xae /* system call via syscall (64-bit) */ 302 #define TT_INTERRUPT 0xbb 303 #define TT_TRAP 0xcc 304 #define TT_INTTRAP 0xdd 305 #define TT_EVENT 0xee /* hypervisor event */ 306 #define TT_XCALL 0xf0 /* x-call handling */ 307 308 /* 309 * TT_XCALL subcodes: 310 */ 311 #define TT_XC_SVC_BEGIN 0 /* xc_serv() entry */ 312 #define TT_XC_SVC_END 1 /* xc_serv() return */ 313 #define TT_XC_START 2 /* xc_common() - pre-dirint */ 314 #define TT_XC_WAIT 3 /* xc_common() - wait for completion */ 315 #define TT_XC_ACK 4 /* xc_common() - ack completion */ 316 #define TT_XC_CAPTURE 5 /* xc_capture() */ 317 #define TT_XC_RELEASE 6 /* xc_release() */ 318 #define TT_XC_POKE_CPU 7 /* poke_cpu() */ 319 #define TT_XC_CBE_FIRE 8 /* cbe_fire() */ 320 #define TT_XC_CBE_XCALL 9 /* cbe_xcall() */ 321 322 #ifdef __cplusplus 323 } 324 #endif 325 326 #endif /* _IA32_SYS_TRAPTRACE_H */ 327