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