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.
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.
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]
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
25 #ifndef _IA32_SYS_TRAPTRACE_H
26 #define _IA32_SYS_TRAPTRACE_H
32 #include <sys/privregs.h>
35 * Trap tracing. If TRAPTRACE is defined, an entry is recorded every time
36 * the CPU jumps through the Interrupt Descriptor Table (IDT). One exception
37 * is the Double Fault handler, which does not record a traptrace entry.
39 * There are facilities to (conditionally) interleave tracing of related
40 * facilities e.h. x-calls.
44 * Note: non-assembler files that include this file must include
45 * <sys/systm.h> before it, for the typedef of pc_t to be visible.
48 #define TTR_STACK_DEPTH 10
52 #define TTR_PAD1_SIZE (sizeof (long) - 1)
58 uintptr_t ttc_current
;
76 uintptr_t ttr_curthread
;
77 uchar_t ttr_pad
[TTR_PAD1_SIZE
];
81 pc_t ttr_stack
[TTR_STACK_DEPTH
];
84 #define ttr_cpuid ttr_info.idt_entry.cpuid
85 #define ttr_vector ttr_info.idt_entry.vector
86 #define ttr_ipl ttr_info.idt_entry.ipl
87 #define ttr_spl ttr_info.idt_entry.spl
88 #define ttr_pri ttr_info.idt_entry.pri
89 #define ttr_sysnum ttr_info.gate_entry.sysnum
91 #define TRAPTR_NENT 128
93 extern trap_trace_ctl_t trap_trace_ctl
[NCPU
]; /* Allocated in locore.s */
94 extern size_t trap_trace_bufsize
;
95 extern int trap_trace_freeze
;
96 extern trap_trace_rec_t trap_trace_postmort
; /* Entry used after death */
98 #define TRAPTRACE_FREEZE trap_trace_freeze = 1;
99 #define TRAPTRACE_UNFREEZE trap_trace_freeze = 0;
104 * ptr -- will be set to a TRAPTRACE entry.
106 * scr1_32 -- 32-bit version of scr1
108 * marker -- register containing byte to store in marker field of entry
110 * Note that this macro defines labels "8" and "9".
116 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker) \
117 leaq trap_trace_postmort(%rip), ptr; \
118 cmpl $0, trap_trace_freeze(%rip); \
121 movl CPU_ID(ptr), scr1_32; \
122 shlq $TRAPTR_SIZE_SHIFT, scr1; \
123 leaq trap_trace_ctl(%rip), scr2; \
125 movq TRAPTR_NEXT(scr1), ptr; \
126 leaq TRAP_ENT_SIZE(ptr), scr2; \
127 cmpq TRAPTR_LIMIT(scr1), scr2; \
129 movq TRAPTR_FIRST(scr1), scr2; \
130 8: movq scr2, TRAPTR_NEXT(scr1); \
131 9: movb marker, TTR_MARKER(ptr);
133 #elif defined(__i386)
135 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker) \
136 movl $trap_trace_postmort, ptr; \
137 cmpl $0, trap_trace_freeze; \
140 movl CPU_ID(ptr), scr1_32; \
141 shll $TRAPTR_SIZE_SHIFT, scr1; \
142 addl $trap_trace_ctl, scr1; \
143 movl TRAPTR_NEXT(scr1), ptr; \
144 leal TRAP_ENT_SIZE(ptr), scr2; \
145 cmpl TRAPTR_LIMIT(scr1), scr2; \
147 movl TRAPTR_FIRST(scr1), scr2; \
148 8: movl scr2, TRAPTR_NEXT(scr1); \
149 9: movb marker, TTR_MARKER(ptr);
154 * ptr -- pointer to the current TRAPTRACE entry.
155 * reg -- pointer to the stored registers; must be on the stack
156 * scr1 -- scratch used as array index
157 * scr2 -- scratch used as temporary
159 * Note that this macro defines label "9".
160 * Also captures curthread on exit of loop.
163 #define __GETCR2(_mov, reg) \
164 _mov %gs:CPU_VCPU_INFO, reg; \
165 _mov VCPU_INFO_ARCH_CR2(reg), reg
167 #define __GETCR2(_mov, reg) \
173 #define TRACE_REGS(ptr, reg, scr1, scr2) \
176 9: movq (reg, scr1, 1), scr2; \
177 movq scr2, (ptr, scr1, 1); \
178 addq $CLONGSIZE, scr1; \
179 cmpq $REGSIZE, scr1; \
181 movq %gs:CPU_THREAD, scr2; \
182 movq scr2, TTR_CURTHREAD(ptr); \
183 __GETCR2(movq, scr2); \
184 movq scr2, TTR_CR2(ptr)
186 #elif defined(__i386)
188 #define TRACE_REGS(ptr, reg, scr1, scr2) \
191 9: movl (reg, scr1, 1), scr2; \
192 movl scr2, (ptr, scr1, 1); \
193 addl $CLONGSIZE, scr1; \
194 cmpl $REGSIZE, scr1; \
196 movl %gs:CPU_THREAD, scr2; \
197 movl scr2, TTR_CURTHREAD(ptr); \
198 __GETCR2(movl, scr2); \
199 movl scr2, TTR_CR2(ptr)
204 * The time stamp macro records a high-resolution time stamp for the
205 * given TRAPTRACE entry. Note that %eax and %edx are plowed by this
206 * macro; if they are to be preserved, it's up to the caller of the macro.
211 #define TRACE_STAMP(reg) \
213 movl %eax, TTR_STAMP(reg); \
214 movl %edx, TTR_STAMP+4(reg)
217 * %rbp should be set before invoking this macro.
220 #define TRACE_STACK(tt) \
230 leaq TTR_STACK(%r12), %rdi; \
231 movl $TTR_STACK_DEPTH, %esi; \
233 movl %eax, TTR_SDEPTH(%r12); \
243 #elif defined(__i386)
245 #define TRACE_STAMP(reg) \
248 btl $X86FSET_TSC, x86_featureset; \
251 9: movl %eax, TTR_STAMP(reg); \
252 movl %edx, TTR_STAMP+4(reg)
254 #define TRACE_STACK(tt) \
259 pushl $TTR_STACK_DEPTH; \
261 leal TTR_STACK(%ebx), %eax; \
265 movl %eax, TTR_SDEPTH(%ebx); \
275 #define TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)
276 #define TRACE_REGS(ptr, reg, scr1, scr2)
277 #define TRACE_STAMP(reg)
278 #define TRACE_STACK(reg)
280 #endif /* TRAPTRACE */
284 #define TT_SYSCALL 0xaa /* system call via lcall */
285 #define TT_SYSENTER 0xab /* system call via sysenter */
286 #define TT_SYSC 0xad /* system call via syscall (32-bit) */
287 #define TT_SYSC64 0xae /* system call via syscall (64-bit) */
288 #define TT_INTERRUPT 0xbb
290 #define TT_INTTRAP 0xdd
291 #define TT_EVENT 0xee /* hypervisor event */
297 #endif /* _IA32_SYS_TRAPTRACE_H */