xref: /titanic_41/usr/src/uts/intel/ia32/sys/traptrace.h (revision 4bff34e37def8a90f9194d81bc345c52ba20086a)
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