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 */
21ae115bc7Smrj
227c478bd9Sstevel@tonic-gate /*
23ae115bc7Smrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #ifndef _AMD64_SYS_PRIVREGS_H
287c478bd9Sstevel@tonic-gate #define _AMD64_SYS_PRIVREGS_H
297c478bd9Sstevel@tonic-gate
30*6b7143d7SRichard Lowe #include <sys/ccompile.h>
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #ifdef __cplusplus
337c478bd9Sstevel@tonic-gate extern "C" {
347c478bd9Sstevel@tonic-gate #endif
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate * This file describes the cpu's privileged register set, and
387c478bd9Sstevel@tonic-gate * how the machine state is saved on the stack when a trap occurs.
397c478bd9Sstevel@tonic-gate */
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate #if !defined(__amd64)
427c478bd9Sstevel@tonic-gate #error "non-amd64 code depends on amd64 privileged header!"
437c478bd9Sstevel@tonic-gate #endif
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #ifndef _ASM
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate * This is NOT the structure to use for general purpose debugging;
497c478bd9Sstevel@tonic-gate * see /proc for that. This is NOT the structure to use to decode
507c478bd9Sstevel@tonic-gate * the ucontext or grovel about in a core file; see <sys/regset.h>.
517c478bd9Sstevel@tonic-gate */
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate struct regs {
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate * Extra frame for mdb to follow through high level interrupts and
567c478bd9Sstevel@tonic-gate * system traps. Set them to 0 to terminate stacktrace.
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate greg_t r_savfp; /* a copy of %rbp */
597c478bd9Sstevel@tonic-gate greg_t r_savpc; /* a copy of %rip */
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate greg_t r_rdi; /* 1st arg to function */
627c478bd9Sstevel@tonic-gate greg_t r_rsi; /* 2nd arg to function */
637c478bd9Sstevel@tonic-gate greg_t r_rdx; /* 3rd arg to function, 2nd return register */
647c478bd9Sstevel@tonic-gate greg_t r_rcx; /* 4th arg to function */
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate greg_t r_r8; /* 5th arg to function */
677c478bd9Sstevel@tonic-gate greg_t r_r9; /* 6th arg to function */
687c478bd9Sstevel@tonic-gate greg_t r_rax; /* 1st return register, # SSE registers */
697c478bd9Sstevel@tonic-gate greg_t r_rbx; /* callee-saved, optional base pointer */
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate greg_t r_rbp; /* callee-saved, optional frame pointer */
727c478bd9Sstevel@tonic-gate greg_t r_r10; /* temporary register, static chain pointer */
737c478bd9Sstevel@tonic-gate greg_t r_r11; /* temporary register */
747c478bd9Sstevel@tonic-gate greg_t r_r12; /* callee-saved */
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate greg_t r_r13; /* callee-saved */
777c478bd9Sstevel@tonic-gate greg_t r_r14; /* callee-saved */
787c478bd9Sstevel@tonic-gate greg_t r_r15; /* callee-saved */
797c478bd9Sstevel@tonic-gate
80ae115bc7Smrj /*
81ddece0baSsethg * fsbase and gsbase are sampled on every exception in DEBUG kernels
82ddece0baSsethg * only. They remain in the non-DEBUG kernel to avoid any flag days.
83ae115bc7Smrj */
84ddece0baSsethg greg_t __r_fsbase; /* no longer used in non-DEBUG builds */
85ddece0baSsethg greg_t __r_gsbase; /* no longer used in non-DEBUG builds */
867c478bd9Sstevel@tonic-gate greg_t r_ds;
877c478bd9Sstevel@tonic-gate greg_t r_es;
887c478bd9Sstevel@tonic-gate greg_t r_fs; /* %fs is *never* used by the kernel */
897c478bd9Sstevel@tonic-gate greg_t r_gs;
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate greg_t r_trapno;
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate /*
947c478bd9Sstevel@tonic-gate * (the rest of these are defined by the hardware)
957c478bd9Sstevel@tonic-gate */
967c478bd9Sstevel@tonic-gate greg_t r_err;
977c478bd9Sstevel@tonic-gate greg_t r_rip;
987c478bd9Sstevel@tonic-gate greg_t r_cs;
997c478bd9Sstevel@tonic-gate greg_t r_rfl;
1007c478bd9Sstevel@tonic-gate greg_t r_rsp;
1017c478bd9Sstevel@tonic-gate greg_t r_ss;
1027c478bd9Sstevel@tonic-gate };
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate #define r_r0 r_rax /* r0 for portability */
1057c478bd9Sstevel@tonic-gate #define r_r1 r_rdx /* r1 for portability */
1067c478bd9Sstevel@tonic-gate #define r_fp r_rbp /* kernel frame pointer */
1077c478bd9Sstevel@tonic-gate #define r_sp r_rsp /* user stack pointer */
1087c478bd9Sstevel@tonic-gate #define r_pc r_rip /* user's instruction pointer */
1097c478bd9Sstevel@tonic-gate #define r_ps r_rfl /* user's RFLAGS */
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate #ifdef _KERNEL
1127c478bd9Sstevel@tonic-gate #define lwptoregs(lwp) ((struct regs *)((lwp)->lwp_regs))
1137c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate #else /* !_ASM */
1167c478bd9Sstevel@tonic-gate
117ae115bc7Smrj #if defined(_MACHDEP)
118ae115bc7Smrj
119ae115bc7Smrj #include <sys/machprivregs.h>
120ae115bc7Smrj #include <sys/pcb.h>
1217c478bd9Sstevel@tonic-gate
122843e1988Sjohnlev /*
123843e1988Sjohnlev * We can not safely sample {fs,gs}base on the hypervisor. The rdmsr
124843e1988Sjohnlev * instruction triggers a #gp fault which is emulated in the hypervisor
125843e1988Sjohnlev * on behalf of the guest. This is normally ok but if the guest is in
126843e1988Sjohnlev * the special failsafe handler it must not fault again or the hypervisor
127843e1988Sjohnlev * will kill the domain. We could use something different than INTR_PUSH
128843e1988Sjohnlev * in xen_failsafe_callback but for now we will not sample them.
129843e1988Sjohnlev */
130843e1988Sjohnlev #if defined(DEBUG) && !defined(__xpv)
131ddece0baSsethg #define __SAVE_BASES \
132ddece0baSsethg movl $MSR_AMD_FSBASE, %ecx; \
133ddece0baSsethg rdmsr; \
134ddece0baSsethg movl %eax, REGOFF_FSBASE(%rsp); \
135ddece0baSsethg movl %edx, REGOFF_FSBASE+4(%rsp); \
136ddece0baSsethg movl $MSR_AMD_GSBASE, %ecx; \
137ddece0baSsethg rdmsr; \
138ddece0baSsethg movl %eax, REGOFF_GSBASE(%rsp); \
139ddece0baSsethg movl %edx, REGOFF_GSBASE+4(%rsp)
140ddece0baSsethg #else
141ddece0baSsethg #define __SAVE_BASES
142ddece0baSsethg #endif
143ddece0baSsethg
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate * Create a struct regs on the stack suitable for an
1467c478bd9Sstevel@tonic-gate * interrupt trap.
1477c478bd9Sstevel@tonic-gate *
1487c478bd9Sstevel@tonic-gate * Assumes that the trap handler has already pushed an
1497c478bd9Sstevel@tonic-gate * appropriate r_err and r_trapno
1507c478bd9Sstevel@tonic-gate */
1517c478bd9Sstevel@tonic-gate #define __SAVE_REGS \
1527c478bd9Sstevel@tonic-gate movq %r15, REGOFF_R15(%rsp); \
1537c478bd9Sstevel@tonic-gate movq %r14, REGOFF_R14(%rsp); \
1547c478bd9Sstevel@tonic-gate movq %r13, REGOFF_R13(%rsp); \
1557c478bd9Sstevel@tonic-gate movq %r12, REGOFF_R12(%rsp); \
1567c478bd9Sstevel@tonic-gate movq %r11, REGOFF_R11(%rsp); \
1577c478bd9Sstevel@tonic-gate movq %r10, REGOFF_R10(%rsp); \
1587c478bd9Sstevel@tonic-gate movq %rbp, REGOFF_RBP(%rsp); \
1597c478bd9Sstevel@tonic-gate movq %rbx, REGOFF_RBX(%rsp); \
1607c478bd9Sstevel@tonic-gate movq %rax, REGOFF_RAX(%rsp); \
1617c478bd9Sstevel@tonic-gate movq %r9, REGOFF_R9(%rsp); \
1627c478bd9Sstevel@tonic-gate movq %r8, REGOFF_R8(%rsp); \
1637c478bd9Sstevel@tonic-gate movq %rcx, REGOFF_RCX(%rsp); \
1647c478bd9Sstevel@tonic-gate movq %rdx, REGOFF_RDX(%rsp); \
1657c478bd9Sstevel@tonic-gate movq %rsi, REGOFF_RSI(%rsp); \
1667c478bd9Sstevel@tonic-gate movq %rdi, REGOFF_RDI(%rsp); \
1677c478bd9Sstevel@tonic-gate movq %rbp, REGOFF_SAVFP(%rsp); \
1687c478bd9Sstevel@tonic-gate movq REGOFF_RIP(%rsp), %rcx; \
1697c478bd9Sstevel@tonic-gate movq %rcx, REGOFF_SAVPC(%rsp); \
1707c478bd9Sstevel@tonic-gate xorl %ecx, %ecx; \
1717c478bd9Sstevel@tonic-gate movw %gs, %cx; \
1727c478bd9Sstevel@tonic-gate movq %rcx, REGOFF_GS(%rsp); \
1737c478bd9Sstevel@tonic-gate movw %fs, %cx; \
1747c478bd9Sstevel@tonic-gate movq %rcx, REGOFF_FS(%rsp); \
1757c478bd9Sstevel@tonic-gate movw %es, %cx; \
1767c478bd9Sstevel@tonic-gate movq %rcx, REGOFF_ES(%rsp); \
1777c478bd9Sstevel@tonic-gate movw %ds, %cx; \
178ddece0baSsethg movq %rcx, REGOFF_DS(%rsp); \
179ddece0baSsethg __SAVE_BASES
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate #define __RESTORE_REGS \
1827c478bd9Sstevel@tonic-gate movq REGOFF_RDI(%rsp), %rdi; \
1837c478bd9Sstevel@tonic-gate movq REGOFF_RSI(%rsp), %rsi; \
1847c478bd9Sstevel@tonic-gate movq REGOFF_RDX(%rsp), %rdx; \
1857c478bd9Sstevel@tonic-gate movq REGOFF_RCX(%rsp), %rcx; \
1867c478bd9Sstevel@tonic-gate movq REGOFF_R8(%rsp), %r8; \
1877c478bd9Sstevel@tonic-gate movq REGOFF_R9(%rsp), %r9; \
1887c478bd9Sstevel@tonic-gate movq REGOFF_RAX(%rsp), %rax; \
1897c478bd9Sstevel@tonic-gate movq REGOFF_RBX(%rsp), %rbx; \
1907c478bd9Sstevel@tonic-gate movq REGOFF_RBP(%rsp), %rbp; \
1917c478bd9Sstevel@tonic-gate movq REGOFF_R10(%rsp), %r10; \
1927c478bd9Sstevel@tonic-gate movq REGOFF_R11(%rsp), %r11; \
1937c478bd9Sstevel@tonic-gate movq REGOFF_R12(%rsp), %r12; \
1947c478bd9Sstevel@tonic-gate movq REGOFF_R13(%rsp), %r13; \
1957c478bd9Sstevel@tonic-gate movq REGOFF_R14(%rsp), %r14; \
1967c478bd9Sstevel@tonic-gate movq REGOFF_R15(%rsp), %r15
1977c478bd9Sstevel@tonic-gate
198ae115bc7Smrj /*
199ae115bc7Smrj * Push register state onto the stack. If we've
200ae115bc7Smrj * interrupted userland, do a swapgs as well.
201ae115bc7Smrj */
202ae115bc7Smrj #define INTR_PUSH \
203ae115bc7Smrj subq $REGOFF_TRAPNO, %rsp; \
204ae115bc7Smrj __SAVE_REGS; \
205ae115bc7Smrj cmpw $KCS_SEL, REGOFF_CS(%rsp); \
206ae115bc7Smrj je 6f; \
207ae115bc7Smrj movq $0, REGOFF_SAVFP(%rsp); \
208ae115bc7Smrj SWAPGS; \
209ae115bc7Smrj 6: CLEAN_CS
210ae115bc7Smrj
2117c478bd9Sstevel@tonic-gate #define INTR_POP \
2127c478bd9Sstevel@tonic-gate leaq sys_lcall32(%rip), %r11;\
2137c478bd9Sstevel@tonic-gate cmpq %r11, REGOFF_RIP(%rsp); \
2147c478bd9Sstevel@tonic-gate __RESTORE_REGS; \
2157c478bd9Sstevel@tonic-gate je 5f; \
2167c478bd9Sstevel@tonic-gate cmpw $KCS_SEL, REGOFF_CS(%rsp);\
2177c478bd9Sstevel@tonic-gate je 8f; \
218ae115bc7Smrj 5: SWAPGS; \
2197c478bd9Sstevel@tonic-gate 8: addq $REGOFF_RIP, %rsp
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate #define USER_POP \
2227c478bd9Sstevel@tonic-gate __RESTORE_REGS; \
223ae115bc7Smrj SWAPGS; \
2247c478bd9Sstevel@tonic-gate addq $REGOFF_RIP, %rsp /* Adjust %rsp to prepare for iretq */
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate #define USER32_POP \
2277c478bd9Sstevel@tonic-gate movl REGOFF_RDI(%rsp), %edi; \
2287c478bd9Sstevel@tonic-gate movl REGOFF_RSI(%rsp), %esi; \
2297c478bd9Sstevel@tonic-gate movl REGOFF_RDX(%rsp), %edx; \
2307c478bd9Sstevel@tonic-gate movl REGOFF_RCX(%rsp), %ecx; \
2317c478bd9Sstevel@tonic-gate movl REGOFF_RAX(%rsp), %eax; \
2327c478bd9Sstevel@tonic-gate movl REGOFF_RBX(%rsp), %ebx; \
2337c478bd9Sstevel@tonic-gate movl REGOFF_RBP(%rsp), %ebp; \
234ae115bc7Smrj SWAPGS; \
2357c478bd9Sstevel@tonic-gate addq $REGOFF_RIP, %rsp /* Adjust %rsp to prepare for iretq */
2367c478bd9Sstevel@tonic-gate
237ae115bc7Smrj #define DFTRAP_PUSH \
238ae115bc7Smrj subq $REGOFF_TRAPNO, %rsp; \
239ae115bc7Smrj __SAVE_REGS
240ae115bc7Smrj
241ae115bc7Smrj #endif /* _MACHDEP */
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate /*
244ae115bc7Smrj * Used to set rflags to known values at the head of an
245ae115bc7Smrj * interrupt gate handler, i.e. interrupts are -already- disabled.
2467c478bd9Sstevel@tonic-gate */
247ae115bc7Smrj #define INTGATE_INIT_KERNEL_FLAGS \
2487c478bd9Sstevel@tonic-gate pushq $F_OFF; \
2497c478bd9Sstevel@tonic-gate popfq
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate #endif /* !_ASM */
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate #include <sys/controlregs.h>
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && !defined(_ASM)
2567c478bd9Sstevel@tonic-gate #if !defined(__lint) && defined(__GNUC__)
2577c478bd9Sstevel@tonic-gate
258*6b7143d7SRichard Lowe extern __GNU_INLINE ulong_t
getcr8(void)259*6b7143d7SRichard Lowe getcr8(void)
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate uint64_t value;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate __asm__ __volatile__(
2647c478bd9Sstevel@tonic-gate "movq %%cr8, %0"
2657c478bd9Sstevel@tonic-gate : "=r" (value));
2667c478bd9Sstevel@tonic-gate return (value);
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate
269*6b7143d7SRichard Lowe extern __GNU_INLINE void
setcr8(ulong_t value)270*6b7143d7SRichard Lowe setcr8(ulong_t value)
2717c478bd9Sstevel@tonic-gate {
2727c478bd9Sstevel@tonic-gate __asm__ __volatile__(
2737c478bd9Sstevel@tonic-gate "movq %0, %%cr8"
2747c478bd9Sstevel@tonic-gate : /* no output */
2757c478bd9Sstevel@tonic-gate : "r" (value));
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate #else
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate extern ulong_t getcr8(void);
2817c478bd9Sstevel@tonic-gate extern void setcr8(ulong_t);
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate #endif /* !defined(__lint) && defined(__GNUC__) */
2847c478bd9Sstevel@tonic-gate #endif /* _KERNEL && !_ASM */
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate /* Control register layout for panic dump */
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate #define CREGSZ 0x68
2897c478bd9Sstevel@tonic-gate #define CREG_GDT 0
2907c478bd9Sstevel@tonic-gate #define CREG_IDT 0x10
2917c478bd9Sstevel@tonic-gate #define CREG_LDT 0x20
2927c478bd9Sstevel@tonic-gate #define CREG_TASKR 0x28
2937c478bd9Sstevel@tonic-gate #define CREG_CR0 0x30
2947c478bd9Sstevel@tonic-gate #define CREG_CR2 0x38
2957c478bd9Sstevel@tonic-gate #define CREG_CR3 0x40
2967c478bd9Sstevel@tonic-gate #define CREG_CR4 0x48
2977c478bd9Sstevel@tonic-gate #define CREG_CR8 0x50
2987c478bd9Sstevel@tonic-gate #define CREG_KGSBASE 0x58
2997c478bd9Sstevel@tonic-gate #define CREG_EFER 0x60
3007c478bd9Sstevel@tonic-gate
301ae115bc7Smrj #if !defined(_ASM) && defined(_INT64_TYPE)
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate typedef uint64_t creg64_t;
3047c478bd9Sstevel@tonic-gate typedef upad128_t creg128_t;
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate struct cregs {
3077c478bd9Sstevel@tonic-gate creg128_t cr_gdt;
3087c478bd9Sstevel@tonic-gate creg128_t cr_idt;
3097c478bd9Sstevel@tonic-gate creg64_t cr_ldt;
3107c478bd9Sstevel@tonic-gate creg64_t cr_task;
3117c478bd9Sstevel@tonic-gate creg64_t cr_cr0;
3127c478bd9Sstevel@tonic-gate creg64_t cr_cr2;
3137c478bd9Sstevel@tonic-gate creg64_t cr_cr3;
3147c478bd9Sstevel@tonic-gate creg64_t cr_cr4;
3157c478bd9Sstevel@tonic-gate creg64_t cr_cr8;
3167c478bd9Sstevel@tonic-gate creg64_t cr_kgsbase;
3177c478bd9Sstevel@tonic-gate creg64_t cr_efer;
3187c478bd9Sstevel@tonic-gate };
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
3217c478bd9Sstevel@tonic-gate extern void getcregs(struct cregs *);
3227c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
3237c478bd9Sstevel@tonic-gate
324ae115bc7Smrj #endif /* !_ASM && _INT64_TYPE */
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate #ifdef __cplusplus
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate #endif
3297c478bd9Sstevel@tonic-gate
330ae115bc7Smrj #endif /* !_AMD64_SYS_PRIVREGS_H */
331