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