xref: /titanic_52/usr/src/uts/intel/ia32/sys/traptrace.h (revision 2cb27123907a098a777e39eebc349d73e99a518f)
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