xref: /onnv-gate/usr/src/uts/intel/ia32/sys/traptrace.h (revision 12826:fca99d9e3f2f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53446Smrj  * Common Development and Distribution License (the "License").
63446Smrj  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
2212825SJimmy.Vetayases@oracle.com  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #ifndef _IA32_SYS_TRAPTRACE_H
260Sstevel@tonic-gate #define	_IA32_SYS_TRAPTRACE_H
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #ifdef	__cplusplus
290Sstevel@tonic-gate extern "C" {
300Sstevel@tonic-gate #endif
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/privregs.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate /*
350Sstevel@tonic-gate  * Trap tracing.  If TRAPTRACE is defined, an entry is recorded every time
360Sstevel@tonic-gate  * the CPU jumps through the Interrupt Descriptor Table (IDT).  One exception
370Sstevel@tonic-gate  * is the Double Fault handler, which does not record a traptrace entry.
383446Smrj  *
393446Smrj  * There are facilities to (conditionally) interleave tracing of related
403446Smrj  * facilities e.h. x-calls.
410Sstevel@tonic-gate  */
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /*
443446Smrj  * Note: non-assembler files that include this file must include
450Sstevel@tonic-gate  * <sys/systm.h> before it, for the typedef of pc_t to be visible.
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate 
483446Smrj #define	TTR_STACK_DEPTH	10
490Sstevel@tonic-gate 
500Sstevel@tonic-gate #ifndef	_ASM
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #define	TTR_PAD1_SIZE	(sizeof (long) - 1)
530Sstevel@tonic-gate 
540Sstevel@tonic-gate typedef struct {
550Sstevel@tonic-gate 	uintptr_t	ttc_next;
560Sstevel@tonic-gate 	uintptr_t	ttc_first;
570Sstevel@tonic-gate 	uintptr_t	ttc_limit;
580Sstevel@tonic-gate 	uintptr_t	ttc_current;
590Sstevel@tonic-gate } trap_trace_ctl_t;
600Sstevel@tonic-gate 
610Sstevel@tonic-gate typedef struct {
620Sstevel@tonic-gate 	struct regs	ttr_regs;
630Sstevel@tonic-gate 	greg_t		ttr_cr2;
640Sstevel@tonic-gate 	union _ttr_info {
650Sstevel@tonic-gate 		struct _idt_entry {
6612683SJimmy.Vetayases@oracle.com 			int	cpuid;
673446Smrj 			short	vector;
680Sstevel@tonic-gate 			uchar_t	ipl;
690Sstevel@tonic-gate 			uchar_t	spl;
700Sstevel@tonic-gate 			uchar_t	pri;
710Sstevel@tonic-gate 		} idt_entry;
720Sstevel@tonic-gate 		struct _gate_entry {
730Sstevel@tonic-gate 			int	sysnum;
740Sstevel@tonic-gate 		} gate_entry;
750Sstevel@tonic-gate 	} ttr_info;
760Sstevel@tonic-gate 	uintptr_t	ttr_curthread;
770Sstevel@tonic-gate 	uchar_t		ttr_pad[TTR_PAD1_SIZE];
780Sstevel@tonic-gate 	uchar_t		ttr_marker;
790Sstevel@tonic-gate 	hrtime_t	ttr_stamp;
800Sstevel@tonic-gate 	int		ttr_sdepth;
810Sstevel@tonic-gate 	pc_t		ttr_stack[TTR_STACK_DEPTH];
820Sstevel@tonic-gate } trap_trace_rec_t;
830Sstevel@tonic-gate 
8412683SJimmy.Vetayases@oracle.com #define	ttr_cpuid	ttr_info.idt_entry.cpuid
850Sstevel@tonic-gate #define	ttr_vector	ttr_info.idt_entry.vector
860Sstevel@tonic-gate #define	ttr_ipl		ttr_info.idt_entry.ipl
870Sstevel@tonic-gate #define	ttr_spl		ttr_info.idt_entry.spl
880Sstevel@tonic-gate #define	ttr_pri		ttr_info.idt_entry.pri
890Sstevel@tonic-gate #define	ttr_sysnum	ttr_info.gate_entry.sysnum
900Sstevel@tonic-gate 
910Sstevel@tonic-gate #define	TRAPTR_NENT	128
920Sstevel@tonic-gate 
930Sstevel@tonic-gate extern trap_trace_ctl_t	trap_trace_ctl[NCPU];	/* Allocated in locore.s */
940Sstevel@tonic-gate extern size_t		trap_trace_bufsize;
950Sstevel@tonic-gate extern int		trap_trace_freeze;
960Sstevel@tonic-gate extern trap_trace_rec_t	trap_trace_postmort;	/* Entry used after death */
970Sstevel@tonic-gate 
980Sstevel@tonic-gate #define	TRAPTRACE_FREEZE	trap_trace_freeze = 1;
990Sstevel@tonic-gate #define	TRAPTRACE_UNFREEZE	trap_trace_freeze = 0;
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate #else	/* _ASM */
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate /*
1040Sstevel@tonic-gate  * ptr       -- will be set to a TRAPTRACE entry.
1050Sstevel@tonic-gate  * scr1      -- scratch
1060Sstevel@tonic-gate  * scr1_32   -- 32-bit version of scr1
1070Sstevel@tonic-gate  * scr2      -- scratch
1080Sstevel@tonic-gate  * marker    -- register containing byte to store in marker field of entry
1090Sstevel@tonic-gate  *
1100Sstevel@tonic-gate  * Note that this macro defines labels "8" and "9".
1110Sstevel@tonic-gate  */
1120Sstevel@tonic-gate #ifdef TRAPTRACE
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate #if defined(__amd64)
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate #define	TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)	\
1170Sstevel@tonic-gate 	leaq	trap_trace_postmort(%rip), ptr;	\
1180Sstevel@tonic-gate 	cmpl	$0, trap_trace_freeze(%rip);	\
1190Sstevel@tonic-gate 	jne	9f;				\
1200Sstevel@tonic-gate 	LOADCPU(ptr);				\
1210Sstevel@tonic-gate 	movl	CPU_ID(ptr), scr1_32;		\
1220Sstevel@tonic-gate 	shlq	$TRAPTR_SIZE_SHIFT, scr1;	\
1230Sstevel@tonic-gate 	leaq	trap_trace_ctl(%rip), scr2;	\
1240Sstevel@tonic-gate 	addq	scr2, scr1;			\
1250Sstevel@tonic-gate 	movq	TRAPTR_NEXT(scr1), ptr;		\
1260Sstevel@tonic-gate 	leaq	TRAP_ENT_SIZE(ptr), scr2;	\
1270Sstevel@tonic-gate 	cmpq	TRAPTR_LIMIT(scr1), scr2;	\
1280Sstevel@tonic-gate 	jl	8f;				\
1290Sstevel@tonic-gate 	movq	TRAPTR_FIRST(scr1), scr2;	\
1300Sstevel@tonic-gate 8:	movq	scr2, TRAPTR_NEXT(scr1);	\
1310Sstevel@tonic-gate 9:	movb	marker, TTR_MARKER(ptr);
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate #elif defined(__i386)
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate #define	TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)	\
1360Sstevel@tonic-gate 	movl	$trap_trace_postmort, ptr;	\
1370Sstevel@tonic-gate 	cmpl	$0, trap_trace_freeze;		\
1380Sstevel@tonic-gate 	jne	9f;				\
1390Sstevel@tonic-gate 	LOADCPU(ptr);				\
1400Sstevel@tonic-gate 	movl	CPU_ID(ptr), scr1_32;		\
1410Sstevel@tonic-gate 	shll	$TRAPTR_SIZE_SHIFT, scr1;	\
1420Sstevel@tonic-gate 	addl	$trap_trace_ctl, scr1;		\
1430Sstevel@tonic-gate 	movl	TRAPTR_NEXT(scr1), ptr;		\
1440Sstevel@tonic-gate 	leal	TRAP_ENT_SIZE(ptr), scr2;	\
1450Sstevel@tonic-gate 	cmpl	TRAPTR_LIMIT(scr1), scr2;	\
1460Sstevel@tonic-gate 	jl	8f;				\
1470Sstevel@tonic-gate 	movl	TRAPTR_FIRST(scr1), scr2;	\
1480Sstevel@tonic-gate 8:	movl	scr2, TRAPTR_NEXT(scr1);	\
1490Sstevel@tonic-gate 9:	movb	marker, TTR_MARKER(ptr);
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate #endif	/* __i386 */
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate /*
1540Sstevel@tonic-gate  * ptr  -- pointer to the current TRAPTRACE entry.
1550Sstevel@tonic-gate  * reg  -- pointer to the stored registers; must be on the stack
1560Sstevel@tonic-gate  * scr1 -- scratch used as array index
1570Sstevel@tonic-gate  * scr2 -- scratch used as temporary
1580Sstevel@tonic-gate  *
1590Sstevel@tonic-gate  * Note that this macro defines label "9".
1600Sstevel@tonic-gate  * Also captures curthread on exit of loop.
1610Sstevel@tonic-gate  */
1625084Sjohnlev #if defined(__xpv)
1635084Sjohnlev #define	__GETCR2(_mov, reg)			\
1645084Sjohnlev 	_mov	%gs:CPU_VCPU_INFO, reg;		\
1655084Sjohnlev 	_mov	VCPU_INFO_ARCH_CR2(reg), reg
1665084Sjohnlev #else
1673446Smrj #define	__GETCR2(_mov, reg)			\
1683446Smrj 	_mov	%cr2, reg
1695084Sjohnlev #endif
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate #if defined(__amd64)
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate #define	TRACE_REGS(ptr, reg, scr1, scr2)	\
1740Sstevel@tonic-gate 	xorq	scr1, scr1;			\
1750Sstevel@tonic-gate 	/*CSTYLED*/				\
1760Sstevel@tonic-gate 9:	movq	(reg, scr1, 1), scr2;		\
1770Sstevel@tonic-gate 	movq	scr2, (ptr, scr1, 1);		\
1780Sstevel@tonic-gate 	addq	$CLONGSIZE, scr1;		\
1790Sstevel@tonic-gate 	cmpq	$REGSIZE, scr1;			\
1800Sstevel@tonic-gate 	jl	9b;				\
1810Sstevel@tonic-gate 	movq	%gs:CPU_THREAD, scr2;		\
1820Sstevel@tonic-gate 	movq	scr2, TTR_CURTHREAD(ptr);	\
1833446Smrj 	__GETCR2(movq, scr2);			\
1840Sstevel@tonic-gate 	movq	scr2, TTR_CR2(ptr)
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate #elif defined(__i386)
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate #define	TRACE_REGS(ptr, reg, scr1, scr2)	\
1890Sstevel@tonic-gate 	xorl	scr1, scr1;			\
1900Sstevel@tonic-gate 	/*CSTYLED*/				\
1910Sstevel@tonic-gate 9:	movl	(reg, scr1, 1), scr2;		\
1920Sstevel@tonic-gate 	movl	scr2, (ptr, scr1, 1);		\
1930Sstevel@tonic-gate 	addl	$CLONGSIZE, scr1;		\
1940Sstevel@tonic-gate 	cmpl	$REGSIZE, scr1;			\
1950Sstevel@tonic-gate 	jl	9b;				\
1960Sstevel@tonic-gate 	movl	%gs:CPU_THREAD, scr2;		\
1970Sstevel@tonic-gate 	movl	scr2, TTR_CURTHREAD(ptr);	\
1983446Smrj 	__GETCR2(movl, scr2);			\
1990Sstevel@tonic-gate 	movl	scr2, TTR_CR2(ptr)
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate #endif	/* __i386 */
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate /*
2040Sstevel@tonic-gate  * The time stamp macro records a high-resolution time stamp for the
2050Sstevel@tonic-gate  * given TRAPTRACE entry.  Note that %eax and %edx are plowed by this
2060Sstevel@tonic-gate  * macro;  if they are to be preserved, it's up to the caller of the macro.
2070Sstevel@tonic-gate  */
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate #if defined(__amd64)
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate #define	TRACE_STAMP(reg)			\
2120Sstevel@tonic-gate 	rdtsc;					\
2130Sstevel@tonic-gate 	movl	%eax, TTR_STAMP(reg);		\
2140Sstevel@tonic-gate 	movl	%edx, TTR_STAMP+4(reg)
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate /*
2170Sstevel@tonic-gate  * %rbp should be set before invoking this macro.
2180Sstevel@tonic-gate  */
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate #define	TRACE_STACK(tt)				\
2210Sstevel@tonic-gate 	pushq	%rdi;				\
2220Sstevel@tonic-gate 	pushq	%rsi;				\
2230Sstevel@tonic-gate 	pushq	%rdx;				\
2240Sstevel@tonic-gate 	pushq	%rcx;				\
2250Sstevel@tonic-gate 	pushq	%r8;				\
2260Sstevel@tonic-gate 	pushq	%r9;				\
2270Sstevel@tonic-gate 	pushq	%rax;				\
2280Sstevel@tonic-gate 	pushq	%r12;				\
2290Sstevel@tonic-gate 	movq	tt, %r12;			\
2300Sstevel@tonic-gate 	leaq	TTR_STACK(%r12), %rdi;		\
2310Sstevel@tonic-gate 	movl	$TTR_STACK_DEPTH, %esi;		\
2320Sstevel@tonic-gate 	call	getpcstack;			\
2330Sstevel@tonic-gate 	movl	%eax, TTR_SDEPTH(%r12);		\
2340Sstevel@tonic-gate 	popq	%r12;				\
2350Sstevel@tonic-gate 	popq	%rax;				\
2360Sstevel@tonic-gate 	popq	%r9;				\
2370Sstevel@tonic-gate 	popq	%r8;				\
2380Sstevel@tonic-gate 	popq	%rcx;				\
2390Sstevel@tonic-gate 	popq	%rdx;				\
2400Sstevel@tonic-gate 	popq	%rsi;				\
2410Sstevel@tonic-gate 	popq	%rdi
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate #elif defined(__i386)
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate #define	TRACE_STAMP(reg)			\
2460Sstevel@tonic-gate 	xorl	%eax, %eax;			\
2470Sstevel@tonic-gate 	xorl	%edx, %edx;			\
248*12826Skuriakose.kuruvilla@oracle.com 	btl	$X86FSET_TSC, x86_featureset;	\
249*12826Skuriakose.kuruvilla@oracle.com 	jnc	9f;				\
2500Sstevel@tonic-gate 	rdtsc;					\
2510Sstevel@tonic-gate 9:	movl	%eax, TTR_STAMP(reg);		\
2520Sstevel@tonic-gate 	movl	%edx, TTR_STAMP+4(reg)
2530Sstevel@tonic-gate 
2543446Smrj #define	TRACE_STACK(tt)				\
2553446Smrj 	pushl	%eax;				\
2563446Smrj 	pushl	%ecx;				\
2573446Smrj 	pushl	%edx;				\
2583446Smrj 	pushl	%ebx;				\
2593446Smrj 	pushl	$TTR_STACK_DEPTH;		\
2603446Smrj 	movl	tt, %ebx;			\
2613446Smrj 	leal	TTR_STACK(%ebx), %eax;		\
2623446Smrj 	pushl	%eax;				\
2633446Smrj 	call	getpcstack;			\
2643446Smrj 	addl	$8, %esp;			\
2653446Smrj 	movl	%eax, TTR_SDEPTH(%ebx);		\
2663446Smrj 	popl	%ebx;				\
2673446Smrj 	popl	%edx;				\
2683446Smrj 	popl	%ecx;				\
2693446Smrj 	popl	%eax
2703446Smrj 
2710Sstevel@tonic-gate #endif	/* __i386 */
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate #else
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate #define	TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)
2760Sstevel@tonic-gate #define	TRACE_REGS(ptr, reg, scr1, scr2)
2770Sstevel@tonic-gate #define	TRACE_STAMP(reg)
2780Sstevel@tonic-gate #define	TRACE_STACK(reg)
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate #endif	/* TRAPTRACE */
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate #endif 	/* _ASM */
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate #define	TT_SYSCALL	0xaa	/* system call via lcall */
2850Sstevel@tonic-gate #define	TT_SYSENTER	0xab	/* system call via sysenter */
2860Sstevel@tonic-gate #define	TT_SYSC		0xad	/* system call via syscall (32-bit) */
2870Sstevel@tonic-gate #define	TT_SYSC64	0xae	/* system call via syscall (64-bit) */
2880Sstevel@tonic-gate #define	TT_INTERRUPT	0xbb
2890Sstevel@tonic-gate #define	TT_TRAP		0xcc
2900Sstevel@tonic-gate #define	TT_INTTRAP	0xdd
2913446Smrj #define	TT_EVENT	0xee	/* hypervisor event */
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate #ifdef	__cplusplus
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate #endif
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate #endif	/* _IA32_SYS_TRAPTRACE_H */
298