Home | History | Annotate | Download | only in sys
      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