xref: /onnv-gate/usr/src/uts/intel/ia32/sys/traptrace.h (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #ifndef _IA32_SYS_TRAPTRACE_H
28*0Sstevel@tonic-gate #define	_IA32_SYS_TRAPTRACE_H
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate #ifdef	__cplusplus
33*0Sstevel@tonic-gate extern "C" {
34*0Sstevel@tonic-gate #endif
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include <sys/privregs.h>
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate /*
39*0Sstevel@tonic-gate  * XX64 Need to fix the following comment.
40*0Sstevel@tonic-gate  *
41*0Sstevel@tonic-gate  * Trap tracing.  If TRAPTRACE is defined, an entry is recorded every time
42*0Sstevel@tonic-gate  * the CPU jumps through the Interrupt Descriptor Table (IDT).  One exception
43*0Sstevel@tonic-gate  * is the Double Fault handler, which does not record a traptrace entry.
44*0Sstevel@tonic-gate  */
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*
47*0Sstevel@tonic-gate  * XX64 -- non-assembler files that include this file must include
48*0Sstevel@tonic-gate  * <sys/systm.h> before it, for the typedef of pc_t to be visible.
49*0Sstevel@tonic-gate  */
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate #define	TTR_STACK_DEPTH	15
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate #ifndef	_ASM
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate #define	TTR_PAD1_SIZE	(sizeof (long) - 1)
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate typedef struct {
58*0Sstevel@tonic-gate 	uintptr_t	ttc_next;
59*0Sstevel@tonic-gate 	uintptr_t	ttc_first;
60*0Sstevel@tonic-gate 	uintptr_t	ttc_limit;
61*0Sstevel@tonic-gate 	uintptr_t	ttc_current;
62*0Sstevel@tonic-gate } trap_trace_ctl_t;
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate typedef struct {
65*0Sstevel@tonic-gate 	struct regs	ttr_regs;
66*0Sstevel@tonic-gate 	greg_t		ttr_cr2;
67*0Sstevel@tonic-gate 	union _ttr_info {
68*0Sstevel@tonic-gate 		struct _idt_entry {
69*0Sstevel@tonic-gate 			uchar_t	vector;
70*0Sstevel@tonic-gate 			uchar_t	ipl;
71*0Sstevel@tonic-gate 			uchar_t	spl;
72*0Sstevel@tonic-gate 			uchar_t	pri;
73*0Sstevel@tonic-gate 		} idt_entry;
74*0Sstevel@tonic-gate 		struct _gate_entry {
75*0Sstevel@tonic-gate 			int	sysnum;
76*0Sstevel@tonic-gate 		} gate_entry;
77*0Sstevel@tonic-gate 	} ttr_info;
78*0Sstevel@tonic-gate 	uintptr_t	ttr_curthread;
79*0Sstevel@tonic-gate 	uchar_t		ttr_pad[TTR_PAD1_SIZE];
80*0Sstevel@tonic-gate 	uchar_t		ttr_marker;
81*0Sstevel@tonic-gate 	hrtime_t	ttr_stamp;
82*0Sstevel@tonic-gate 	int		ttr_sdepth;
83*0Sstevel@tonic-gate 	pc_t		ttr_stack[TTR_STACK_DEPTH];
84*0Sstevel@tonic-gate } trap_trace_rec_t;
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate #define	ttr_vector	ttr_info.idt_entry.vector
87*0Sstevel@tonic-gate #define	ttr_ipl		ttr_info.idt_entry.ipl
88*0Sstevel@tonic-gate #define	ttr_spl		ttr_info.idt_entry.spl
89*0Sstevel@tonic-gate #define	ttr_pri		ttr_info.idt_entry.pri
90*0Sstevel@tonic-gate #define	ttr_sysnum	ttr_info.gate_entry.sysnum
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate #define	TRAPTR_NENT	128
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate extern trap_trace_ctl_t	trap_trace_ctl[NCPU];	/* Allocated in locore.s */
95*0Sstevel@tonic-gate extern size_t		trap_trace_bufsize;
96*0Sstevel@tonic-gate extern int		trap_trace_freeze;
97*0Sstevel@tonic-gate extern trap_trace_rec_t	trap_trace_postmort;	/* Entry used after death */
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate #define	TRAPTRACE_FREEZE	trap_trace_freeze = 1;
100*0Sstevel@tonic-gate #define	TRAPTRACE_UNFREEZE	trap_trace_freeze = 0;
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate #else	/* _ASM */
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate /*
105*0Sstevel@tonic-gate  * ptr       -- will be set to a TRAPTRACE entry.
106*0Sstevel@tonic-gate  * scr1      -- scratch
107*0Sstevel@tonic-gate  * scr1_32   -- 32-bit version of scr1
108*0Sstevel@tonic-gate  * scr2      -- scratch
109*0Sstevel@tonic-gate  * marker    -- register containing byte to store in marker field of entry
110*0Sstevel@tonic-gate  *
111*0Sstevel@tonic-gate  * Note that this macro defines labels "8" and "9".
112*0Sstevel@tonic-gate  */
113*0Sstevel@tonic-gate #ifdef TRAPTRACE
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate #if defined(__amd64)
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate #define	TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)	\
118*0Sstevel@tonic-gate 	leaq	trap_trace_postmort(%rip), ptr;	\
119*0Sstevel@tonic-gate 	cmpl	$0, trap_trace_freeze(%rip);	\
120*0Sstevel@tonic-gate 	jne	9f;				\
121*0Sstevel@tonic-gate 	LOADCPU(ptr);				\
122*0Sstevel@tonic-gate 	movl	CPU_ID(ptr), scr1_32;		\
123*0Sstevel@tonic-gate 	shlq	$TRAPTR_SIZE_SHIFT, scr1;	\
124*0Sstevel@tonic-gate 	leaq	trap_trace_ctl(%rip), scr2;	\
125*0Sstevel@tonic-gate 	addq	scr2, scr1;			\
126*0Sstevel@tonic-gate 	movq	TRAPTR_NEXT(scr1), ptr;		\
127*0Sstevel@tonic-gate 	leaq	TRAP_ENT_SIZE(ptr), scr2;	\
128*0Sstevel@tonic-gate 	cmpq	TRAPTR_LIMIT(scr1), scr2;	\
129*0Sstevel@tonic-gate 	jl	8f;				\
130*0Sstevel@tonic-gate 	movq	TRAPTR_FIRST(scr1), scr2;	\
131*0Sstevel@tonic-gate 8:	movq	scr2, TRAPTR_NEXT(scr1);	\
132*0Sstevel@tonic-gate 9:	movb	marker, TTR_MARKER(ptr);
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate #elif defined(__i386)
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate #define	TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)	\
137*0Sstevel@tonic-gate 	movl	$trap_trace_postmort, ptr;	\
138*0Sstevel@tonic-gate 	cmpl	$0, trap_trace_freeze;		\
139*0Sstevel@tonic-gate 	jne	9f;				\
140*0Sstevel@tonic-gate 	LOADCPU(ptr);				\
141*0Sstevel@tonic-gate 	movl	CPU_ID(ptr), scr1_32;		\
142*0Sstevel@tonic-gate 	shll	$TRAPTR_SIZE_SHIFT, scr1;	\
143*0Sstevel@tonic-gate 	addl	$trap_trace_ctl, scr1;		\
144*0Sstevel@tonic-gate 	movl	TRAPTR_NEXT(scr1), ptr;		\
145*0Sstevel@tonic-gate 	leal	TRAP_ENT_SIZE(ptr), scr2;	\
146*0Sstevel@tonic-gate 	cmpl	TRAPTR_LIMIT(scr1), scr2;	\
147*0Sstevel@tonic-gate 	jl	8f;				\
148*0Sstevel@tonic-gate 	movl	TRAPTR_FIRST(scr1), scr2;	\
149*0Sstevel@tonic-gate 8:	movl	scr2, TRAPTR_NEXT(scr1);	\
150*0Sstevel@tonic-gate 9:	movb	marker, TTR_MARKER(ptr);
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate #endif	/* __i386 */
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate /*
155*0Sstevel@tonic-gate  * ptr  -- pointer to the current TRAPTRACE entry.
156*0Sstevel@tonic-gate  * reg  -- pointer to the stored registers; must be on the stack
157*0Sstevel@tonic-gate  * scr1 -- scratch used as array index
158*0Sstevel@tonic-gate  * scr2 -- scratch used as temporary
159*0Sstevel@tonic-gate  *
160*0Sstevel@tonic-gate  * Note that this macro defines label "9".
161*0Sstevel@tonic-gate  * Also captures curthread on exit of loop.
162*0Sstevel@tonic-gate  */
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate #if defined(__amd64)
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate #define	TRACE_REGS(ptr, reg, scr1, scr2)	\
167*0Sstevel@tonic-gate 	xorq	scr1, scr1;			\
168*0Sstevel@tonic-gate 	/*CSTYLED*/				\
169*0Sstevel@tonic-gate 9:	movq	(reg, scr1, 1), scr2;		\
170*0Sstevel@tonic-gate 	movq	scr2, (ptr, scr1, 1);		\
171*0Sstevel@tonic-gate 	addq	$CLONGSIZE, scr1;		\
172*0Sstevel@tonic-gate 	cmpq	$REGSIZE, scr1;			\
173*0Sstevel@tonic-gate 	jl	9b;				\
174*0Sstevel@tonic-gate 	movq	%gs:CPU_THREAD, scr2;		\
175*0Sstevel@tonic-gate 	movq	scr2, TTR_CURTHREAD(ptr);	\
176*0Sstevel@tonic-gate 	movq	%cr2, scr2;			\
177*0Sstevel@tonic-gate 	movq	scr2, TTR_CR2(ptr)
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate #elif defined(__i386)
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate #define	TRACE_REGS(ptr, reg, scr1, scr2)	\
182*0Sstevel@tonic-gate 	xorl	scr1, scr1;			\
183*0Sstevel@tonic-gate 	/*CSTYLED*/				\
184*0Sstevel@tonic-gate 9:	movl	(reg, scr1, 1), scr2;		\
185*0Sstevel@tonic-gate 	movl	scr2, (ptr, scr1, 1);		\
186*0Sstevel@tonic-gate 	addl	$CLONGSIZE, scr1;		\
187*0Sstevel@tonic-gate 	cmpl	$REGSIZE, scr1;			\
188*0Sstevel@tonic-gate 	jl	9b;				\
189*0Sstevel@tonic-gate 	movl	%gs:CPU_THREAD, scr2;		\
190*0Sstevel@tonic-gate 	movl	scr2, TTR_CURTHREAD(ptr);	\
191*0Sstevel@tonic-gate 	movl	%cr2, scr2;			\
192*0Sstevel@tonic-gate 	movl	scr2, TTR_CR2(ptr)
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate #endif	/* __i386 */
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate /*
197*0Sstevel@tonic-gate  * The time stamp macro records a high-resolution time stamp for the
198*0Sstevel@tonic-gate  * given TRAPTRACE entry.  Note that %eax and %edx are plowed by this
199*0Sstevel@tonic-gate  * macro;  if they are to be preserved, it's up to the caller of the macro.
200*0Sstevel@tonic-gate  */
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate #if defined(__amd64)
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate #define	TRACE_STAMP(reg)			\
205*0Sstevel@tonic-gate 	rdtsc;					\
206*0Sstevel@tonic-gate 	movl	%eax, TTR_STAMP(reg);		\
207*0Sstevel@tonic-gate 	movl	%edx, TTR_STAMP+4(reg)
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate /*
210*0Sstevel@tonic-gate  * %rbp should be set before invoking this macro.
211*0Sstevel@tonic-gate  */
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate #define	TRACE_STACK(tt)				\
214*0Sstevel@tonic-gate 	pushq	%rdi;				\
215*0Sstevel@tonic-gate 	pushq	%rsi;				\
216*0Sstevel@tonic-gate 	pushq	%rdx;				\
217*0Sstevel@tonic-gate 	pushq	%rcx;				\
218*0Sstevel@tonic-gate 	pushq	%r8;				\
219*0Sstevel@tonic-gate 	pushq	%r9;				\
220*0Sstevel@tonic-gate 	pushq	%rax;				\
221*0Sstevel@tonic-gate 	pushq	%r12;				\
222*0Sstevel@tonic-gate 	movq	tt, %r12;			\
223*0Sstevel@tonic-gate 	leaq	TTR_STACK(%r12), %rdi;		\
224*0Sstevel@tonic-gate 	movl	$TTR_STACK_DEPTH, %esi;		\
225*0Sstevel@tonic-gate 	call	getpcstack;			\
226*0Sstevel@tonic-gate 	movl	%eax, TTR_SDEPTH(%r12);		\
227*0Sstevel@tonic-gate 	popq	%r12;				\
228*0Sstevel@tonic-gate 	popq	%rax;				\
229*0Sstevel@tonic-gate 	popq	%r9;				\
230*0Sstevel@tonic-gate 	popq	%r8;				\
231*0Sstevel@tonic-gate 	popq	%rcx;				\
232*0Sstevel@tonic-gate 	popq	%rdx;				\
233*0Sstevel@tonic-gate 	popq	%rsi;				\
234*0Sstevel@tonic-gate 	popq	%rdi
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate #elif defined(__i386)
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate #define	TRACE_STAMP(reg)			\
239*0Sstevel@tonic-gate 	xorl	%eax, %eax;			\
240*0Sstevel@tonic-gate 	xorl	%edx, %edx;			\
241*0Sstevel@tonic-gate 	testl	$X86_TSC, x86_feature;		\
242*0Sstevel@tonic-gate 	jz	9f;				\
243*0Sstevel@tonic-gate 	rdtsc;					\
244*0Sstevel@tonic-gate 9:	movl	%eax, TTR_STAMP(reg);		\
245*0Sstevel@tonic-gate 	movl	%edx, TTR_STAMP+4(reg)
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate #endif	/* __i386 */
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate #else
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate #define	TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)
252*0Sstevel@tonic-gate #define	TRACE_REGS(ptr, reg, scr1, scr2)
253*0Sstevel@tonic-gate #define	TRACE_STAMP(reg)
254*0Sstevel@tonic-gate #define	TRACE_STACK(reg)
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate #endif	/* TRAPTRACE */
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate #endif 	/* _ASM */
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate #define	TT_SYSCALL	0xaa	/* system call via lcall */
261*0Sstevel@tonic-gate #define	TT_SYSENTER	0xab	/* system call via sysenter */
262*0Sstevel@tonic-gate #define	TT_SYSC		0xad	/* system call via syscall (32-bit) */
263*0Sstevel@tonic-gate #define	TT_SYSC64	0xae	/* system call via syscall (64-bit) */
264*0Sstevel@tonic-gate #define	TT_INTERRUPT	0xbb
265*0Sstevel@tonic-gate #define	TT_TRAP		0xcc
266*0Sstevel@tonic-gate #define	TT_INTTRAP	0xdd
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate #ifdef	__cplusplus
269*0Sstevel@tonic-gate }
270*0Sstevel@tonic-gate #endif
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate #endif	/* _IA32_SYS_TRAPTRACE_H */
273