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.
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.
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]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #ifndef _AMD64_SYS_PRIVREGS_H
28 #define _AMD64_SYS_PRIVREGS_H
30 #include <sys/ccompile.h>
37 * This file describes the cpu's privileged register set, and
38 * how the machine state is saved on the stack when a trap occurs.
42 #error "non-amd64 code depends on amd64 privileged header!"
48 * This is NOT the structure to use for general purpose debugging;
49 * see /proc for that. This is NOT the structure to use to decode
50 * the ucontext or grovel about in a core file; see <sys/regset.h>.
55 * Extra frame for mdb to follow through high level interrupts and
56 * system traps. Set them to 0 to terminate stacktrace.
58 greg_t r_savfp
; /* a copy of %rbp */
59 greg_t r_savpc
; /* a copy of %rip */
61 greg_t r_rdi
; /* 1st arg to function */
62 greg_t r_rsi
; /* 2nd arg to function */
63 greg_t r_rdx
; /* 3rd arg to function, 2nd return register */
64 greg_t r_rcx
; /* 4th arg to function */
66 greg_t r_r8
; /* 5th arg to function */
67 greg_t r_r9
; /* 6th arg to function */
68 greg_t r_rax
; /* 1st return register, # SSE registers */
69 greg_t r_rbx
; /* callee-saved, optional base pointer */
71 greg_t r_rbp
; /* callee-saved, optional frame pointer */
72 greg_t r_r10
; /* temporary register, static chain pointer */
73 greg_t r_r11
; /* temporary register */
74 greg_t r_r12
; /* callee-saved */
76 greg_t r_r13
; /* callee-saved */
77 greg_t r_r14
; /* callee-saved */
78 greg_t r_r15
; /* callee-saved */
81 * fsbase and gsbase are sampled on every exception in DEBUG kernels
82 * only. They remain in the non-DEBUG kernel to avoid any flag days.
84 greg_t __r_fsbase
; /* no longer used in non-DEBUG builds */
85 greg_t __r_gsbase
; /* no longer used in non-DEBUG builds */
88 greg_t r_fs
; /* %fs is *never* used by the kernel */
94 * (the rest of these are defined by the hardware)
104 #define r_r0 r_rax /* r0 for portability */
105 #define r_r1 r_rdx /* r1 for portability */
106 #define r_fp r_rbp /* kernel frame pointer */
107 #define r_sp r_rsp /* user stack pointer */
108 #define r_pc r_rip /* user's instruction pointer */
109 #define r_ps r_rfl /* user's RFLAGS */
112 #define lwptoregs(lwp) ((struct regs *)((lwp)->lwp_regs))
117 #if defined(_MACHDEP)
119 #include <sys/machprivregs.h>
123 * We can not safely sample {fs,gs}base on the hypervisor. The rdmsr
124 * instruction triggers a #gp fault which is emulated in the hypervisor
125 * on behalf of the guest. This is normally ok but if the guest is in
126 * the special failsafe handler it must not fault again or the hypervisor
127 * will kill the domain. We could use something different than INTR_PUSH
128 * in xen_failsafe_callback but for now we will not sample them.
130 #if defined(DEBUG) && !defined(__xpv)
131 #define __SAVE_BASES \
132 movl $MSR_AMD_FSBASE, %ecx; \
134 movl %eax, REGOFF_FSBASE(%rsp); \
135 movl %edx, REGOFF_FSBASE+4(%rsp); \
136 movl $MSR_AMD_GSBASE, %ecx; \
138 movl %eax, REGOFF_GSBASE(%rsp); \
139 movl %edx, REGOFF_GSBASE+4(%rsp)
145 * Create a struct regs on the stack suitable for an
148 * Assumes that the trap handler has already pushed an
149 * appropriate r_err and r_trapno
151 #define __SAVE_REGS \
152 movq %r15, REGOFF_R15(%rsp); \
153 movq %r14, REGOFF_R14(%rsp); \
154 movq %r13, REGOFF_R13(%rsp); \
155 movq %r12, REGOFF_R12(%rsp); \
156 movq %r11, REGOFF_R11(%rsp); \
157 movq %r10, REGOFF_R10(%rsp); \
158 movq %rbp, REGOFF_RBP(%rsp); \
159 movq %rbx, REGOFF_RBX(%rsp); \
160 movq %rax, REGOFF_RAX(%rsp); \
161 movq %r9, REGOFF_R9(%rsp); \
162 movq %r8, REGOFF_R8(%rsp); \
163 movq %rcx, REGOFF_RCX(%rsp); \
164 movq %rdx, REGOFF_RDX(%rsp); \
165 movq %rsi, REGOFF_RSI(%rsp); \
166 movq %rdi, REGOFF_RDI(%rsp); \
167 movq %rbp, REGOFF_SAVFP(%rsp); \
168 movq REGOFF_RIP(%rsp), %rcx; \
169 movq %rcx, REGOFF_SAVPC(%rsp); \
172 movq %rcx, REGOFF_GS(%rsp); \
174 movq %rcx, REGOFF_FS(%rsp); \
176 movq %rcx, REGOFF_ES(%rsp); \
178 movq %rcx, REGOFF_DS(%rsp); \
181 #define __RESTORE_REGS \
182 movq REGOFF_RDI(%rsp), %rdi; \
183 movq REGOFF_RSI(%rsp), %rsi; \
184 movq REGOFF_RDX(%rsp), %rdx; \
185 movq REGOFF_RCX(%rsp), %rcx; \
186 movq REGOFF_R8(%rsp), %r8; \
187 movq REGOFF_R9(%rsp), %r9; \
188 movq REGOFF_RAX(%rsp), %rax; \
189 movq REGOFF_RBX(%rsp), %rbx; \
190 movq REGOFF_RBP(%rsp), %rbp; \
191 movq REGOFF_R10(%rsp), %r10; \
192 movq REGOFF_R11(%rsp), %r11; \
193 movq REGOFF_R12(%rsp), %r12; \
194 movq REGOFF_R13(%rsp), %r13; \
195 movq REGOFF_R14(%rsp), %r14; \
196 movq REGOFF_R15(%rsp), %r15
199 * Push register state onto the stack. If we've
200 * interrupted userland, do a swapgs as well.
203 subq $REGOFF_TRAPNO, %rsp; \
205 cmpw $KCS_SEL, REGOFF_CS(%rsp); \
207 movq $0, REGOFF_SAVFP(%rsp); \
212 leaq sys_lcall32(%rip), %r11;\
213 cmpq %r11, REGOFF_RIP(%rsp); \
216 cmpw $KCS_SEL, REGOFF_CS(%rsp);\
219 8: addq $REGOFF_RIP, %rsp
224 addq $REGOFF_RIP, %rsp /* Adjust %rsp to prepare for iretq */
227 movl REGOFF_RDI(%rsp), %edi; \
228 movl REGOFF_RSI(%rsp), %esi; \
229 movl REGOFF_RDX(%rsp), %edx; \
230 movl REGOFF_RCX(%rsp), %ecx; \
231 movl REGOFF_RAX(%rsp), %eax; \
232 movl REGOFF_RBX(%rsp), %ebx; \
233 movl REGOFF_RBP(%rsp), %ebp; \
235 addq $REGOFF_RIP, %rsp /* Adjust %rsp to prepare for iretq */
237 #define DFTRAP_PUSH \
238 subq $REGOFF_TRAPNO, %rsp; \
241 #endif /* _MACHDEP */
244 * Used to set rflags to known values at the head of an
245 * interrupt gate handler, i.e. interrupts are -already- disabled.
247 #define INTGATE_INIT_KERNEL_FLAGS \
253 #include <sys/controlregs.h>
255 #if defined(_KERNEL) && !defined(_ASM)
257 extern __GNU_INLINE ulong_t
262 __asm__
__volatile__(
268 extern __GNU_INLINE
void
269 setcr8(ulong_t value
)
271 __asm__
__volatile__(
277 #endif /* _KERNEL && !_ASM */
279 /* Control register layout for panic dump */
283 #define CREG_IDT 0x10
284 #define CREG_LDT 0x20
285 #define CREG_TASKR 0x28
286 #define CREG_CR0 0x30
287 #define CREG_CR2 0x38
288 #define CREG_CR3 0x40
289 #define CREG_CR4 0x48
290 #define CREG_CR8 0x50
291 #define CREG_KGSBASE 0x58
292 #define CREG_EFER 0x60
294 #if !defined(_ASM) && defined(_INT64_TYPE)
296 typedef uint64_t creg64_t
;
297 typedef upad128_t creg128_t
;
314 extern void getcregs(struct cregs
*);
317 #endif /* !_ASM && _INT64_TYPE */
323 #endif /* !_AMD64_SYS_PRIVREGS_H */