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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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 #endif /* !_ASM */ 92 93 #ifdef _KERNEL 94 #define lwptoregs(lwp) ((struct regs *)((lwp)->lwp_regs)) 95 #endif /* _KERNEL */ 96 97 /* 98 * Save current frame on the stack. Uses %eax. 99 */ 100 #define __FRAME_PUSH \ 101 subl $8, %esp; \ 102 movl REGOFF_EIP(%esp), %eax; \ 103 movl %eax, REGOFF_SAVPC(%esp); \ 104 movl %ebp, REGOFF_SAVFP(%esp); 105 106 /* 107 * Save segment registers on the stack. 108 */ 109 #define __SEGREGS_PUSH \ 110 subl $16, %esp; \ 111 movw %ds, 12(%esp); \ 112 movw %es, 8(%esp); \ 113 movw %fs, 4(%esp); \ 114 movw %gs, 0(%esp); 115 116 /* 117 * Load segment register with kernel selectors. 118 * %gs must be the last one to be set to make the 119 * check in cmnint valid. 120 */ 121 #define __SEGREGS_LOAD_KERNEL \ 122 movw $KDS_SEL, %ax; \ 123 movw $KFS_SEL, %cx; \ 124 movw $KGS_SEL, %dx; \ 125 movw %ax, %ds; \ 126 movw %ax, %es; \ 127 movw %cx, %fs; \ 128 movw %dx, %gs; 129 130 /* 131 * Restore segment registers off the stack. 132 * 133 * NOTE THE ORDER IS VITAL! 134 * 135 * Also note the subtle interdependency with kern_gpfault() 136 * that needs to disassemble these instructions to diagnose 137 * what happened when things (like bad segment register 138 * values) go horribly wrong. 139 */ 140 #define __SEGREGS_POP \ 141 movw 0(%esp), %gs; \ 142 movw 4(%esp), %fs; \ 143 movw 8(%esp), %es; \ 144 movw 12(%esp), %ds; \ 145 addl $16, %esp; 146 147 /* 148 * Macros for saving all registers necessary on interrupt entry, 149 * and restoring them on exit. 150 */ 151 #define INTR_PUSH \ 152 pusha; \ 153 __SEGREGS_PUSH \ 154 __FRAME_PUSH \ 155 cmpw $KGS_SEL, REGOFF_GS(%esp); \ 156 je 7f; \ 157 movl $0, REGOFF_SAVFP(%esp); \ 158 __SEGREGS_LOAD_KERNEL \ 159 7: 160 161 #define INTR_POP \ 162 popa; \ 163 addl $8, %esp; /* get TRAPNO and ERR off the stack */ 164 165 #define INTR_POP_USER \ 166 addl $8, %esp; /* get extra frame off the stack */ \ 167 __SEGREGS_POP \ 168 INTR_POP 169 170 #define INTR_POP_KERNEL \ 171 addl $24, %esp; /* skip extra frame and segment registers */ \ 172 INTR_POP 173 174 /* 175 * Macros for saving the original segment registers and restoring them 176 * for fast traps. 177 */ 178 #define FAST_INTR_PUSH \ 179 __SEGREGS_PUSH \ 180 __SEGREGS_LOAD_KERNEL 181 182 #define FAST_INTR_POP \ 183 __SEGREGS_POP 184 185 #define DISABLE_INTR_FLAGS \ 186 pushl $F_OFF; \ 187 popfl; 188 189 #define ENABLE_INTR_FLAGS \ 190 pushl $F_ON; \ 191 popfl; 192 193 /* 194 * Macros for saving all registers necessary on system call entry, 195 * and restoring them on exit. 196 */ 197 #define SYSCALL_PUSH \ 198 pusha; \ 199 __SEGREGS_PUSH \ 200 __FRAME_PUSH \ 201 pushfl; \ 202 popl %ecx; \ 203 orl $PS_IE, %ecx; \ 204 movl %ecx, REGOFF_EFL(%esp); \ 205 movl $0, REGOFF_SAVFP(%esp); \ 206 __SEGREGS_LOAD_KERNEL 207 208 #define SYSENTER_PUSH \ 209 pusha; \ 210 __SEGREGS_PUSH \ 211 __FRAME_PUSH \ 212 movl $0, REGOFF_SAVFP(%esp); \ 213 __SEGREGS_LOAD_KERNEL 214 215 #define SYSCALL_POP \ 216 INTR_POP_USER 217 218 219 220 #include <sys/controlregs.h> 221 222 /* Control register layout for panic dump */ 223 224 #define CREGSZ 36 225 #define CREG_GDT 0 226 #define CREG_IDT 8 227 #define CREG_LDT 16 228 #define CREG_TASKR 18 229 #define CREG_CR0 20 230 #define CREG_CR2 24 231 #define CREG_CR3 28 232 #define CREG_CR4 32 233 234 #if !defined(_ASM) && defined(_INT64_TYPE) 235 236 typedef uint64_t creg64_t; 237 238 struct cregs { 239 creg64_t cr_gdt; 240 creg64_t cr_idt; 241 uint16_t cr_ldt; 242 uint16_t cr_task; 243 uint32_t cr_cr0; 244 uint32_t cr_cr2; 245 uint32_t cr_cr3; 246 uint32_t cr_cr4; 247 }; 248 249 #if defined(_KERNEL) 250 extern void getcregs(struct cregs *); 251 #endif /* _KERNEL */ 252 253 #endif /* !_ASM && _INT64_TYPE */ 254 255 #ifdef __cplusplus 256 } 257 #endif 258 259 #endif /* !_IA32_SYS_PRIVREGS_H */ 260