xref: /illumos-gate/usr/src/uts/intel/ia32/sys/privregs.h (revision 7c478bd9)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 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 #endif	/* !_ASM */
92 
93 #ifdef _KERNEL
94 #define	lwptoregs(lwp)	((struct regs *)((lwp)->lwp_regs))
95 #endif /* _KERNEL */
96 
97 /*
98  * Save current frame on the stack.  Uses %eax.
99  */
100 #define	__FRAME_PUSH				\
101 	subl	$8, %esp;			\
102 	movl	REGOFF_EIP(%esp), %eax;		\
103 	movl	%eax, REGOFF_SAVPC(%esp);	\
104 	movl	%ebp, REGOFF_SAVFP(%esp);
105 
106 /*
107  * Save segment registers on the stack.
108  */
109 #define	__SEGREGS_PUSH		\
110 	subl	$16, %esp;	\
111 	movw	%ds, 12(%esp);	\
112 	movw	%es, 8(%esp);	\
113 	movw	%fs, 4(%esp);	\
114 	movw	%gs, 0(%esp);
115 
116 /*
117  * Load segment register with kernel selectors.
118  * %gs must be the last one to be set to make the
119  * check in cmnint valid.
120  */
121 #define	__SEGREGS_LOAD_KERNEL	\
122 	movw	$KDS_SEL, %ax;	\
123 	movw	$KFS_SEL, %cx;	\
124 	movw	$KGS_SEL, %dx;	\
125 	movw	%ax, %ds;	\
126 	movw	%ax, %es;	\
127 	movw	%cx, %fs;	\
128 	movw	%dx, %gs;
129 
130 /*
131  * Restore segment registers off the stack.
132  *
133  * NOTE THE ORDER IS VITAL!
134  *
135  * Also note the subtle interdependency with kern_gpfault()
136  * that needs to disassemble these instructions to diagnose
137  * what happened when things (like bad segment register
138  * values) go horribly wrong.
139  */
140 #define	__SEGREGS_POP		\
141 	movw	0(%esp), %gs;	\
142 	movw	4(%esp), %fs;	\
143 	movw	8(%esp), %es;	\
144 	movw	12(%esp), %ds;	\
145 	addl	$16, %esp;
146 
147 /*
148  * Macros for saving all registers necessary on interrupt entry,
149  * and restoring them on exit.
150  */
151 #define	INTR_PUSH			\
152 	pusha;				\
153 	__SEGREGS_PUSH			\
154 	__FRAME_PUSH			\
155 	cmpw	$KGS_SEL, REGOFF_GS(%esp);	\
156 	je	7f;			\
157 	movl	$0, REGOFF_SAVFP(%esp);	\
158 	__SEGREGS_LOAD_KERNEL		\
159 7:
160 
161 #define	INTR_POP			\
162 	popa;				\
163 	addl	$8, %esp;	/* get TRAPNO and ERR off the stack */
164 
165 #define	INTR_POP_USER			\
166 	addl	$8, %esp;	/* get extra frame off the stack */ \
167 	__SEGREGS_POP			\
168 	INTR_POP
169 
170 #define	INTR_POP_KERNEL			\
171 	addl	$24, %esp;	/* skip extra frame and segment registers */ \
172 	INTR_POP
173 
174 /*
175  * Macros for saving the original segment registers and restoring them
176  * for fast traps.
177  */
178 #define	FAST_INTR_PUSH	\
179 	__SEGREGS_PUSH	\
180 	__SEGREGS_LOAD_KERNEL
181 
182 #define	FAST_INTR_POP	\
183 	__SEGREGS_POP
184 
185 #define	DISABLE_INTR_FLAGS		\
186 	pushl	$F_OFF;			\
187 	popfl;
188 
189 #define	ENABLE_INTR_FLAGS		\
190 	pushl	$F_ON;			\
191 	popfl;
192 
193 /*
194  * Macros for saving all registers necessary on system call entry,
195  * and restoring them on exit.
196  */
197 #define	SYSCALL_PUSH			\
198 	pusha;				\
199 	__SEGREGS_PUSH			\
200 	__FRAME_PUSH			\
201 	pushfl;				\
202 	popl	%ecx;			\
203 	orl	$PS_IE, %ecx;		\
204 	movl	%ecx, REGOFF_EFL(%esp);	\
205 	movl	$0, REGOFF_SAVFP(%esp);	\
206 	__SEGREGS_LOAD_KERNEL
207 
208 #define	SYSENTER_PUSH			\
209 	pusha;				\
210 	__SEGREGS_PUSH			\
211 	__FRAME_PUSH			\
212 	movl	$0, REGOFF_SAVFP(%esp);	\
213 	__SEGREGS_LOAD_KERNEL
214 
215 #define	SYSCALL_POP			\
216 	INTR_POP_USER
217 
218 
219 
220 #include <sys/controlregs.h>
221 
222 /* Control register layout for panic dump */
223 
224 #define	CREGSZ		36
225 #define	CREG_GDT	0
226 #define	CREG_IDT	8
227 #define	CREG_LDT	16
228 #define	CREG_TASKR	18
229 #define	CREG_CR0	20
230 #define	CREG_CR2	24
231 #define	CREG_CR3	28
232 #define	CREG_CR4	32
233 
234 #if !defined(_ASM) && defined(_INT64_TYPE)
235 
236 typedef	uint64_t	creg64_t;
237 
238 struct cregs {
239 	creg64_t	cr_gdt;
240 	creg64_t	cr_idt;
241 	uint16_t	cr_ldt;
242 	uint16_t	cr_task;
243 	uint32_t	cr_cr0;
244 	uint32_t	cr_cr2;
245 	uint32_t	cr_cr3;
246 	uint32_t	cr_cr4;
247 };
248 
249 #if defined(_KERNEL)
250 extern void getcregs(struct cregs *);
251 #endif	/* _KERNEL */
252 
253 #endif	/* !_ASM && _INT64_TYPE */
254 
255 #ifdef __cplusplus
256 }
257 #endif
258 
259 #endif	/* !_IA32_SYS_PRIVREGS_H */
260