1 /*
   2  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 
   5 #ifndef _SYS_SEGMENTS_H
   6 #define _SYS_SEGMENTS_H
   7 
   8 #ifdef  __cplusplus
   9 extern "C" {
  10 #endif
  11 
  12 /*
  13  * Copyright (c) 1989, 1990 William F. Jolitz
  14  * Copyright (c) 1990 The Regents of the University of California.
  15  * All rights reserved.
  16  *
  17  * This code is derived from software contributed to Berkeley by
  18  * William Jolitz.
  19  *
  20  * Redistribution and use in source and binary forms, with or without
  21  * modification, are permitted provided that the following conditions
  22  * are met:
  23  * 1. Redistributions of source code must retain the above copyright
  24  *    notice, this list of conditions and the following disclaimer.
  25  * 2. Redistributions in binary form must reproduce the above copyright
  26  *    notice, this list of conditions and the following disclaimer in the
  27  *    documentation and/or other materials provided with the distribution.
  28  * 3. All advertising materials mentioning features or use of this software
  29  *    must display the following acknowledgement:
  30  *      This product includes software developed by the University of
  31  *      California, Berkeley and its contributors.
  32  * 4. Neither the name of the University nor the names of its contributors
  33  *    may be used to endorse or promote products derived from this software
  34  *    without specific prior written permission.
  35  *
  36  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  37  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  39  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  40  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  41  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  42  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  44  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  45  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46  * SUCH DAMAGE.
  47  *
  48  *      from: @(#)segments.h    7.1 (Berkeley) 5/9/91
  49  * $FreeBSD: src/sys/i386/include/segments.h,v 1.34 2003/09/10 01:07:04
  50  * jhb Exp $
  51  *
  52  * 386 Segmentation Data Structures and definitions
  53  *      William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989
  54  */
  55 
  56 #include <sys/tss.h>
  57 
  58 /*
  59  * Selector register format
  60  * CS, DS, ES, FS, GS, SS
  61  *
  62  *  15                  3  2  1 0
  63  * +---------------------+---+----+
  64  * |          SI         |TI |RPL |
  65  * +---------------------+---+----+
  66  *
  67  * SI  = selector index
  68  * TI  = table indicator (0 = GDT, 1 = LDT)
  69  * RPL = requestor privilege level
  70  */
  71 #if !defined(_ASM) || defined(__GNUC_AS__)
  72 #define IDXTOSEL(s)     ((s) << 3)                /* index to selector */
  73 #define SEL_GDT(s, r)   (IDXTOSEL(s) | r)       /* global sel */
  74 #else
  75 #define IDXTOSEL(s)     [s << 3]
  76 #define SEL_GDT(s, r)   [IDXTOSEL(s) | r]
  77 #endif
  78 
  79 #define SELTOIDX(s)     ((s) >> 3)        /* selector to index */
  80 
  81 /*
  82  * SEL_(KPL,UPL,XPL) is the RPL or DPL value for code and data selectors
  83  * and their descriptors respectively.
  84  *
  85  * TRP_(KPL,UPL,XPL) is used to indicate the DPL for system gates only.
  86  *
  87  * This distinction is important to support para-virt guests on the
  88  * 64-bit hypervisor. Both guest kernel and user run in ring 3 and the
  89  * hypervisor runs in ring 0. When the kernel creates its trap and
  90  * interrupt gates it needs a way to prevent any arbitrary int $n
  91  * instruction from entering a gate that is not expected. The hypervisor
  92  * allows these gates to have a DPL from 1 to 3. By creating gates
  93  * with a DPL below user (ring 3) the int $n will generate a #gp fault
  94  * which the hypervisor catches and forwards to the guest.
  95  */
  96 #if defined(__xpv)
  97 
  98 #if defined(__amd64)
  99 
 100 #define SEL_XPL         0               /* hypervisor privilege level */
 101 #define SEL_KPL         3               /* both kernel and user in ring 3 */
 102 #define TRP_KPL         1               /* system gate priv (user blocked) */
 103 
 104 #elif defined(__i386)
 105 
 106 #define SEL_XPL         0               /* hypervisor privilege level */
 107 #define SEL_KPL         1               /* kernel privilege level */
 108 #define TRP_KPL         SEL_KPL         /* system gate priv (user blocked) */
 109 
 110 #endif  /* __i386 */
 111 
 112 #define TRP_XPL         0               /* system gate priv (hypervisor) */
 113 
 114 #else   /* __xpv */
 115 
 116 #define SEL_KPL         0               /* kernel privilege level on metal */
 117 #define TRP_KPL         SEL_KPL         /* system gate priv (user blocked) */
 118 
 119 #endif  /* __xpv */
 120 
 121 #define SEL_UPL         3               /* user priority level */
 122 #define TRP_UPL         3               /* system gate priv (user allowed) */
 123 #define SEL_TI_LDT      4               /* local descriptor table */
 124 #define SEL_LDT(s)      (IDXTOSEL(s) | SEL_TI_LDT | SEL_UPL)    /* local sel */
 125 #define CPL_MASK        3               /* RPL mask for selector */
 126 #define SELISLDT(s)     (((s) & SEL_TI_LDT) == SEL_TI_LDT)
 127 #define SELISUPL(s)     (((s) & CPL_MASK) == SEL_UPL)
 128 
 129 #ifndef _ASM
 130 
 131 typedef uint16_t        selector_t;     /* selector reigster */
 132 
 133 /*
 134  * Hardware descriptor table register format for GDT and IDT.
 135  */
 136 #if defined(__amd64)
 137 
 138 #pragma pack(2)
 139 typedef struct {
 140         uint16_t dtr_limit;     /* table limit */
 141         uint64_t dtr_base;      /* table base address  */
 142 } desctbr_t;
 143 #pragma pack()
 144 
 145 #elif defined(__i386)
 146 
 147 #pragma pack(2)
 148 typedef struct {
 149         uint16_t dtr_limit;     /* table limit */
 150         uint32_t dtr_base;      /* table base address  */
 151 } desctbr_t;
 152 #pragma pack()
 153 
 154 #endif  /* __i386 */
 155 
 156 /*
 157  * Functions for loading and storing descriptor table
 158  * registers.
 159  */
 160 extern void rd_idtr(desctbr_t *);
 161 extern void wr_idtr(desctbr_t *);
 162 extern void rd_gdtr(desctbr_t *);
 163 extern void wr_gdtr(desctbr_t *);
 164 extern void wr_ldtr(selector_t);
 165 extern selector_t rd_ldtr(void);
 166 extern void wr_tsr(selector_t);
 167 extern void kmdb_enter(void);
 168 
 169 #if defined(__amd64)
 170 
 171 /*
 172  * inlines for update_segregs
 173  */
 174 extern void __set_ds(selector_t);
 175 extern void __set_es(selector_t);
 176 extern void __set_fs(selector_t);
 177 extern void __set_gs(selector_t);
 178 extern void __swapgs(void);
 179 #endif  /* __amd64 */
 180 
 181 #if defined(__amd64)
 182 extern void load_segment_registers(selector_t, selector_t, selector_t,
 183     selector_t);        /* (alphabetical) */
 184 #elif defined(__i386)
 185 extern void load_segment_registers(selector_t, selector_t, selector_t,
 186     selector_t, selector_t, selector_t);        /* (alphabetical) */
 187 #endif  /* __i386 */
 188 
 189 selector_t get_cs_register();
 190 
 191 #if !defined(__amd64)
 192 
 193 /*
 194  * User segment descriptors (code and data).
 195  * Legacy mode 64-bits wide.
 196  */
 197 typedef struct user_desc {
 198         uint32_t usd_lolimit:16;        /* segment limit 15:0 */
 199         uint32_t usd_lobase:16;         /* segment base 15:0 */
 200         uint32_t usd_midbase:8;         /* segment base 23:16 */
 201         uint32_t usd_type:5;            /* segment type, includes S bit */
 202         uint32_t usd_dpl:2;             /* segment descriptor priority level */
 203         uint32_t usd_p:1;               /* segment descriptor present */
 204         uint32_t usd_hilimit:4;         /* segment limit 19:16 */
 205         uint32_t usd_avl:1;             /* available to sw, but not used */
 206         uint32_t usd_reserved:1;        /* unused, ignored */
 207         uint32_t usd_def32:1;           /* default 32 vs 16 bit operand */
 208         uint32_t usd_gran:1;            /* limit units (bytes vs pages) */
 209         uint32_t usd_hibase:8;          /* segment base 31:24 */
 210 } user_desc_t;
 211 
 212 #define USEGD_GETBASE(usd)              ((usd)->usd_lobase |         \
 213                                         (usd)->usd_midbase << 16 |     \
 214                                         (usd)->usd_hibase << (16 + 8))
 215 
 216 #define USEGD_SETBASE(usd, b)           ((usd)->usd_lobase = (b),    \
 217                                         (usd)->usd_midbase = (b) >> 16, \
 218                                         (usd)->usd_hibase = (b) >> (16 + 8))
 219 
 220 #define USEGD_GETLIMIT(usd)             ((usd)->usd_lolimit |                \
 221                                         (usd)->usd_hilimit << 16)
 222 
 223 #define USEGD_SETLIMIT(usd, lim)        ((usd)->usd_lolimit = lim,   \
 224                                         (usd)->usd_hilimit = lim >> 16)
 225 
 226 #define USD_TYPESHIFT                   5       /* size of usd_type field */
 227 
 228 #else   /* __amd64 */
 229 
 230 /*
 231  * User segment descriptors.
 232  * Long mode 64-bits wide.
 233  *
 234  * In 32-bit compatibility mode (%cs:usd_long=0) all fields are interpreted
 235  * as in legacy mode for both code and data.
 236  *
 237  * In 64-bit mode (%cs:usd_long=1) code segments only have the conforming
 238  * bit in usd_type, usd_dpl, usd_p, usd_long and usd_def32=0. usd_def32
 239  * must be zero in 64-bit mode. Setting it to 1 is reserved for future use.
 240  * All other fields are loaded but ignored by hardware.
 241  *
 242  * 64-bit data segments only have usd_p. All other fields are loaded but
 243  * ignored by hardware when in 64-bit mode.
 244  */
 245 typedef struct user_desc {
 246         uint64_t usd_lolimit:16;        /* segment limit 15:0 */
 247         uint64_t usd_lobase:16;         /* segment base 15:0 */
 248         uint64_t usd_midbase:8;         /* segment base 23:16 */
 249         uint64_t usd_type:5;            /* segment type, includes S bit */
 250         uint64_t usd_dpl:2;             /* segment descriptor priority level */
 251         uint64_t usd_p:1;               /* segment descriptor present */
 252         uint64_t usd_hilimit:4;         /* segment limit 19:16 */
 253         uint64_t usd_avl:1;             /* available to sw, but not used */
 254         uint64_t usd_long:1;            /* long mode (%cs only) */
 255         uint64_t usd_def32:1;           /* default 32 vs 16 bit operand */
 256         uint64_t usd_gran:1;            /* limit units (bytes vs page) */
 257         uint64_t usd_hibase:8;          /* segment base 31:24 */
 258 } user_desc_t;
 259 
 260 #define USEGD_GETBASE(usd)              ((usd)->usd_lobase |         \
 261                                         (usd)->usd_midbase << 16 |     \
 262                                         (usd)->usd_hibase << (16 + 8))
 263 
 264 #define USEGD_SETBASE(usd, b)           ((usd)->usd_lobase = (b),    \
 265                                         (usd)->usd_midbase = (b) >> 16, \
 266                                         (usd)->usd_hibase = (b) >> (16 + 8))
 267 
 268 #define USEGD_GETLIMIT(usd)             ((usd)->usd_lolimit |                \
 269                                         (usd)->usd_hilimit << 16)
 270 
 271 #define USEGD_SETLIMIT(usd, lim)        ((usd)->usd_lolimit = lim,   \
 272                                         (usd)->usd_hilimit = lim >> 16)
 273 
 274 #define USD_TYPESHIFT                   5       /* size of usd_type field */
 275 
 276 #endif /* __amd64 */
 277 
 278 #if !defined(__amd64)
 279 
 280 /*
 281  * System segment descriptors for LDT and TSS segments.
 282  * Legacy mode 64-bits wide.
 283  */
 284 typedef struct system_desc {
 285         uint32_t ssd_lolimit:16;        /* segment limit 15:0 */
 286         uint32_t ssd_lobase:16;         /* segment base 15:0 */
 287         uint32_t ssd_midbase:8;         /* segment base 23:16 */
 288         uint32_t ssd_type:4;            /* segment type */
 289         uint32_t ssd_zero:1;            /* must be zero */
 290         uint32_t ssd_dpl:2;             /* segment descriptor priority level */
 291         uint32_t ssd_p:1;               /* segment descriptor present */
 292         uint32_t ssd_hilimit:4;         /* segment limit 19:16 */
 293         uint32_t ssd_avl:1;             /* available to sw, but not used */
 294         uint32_t ssd_reserved:2;        /* unused, ignored */
 295         uint32_t ssd_gran:1;            /* limit unit (bytes vs pages) */
 296         uint32_t ssd_hibase:8;          /* segment base 31:24 */
 297 } system_desc_t;
 298 
 299 #else   /* __amd64 */
 300 
 301 /*
 302  * System segment descriptors for LDT and TSS segments.
 303  * Long mode 128-bits wide.
 304  *
 305  * 32-bit LDT and TSS descriptor types are redefined to 64-bit equivalents.
 306  * All other legacy types are reserved and illegal.
 307  */
 308 typedef struct system_desc {
 309         uint64_t ssd_lolimit:16;        /* segment limit 15:0 */
 310         uint64_t ssd_lobase:16;         /* segment base 15:0 */
 311         uint64_t ssd_midbase:8;         /* segment base 23:16 */
 312         uint64_t ssd_type:4;            /* segment type */
 313         uint64_t ssd_zero1:1;           /* must be zero */
 314         uint64_t ssd_dpl:2;             /* segment descriptor priority level */
 315         uint64_t ssd_p:1;               /* segment descriptor present */
 316         uint64_t ssd_hilimit:4;         /* segment limit 19:16 */
 317         uint64_t ssd_avl:1;             /* available to sw, but not used */
 318         uint64_t ssd_resv1:2;           /* unused, ignored */
 319         uint64_t ssd_gran:1;            /* limit unit (bytes vs pages) */
 320         uint64_t ssd_hibase:8;          /* segment base 31:24 */
 321         uint64_t ssd_hi64base:32;       /* segment base 63:32 */
 322         uint64_t ssd_resv2:8;           /* unused, ignored */
 323         uint64_t ssd_zero2:5;           /* must be zero */
 324         uint64_t ssd_resv3:19;          /* unused, ignored */
 325 } system_desc_t;
 326 
 327 #endif  /* __amd64 */
 328 
 329 #define SYSSEGD_SETLIMIT(ssd, lim)      ((ssd)->ssd_lolimit = lim,   \
 330                                         (ssd)->ssd_hilimit = lim >> 16)
 331 
 332 #define SYSSEGD_GETLIMIT(ssd)           (((ssd)->ssd_hilimit << 16) |   \
 333                                         (ssd)->ssd_lolimit)
 334 
 335 #if !defined(__amd64)
 336 
 337 /*
 338  * System gate segment descriptors for interrupt, trap, call and task gates.
 339  * Legacy mode 64-bits wide.
 340  */
 341 typedef struct gate_desc {
 342         uint32_t sgd_looffset:16;       /* segment code offset 15:0 */
 343         uint32_t sgd_selector:16;       /* target code or task selector */
 344         uint32_t sgd_stkcpy:5;          /* number of stack wds to cpy */
 345         uint32_t sgd_resv:3;            /* unused, ignored */
 346         uint32_t sgd_type:5;            /* segment type, includes S bit */
 347         uint32_t sgd_dpl:2;             /* segment descriptor priority level */
 348         uint32_t sgd_p:1;               /* segment descriptor present */
 349         uint32_t sgd_hioffset:16;       /* code seg off 31:16 */
 350 } gate_desc_t;
 351 
 352 #define GATESEG_GETOFFSET(sgd)          ((sgd)->sgd_looffset |               \
 353                                         (sgd)->sgd_hioffset << 16)
 354 
 355 #else   /* __amd64 */
 356 
 357 /*
 358  * System segment descriptors for interrupt, trap and call gates.
 359  * Long mode 128-bits wide.
 360  *
 361  * 32-bit interrupt, trap and call gate types are redefined to 64-bit
 362  * equivalents. Task gates along with all other legacy types are reserved
 363  * and illegal.
 364  */
 365 typedef struct gate_desc {
 366         uint64_t sgd_looffset:16;       /* segment code offset 15:0 */
 367         uint64_t sgd_selector:16;       /* target code or task selector */
 368         uint64_t sgd_ist:3;             /* IST table index */
 369         uint64_t sgd_resv1:5;           /* unused, ignored */
 370         uint64_t sgd_type:5;            /* segment type, includes S bit */
 371         uint64_t sgd_dpl:2;             /* segment descriptor priority level */
 372         uint64_t sgd_p:1;               /* segment descriptor present */
 373         uint64_t sgd_hioffset:16;       /* segment code offset 31:16 */
 374         uint64_t sgd_hi64offset:32;     /* segment code offset 63:32 */
 375         uint64_t sgd_resv2:8;           /* unused, ignored */
 376         uint64_t sgd_zero:5;            /* call gate only: must be zero */
 377         uint64_t sgd_resv3:19;          /* unused, ignored */
 378 } gate_desc_t;
 379 
 380 #define GATESEG_GETOFFSET(sgd)          ((sgd)->sgd_looffset |               \
 381                                         (sgd)->sgd_hioffset << 16 |    \
 382                                         (sgd)->sgd_hi64offset << 32)
 383 
 384 #endif  /* __amd64 */
 385 
 386 /*
 387  * functions for initializing and updating segment descriptors.
 388  */
 389 #if defined(__amd64)
 390 
 391 extern void set_usegd(user_desc_t *, uint_t, void *, size_t, uint_t, uint_t,
 392     uint_t, uint_t);
 393 
 394 #elif defined(__i386)
 395 
 396 extern void set_usegd(user_desc_t *, void *, size_t, uint_t, uint_t,
 397     uint_t, uint_t);
 398 
 399 #endif  /* __i386 */
 400 
 401 extern void set_gatesegd(gate_desc_t *, void (*)(void), selector_t,
 402     uint_t, uint_t, uint_t);
 403 
 404 extern void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t);
 405 
 406 extern void *get_ssd_base(system_desc_t *);
 407 
 408 extern void gdt_update_usegd(uint_t, user_desc_t *);
 409 
 410 extern int ldt_update_segd(user_desc_t *, user_desc_t *);
 411 
 412 #if defined(__xpv)
 413 
 414 extern int xen_idt_to_trap_info(uint_t, gate_desc_t *, void *);
 415 extern void xen_idt_write(gate_desc_t *, uint_t);
 416 
 417 #endif  /* __xen */
 418 
 419 void init_boot_gdt(user_desc_t *);
 420 
 421 #endif  /* _ASM */
 422 
 423 /*
 424  * Common segment parameter defintions for granularity, default
 425  * operand size and operaton mode.
 426  */
 427 #define SDP_BYTES       0       /* segment limit scaled to bytes */
 428 #define SDP_PAGES       1       /* segment limit scaled to pages */
 429 #define SDP_OP32        1       /* code and data default operand = 32 bits */
 430 #define SDP_LONG        1       /* long mode code segment (64 bits) */
 431 #define SDP_SHORT       0       /* compat/legacy code segment (32 bits) */
 432 /*
 433  * System segments and gate types.
 434  *
 435  * In long mode i386 32-bit ldt, tss, call, interrupt and trap gate
 436  * types are redefined into 64-bit equivalents.
 437  */
 438 #define SDT_SYSNULL      0      /* system null */
 439 #define SDT_SYS286TSS    1      /* system 286 TSS available */
 440 #define SDT_SYSLDT       2      /* system local descriptor table */
 441 #define SDT_SYS286BSY    3      /* system 286 TSS busy */
 442 #define SDT_SYS286CGT    4      /* system 286 call gate */
 443 #define SDT_SYSTASKGT    5      /* system task gate */
 444 #define SDT_SYS286IGT    6      /* system 286 interrupt gate */
 445 #define SDT_SYS286TGT    7      /* system 286 trap gate */
 446 #define SDT_SYSNULL2     8      /* system null again */
 447 #define SDT_SYSTSS       9      /* system TSS available */
 448 #define SDT_SYSNULL3    10      /* system null again */
 449 #define SDT_SYSTSSBSY   11      /* system TSS busy */
 450 #define SDT_SYSCGT      12      /* system call gate */
 451 #define SDT_SYSNULL4    13      /* system null again */
 452 #define SDT_SYSIGT      14      /* system interrupt gate */
 453 #define SDT_SYSTGT      15      /* system trap gate */
 454 
 455 /*
 456  * Memory segment types.
 457  *
 458  * While in long mode expand-down, writable and accessed type field
 459  * attributes are ignored. Only the conforming bit is loaded by hardware
 460  * for long mode code segment descriptors.
 461  */
 462 #define SDT_MEMRO       16      /* read only */
 463 #define SDT_MEMROA      17      /* read only accessed */
 464 #define SDT_MEMRW       18      /* read write */
 465 #define SDT_MEMRWA      19      /* read write accessed */
 466 #define SDT_MEMROD      20      /* read only expand dwn limit */
 467 #define SDT_MEMRODA     21      /* read only expand dwn limit accessed */
 468 #define SDT_MEMRWD      22      /* read write expand dwn limit */
 469 #define SDT_MEMRWDA     23      /* read write expand dwn limit accessed */
 470 #define SDT_MEME        24      /* execute only */
 471 #define SDT_MEMEA       25      /* execute only accessed */
 472 #define SDT_MEMER       26      /* execute read */
 473 #define SDT_MEMERA      27      /* execute read accessed */
 474 #define SDT_MEMEC       28      /* execute only conforming */
 475 #define SDT_MEMEAC      29      /* execute only accessed conforming */
 476 #define SDT_MEMERC      30      /* execute read conforming */
 477 #define SDT_MEMERAC     31      /* execute read accessed conforming */
 478 
 479 /*
 480  * Entries in the Interrupt Descriptor Table (IDT)
 481  */
 482 #define IDT_DE          0       /* #DE: Divide Error */
 483 #define IDT_DB          1       /* #DB: Debug */
 484 #define IDT_NMI         2       /* Nonmaskable External Interrupt */
 485 #define IDT_BP          3       /* #BP: Breakpoint */
 486 #define IDT_OF          4       /* #OF: Overflow */
 487 #define IDT_BR          5       /* #BR: Bound Range Exceeded */
 488 #define IDT_UD          6       /* #UD: Undefined/Invalid Opcode */
 489 #define IDT_NM          7       /* #NM: No Math Coprocessor */
 490 #define IDT_DF          8       /* #DF: Double Fault */
 491 #define IDT_FPUGP       9       /* Coprocessor Segment Overrun */
 492 #define IDT_TS          10      /* #TS: Invalid TSS */
 493 #define IDT_NP          11      /* #NP: Segment Not Present */
 494 #define IDT_SS          12      /* #SS: Stack Segment Fault */
 495 #define IDT_GP          13      /* #GP: General Protection Fault */
 496 #define IDT_PF          14      /* #PF: Page Fault */
 497 #define IDT_MF          16      /* #MF: FPU Floating-Point Error */
 498 #define IDT_AC          17      /* #AC: Alignment Check */
 499 #define IDT_MC          18      /* #MC: Machine Check */
 500 #define IDT_XF          19      /* #XF: SIMD Floating-Point Exception */
 501 #define NIDT            256     /* size in entries of IDT */
 502 
 503 /*
 504  * Entries in the Global Descriptor Table (GDT)
 505  *
 506  * We make sure to space the system descriptors (LDT's, TSS')
 507  * such that they are double gdt slot aligned. This is because
 508  * in long mode system segment decriptors expand to 128 bits.
 509  *
 510  * GDT_LWPFS and GDT_LWPGS must be the same for both 32 and 64-bit
 511  * kernels. See setup_context in libc. 64-bit processes must set
 512  * %fs or %gs to null selector to use 64-bit fsbase or gsbase
 513  * respectively.
 514  */
 515 #define GDT_NULL        0       /* null */
 516 #define GDT_B32DATA     1       /* dboot 32 bit data descriptor */
 517 #define GDT_B32CODE     2       /* dboot 32 bit code descriptor */
 518 #define GDT_B16CODE     3       /* bios call 16 bit code descriptor */
 519 #define GDT_B16DATA     4       /* bios call 16 bit data descriptor */
 520 #define GDT_B64CODE     5       /* dboot 64 bit code descriptor */
 521 #define GDT_BGSTMP      7       /* kmdb descriptor only used early in boot */
 522 
 523 #if defined(__amd64)
 524 
 525 #define GDT_KCODE       6       /* kernel code seg %cs */
 526 #define GDT_KDATA       7       /* kernel data seg %ds */
 527 #define GDT_U32CODE     8       /* 32-bit process on 64-bit kernel %cs */
 528 #define GDT_UDATA       9       /* user data seg %ds (32 and 64 bit) */
 529 #define GDT_UCODE       10      /* native user code  seg %cs */
 530 #define GDT_LDT         12      /* LDT for current process */
 531 #define GDT_KTSS        14      /* kernel tss */
 532 #define GDT_FS          GDT_NULL /* kernel %fs segment selector */
 533 #define GDT_GS          GDT_NULL /* kernel %gs segment selector */
 534 #define GDT_LWPFS       55      /* lwp private %fs segment selector (32-bit) */
 535 #define GDT_LWPGS       56      /* lwp private %gs segment selector (32-bit) */
 536 #define GDT_BRANDMIN    57      /* first entry in GDT for brand usage */
 537 #define GDT_BRANDMAX    61      /* last entry in GDT for brand usage */
 538 #define NGDT            62      /* number of entries in GDT */
 539 
 540 /*
 541  * This selector is only used in the temporary GDT used to bring additional
 542  * CPUs from 16-bit real mode into long mode in real_mode_start().
 543  */
 544 #define TEMPGDT_KCODE64 1       /* 64-bit code selector */
 545 
 546 #elif defined(__i386)
 547 
 548 #define GDT_LDT         40      /* LDT for current process */
 549 #define GDT_KTSS        42      /* kernel tss */
 550 #define GDT_KCODE       43      /* kernel code seg %cs */
 551 #define GDT_KDATA       44      /* kernel data seg %ds */
 552 #define GDT_UCODE       45      /* native user code  seg %cs */
 553 #define GDT_UDATA       46      /* user data seg %ds (32 and 64 bit) */
 554 #define GDT_DBFLT       47      /* double fault #DF selector */
 555 #define GDT_FS          53      /* kernel %fs segment selector */
 556 #define GDT_GS          54      /* kernel %gs segment selector */
 557 #define GDT_LWPFS       55      /* lwp private %fs segment selector */
 558 #define GDT_LWPGS       56      /* lwp private %gs segment selector */
 559 #define GDT_BRANDMIN    57      /* first entry in GDT for brand usage */
 560 #define GDT_BRANDMAX    61      /* last entry in GDT for brand usage */
 561 #if !defined(__xpv)
 562 #define NGDT            90      /* number of entries in GDT */
 563 #else
 564 #define NGDT            512     /* single 4K page for the hypervisor */
 565 #endif
 566 
 567 #endif  /* __i386 */
 568 
 569 /*
 570  * Convenient selector definitions.
 571  */
 572 
 573 /*
 574  * XXPV 64 bit Xen only allows the guest %cs/%ss be the private ones it
 575  * provides, not the ones we create for ourselves.  See FLAT_RING3_CS64 in
 576  * public/arch-x86_64.h
 577  *
 578  * 64-bit Xen runs paravirtual guests in ring 3 but emulates them running in
 579  * ring 0 by clearing CPL in %cs value pushed on guest exception stacks.
 580  * Therefore we will have KCS_SEL value indicate ring 0 and use that everywhere
 581  * in the kernel. But in the few files where we initialize segment registers or
 582  * create and update descriptors we will explicity OR in SEL_KPL (ring 3) for
 583  * kernel %cs. See desctbls.c for an example.
 584  */
 585 
 586 #if defined(__xpv) && defined(__amd64)
 587 #define KCS_SEL         0xe030          /* FLAT_RING3_CS64 & 0xFFF0 */
 588 #define KDS_SEL         0xe02b          /* FLAT_RING3_SS64 */
 589 #else
 590 #define KCS_SEL         SEL_GDT(GDT_KCODE, SEL_KPL)
 591 #define KDS_SEL         SEL_GDT(GDT_KDATA, SEL_KPL)
 592 #endif
 593 
 594 #define UCS_SEL         SEL_GDT(GDT_UCODE, SEL_UPL)
 595 #if defined(__amd64)
 596 #define TEMP_CS64_SEL   SEL_GDT(TEMPGDT_KCODE64, SEL_KPL)
 597 #define U32CS_SEL       SEL_GDT(GDT_U32CODE, SEL_UPL)
 598 #endif
 599 
 600 #define UDS_SEL         SEL_GDT(GDT_UDATA, SEL_UPL)
 601 #define ULDT_SEL        SEL_GDT(GDT_LDT, SEL_KPL)
 602 #define KTSS_SEL        SEL_GDT(GDT_KTSS, SEL_KPL)
 603 #define DFTSS_SEL       SEL_GDT(GDT_DBFLT, SEL_KPL)
 604 #define KFS_SEL         0
 605 #define KGS_SEL         SEL_GDT(GDT_GS, SEL_KPL)
 606 #define LWPFS_SEL       SEL_GDT(GDT_LWPFS, SEL_UPL)
 607 #define LWPGS_SEL       SEL_GDT(GDT_LWPGS, SEL_UPL)
 608 #define BRANDMIN_SEL    SEL_GDT(GDT_BRANDMIN, SEL_UPL)
 609 #define BRANDMAX_SEL    SEL_GDT(GDT_BRANDMAX, SEL_UPL)
 610 
 611 #define B64CODE_SEL     SEL_GDT(GDT_B64CODE, SEL_KPL)
 612 #define B32CODE_SEL     SEL_GDT(GDT_B32CODE, SEL_KPL)
 613 #define B32DATA_SEL     SEL_GDT(GDT_B32DATA, SEL_KPL)
 614 #define B16CODE_SEL     SEL_GDT(GDT_B16CODE, SEL_KPL)
 615 #define B16DATA_SEL     SEL_GDT(GDT_B16DATA, SEL_KPL)
 616 
 617 /*
 618  * Temporary %gs descriptor used by kmdb with -d option. Only lives
 619  * in boot's GDT and is not copied into kernel's GDT from boot.
 620  */
 621 #define KMDBGS_SEL      SEL_GDT(GDT_BGSTMP, SEL_KPL)
 622 
 623 /*
 624  * Selector used for kdi_idt when kmdb has taken over the IDT.
 625  */
 626 #if defined(__amd64)
 627 #define KMDBCODE_SEL    B64CODE_SEL
 628 #else
 629 #define KMDBCODE_SEL    B32CODE_SEL
 630 #endif
 631 
 632 /*
 633  * Entries in default Local Descriptor Table (LDT) for every process.
 634  */
 635 #define LDT_SYSCALL     0       /* call gate for libc.a (obsolete) */
 636 #define LDT_SIGCALL     1       /* EOL me, call gate for static sigreturn */
 637 #define LDT_RESVD1      2       /* old user %cs */
 638 #define LDT_RESVD2      3       /* old user %ds */
 639 #define LDT_ALTSYSCALL  4       /* alternate call gate for system calls */
 640 #define LDT_ALTSIGCALL  5       /* EOL me, alternate call gate for sigreturn */
 641 #define LDT_UDBASE      6       /* user descriptor base index */
 642 #define MINNLDT         512     /* Current min solaris ldt size (1 4K page) */
 643 #define MAXNLDT         8192    /* max solaris ldt size (16 4K pages) */
 644 
 645 #ifndef _ASM
 646 
 647 extern  gate_desc_t     *idt0;
 648 extern  desctbr_t       idt0_default_reg;
 649 extern  user_desc_t     *gdt0;
 650 
 651 extern user_desc_t      zero_udesc;
 652 extern user_desc_t      null_udesc;
 653 extern system_desc_t    null_sdesc;
 654 
 655 #if defined(__amd64)
 656 extern user_desc_t      zero_u32desc;
 657 #endif
 658 #if defined(__amd64)
 659 extern user_desc_t      ucs_on;
 660 extern user_desc_t      ucs_off;
 661 extern user_desc_t      ucs32_on;
 662 extern user_desc_t      ucs32_off;
 663 #endif  /* __amd64 */
 664 
 665 extern struct tss *ktss0;
 666 
 667 #if defined(__i386)
 668 extern struct tss *dftss0;
 669 #endif  /* __i386 */
 670 
 671 extern void div0trap(), dbgtrap(), nmiint(), brktrap(), ovflotrap();
 672 extern void boundstrap(), invoptrap(), ndptrap();
 673 #if !defined(__xpv)
 674 extern void syserrtrap();
 675 #endif
 676 extern void invaltrap(), invtsstrap(), segnptrap(), stktrap();
 677 extern void gptrap(), pftrap(), ndperr();
 678 extern void overrun(), resvtrap();
 679 extern void _start(), cmnint();
 680 extern void achktrap(), mcetrap();
 681 extern void xmtrap();
 682 extern void fasttrap();
 683 extern void dtrace_ret();
 684 
 685 #if !defined(__amd64)
 686 extern void pentium_pftrap();
 687 #endif
 688 
 689 #endif /* _ASM */
 690 
 691 #ifdef  __cplusplus
 692 }
 693 #endif
 694 
 695 #endif /* _SYS_SEGMENTS_H */