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