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