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