xref: /illumos-gate/usr/src/uts/intel/ia32/sys/privregs.h (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
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 #endif /* _KERNEL */
92 
93 #else	/* !_ASM */
94 
95 #if defined(_MACHDEP)
96 
97 #include <sys/machprivregs.h>
98 
99 /*
100  * Save current frame on the stack.  Uses %eax.
101  */
102 #define	__FRAME_PUSH				\
103 	subl	$8, %esp;			\
104 	movl	REGOFF_EIP(%esp), %eax;		\
105 	movl	%eax, REGOFF_SAVPC(%esp);	\
106 	movl	%ebp, REGOFF_SAVFP(%esp);
107 
108 /*
109  * Save segment registers on the stack.
110  */
111 #define	__SEGREGS_PUSH		\
112 	subl	$16, %esp;	\
113 	movw	%ds, 12(%esp);	\
114 	movw	%es, 8(%esp);	\
115 	movw	%fs, 4(%esp);	\
116 	movw	%gs, 0(%esp);
117 
118 /*
119  * Load segment register with kernel selectors.
120  * %gs must be the last one to be set to make the
121  * check in cmnint valid.
122  */
123 #define	__SEGREGS_LOAD_KERNEL	\
124 	movw	$KDS_SEL, %cx;	\
125 	movw	%cx, %ds;	\
126 	movw	%cx, %es;	\
127 	movw	$KFS_SEL, %cx;	\
128 	movw	$KGS_SEL, %dx;	\
129 	movw	%cx, %fs;	\
130 	movw	%dx, %gs;
131 
132 /*
133  * Restore segment registers off the stack.
134  *
135  * NOTE THE ORDER IS VITAL!
136  *
137  * Also note the subtle interdependency with kern_gpfault()
138  * that needs to disassemble these instructions to diagnose
139  * what happened when things (like bad segment register
140  * values) go horribly wrong.
141  */
142 #define	__SEGREGS_POP		\
143 	movw	0(%esp), %gs;	\
144 	movw	4(%esp), %fs;	\
145 	movw	8(%esp), %es;	\
146 	movw	12(%esp), %ds;	\
147 	addl	$16, %esp;
148 
149 /*
150  * Macros for saving all registers necessary on interrupt entry,
151  * and restoring them on exit.
152  */
153 #define	INTR_PUSH			\
154 	cld;				\
155 	pusha;				\
156 	__SEGREGS_PUSH			\
157 	__FRAME_PUSH			\
158 	cmpw	$KGS_SEL, REGOFF_GS(%esp); \
159 	je	8f;			\
160 	movl	$0, REGOFF_SAVFP(%esp);	\
161 	__SEGREGS_LOAD_KERNEL		\
162 8:	CLEAN_CS
163 
164 #define	__INTR_POP			\
165 	popa;				\
166 	addl	$8, %esp;	/* get TRAPNO and ERR off the stack */
167 
168 #define	INTR_POP_USER			\
169 	addl	$8, %esp;	/* get extra frame off the stack */ \
170 	__SEGREGS_POP			\
171 	__INTR_POP
172 
173 #define	INTR_POP_KERNEL					\
174 	addl	$24, %esp;	/* skip extra frame and segment registers */ \
175 	__INTR_POP
176 /*
177  * Macros for saving all registers necessary on system call entry,
178  * and restoring them on exit.
179  */
180 #define	SYSCALL_PUSH			\
181 	cld;				\
182 	pusha;				\
183 	__SEGREGS_PUSH			\
184 	subl	$8, %esp;		\
185 	pushfl;				\
186 	popl	%ecx;			\
187 	orl	$PS_IE, %ecx;		\
188 	movl	%ecx, REGOFF_EFL(%esp);	\
189 	movl	$0, REGOFF_SAVPC(%esp);	\
190 	movl	$0, REGOFF_SAVFP(%esp);	\
191 	__SEGREGS_LOAD_KERNEL;		\
192 
193 #define	SYSENTER_PUSH			\
194 	cld;				\
195 	pusha;				\
196 	__SEGREGS_PUSH			\
197 	subl	$8, %esp;		\
198 	movl	$0, REGOFF_SAVPC(%esp);	\
199 	movl	$0, REGOFF_SAVFP(%esp);	\
200 	__SEGREGS_LOAD_KERNEL
201 
202 #define	SYSCALL_POP			\
203 	INTR_POP_USER
204 
205 #endif	/* _MACHDEP */
206 
207 /*
208  * This is used to set eflags to known values at the head of an
209  * interrupt gate handler, i.e. interrupts are -already- disabled.
210  */
211 #define	INTGATE_INIT_KERNEL_FLAGS	\
212 	pushl	$F_OFF;			\
213 	popfl
214 
215 #endif	/* !_ASM */
216 
217 #include <sys/controlregs.h>
218 
219 /* Control register layout for panic dump */
220 
221 #define	CREGSZ		36
222 #define	CREG_GDT	0
223 #define	CREG_IDT	8
224 #define	CREG_LDT	16
225 #define	CREG_TASKR	18
226 #define	CREG_CR0	20
227 #define	CREG_CR2	24
228 #define	CREG_CR3	28
229 #define	CREG_CR4	32
230 
231 #if !defined(_ASM) && defined(_INT64_TYPE)
232 
233 typedef	uint64_t	creg64_t;
234 
235 struct cregs {
236 	creg64_t	cr_gdt;
237 	creg64_t	cr_idt;
238 	uint16_t	cr_ldt;
239 	uint16_t	cr_task;
240 	uint32_t	cr_cr0;
241 	uint32_t	cr_cr2;
242 	uint32_t	cr_cr3;
243 	uint32_t	cr_cr4;
244 };
245 
246 #if defined(_KERNEL)
247 extern void getcregs(struct cregs *);
248 #endif	/* _KERNEL */
249 
250 #endif	/* !_ASM && _INT64_TYPE */
251 
252 #ifdef __cplusplus
253 }
254 #endif
255 
256 #endif	/* !_IA32_SYS_PRIVREGS_H */
257