privregs.h revision ae115bc77f6fcde83175c75b4206dc2e50747966
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _IA32_SYS_PRIVREGS_H
#define _IA32_SYS_PRIVREGS_H
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
#endif
/*
* This file describes the cpu's privileged register set, and
* how the machine state is saved on the stack when a trap occurs.
*/
#if !defined(__i386)
#error "non-i386 code depends on i386 privileged header!"
#endif
#ifndef _ASM
/*
* This is NOT the structure to use for general purpose debugging;
* see /proc for that. This is NOT the structure to use to decode
* the ucontext or grovel about in a core file; see <sys/regset.h>.
*/
struct regs {
/*
* Extra frame for mdb to follow through high level interrupts and
* system traps. Set them to 0 to terminate stacktrace.
*/
greg_t r_savfp; /* a copy of %ebp */
greg_t r_savpc; /* a copy of %eip */
greg_t r_gs;
greg_t r_fs;
greg_t r_es;
greg_t r_ds;
greg_t r_edi;
greg_t r_esi;
greg_t r_ebp;
greg_t r_esp;
greg_t r_ebx;
greg_t r_edx;
greg_t r_ecx;
greg_t r_eax;
greg_t r_trapno;
greg_t r_err;
greg_t r_eip;
greg_t r_cs;
greg_t r_efl;
greg_t r_uesp;
greg_t r_ss;
};
#define r_r0 r_eax /* r0 for portability */
#define r_r1 r_edx /* r1 for portability */
#define r_fp r_ebp /* system frame pointer */
#define r_sp r_uesp /* user stack pointer */
#define r_pc r_eip /* user's instruction pointer */
#define r_ps r_efl /* user's EFLAGS */
#define GREG_NUM 8 /* Number of regs between %edi and %eax */
#ifdef _KERNEL
#define lwptoregs(lwp) ((struct regs *)((lwp)->lwp_regs))
#endif /* _KERNEL */
#else /* !_ASM */
#if defined(_MACHDEP)
#include <sys/machprivregs.h>
/*
* Save current frame on the stack. Uses %eax.
*/
#define __FRAME_PUSH \
subl $8, %esp; \
movl REGOFF_EIP(%esp), %eax; \
movl %eax, REGOFF_SAVPC(%esp); \
movl %ebp, REGOFF_SAVFP(%esp);
/*
* Save segment registers on the stack.
*/
#define __SEGREGS_PUSH \
subl $16, %esp; \
movw %ds, 12(%esp); \
movw %es, 8(%esp); \
movw %fs, 4(%esp); \
movw %gs, 0(%esp);
/*
* Load segment register with kernel selectors.
* %gs must be the last one to be set to make the
* check in cmnint valid.
*/
#define __SEGREGS_LOAD_KERNEL \
movw $KDS_SEL, %cx; \
movw %cx, %ds; \
movw %cx, %es; \
movw $KFS_SEL, %cx; \
movw $KGS_SEL, %dx; \
movw %cx, %fs; \
movw %dx, %gs;
/*
* Restore segment registers off the stack.
*
* NOTE THE ORDER IS VITAL!
*
* Also note the subtle interdependency with kern_gpfault()
* that needs to disassemble these instructions to diagnose
* what happened when things (like bad segment register
* values) go horribly wrong.
*/
#define __SEGREGS_POP \
movw 0(%esp), %gs; \
movw 4(%esp), %fs; \
movw 8(%esp), %es; \
movw 12(%esp), %ds; \
addl $16, %esp;
/*
* Macros for saving all registers necessary on interrupt entry,
* and restoring them on exit.
*/
#define INTR_PUSH \
cld; \
pusha; \
__SEGREGS_PUSH \
__FRAME_PUSH \
cmpw $KGS_SEL, REGOFF_GS(%esp); \
je 8f; \
movl $0, REGOFF_SAVFP(%esp); \
__SEGREGS_LOAD_KERNEL \
8: CLEAN_CS
#define __INTR_POP \
popa; \
addl $8, %esp; /* get TRAPNO and ERR off the stack */
#define INTR_POP_USER \
addl $8, %esp; /* get extra frame off the stack */ \
__SEGREGS_POP \
__INTR_POP
#define INTR_POP_KERNEL \
addl $24, %esp; /* skip extra frame and segment registers */ \
__INTR_POP
/*
* Macros for saving all registers necessary on system call entry,
* and restoring them on exit.
*/
#define SYSCALL_PUSH \
cld; \
pusha; \
__SEGREGS_PUSH \
subl $8, %esp; \
pushfl; \
popl %ecx; \
orl $PS_IE, %ecx; \
movl %ecx, REGOFF_EFL(%esp); \
movl $0, REGOFF_SAVPC(%esp); \
movl $0, REGOFF_SAVFP(%esp); \
__SEGREGS_LOAD_KERNEL; \
#define SYSENTER_PUSH \
cld; \
pusha; \
__SEGREGS_PUSH \
subl $8, %esp; \
movl $0, REGOFF_SAVPC(%esp); \
movl $0, REGOFF_SAVFP(%esp); \
__SEGREGS_LOAD_KERNEL
#define SYSCALL_POP \
INTR_POP_USER
#endif /* _MACHDEP */
/*
* This is used to set eflags to known values at the head of an
* interrupt gate handler, i.e. interrupts are -already- disabled.
*/
#define INTGATE_INIT_KERNEL_FLAGS \
pushl $F_OFF; \
popfl
#endif /* !_ASM */
#include <sys/controlregs.h>
/* Control register layout for panic dump */
#define CREGSZ 36
#define CREG_GDT 0
#define CREG_IDT 8
#define CREG_LDT 16
#define CREG_TASKR 18
#define CREG_CR0 20
#define CREG_CR2 24
#define CREG_CR3 28
#define CREG_CR4 32
#if !defined(_ASM) && defined(_INT64_TYPE)
typedef uint64_t creg64_t;
struct cregs {
creg64_t cr_gdt;
creg64_t cr_idt;
uint16_t cr_ldt;
uint16_t cr_task;
uint32_t cr_cr0;
uint32_t cr_cr2;
uint32_t cr_cr3;
uint32_t cr_cr4;
};
#if defined(_KERNEL)
extern void getcregs(struct cregs *);
#endif /* _KERNEL */
#endif /* !_ASM && _INT64_TYPE */
#ifdef __cplusplus
}
#endif
#endif /* !_IA32_SYS_PRIVREGS_H */