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 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _IA32_SYS_TRAPTRACE_H 28 #define _IA32_SYS_TRAPTRACE_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 #include <sys/privregs.h> 37 38 /* 39 * XX64 Need to fix the following comment. 40 * 41 * Trap tracing. If TRAPTRACE is defined, an entry is recorded every time 42 * the CPU jumps through the Interrupt Descriptor Table (IDT). One exception 43 * is the Double Fault handler, which does not record a traptrace entry. 44 */ 45 46 /* 47 * XX64 -- 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 15 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 uchar_t 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 } ttr_info; 78 uintptr_t ttr_curthread; 79 uchar_t ttr_pad[TTR_PAD1_SIZE]; 80 uchar_t ttr_marker; 81 hrtime_t ttr_stamp; 82 int ttr_sdepth; 83 pc_t ttr_stack[TTR_STACK_DEPTH]; 84 } trap_trace_rec_t; 85 86 #define ttr_vector ttr_info.idt_entry.vector 87 #define ttr_ipl ttr_info.idt_entry.ipl 88 #define ttr_spl ttr_info.idt_entry.spl 89 #define ttr_pri ttr_info.idt_entry.pri 90 #define ttr_sysnum ttr_info.gate_entry.sysnum 91 92 #define TRAPTR_NENT 128 93 94 extern trap_trace_ctl_t trap_trace_ctl[NCPU]; /* Allocated in locore.s */ 95 extern size_t trap_trace_bufsize; 96 extern int trap_trace_freeze; 97 extern trap_trace_rec_t trap_trace_postmort; /* Entry used after death */ 98 99 #define TRAPTRACE_FREEZE trap_trace_freeze = 1; 100 #define TRAPTRACE_UNFREEZE trap_trace_freeze = 0; 101 102 #else /* _ASM */ 103 104 /* 105 * ptr -- will be set to a TRAPTRACE entry. 106 * scr1 -- scratch 107 * scr1_32 -- 32-bit version of scr1 108 * scr2 -- scratch 109 * marker -- register containing byte to store in marker field of entry 110 * 111 * Note that this macro defines labels "8" and "9". 112 */ 113 #ifdef TRAPTRACE 114 115 #if defined(__amd64) 116 117 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker) \ 118 leaq trap_trace_postmort(%rip), ptr; \ 119 cmpl $0, trap_trace_freeze(%rip); \ 120 jne 9f; \ 121 LOADCPU(ptr); \ 122 movl CPU_ID(ptr), scr1_32; \ 123 shlq $TRAPTR_SIZE_SHIFT, scr1; \ 124 leaq trap_trace_ctl(%rip), scr2; \ 125 addq scr2, scr1; \ 126 movq TRAPTR_NEXT(scr1), ptr; \ 127 leaq TRAP_ENT_SIZE(ptr), scr2; \ 128 cmpq TRAPTR_LIMIT(scr1), scr2; \ 129 jl 8f; \ 130 movq TRAPTR_FIRST(scr1), scr2; \ 131 8: movq scr2, TRAPTR_NEXT(scr1); \ 132 9: movb marker, TTR_MARKER(ptr); 133 134 #elif defined(__i386) 135 136 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker) \ 137 movl $trap_trace_postmort, ptr; \ 138 cmpl $0, trap_trace_freeze; \ 139 jne 9f; \ 140 LOADCPU(ptr); \ 141 movl CPU_ID(ptr), scr1_32; \ 142 shll $TRAPTR_SIZE_SHIFT, scr1; \ 143 addl $trap_trace_ctl, scr1; \ 144 movl TRAPTR_NEXT(scr1), ptr; \ 145 leal TRAP_ENT_SIZE(ptr), scr2; \ 146 cmpl TRAPTR_LIMIT(scr1), scr2; \ 147 jl 8f; \ 148 movl TRAPTR_FIRST(scr1), scr2; \ 149 8: movl scr2, TRAPTR_NEXT(scr1); \ 150 9: movb marker, TTR_MARKER(ptr); 151 152 #endif /* __i386 */ 153 154 /* 155 * ptr -- pointer to the current TRAPTRACE entry. 156 * reg -- pointer to the stored registers; must be on the stack 157 * scr1 -- scratch used as array index 158 * scr2 -- scratch used as temporary 159 * 160 * Note that this macro defines label "9". 161 * Also captures curthread on exit of loop. 162 */ 163 164 #if defined(__amd64) 165 166 #define TRACE_REGS(ptr, reg, scr1, scr2) \ 167 xorq scr1, scr1; \ 168 /*CSTYLED*/ \ 169 9: movq (reg, scr1, 1), scr2; \ 170 movq scr2, (ptr, scr1, 1); \ 171 addq $CLONGSIZE, scr1; \ 172 cmpq $REGSIZE, scr1; \ 173 jl 9b; \ 174 movq %gs:CPU_THREAD, scr2; \ 175 movq scr2, TTR_CURTHREAD(ptr); \ 176 movq %cr2, scr2; \ 177 movq scr2, TTR_CR2(ptr) 178 179 #elif defined(__i386) 180 181 #define TRACE_REGS(ptr, reg, scr1, scr2) \ 182 xorl scr1, scr1; \ 183 /*CSTYLED*/ \ 184 9: movl (reg, scr1, 1), scr2; \ 185 movl scr2, (ptr, scr1, 1); \ 186 addl $CLONGSIZE, scr1; \ 187 cmpl $REGSIZE, scr1; \ 188 jl 9b; \ 189 movl %gs:CPU_THREAD, scr2; \ 190 movl scr2, TTR_CURTHREAD(ptr); \ 191 movl %cr2, scr2; \ 192 movl scr2, TTR_CR2(ptr) 193 194 #endif /* __i386 */ 195 196 /* 197 * The time stamp macro records a high-resolution time stamp for the 198 * given TRAPTRACE entry. Note that %eax and %edx are plowed by this 199 * macro; if they are to be preserved, it's up to the caller of the macro. 200 */ 201 202 #if defined(__amd64) 203 204 #define TRACE_STAMP(reg) \ 205 rdtsc; \ 206 movl %eax, TTR_STAMP(reg); \ 207 movl %edx, TTR_STAMP+4(reg) 208 209 /* 210 * %rbp should be set before invoking this macro. 211 */ 212 213 #define TRACE_STACK(tt) \ 214 pushq %rdi; \ 215 pushq %rsi; \ 216 pushq %rdx; \ 217 pushq %rcx; \ 218 pushq %r8; \ 219 pushq %r9; \ 220 pushq %rax; \ 221 pushq %r12; \ 222 movq tt, %r12; \ 223 leaq TTR_STACK(%r12), %rdi; \ 224 movl $TTR_STACK_DEPTH, %esi; \ 225 call getpcstack; \ 226 movl %eax, TTR_SDEPTH(%r12); \ 227 popq %r12; \ 228 popq %rax; \ 229 popq %r9; \ 230 popq %r8; \ 231 popq %rcx; \ 232 popq %rdx; \ 233 popq %rsi; \ 234 popq %rdi 235 236 #elif defined(__i386) 237 238 #define TRACE_STAMP(reg) \ 239 xorl %eax, %eax; \ 240 xorl %edx, %edx; \ 241 testl $X86_TSC, x86_feature; \ 242 jz 9f; \ 243 rdtsc; \ 244 9: movl %eax, TTR_STAMP(reg); \ 245 movl %edx, TTR_STAMP+4(reg) 246 247 #endif /* __i386 */ 248 249 #else 250 251 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker) 252 #define TRACE_REGS(ptr, reg, scr1, scr2) 253 #define TRACE_STAMP(reg) 254 #define TRACE_STACK(reg) 255 256 #endif /* TRAPTRACE */ 257 258 #endif /* _ASM */ 259 260 #define TT_SYSCALL 0xaa /* system call via lcall */ 261 #define TT_SYSENTER 0xab /* system call via sysenter */ 262 #define TT_SYSC 0xad /* system call via syscall (32-bit) */ 263 #define TT_SYSC64 0xae /* system call via syscall (64-bit) */ 264 #define TT_INTERRUPT 0xbb 265 #define TT_TRAP 0xcc 266 #define TT_INTTRAP 0xdd 267 268 #ifdef __cplusplus 269 } 270 #endif 271 272 #endif /* _IA32_SYS_TRAPTRACE_H */ 273