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 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 /* 35 * This file describes the cpu's privileged register set, and 36 * how the machine state is saved on the stack when a trap occurs. 37 */ 38 39 #if !defined(__i386) 40 #error "non-i386 code depends on i386 privileged header!" 41 #endif 42 43 #ifndef _ASM 44 45 /* 46 * This is NOT the structure to use for general purpose debugging; 47 * see /proc for that. This is NOT the structure to use to decode 48 * the ucontext or grovel about in a core file; see <sys/regset.h>. 49 */ 50 51 struct regs { 52 /* 53 * Extra frame for mdb to follow through high level interrupts and 54 * system traps. Set them to 0 to terminate stacktrace. 55 */ 56 greg_t r_savfp; /* a copy of %ebp */ 57 greg_t r_savpc; /* a copy of %eip */ 58 59 greg_t r_gs; 60 greg_t r_fs; 61 greg_t r_es; 62 greg_t r_ds; 63 greg_t r_edi; 64 greg_t r_esi; 65 greg_t r_ebp; 66 greg_t r_esp; 67 greg_t r_ebx; 68 greg_t r_edx; 69 greg_t r_ecx; 70 greg_t r_eax; 71 greg_t r_trapno; 72 greg_t r_err; 73 greg_t r_eip; 74 greg_t r_cs; 75 greg_t r_efl; 76 greg_t r_uesp; 77 greg_t r_ss; 78 }; 79 80 #define r_r0 r_eax /* r0 for portability */ 81 #define r_r1 r_edx /* r1 for portability */ 82 #define r_fp r_ebp /* system frame pointer */ 83 #define r_sp r_uesp /* user stack pointer */ 84 #define r_pc r_eip /* user's instruction pointer */ 85 #define r_ps r_efl /* user's EFLAGS */ 86 87 #define GREG_NUM 8 /* Number of regs between %edi and %eax */ 88 89 #ifdef _KERNEL 90 #define lwptoregs(lwp) ((struct regs *)((lwp)->lwp_regs)) 91 #define lwptofpu(lwp) ((kfpu_t *)((lwp)->lwp_fpu)) 92 #endif /* _KERNEL */ 93 94 #else /* !_ASM */ 95 96 #if defined(_MACHDEP) 97 98 #include <sys/machprivregs.h> 99 100 /* 101 * Save current frame on the stack. Uses %eax. 102 */ 103 #define __FRAME_PUSH \ 104 subl $8, %esp; \ 105 movl REGOFF_EIP(%esp), %eax; \ 106 movl %eax, REGOFF_SAVPC(%esp); \ 107 movl %ebp, REGOFF_SAVFP(%esp); 108 109 /* 110 * Save segment registers on the stack. 111 */ 112 #define __SEGREGS_PUSH \ 113 subl $16, %esp; \ 114 movw %ds, 12(%esp); \ 115 movw %es, 8(%esp); \ 116 movw %fs, 4(%esp); \ 117 movw %gs, 0(%esp); 118 119 /* 120 * Load segment register with kernel selectors. 121 * %gs must be the last one to be set to make the 122 * check in cmnint valid. 123 */ 124 #define __SEGREGS_LOAD_KERNEL \ 125 movw $KDS_SEL, %cx; \ 126 movw %cx, %ds; \ 127 movw %cx, %es; \ 128 movw $KFS_SEL, %cx; \ 129 movw $KGS_SEL, %dx; \ 130 movw %cx, %fs; \ 131 movw %dx, %gs; 132 133 /* 134 * Restore segment registers off the stack. 135 * 136 * NOTE THE ORDER IS VITAL! 137 * 138 * Also note the subtle interdependency with kern_gpfault() 139 * that needs to disassemble these instructions to diagnose 140 * what happened when things (like bad segment register 141 * values) go horribly wrong. 142 */ 143 #define __SEGREGS_POP \ 144 movw 0(%esp), %gs; \ 145 movw 4(%esp), %fs; \ 146 movw 8(%esp), %es; \ 147 movw 12(%esp), %ds; \ 148 addl $16, %esp; 149 150 /* 151 * Macros for saving all registers necessary on interrupt entry, 152 * and restoring them on exit. 153 */ 154 #define INTR_PUSH \ 155 cld; \ 156 pusha; \ 157 __SEGREGS_PUSH \ 158 __FRAME_PUSH \ 159 cmpw $KGS_SEL, REGOFF_GS(%esp); \ 160 je 8f; \ 161 movl $0, REGOFF_SAVFP(%esp); \ 162 __SEGREGS_LOAD_KERNEL \ 163 8: CLEAN_CS 164 165 #define __INTR_POP \ 166 popa; \ 167 addl $8, %esp; /* get TRAPNO and ERR off the stack */ 168 169 #define INTR_POP_USER \ 170 addl $8, %esp; /* get extra frame off the stack */ \ 171 __SEGREGS_POP \ 172 __INTR_POP 173 174 #define INTR_POP_KERNEL \ 175 addl $24, %esp; /* skip extra frame and segment registers */ \ 176 __INTR_POP 177 /* 178 * Macros for saving all registers necessary on system call entry, 179 * and restoring them on exit. 180 */ 181 #define SYSCALL_PUSH \ 182 cld; \ 183 pusha; \ 184 __SEGREGS_PUSH \ 185 subl $8, %esp; \ 186 pushfl; \ 187 popl %ecx; \ 188 orl $PS_IE, %ecx; \ 189 movl %ecx, REGOFF_EFL(%esp); \ 190 movl $0, REGOFF_SAVPC(%esp); \ 191 movl $0, REGOFF_SAVFP(%esp); \ 192 __SEGREGS_LOAD_KERNEL; \ 193 194 #define SYSENTER_PUSH \ 195 cld; \ 196 pusha; \ 197 __SEGREGS_PUSH \ 198 subl $8, %esp; \ 199 movl $0, REGOFF_SAVPC(%esp); \ 200 movl $0, REGOFF_SAVFP(%esp); \ 201 __SEGREGS_LOAD_KERNEL 202 203 #define SYSCALL_POP \ 204 INTR_POP_USER 205 206 #endif /* _MACHDEP */ 207 208 /* 209 * This is used to set eflags to known values at the head of an 210 * interrupt gate handler, i.e. interrupts are -already- disabled. 211 */ 212 #define INTGATE_INIT_KERNEL_FLAGS \ 213 pushl $F_OFF; \ 214 popfl 215 216 #endif /* !_ASM */ 217 218 #include <sys/controlregs.h> 219 220 /* Control register layout for panic dump */ 221 222 #define CREGSZ 36 223 #define CREG_GDT 0 224 #define CREG_IDT 8 225 #define CREG_LDT 16 226 #define CREG_TASKR 18 227 #define CREG_CR0 20 228 #define CREG_CR2 24 229 #define CREG_CR3 28 230 #define CREG_CR4 32 231 232 #if !defined(_ASM) && defined(_INT64_TYPE) 233 234 typedef uint64_t creg64_t; 235 236 struct cregs { 237 creg64_t cr_gdt; 238 creg64_t cr_idt; 239 uint16_t cr_ldt; 240 uint16_t cr_task; 241 uint32_t cr_cr0; 242 uint32_t cr_cr2; 243 uint32_t cr_cr3; 244 uint32_t cr_cr4; 245 }; 246 247 #if defined(_KERNEL) 248 extern void getcregs(struct cregs *); 249 #endif /* _KERNEL */ 250 251 #endif /* !_ASM && _INT64_TYPE */ 252 253 #ifdef __cplusplus 254 } 255 #endif 256 257 #endif /* !_IA32_SYS_PRIVREGS_H */