xref: /titanic_51/usr/src/uts/intel/ia32/sys/traptrace.h (revision 7417cfdecea1902cef03c0d61a72df97d945925d)
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
5ae115bc7Smrj  * Common Development and Distribution License (the "License").
6ae115bc7Smrj  * 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 /*
225cd376e8SJimmy Vetayases  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #ifndef _IA32_SYS_TRAPTRACE_H
267c478bd9Sstevel@tonic-gate #define	_IA32_SYS_TRAPTRACE_H
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
297c478bd9Sstevel@tonic-gate extern "C" {
307c478bd9Sstevel@tonic-gate #endif
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/privregs.h>
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate  * Trap tracing.  If TRAPTRACE is defined, an entry is recorded every time
367c478bd9Sstevel@tonic-gate  * the CPU jumps through the Interrupt Descriptor Table (IDT).  One exception
377c478bd9Sstevel@tonic-gate  * is the Double Fault handler, which does not record a traptrace entry.
38ae115bc7Smrj  *
39ae115bc7Smrj  * There are facilities to (conditionally) interleave tracing of related
40ae115bc7Smrj  * facilities e.h. x-calls.
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /*
44ae115bc7Smrj  * Note: non-assembler files that include this file must include
457c478bd9Sstevel@tonic-gate  * <sys/systm.h> before it, for the typedef of pc_t to be visible.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
48ae115bc7Smrj #define	TTR_STACK_DEPTH	10
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #ifndef	_ASM
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #define	TTR_PAD1_SIZE	(sizeof (long) - 1)
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate typedef struct {
557c478bd9Sstevel@tonic-gate 	uintptr_t	ttc_next;
567c478bd9Sstevel@tonic-gate 	uintptr_t	ttc_first;
577c478bd9Sstevel@tonic-gate 	uintptr_t	ttc_limit;
587c478bd9Sstevel@tonic-gate 	uintptr_t	ttc_current;
597c478bd9Sstevel@tonic-gate } trap_trace_ctl_t;
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate typedef struct {
627c478bd9Sstevel@tonic-gate 	struct regs	ttr_regs;
637c478bd9Sstevel@tonic-gate 	greg_t		ttr_cr2;
647c478bd9Sstevel@tonic-gate 	union _ttr_info {
657c478bd9Sstevel@tonic-gate 		struct _idt_entry {
667ff178cdSJimmy Vetayases 			int	cpuid;
67ae115bc7Smrj 			short	vector;
687c478bd9Sstevel@tonic-gate 			uchar_t	ipl;
697c478bd9Sstevel@tonic-gate 			uchar_t	spl;
707c478bd9Sstevel@tonic-gate 			uchar_t	pri;
717c478bd9Sstevel@tonic-gate 		} idt_entry;
727c478bd9Sstevel@tonic-gate 		struct _gate_entry {
737c478bd9Sstevel@tonic-gate 			int	sysnum;
747c478bd9Sstevel@tonic-gate 		} gate_entry;
757c478bd9Sstevel@tonic-gate 	} ttr_info;
767c478bd9Sstevel@tonic-gate 	uintptr_t	ttr_curthread;
777c478bd9Sstevel@tonic-gate 	uchar_t		ttr_pad[TTR_PAD1_SIZE];
787c478bd9Sstevel@tonic-gate 	uchar_t		ttr_marker;
797c478bd9Sstevel@tonic-gate 	hrtime_t	ttr_stamp;
807c478bd9Sstevel@tonic-gate 	int		ttr_sdepth;
817c478bd9Sstevel@tonic-gate 	pc_t		ttr_stack[TTR_STACK_DEPTH];
827c478bd9Sstevel@tonic-gate } trap_trace_rec_t;
837c478bd9Sstevel@tonic-gate 
847ff178cdSJimmy Vetayases #define	ttr_cpuid	ttr_info.idt_entry.cpuid
857c478bd9Sstevel@tonic-gate #define	ttr_vector	ttr_info.idt_entry.vector
867c478bd9Sstevel@tonic-gate #define	ttr_ipl		ttr_info.idt_entry.ipl
877c478bd9Sstevel@tonic-gate #define	ttr_spl		ttr_info.idt_entry.spl
887c478bd9Sstevel@tonic-gate #define	ttr_pri		ttr_info.idt_entry.pri
897c478bd9Sstevel@tonic-gate #define	ttr_sysnum	ttr_info.gate_entry.sysnum
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate #define	TRAPTR_NENT	128
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate extern trap_trace_ctl_t	trap_trace_ctl[NCPU];	/* Allocated in locore.s */
947c478bd9Sstevel@tonic-gate extern size_t		trap_trace_bufsize;
957c478bd9Sstevel@tonic-gate extern int		trap_trace_freeze;
967c478bd9Sstevel@tonic-gate extern trap_trace_rec_t	trap_trace_postmort;	/* Entry used after death */
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #define	TRAPTRACE_FREEZE	trap_trace_freeze = 1;
997c478bd9Sstevel@tonic-gate #define	TRAPTRACE_UNFREEZE	trap_trace_freeze = 0;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #else	/* _ASM */
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * ptr       -- will be set to a TRAPTRACE entry.
1057c478bd9Sstevel@tonic-gate  * scr1      -- scratch
1067c478bd9Sstevel@tonic-gate  * scr1_32   -- 32-bit version of scr1
1077c478bd9Sstevel@tonic-gate  * scr2      -- scratch
1087c478bd9Sstevel@tonic-gate  * marker    -- register containing byte to store in marker field of entry
1097c478bd9Sstevel@tonic-gate  *
1107c478bd9Sstevel@tonic-gate  * Note that this macro defines labels "8" and "9".
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate #if defined(__amd64)
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate #define	TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)	\
1177c478bd9Sstevel@tonic-gate 	leaq	trap_trace_postmort(%rip), ptr;	\
1187c478bd9Sstevel@tonic-gate 	cmpl	$0, trap_trace_freeze(%rip);	\
1197c478bd9Sstevel@tonic-gate 	jne	9f;				\
1207c478bd9Sstevel@tonic-gate 	LOADCPU(ptr);				\
1217c478bd9Sstevel@tonic-gate 	movl	CPU_ID(ptr), scr1_32;		\
1227c478bd9Sstevel@tonic-gate 	shlq	$TRAPTR_SIZE_SHIFT, scr1;	\
1237c478bd9Sstevel@tonic-gate 	leaq	trap_trace_ctl(%rip), scr2;	\
1247c478bd9Sstevel@tonic-gate 	addq	scr2, scr1;			\
1257c478bd9Sstevel@tonic-gate 	movq	TRAPTR_NEXT(scr1), ptr;		\
1267c478bd9Sstevel@tonic-gate 	leaq	TRAP_ENT_SIZE(ptr), scr2;	\
1277c478bd9Sstevel@tonic-gate 	cmpq	TRAPTR_LIMIT(scr1), scr2;	\
1287c478bd9Sstevel@tonic-gate 	jl	8f;				\
1297c478bd9Sstevel@tonic-gate 	movq	TRAPTR_FIRST(scr1), scr2;	\
1307c478bd9Sstevel@tonic-gate 8:	movq	scr2, TRAPTR_NEXT(scr1);	\
1317c478bd9Sstevel@tonic-gate 9:	movb	marker, TTR_MARKER(ptr);
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate #elif defined(__i386)
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate #define	TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)	\
1367c478bd9Sstevel@tonic-gate 	movl	$trap_trace_postmort, ptr;	\
1377c478bd9Sstevel@tonic-gate 	cmpl	$0, trap_trace_freeze;		\
1387c478bd9Sstevel@tonic-gate 	jne	9f;				\
1397c478bd9Sstevel@tonic-gate 	LOADCPU(ptr);				\
1407c478bd9Sstevel@tonic-gate 	movl	CPU_ID(ptr), scr1_32;		\
1417c478bd9Sstevel@tonic-gate 	shll	$TRAPTR_SIZE_SHIFT, scr1;	\
1427c478bd9Sstevel@tonic-gate 	addl	$trap_trace_ctl, scr1;		\
1437c478bd9Sstevel@tonic-gate 	movl	TRAPTR_NEXT(scr1), ptr;		\
1447c478bd9Sstevel@tonic-gate 	leal	TRAP_ENT_SIZE(ptr), scr2;	\
1457c478bd9Sstevel@tonic-gate 	cmpl	TRAPTR_LIMIT(scr1), scr2;	\
1467c478bd9Sstevel@tonic-gate 	jl	8f;				\
1477c478bd9Sstevel@tonic-gate 	movl	TRAPTR_FIRST(scr1), scr2;	\
1487c478bd9Sstevel@tonic-gate 8:	movl	scr2, TRAPTR_NEXT(scr1);	\
1497c478bd9Sstevel@tonic-gate 9:	movb	marker, TTR_MARKER(ptr);
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate #endif	/* __i386 */
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate  * ptr  -- pointer to the current TRAPTRACE entry.
1557c478bd9Sstevel@tonic-gate  * reg  -- pointer to the stored registers; must be on the stack
1567c478bd9Sstevel@tonic-gate  * scr1 -- scratch used as array index
1577c478bd9Sstevel@tonic-gate  * scr2 -- scratch used as temporary
1587c478bd9Sstevel@tonic-gate  *
1597c478bd9Sstevel@tonic-gate  * Note that this macro defines label "9".
1607c478bd9Sstevel@tonic-gate  * Also captures curthread on exit of loop.
1617c478bd9Sstevel@tonic-gate  */
162843e1988Sjohnlev #if defined(__xpv)
163843e1988Sjohnlev #define	__GETCR2(_mov, reg)			\
164843e1988Sjohnlev 	_mov	%gs:CPU_VCPU_INFO, reg;		\
165843e1988Sjohnlev 	_mov	VCPU_INFO_ARCH_CR2(reg), reg
166843e1988Sjohnlev #else
167ae115bc7Smrj #define	__GETCR2(_mov, reg)			\
168ae115bc7Smrj 	_mov	%cr2, reg
169843e1988Sjohnlev #endif
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate #if defined(__amd64)
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate #define	TRACE_REGS(ptr, reg, scr1, scr2)	\
1747c478bd9Sstevel@tonic-gate 	xorq	scr1, scr1;			\
1757c478bd9Sstevel@tonic-gate 	/*CSTYLED*/				\
1767c478bd9Sstevel@tonic-gate 9:	movq	(reg, scr1, 1), scr2;		\
1777c478bd9Sstevel@tonic-gate 	movq	scr2, (ptr, scr1, 1);		\
1787c478bd9Sstevel@tonic-gate 	addq	$CLONGSIZE, scr1;		\
1797c478bd9Sstevel@tonic-gate 	cmpq	$REGSIZE, scr1;			\
1807c478bd9Sstevel@tonic-gate 	jl	9b;				\
1817c478bd9Sstevel@tonic-gate 	movq	%gs:CPU_THREAD, scr2;		\
1827c478bd9Sstevel@tonic-gate 	movq	scr2, TTR_CURTHREAD(ptr);	\
183ae115bc7Smrj 	__GETCR2(movq, scr2);			\
1847c478bd9Sstevel@tonic-gate 	movq	scr2, TTR_CR2(ptr)
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate #elif defined(__i386)
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate #define	TRACE_REGS(ptr, reg, scr1, scr2)	\
1897c478bd9Sstevel@tonic-gate 	xorl	scr1, scr1;			\
1907c478bd9Sstevel@tonic-gate 	/*CSTYLED*/				\
1917c478bd9Sstevel@tonic-gate 9:	movl	(reg, scr1, 1), scr2;		\
1927c478bd9Sstevel@tonic-gate 	movl	scr2, (ptr, scr1, 1);		\
1937c478bd9Sstevel@tonic-gate 	addl	$CLONGSIZE, scr1;		\
1947c478bd9Sstevel@tonic-gate 	cmpl	$REGSIZE, scr1;			\
1957c478bd9Sstevel@tonic-gate 	jl	9b;				\
1967c478bd9Sstevel@tonic-gate 	movl	%gs:CPU_THREAD, scr2;		\
1977c478bd9Sstevel@tonic-gate 	movl	scr2, TTR_CURTHREAD(ptr);	\
198ae115bc7Smrj 	__GETCR2(movl, scr2);			\
1997c478bd9Sstevel@tonic-gate 	movl	scr2, TTR_CR2(ptr)
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate #endif	/* __i386 */
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * The time stamp macro records a high-resolution time stamp for the
2057c478bd9Sstevel@tonic-gate  * given TRAPTRACE entry.  Note that %eax and %edx are plowed by this
2067c478bd9Sstevel@tonic-gate  * macro;  if they are to be preserved, it's up to the caller of the macro.
2077c478bd9Sstevel@tonic-gate  */
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate #if defined(__amd64)
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate #define	TRACE_STAMP(reg)			\
2127c478bd9Sstevel@tonic-gate 	rdtsc;					\
2137c478bd9Sstevel@tonic-gate 	movl	%eax, TTR_STAMP(reg);		\
2147c478bd9Sstevel@tonic-gate 	movl	%edx, TTR_STAMP+4(reg)
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate  * %rbp should be set before invoking this macro.
2187c478bd9Sstevel@tonic-gate  */
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate #define	TRACE_STACK(tt)				\
2217c478bd9Sstevel@tonic-gate 	pushq	%rdi;				\
2227c478bd9Sstevel@tonic-gate 	pushq	%rsi;				\
2237c478bd9Sstevel@tonic-gate 	pushq	%rdx;				\
2247c478bd9Sstevel@tonic-gate 	pushq	%rcx;				\
2257c478bd9Sstevel@tonic-gate 	pushq	%r8;				\
2267c478bd9Sstevel@tonic-gate 	pushq	%r9;				\
2277c478bd9Sstevel@tonic-gate 	pushq	%rax;				\
2287c478bd9Sstevel@tonic-gate 	pushq	%r12;				\
2297c478bd9Sstevel@tonic-gate 	movq	tt, %r12;			\
2307c478bd9Sstevel@tonic-gate 	leaq	TTR_STACK(%r12), %rdi;		\
2317c478bd9Sstevel@tonic-gate 	movl	$TTR_STACK_DEPTH, %esi;		\
2327c478bd9Sstevel@tonic-gate 	call	getpcstack;			\
2337c478bd9Sstevel@tonic-gate 	movl	%eax, TTR_SDEPTH(%r12);		\
2347c478bd9Sstevel@tonic-gate 	popq	%r12;				\
2357c478bd9Sstevel@tonic-gate 	popq	%rax;				\
2367c478bd9Sstevel@tonic-gate 	popq	%r9;				\
2377c478bd9Sstevel@tonic-gate 	popq	%r8;				\
2387c478bd9Sstevel@tonic-gate 	popq	%rcx;				\
2397c478bd9Sstevel@tonic-gate 	popq	%rdx;				\
2407c478bd9Sstevel@tonic-gate 	popq	%rsi;				\
2417c478bd9Sstevel@tonic-gate 	popq	%rdi
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate #elif defined(__i386)
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate #define	TRACE_STAMP(reg)			\
2467c478bd9Sstevel@tonic-gate 	xorl	%eax, %eax;			\
2477c478bd9Sstevel@tonic-gate 	xorl	%edx, %edx;			\
248*7417cfdeSKuriakose Kuruvilla 	btl	$X86FSET_TSC, x86_featureset;	\
249*7417cfdeSKuriakose Kuruvilla 	jnc	9f;				\
2507c478bd9Sstevel@tonic-gate 	rdtsc;					\
2517c478bd9Sstevel@tonic-gate 9:	movl	%eax, TTR_STAMP(reg);		\
2527c478bd9Sstevel@tonic-gate 	movl	%edx, TTR_STAMP+4(reg)
2537c478bd9Sstevel@tonic-gate 
254ae115bc7Smrj #define	TRACE_STACK(tt)				\
255ae115bc7Smrj 	pushl	%eax;				\
256ae115bc7Smrj 	pushl	%ecx;				\
257ae115bc7Smrj 	pushl	%edx;				\
258ae115bc7Smrj 	pushl	%ebx;				\
259ae115bc7Smrj 	pushl	$TTR_STACK_DEPTH;		\
260ae115bc7Smrj 	movl	tt, %ebx;			\
261ae115bc7Smrj 	leal	TTR_STACK(%ebx), %eax;		\
262ae115bc7Smrj 	pushl	%eax;				\
263ae115bc7Smrj 	call	getpcstack;			\
264ae115bc7Smrj 	addl	$8, %esp;			\
265ae115bc7Smrj 	movl	%eax, TTR_SDEPTH(%ebx);		\
266ae115bc7Smrj 	popl	%ebx;				\
267ae115bc7Smrj 	popl	%edx;				\
268ae115bc7Smrj 	popl	%ecx;				\
269ae115bc7Smrj 	popl	%eax
270ae115bc7Smrj 
2717c478bd9Sstevel@tonic-gate #endif	/* __i386 */
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate #else
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate #define	TRACE_PTR(ptr, scr1, scr1_32, scr2, marker)
2767c478bd9Sstevel@tonic-gate #define	TRACE_REGS(ptr, reg, scr1, scr2)
2777c478bd9Sstevel@tonic-gate #define	TRACE_STAMP(reg)
2787c478bd9Sstevel@tonic-gate #define	TRACE_STACK(reg)
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate #endif	/* TRAPTRACE */
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate #endif 	/* _ASM */
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate #define	TT_SYSCALL	0xaa	/* system call via lcall */
2857c478bd9Sstevel@tonic-gate #define	TT_SYSENTER	0xab	/* system call via sysenter */
2867c478bd9Sstevel@tonic-gate #define	TT_SYSC		0xad	/* system call via syscall (32-bit) */
2877c478bd9Sstevel@tonic-gate #define	TT_SYSC64	0xae	/* system call via syscall (64-bit) */
2887c478bd9Sstevel@tonic-gate #define	TT_INTERRUPT	0xbb
2897c478bd9Sstevel@tonic-gate #define	TT_TRAP		0xcc
2907c478bd9Sstevel@tonic-gate #define	TT_INTTRAP	0xdd
291ae115bc7Smrj #define	TT_EVENT	0xee	/* hypervisor event */
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate #endif
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate #endif	/* _IA32_SYS_TRAPTRACE_H */
298