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 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #ifndef _IA32_SYS_PRIVREGS_H
28 #define _IA32_SYS_PRIVREGS_H
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 /*
35 * This file describes the cpu's privileged register set, and
36 * how the machine state is saved on the stack when a trap occurs.
37 */
38
39 #if !defined(__i386)
40 #error "non-i386 code depends on i386 privileged header!"
41 #endif
42
43 #ifndef _ASM
44
45 /*
46 * This is NOT the structure to use for general purpose debugging;
47 * see /proc for that. This is NOT the structure to use to decode
48 * the ucontext or grovel about in a core file; see <sys/regset.h>.
49 */
50
51 struct regs {
52 /*
53 * Extra frame for mdb to follow through high level interrupts and
54 * system traps. Set them to 0 to terminate stacktrace.
55 */
56 greg_t r_savfp; /* a copy of %ebp */
57 greg_t r_savpc; /* a copy of %eip */
58
59 greg_t r_gs;
60 greg_t r_fs;
61 greg_t r_es;
62 greg_t r_ds;
63 greg_t r_edi;
64 greg_t r_esi;
65 greg_t r_ebp;
66 greg_t r_esp;
67 greg_t r_ebx;
68 greg_t r_edx;
69 greg_t r_ecx;
70 greg_t r_eax;
71 greg_t r_trapno;
72 greg_t r_err;
73 greg_t r_eip;
74 greg_t r_cs;
75 greg_t r_efl;
76 greg_t r_uesp;
77 greg_t r_ss;
78 };
79
80 #define r_r0 r_eax /* r0 for portability */
81 #define r_r1 r_edx /* r1 for portability */
82 #define r_fp r_ebp /* system frame pointer */
83 #define r_sp r_uesp /* user stack pointer */
84 #define r_pc r_eip /* user's instruction pointer */
85 #define r_ps r_efl /* user's EFLAGS */
86
87 #define GREG_NUM 8 /* Number of regs between %edi and %eax */
88
89 #ifdef _KERNEL
90 #define lwptoregs(lwp) ((struct regs *)((lwp)->lwp_regs))
91 #define lwptofpu(lwp) ((kfpu_t *)((lwp)->lwp_fpu))
92 #endif /* _KERNEL */
93
94 #else /* !_ASM */
95
96 #if defined(_MACHDEP)
97
98 #include <sys/machprivregs.h>
99
100 /*
101 * Save current frame on the stack. Uses %eax.
102 */
103 #define __FRAME_PUSH \
104 subl $8, %esp; \
105 movl REGOFF_EIP(%esp), %eax; \
106 movl %eax, REGOFF_SAVPC(%esp); \
107 movl %ebp, REGOFF_SAVFP(%esp);
108
109 /*
110 * Save segment registers on the stack.
111 */
112 #define __SEGREGS_PUSH \
113 subl $16, %esp; \
114 movw %ds, 12(%esp); \
115 movw %es, 8(%esp); \
116 movw %fs, 4(%esp); \
117 movw %gs, 0(%esp);
118
119 /*
120 * Load segment register with kernel selectors.
121 * %gs must be the last one to be set to make the
122 * check in cmnint valid.
123 */
124 #define __SEGREGS_LOAD_KERNEL \
125 movw $KDS_SEL, %cx; \
126 movw %cx, %ds; \
127 movw %cx, %es; \
128 movw $KFS_SEL, %cx; \
129 movw $KGS_SEL, %dx; \
130 movw %cx, %fs; \
131 movw %dx, %gs;
132
133 /*
134 * Restore segment registers off the stack.
135 *
136 * NOTE THE ORDER IS VITAL!
137 *
138 * Also note the subtle interdependency with kern_gpfault()
139 * that needs to disassemble these instructions to diagnose
140 * what happened when things (like bad segment register
141 * values) go horribly wrong.
142 */
143 #define __SEGREGS_POP \
144 movw 0(%esp), %gs; \
145 movw 4(%esp), %fs; \
146 movw 8(%esp), %es; \
147 movw 12(%esp), %ds; \
148 addl $16, %esp;
149
150 /*
151 * Macros for saving all registers necessary on interrupt entry,
152 * and restoring them on exit.
153 */
154 #define INTR_PUSH \
155 cld; \
156 pusha; \
157 __SEGREGS_PUSH \
158 __FRAME_PUSH \
159 cmpw $KGS_SEL, REGOFF_GS(%esp); \
160 je 8f; \
161 movl $0, REGOFF_SAVFP(%esp); \
162 __SEGREGS_LOAD_KERNEL \
163 8: CLEAN_CS
164
165 #define __INTR_POP \
166 popa; \
167 addl $8, %esp; /* get TRAPNO and ERR off the stack */
168
169 #define INTR_POP_USER \
170 addl $8, %esp; /* get extra frame off the stack */ \
171 __SEGREGS_POP \
172 __INTR_POP
173
174 #define INTR_POP_KERNEL \
175 addl $24, %esp; /* skip extra frame and segment registers */ \
176 __INTR_POP
177 /*
178 * Macros for saving all registers necessary on system call entry,
179 * and restoring them on exit.
180 */
181 #define SYSCALL_PUSH \
182 cld; \
183 pusha; \
184 __SEGREGS_PUSH \
185 subl $8, %esp; \
186 pushfl; \
187 popl %ecx; \
188 orl $PS_IE, %ecx; \
189 movl %ecx, REGOFF_EFL(%esp); \
190 movl $0, REGOFF_SAVPC(%esp); \
191 movl $0, REGOFF_SAVFP(%esp); \
192 __SEGREGS_LOAD_KERNEL; \
193
194 #define SYSENTER_PUSH \
195 cld; \
196 pusha; \
197 __SEGREGS_PUSH \
198 subl $8, %esp; \
199 movl $0, REGOFF_SAVPC(%esp); \
200 movl $0, REGOFF_SAVFP(%esp); \
201 __SEGREGS_LOAD_KERNEL
202
203 #define SYSCALL_POP \
204 INTR_POP_USER
205
206 #endif /* _MACHDEP */
207
208 /*
209 * This is used to set eflags to known values at the head of an
210 * interrupt gate handler, i.e. interrupts are -already- disabled.
211 */
212 #define INTGATE_INIT_KERNEL_FLAGS \
213 pushl $F_OFF; \
214 popfl
215
216 #endif /* !_ASM */
217
218 #include <sys/controlregs.h>
219
220 /* Control register layout for panic dump */
221
222 #define CREGSZ 36
223 #define CREG_GDT 0
224 #define CREG_IDT 8
225 #define CREG_LDT 16
226 #define CREG_TASKR 18
227 #define CREG_CR0 20
228 #define CREG_CR2 24
229 #define CREG_CR3 28
230 #define CREG_CR4 32
231
232 #if !defined(_ASM) && defined(_INT64_TYPE)
233
234 typedef uint64_t creg64_t;
235
236 struct cregs {
237 creg64_t cr_gdt;
238 creg64_t cr_idt;
239 uint16_t cr_ldt;
240 uint16_t cr_task;
241 uint32_t cr_cr0;
242 uint32_t cr_cr2;
243 uint32_t cr_cr3;
244 uint32_t cr_cr4;
245 };
246
247 #if defined(_KERNEL)
248 extern void getcregs(struct cregs *);
249 #endif /* _KERNEL */
250
251 #endif /* !_ASM && _INT64_TYPE */
252
253 #ifdef __cplusplus
254 }
255 #endif
256
257 #endif /* !_IA32_SYS_PRIVREGS_H */