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