Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
   1 /*
   2  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Copyright 2016 Joyent, Inc.
   6  */
   7 
   8 #ifndef _SYS_SEGMENTS_H
   9 #define _SYS_SEGMENTS_H
  10 
  11 #ifdef  __cplusplus
  12 extern "C" {
  13 #endif
  14 
  15 /*
  16  * Copyright (c) 1989, 1990 William F. Jolitz
  17  * Copyright (c) 1990 The Regents of the University of California.
  18  * All rights reserved.
  19  *
  20  * This code is derived from software contributed to Berkeley by
  21  * William Jolitz.
  22  *
  23  * Redistribution and use in source and binary forms, with or without
  24  * modification, are permitted provided that the following conditions
  25  * are met:


  81 
  82 #define SELTOIDX(s)     ((s) >> 3)        /* selector to index */
  83 
  84 /*
  85  * SEL_(KPL,UPL,XPL) is the RPL or DPL value for code and data selectors
  86  * and their descriptors respectively.
  87  *
  88  * TRP_(KPL,UPL,XPL) is used to indicate the DPL for system gates only.
  89  *
  90  * This distinction is important to support para-virt guests on the
  91  * 64-bit hypervisor. Both guest kernel and user run in ring 3 and the
  92  * hypervisor runs in ring 0. When the kernel creates its trap and
  93  * interrupt gates it needs a way to prevent any arbitrary int $n
  94  * instruction from entering a gate that is not expected. The hypervisor
  95  * allows these gates to have a DPL from 1 to 3. By creating gates
  96  * with a DPL below user (ring 3) the int $n will generate a #gp fault
  97  * which the hypervisor catches and forwards to the guest.
  98  */
  99 #if defined(__xpv)
 100 
 101 #if defined(__amd64)
 102 
 103 #define SEL_XPL         0               /* hypervisor privilege level */
 104 #define SEL_KPL         3               /* both kernel and user in ring 3 */
 105 #define TRP_KPL         1               /* system gate priv (user blocked) */
 106 
 107 #elif defined(__i386)
 108 
 109 #define SEL_XPL         0               /* hypervisor privilege level */
 110 #define SEL_KPL         1               /* kernel privilege level */
 111 #define TRP_KPL         SEL_KPL         /* system gate priv (user blocked) */
 112 
 113 #endif  /* __i386 */
 114 
 115 #define TRP_XPL         0               /* system gate priv (hypervisor) */
 116 


 117 #else   /* __xpv */
 118 
 119 #define SEL_KPL         0               /* kernel privilege level on metal */
 120 #define TRP_KPL         SEL_KPL         /* system gate priv (user blocked) */
 121 








 122 #endif  /* __xpv */
 123 


 124 #define SEL_UPL         3               /* user priority level */
 125 #define TRP_UPL         3               /* system gate priv (user allowed) */
 126 #define SEL_TI_LDT      4               /* local descriptor table */
 127 #define SEL_LDT(s)      (IDXTOSEL(s) | SEL_TI_LDT | SEL_UPL)    /* local sel */
 128 #define CPL_MASK        3               /* RPL mask for selector */
 129 #define SELISLDT(s)     (((s) & SEL_TI_LDT) == SEL_TI_LDT)
 130 #define SELISUPL(s)     (((s) & CPL_MASK) == SEL_UPL)
 131 
 132 #ifndef _ASM
 133 
 134 typedef uint16_t        selector_t;     /* selector reigster */
 135 
 136 /*
 137  * Hardware descriptor table register format for GDT and IDT.
 138  */
 139 #if defined(__amd64)
 140 
 141 #pragma pack(2)
 142 typedef struct {
 143         uint16_t dtr_limit;     /* table limit */


 384                                 (sgd)->sgd_hioffset << 16 |            \
 385                                 (uint64_t)((sgd)->sgd_hi64offset) << 32))
 386 
 387 #endif  /* __amd64 */
 388 
 389 /*
 390  * functions for initializing and updating segment descriptors.
 391  */
 392 #if defined(__amd64)
 393 
 394 extern void set_usegd(user_desc_t *, uint_t, void *, size_t, uint_t, uint_t,
 395     uint_t, uint_t);
 396 
 397 #elif defined(__i386)
 398 
 399 extern void set_usegd(user_desc_t *, void *, size_t, uint_t, uint_t,
 400     uint_t, uint_t);
 401 
 402 #endif  /* __i386 */
 403 


 404 extern void set_gatesegd(gate_desc_t *, void (*)(void), selector_t,
 405     uint_t, uint_t, uint_t);
 406 
 407 extern void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t);
 408 
 409 extern void *get_ssd_base(system_desc_t *);
 410 
 411 extern void gdt_update_usegd(uint_t, user_desc_t *);
 412 
 413 extern int ldt_update_segd(user_desc_t *, user_desc_t *);
 414 
 415 #if defined(__xpv)
 416 
 417 extern int xen_idt_to_trap_info(uint_t, gate_desc_t *, void *);
 418 extern void xen_idt_write(gate_desc_t *, uint_t);
 419 
 420 #endif  /* __xen */
 421 
 422 void init_boot_gdt(user_desc_t *);
 423 


 629  */
 630 #if defined(__amd64)
 631 #define KMDBCODE_SEL    B64CODE_SEL
 632 #else
 633 #define KMDBCODE_SEL    B32CODE_SEL
 634 #endif
 635 
 636 /*
 637  * Entries in default Local Descriptor Table (LDT) for every process.
 638  */
 639 #define LDT_SYSCALL     0       /* call gate for libc.a (obsolete) */
 640 #define LDT_SIGCALL     1       /* EOL me, call gate for static sigreturn */
 641 #define LDT_RESVD1      2       /* old user %cs */
 642 #define LDT_RESVD2      3       /* old user %ds */
 643 #define LDT_ALTSYSCALL  4       /* alternate call gate for system calls */
 644 #define LDT_ALTSIGCALL  5       /* EOL me, alternate call gate for sigreturn */
 645 #define LDT_UDBASE      6       /* user descriptor base index */
 646 #define MINNLDT         512     /* Current min solaris ldt size (1 4K page) */
 647 #define MAXNLDT         8192    /* max solaris ldt size (16 4K pages) */
 648 




 649 #ifndef _ASM
 650 
 651 extern  gate_desc_t     *idt0;
 652 extern  desctbr_t       idt0_default_reg;
 653 extern  user_desc_t     *gdt0;
 654 
 655 extern user_desc_t      zero_udesc;
 656 extern user_desc_t      null_udesc;
 657 extern system_desc_t    null_sdesc;
 658 
 659 #if defined(__amd64)
 660 extern user_desc_t      zero_u32desc;
 661 #endif
 662 #if defined(__amd64)
 663 extern user_desc_t      ucs_on;
 664 extern user_desc_t      ucs_off;
 665 extern user_desc_t      ucs32_on;
 666 extern user_desc_t      ucs32_off;
 667 #endif  /* __amd64 */
 668 
 669 extern tss_t *ktss0;
 670 
 671 #if defined(__i386)
 672 extern tss_t *dftss0;
 673 #endif  /* __i386 */
 674 
 675 extern void div0trap(), dbgtrap(), nmiint(), brktrap(), ovflotrap();
 676 extern void boundstrap(), invoptrap(), ndptrap();
 677 #if !defined(__xpv)
 678 extern void syserrtrap();
 679 #endif
 680 extern void invaltrap(), invtsstrap(), segnptrap(), stktrap();
 681 extern void gptrap(), pftrap(), ndperr();
 682 extern void overrun(), resvtrap();
 683 extern void _start(), cmnint();
 684 extern void achktrap(), mcetrap();
 685 extern void xmtrap();
 686 extern void fasttrap();
 687 extern void dtrace_ret();
 688 















 689 #if !defined(__amd64)
 690 extern void pentium_pftrap();
 691 #endif
 692 


 693 #endif /* _ASM */
 694 
 695 #ifdef  __cplusplus
 696 }
 697 #endif
 698 
 699 #endif /* _SYS_SEGMENTS_H */
   1 /*
   2  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Copyright 2018 Joyent, Inc.
   6  */
   7 
   8 #ifndef _SYS_SEGMENTS_H
   9 #define _SYS_SEGMENTS_H
  10 
  11 #ifdef  __cplusplus
  12 extern "C" {
  13 #endif
  14 
  15 /*
  16  * Copyright (c) 1989, 1990 William F. Jolitz
  17  * Copyright (c) 1990 The Regents of the University of California.
  18  * All rights reserved.
  19  *
  20  * This code is derived from software contributed to Berkeley by
  21  * William Jolitz.
  22  *
  23  * Redistribution and use in source and binary forms, with or without
  24  * modification, are permitted provided that the following conditions
  25  * are met:


  81 
  82 #define SELTOIDX(s)     ((s) >> 3)        /* selector to index */
  83 
  84 /*
  85  * SEL_(KPL,UPL,XPL) is the RPL or DPL value for code and data selectors
  86  * and their descriptors respectively.
  87  *
  88  * TRP_(KPL,UPL,XPL) is used to indicate the DPL for system gates only.
  89  *
  90  * This distinction is important to support para-virt guests on the
  91  * 64-bit hypervisor. Both guest kernel and user run in ring 3 and the
  92  * hypervisor runs in ring 0. When the kernel creates its trap and
  93  * interrupt gates it needs a way to prevent any arbitrary int $n
  94  * instruction from entering a gate that is not expected. The hypervisor
  95  * allows these gates to have a DPL from 1 to 3. By creating gates
  96  * with a DPL below user (ring 3) the int $n will generate a #gp fault
  97  * which the hypervisor catches and forwards to the guest.
  98  */
  99 #if defined(__xpv)
 100 


 101 #define SEL_XPL         0               /* hypervisor privilege level */
 102 #define SEL_KPL         3               /* both kernel and user in ring 3 */
 103 #define TRP_KPL         1               /* system gate priv (user blocked) */









 104 #define TRP_XPL         0               /* system gate priv (hypervisor) */
 105 
 106 #define IST_DBG         0
 107 
 108 #else   /* __xpv */
 109 
 110 #define SEL_KPL         0               /* kernel privilege level on metal */
 111 #define TRP_KPL         SEL_KPL         /* system gate priv (user blocked) */
 112 
 113 
 114 #define IST_DF          1
 115 #define IST_NMI         2
 116 #define IST_MCE         3
 117 #define IST_DBG         4
 118 #define IST_NESTABLE    5
 119 #define IST_DEFAULT     6
 120 
 121 #endif  /* __xpv */
 122 
 123 #define IST_NONE        0
 124 
 125 #define SEL_UPL         3               /* user priority level */
 126 #define TRP_UPL         3               /* system gate priv (user allowed) */
 127 #define SEL_TI_LDT      4               /* local descriptor table */
 128 #define SEL_LDT(s)      (IDXTOSEL(s) | SEL_TI_LDT | SEL_UPL)    /* local sel */
 129 #define CPL_MASK        3               /* RPL mask for selector */
 130 #define SELISLDT(s)     (((s) & SEL_TI_LDT) == SEL_TI_LDT)
 131 #define SELISUPL(s)     (((s) & CPL_MASK) == SEL_UPL)
 132 
 133 #ifndef _ASM
 134 
 135 typedef uint16_t        selector_t;     /* selector reigster */
 136 
 137 /*
 138  * Hardware descriptor table register format for GDT and IDT.
 139  */
 140 #if defined(__amd64)
 141 
 142 #pragma pack(2)
 143 typedef struct {
 144         uint16_t dtr_limit;     /* table limit */


 385                                 (sgd)->sgd_hioffset << 16 |            \
 386                                 (uint64_t)((sgd)->sgd_hi64offset) << 32))
 387 
 388 #endif  /* __amd64 */
 389 
 390 /*
 391  * functions for initializing and updating segment descriptors.
 392  */
 393 #if defined(__amd64)
 394 
 395 extern void set_usegd(user_desc_t *, uint_t, void *, size_t, uint_t, uint_t,
 396     uint_t, uint_t);
 397 
 398 #elif defined(__i386)
 399 
 400 extern void set_usegd(user_desc_t *, void *, size_t, uint_t, uint_t,
 401     uint_t, uint_t);
 402 
 403 #endif  /* __i386 */
 404 
 405 extern uint_t idt_vector_to_ist(uint_t);
 406 
 407 extern void set_gatesegd(gate_desc_t *, void (*)(void), selector_t,
 408     uint_t, uint_t, uint_t);
 409 
 410 extern void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t);
 411 
 412 extern void *get_ssd_base(system_desc_t *);
 413 
 414 extern void gdt_update_usegd(uint_t, user_desc_t *);
 415 
 416 extern int ldt_update_segd(user_desc_t *, user_desc_t *);
 417 
 418 #if defined(__xpv)
 419 
 420 extern int xen_idt_to_trap_info(uint_t, gate_desc_t *, void *);
 421 extern void xen_idt_write(gate_desc_t *, uint_t);
 422 
 423 #endif  /* __xen */
 424 
 425 void init_boot_gdt(user_desc_t *);
 426 


 632  */
 633 #if defined(__amd64)
 634 #define KMDBCODE_SEL    B64CODE_SEL
 635 #else
 636 #define KMDBCODE_SEL    B32CODE_SEL
 637 #endif
 638 
 639 /*
 640  * Entries in default Local Descriptor Table (LDT) for every process.
 641  */
 642 #define LDT_SYSCALL     0       /* call gate for libc.a (obsolete) */
 643 #define LDT_SIGCALL     1       /* EOL me, call gate for static sigreturn */
 644 #define LDT_RESVD1      2       /* old user %cs */
 645 #define LDT_RESVD2      3       /* old user %ds */
 646 #define LDT_ALTSYSCALL  4       /* alternate call gate for system calls */
 647 #define LDT_ALTSIGCALL  5       /* EOL me, alternate call gate for sigreturn */
 648 #define LDT_UDBASE      6       /* user descriptor base index */
 649 #define MINNLDT         512     /* Current min solaris ldt size (1 4K page) */
 650 #define MAXNLDT         8192    /* max solaris ldt size (16 4K pages) */
 651 
 652 #ifdef _KERNEL
 653 #define LDT_CPU_SIZE    (16 * 4096)     /* Size of kernel per-CPU allocation */
 654 #endif
 655 
 656 #ifndef _ASM
 657 
 658 extern  gate_desc_t     *idt0;
 659 extern  desctbr_t       idt0_default_reg;
 660 extern  user_desc_t     *gdt0;
 661 
 662 extern user_desc_t      zero_udesc;
 663 extern user_desc_t      null_udesc;
 664 extern system_desc_t    null_sdesc;
 665 
 666 #if defined(__amd64)
 667 extern user_desc_t      zero_u32desc;
 668 #endif
 669 #if defined(__amd64)
 670 extern user_desc_t      ucs_on;
 671 extern user_desc_t      ucs_off;
 672 extern user_desc_t      ucs32_on;
 673 extern user_desc_t      ucs32_off;
 674 #endif  /* __amd64 */
 675 
 676 extern tss_t *ktss0;
 677 
 678 #if defined(__i386)
 679 extern tss_t *dftss0;
 680 #endif  /* __i386 */
 681 
 682 extern void div0trap(), dbgtrap(), nmiint(), brktrap(), ovflotrap();
 683 extern void boundstrap(), invoptrap(), ndptrap();
 684 #if !defined(__xpv)
 685 extern void syserrtrap();
 686 #endif
 687 extern void invaltrap(), invtsstrap(), segnptrap(), stktrap();
 688 extern void gptrap(), pftrap(), ndperr();
 689 extern void overrun(), resvtrap();
 690 extern void _start(), cmnint();
 691 extern void achktrap(), mcetrap();
 692 extern void xmtrap();
 693 extern void fasttrap();
 694 extern void dtrace_ret();
 695 
 696 /* KPTI trampolines */
 697 extern void tr_invaltrap();
 698 extern void tr_div0trap(), tr_dbgtrap(), tr_nmiint(), tr_brktrap();
 699 extern void tr_ovflotrap(), tr_boundstrap(), tr_invoptrap(), tr_ndptrap();
 700 #if !defined(__xpv)
 701 extern void tr_syserrtrap();
 702 #endif
 703 extern void tr_invaltrap(), tr_invtsstrap(), tr_segnptrap(), tr_stktrap();
 704 extern void tr_gptrap(), tr_pftrap(), tr_ndperr();
 705 extern void tr_overrun(), tr_resvtrap();
 706 extern void tr_achktrap(), tr_mcetrap();
 707 extern void tr_xmtrap();
 708 extern void tr_fasttrap();
 709 extern void tr_dtrace_ret();
 710 
 711 #if !defined(__amd64)
 712 extern void pentium_pftrap();
 713 #endif
 714 
 715 extern uint64_t kpti_enable;
 716 
 717 #endif /* _ASM */
 718 
 719 #ifdef  __cplusplus
 720 }
 721 #endif
 722 
 723 #endif /* _SYS_SEGMENTS_H */