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