xref: /titanic_50/usr/src/uts/intel/ia32/sys/traptrace.h (revision 0e42dee69ed771bf604dd1789fca9d77b5bbe302)
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