/* * 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 #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 . */ 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 /* * 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 /* 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 */