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