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
33extern "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
53struct 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		\
1648:	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
235typedef	uint64_t	creg64_t;
236
237struct 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)
249extern 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