Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
9210 remove KMDB branch debugging support
9211 ::crregs could do with cr2/cr3 support
9209 ::ttrace should be able to filter by thread
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/intel/kdi/kdi_idthdl.s
          +++ new/usr/src/uts/intel/kdi/kdi_idthdl.s
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
       24 + *
       25 + * Copyright 2018 Joyent, Inc.
  24   26   */
  25   27  
  26      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  27      -
  28   28  /*
  29      - * Companion to kdi_idt.c - the implementation of the trap and interrupt
       29 + * Companion to kdi_asm.s - the implementation of the trap and interrupt
  30   30   * handlers.  For the most part, these handlers do the same thing - they
  31   31   * push a trap number onto the stack, followed by a jump to kdi_cmnint.
  32   32   * Each trap and interrupt has its own handler because each one pushes a
  33   33   * different number.
  34   34   */
  35   35  
       36 +#if defined(__lint)
       37 +#include <sys/types.h>
       38 +#else
       39 +
  36   40  #include <sys/asm_linkage.h>
       41 +#include <sys/asm_misc.h>
       42 +#include <sys/machprivregs.h>
       43 +#include <sys/privregs.h>
  37   44  #include <sys/kdi_regs.h>
       45 +#include <sys/trap.h>
       46 +#include <sys/param.h>
  38   47  
  39      -/* Nothing in this file is of interest to lint. */
  40      -#if !defined(__lint)
       48 +#include <kdi_assym.h>
       49 +#include <assym.h>
  41   50  
  42      -/* 
  43      - * The default ASM_ENTRY_ALIGN (16) wastes far too much space.  Pay no
  44      - * attention to the fleet of nop's we're adding to each handler.
       51 +/*
       52 + * The default ASM_ENTRY_ALIGN (16) wastes far too much space.
  45   53   */
  46   54  #undef  ASM_ENTRY_ALIGN
  47   55  #define ASM_ENTRY_ALIGN 8
  48   56  
  49   57  /*
  50      - * We need the .align in ENTRY_NP (defined to be ASM_ENTRY_ALIGN) to match our
  51      - * manual .align (KDI_MSR_PATCHOFF) in order to ensure that the space reserved
  52      - * at the beginning of the handler for code is exactly KDI_MSR_PATCHOFF bytes
  53      - * long.  Note that the #error below isn't supported by the preprocessor invoked
  54      - * by as(1), and won't stop the build, but it'll emit a noticeable error message
  55      - * which won't escape the filters.
       58 + * Generic trap and interrupt handlers.
  56   59   */
  57      -#if ASM_ENTRY_ALIGN != KDI_MSR_PATCHOFF
  58      -#error "ASM_ENTRY_ALIGN != KDI_MSR_PATCHOFF"
  59      -this won't assemble
  60      -#endif
  61   60  
  62      -/*
  63      - * kdi_idt_patch will, on certain processors, replace the patch points below
  64      - * with MSR-clearing code.  kdi_id_patch has intimate knowledge of the size of
  65      - * the nop hole, as well as the structure of the handlers.  Do not change
  66      - * anything here without also changing kdi_idt_patch.
  67      - */
       61 +#if defined(__xpv)
  68   62  
  69      -/*
  70      - * Generic trap and interrupt handlers.
  71      - */
       63 +#define INTERRUPT_TRAMPOLINE
  72   64  
  73      -#if defined(__xpv) && defined(__amd64)
       65 +#else
  74   66  
  75   67  /*
  76      - * The hypervisor places r11 and rcx on the stack.
       68 + * If we're !xpv, then we will need to support KPTI (kernel page table
       69 + * isolation), where we have separate page tables for user and kernel modes.
       70 + * There's more detail about this in kpti_trampolines.s and hat_i86.c
  77   71   */
  78   72  
  79      -#define TRAP_NOERR(trapno) \
  80      -        popq    %rcx;           \
  81      -        popq    %r11;           \
  82      -        pushq   $trapno
       73 +#define INTERRUPT_TRAMPOLINE                    \
       74 +        pushq   %r13;                           \
       75 +        pushq   %r14;                           \
       76 +        subq    $KPTI_R14, %rsp;                \
       77 +        /* Check for clobbering */              \
       78 +        cmp     $0, KPTI_FLAG(%rsp);            \
       79 +        je      1f;                             \
       80 +        /* Don't worry, this totally works */   \
       81 +        int     $8;                             \
       82 +1:                                              \
       83 +        movq    $1, KPTI_FLAG(%rsp);            \
       84 +        /* Save current %cr3. */                \
       85 +        mov     %cr3, %r14;                     \
       86 +        mov     %r14, KPTI_TR_CR3(%rsp);        \
       87 +        /* Switch to paranoid %cr3. */          \
       88 +        mov     kpti_safe_cr3, %r14;            \
       89 +        mov     %r14, %cr3;                     \
       90 +                                                \
       91 +        cmpw    $KCS_SEL, KPTI_CS(%rsp);        \
       92 +        je      3f;                             \
       93 +2:                                              \
       94 +        /* Get our cpu_t in %r13 */             \
       95 +        mov     %rsp, %r13;                     \
       96 +        and     $(~(MMU_PAGESIZE - 1)), %r13;   \
       97 +        subq    $CPU_KPTI_START, %r13;          \
       98 +        /* Use top of the kthread stk */        \
       99 +        mov     CPU_THREAD(%r13), %r14;         \
      100 +        mov     T_STACK(%r14), %r14;            \
      101 +        addq    $REGSIZE+MINFRAME, %r14;        \
      102 +        jmp     5f;                             \
      103 +3:                                              \
      104 +        /* Check the %rsp in the frame. */      \
      105 +        /* Is it above kernel base? */          \
      106 +        mov     kpti_kbase, %r14;               \
      107 +        cmp     %r14, KPTI_RSP(%rsp);           \
      108 +        jb      2b;                             \
      109 +        /* Is it within the kpti_frame page? */ \
      110 +        mov     %rsp, %r13;                     \
      111 +        and     $(~(MMU_PAGESIZE - 1)), %r13;   \
      112 +        mov     KPTI_RSP(%rsp), %r14;           \
      113 +        and     $(~(MMU_PAGESIZE - 1)), %r14;   \
      114 +        cmp     %r13, %r14;                     \
      115 +        je      2b;                             \
      116 +        /* Use the %rsp from the trap frame. */ \
      117 +        /* We already did %cr3. */              \
      118 +        mov     KPTI_RSP(%rsp), %r14;           \
      119 +        and     $(~0xf), %r14;                  \
      120 +5:                                              \
      121 +        mov     %rsp, %r13;                     \
      122 +        /* %r14 contains our destination stk */ \
      123 +        mov     %r14, %rsp;                     \
      124 +        pushq   KPTI_SS(%r13);                  \
      125 +        pushq   KPTI_RSP(%r13);                 \
      126 +        pushq   KPTI_RFLAGS(%r13);              \
      127 +        pushq   KPTI_CS(%r13);                  \
      128 +        pushq   KPTI_RIP(%r13);                 \
      129 +        pushq   KPTI_ERR(%r13);                 \
      130 +        mov     KPTI_R14(%r13), %r14;           \
      131 +        movq    $0, KPTI_FLAG(%r13);            \
      132 +        mov     KPTI_R13(%r13), %r13
  83  133  
  84      -#define TRAP_ERR(trapno)        \
  85      -        popq    %rcx;           \
  86      -        popq    %r11;           \
  87      -        pushq   $0;             \
  88      -        pushq   $trapno
      134 +#endif  /* !__xpv */
  89  135  
  90      -#else
  91  136  
  92      -#define TRAP_NOERR(trapno)      \
  93      -        push    $trapno
  94      -
  95      -#define TRAP_ERR(trapno)        \
  96      -        push    $0;             \
  97      -        push    $trapno
  98      -
  99      -#endif  /* __xpv && __amd64 */
 100      -
 101      -
 102  137  #define MKIVCT(n) \
 103  138          ENTRY_NP(kdi_ivct/**/n/**/);    \
 104      -        TRAP_ERR(n);                    \
 105      -        .align  KDI_MSR_PATCHOFF;       \
 106      -        KDI_MSR_PATCH;                  \
      139 +        XPV_TRAP_POP;                   \
      140 +        push    $0; /* err */           \
      141 +        INTERRUPT_TRAMPOLINE;           \
      142 +        push    $n;                     \
 107  143          jmp     kdi_cmnint;             \
 108  144          SET_SIZE(kdi_ivct/**/n/**/)
 109  145  
 110  146  #define MKTRAPHDLR(n) \
 111  147          ENTRY_NP(kdi_trap/**/n);        \
 112      -        TRAP_ERR(n);                    \
 113      -        .align  KDI_MSR_PATCHOFF;       \
 114      -        KDI_MSR_PATCH;                  \
      148 +        XPV_TRAP_POP;                   \
      149 +        push    $0; /* err */           \
      150 +        INTERRUPT_TRAMPOLINE;           \
      151 +        push    $n;                     \
 115  152          jmp     kdi_cmnint;             \
 116  153          SET_SIZE(kdi_trap/**/n/**/)
 117  154  
 118  155  #define MKTRAPERRHDLR(n) \
 119  156          ENTRY_NP(kdi_traperr/**/n);     \
 120      -        TRAP_NOERR(n);                  \
 121      -        .align  KDI_MSR_PATCHOFF;       \
 122      -        KDI_MSR_PATCH;                  \
      157 +        XPV_TRAP_POP;                   \
      158 +        INTERRUPT_TRAMPOLINE;           \
      159 +        push    $n;                     \
 123  160          jmp     kdi_cmnint;             \
 124  161          SET_SIZE(kdi_traperr/**/n)
 125  162  
      163 +#if !defined(__xpv)
 126  164  #define MKNMIHDLR \
 127  165          ENTRY_NP(kdi_int2);             \
 128      -        TRAP_NOERR(2);                  \
 129      -        .align  KDI_MSR_PATCHOFF;       \
 130      -        KDI_MSR_PATCH;                  \
      166 +        push    $0;                     \
      167 +        push    $2;                     \
      168 +        pushq   %r13;                   \
      169 +        mov     kpti_safe_cr3, %r13;    \
      170 +        mov     %r13, %cr3;             \
      171 +        popq    %r13;                   \
 131  172          jmp     kdi_nmiint;             \
 132  173          SET_SIZE(kdi_int2)
 133  174  
      175 +#define MKMCEHDLR \
      176 +        ENTRY_NP(kdi_trap18);           \
      177 +        push    $0;                     \
      178 +        push    $18;                    \
      179 +        pushq   %r13;                   \
      180 +        mov     kpti_safe_cr3, %r13;    \
      181 +        mov     %r13, %cr3;             \
      182 +        popq    %r13;                   \
      183 +        jmp     kdi_cmnint;             \
      184 +        SET_SIZE(kdi_trap18)
      185 +#else
      186 +#define MKNMIHDLR \
      187 +        ENTRY_NP(kdi_int2);             \
      188 +        push    $0;                     \
      189 +        push    $2;                     \
      190 +        jmp     kdi_nmiint;             \
      191 +        SET_SIZE(kdi_int2)
      192 +
      193 +#define MKMCEHDLR \
      194 +        ENTRY_NP(kdi_trap18);           \
      195 +        push    $0;                     \
      196 +        push    $18;                    \
      197 +        jmp     kdi_cmnint;             \
      198 +        SET_SIZE(kdi_trap18)
      199 +#endif
      200 +
      201 +/*
      202 + * The only way we should reach here is by an explicit "int 0x.." which is
      203 + * defined not to push an error code.
      204 + */
 134  205  #define MKINVALHDLR \
 135  206          ENTRY_NP(kdi_invaltrap);        \
 136      -        TRAP_NOERR(255);                \
 137      -        .align  KDI_MSR_PATCHOFF;       \
 138      -        KDI_MSR_PATCH;                  \
      207 +        XPV_TRAP_POP;                   \
      208 +        push    $0; /* err */           \
      209 +        INTERRUPT_TRAMPOLINE;           \
      210 +        push    $255;                   \
 139  211          jmp     kdi_cmnint;             \
 140  212          SET_SIZE(kdi_invaltrap)
 141  213  
      214 +        .data
      215 +        DGDEF3(kdi_idt, 16 * NIDT, MMU_PAGESIZE)
      216 +        .fill   MMU_PAGESIZE, 1, 0
      217 +
      218 +#if !defined(__xpv)
      219 +.section ".text"
      220 +.align MMU_PAGESIZE
      221 +.global kdi_isr_start
      222 +kdi_isr_start:
      223 +        nop
      224 +
      225 +.global kpti_safe_cr3
      226 +.global kpti_kbase
      227 +#endif
      228 +
 142  229  /*
 143  230   * The handlers themselves
 144  231   */
 145  232  
 146  233          MKINVALHDLR
 147  234          MKTRAPHDLR(0)
 148  235          MKTRAPHDLR(1)
 149  236          MKNMIHDLR/*2*/
 150  237          MKTRAPHDLR(3)
 151  238          MKTRAPHDLR(4)
 152  239          MKTRAPHDLR(5)
 153  240          MKTRAPHDLR(6)
 154  241          MKTRAPHDLR(7)
 155  242          MKTRAPHDLR(9)
 156  243          MKTRAPHDLR(15)
 157  244          MKTRAPHDLR(16)
 158      -        MKTRAPHDLR(17)
 159      -        MKTRAPHDLR(18)
      245 +        MKMCEHDLR/*18*/
 160  246          MKTRAPHDLR(19)
 161  247          MKTRAPHDLR(20)
 162  248  
 163  249          MKTRAPERRHDLR(8)
 164  250          MKTRAPERRHDLR(10)
 165  251          MKTRAPERRHDLR(11)
 166  252          MKTRAPERRHDLR(12)
 167  253          MKTRAPERRHDLR(13)
 168  254          MKTRAPERRHDLR(14)
      255 +        MKTRAPERRHDLR(17)
 169  256  
 170  257          .globl  kdi_ivct_size
 171  258  kdi_ivct_size:
 172  259          .NWORD [kdi_ivct33-kdi_ivct32]
 173      -        
      260 +
 174  261          /* 10 billion and one interrupt handlers */
 175  262  kdi_ivct_base:
 176  263          MKIVCT(32);     MKIVCT(33);     MKIVCT(34);     MKIVCT(35);
 177  264          MKIVCT(36);     MKIVCT(37);     MKIVCT(38);     MKIVCT(39);
 178  265          MKIVCT(40);     MKIVCT(41);     MKIVCT(42);     MKIVCT(43);
 179  266          MKIVCT(44);     MKIVCT(45);     MKIVCT(46);     MKIVCT(47);
 180  267          MKIVCT(48);     MKIVCT(49);     MKIVCT(50);     MKIVCT(51);
 181  268          MKIVCT(52);     MKIVCT(53);     MKIVCT(54);     MKIVCT(55);
 182  269          MKIVCT(56);     MKIVCT(57);     MKIVCT(58);     MKIVCT(59);
 183  270          MKIVCT(60);     MKIVCT(61);     MKIVCT(62);     MKIVCT(63);
↓ open down ↓ 39 lines elided ↑ open up ↑
 223  310          MKIVCT(220);    MKIVCT(221);    MKIVCT(222);    MKIVCT(223);
 224  311          MKIVCT(224);    MKIVCT(225);    MKIVCT(226);    MKIVCT(227);
 225  312          MKIVCT(228);    MKIVCT(229);    MKIVCT(230);    MKIVCT(231);
 226  313          MKIVCT(232);    MKIVCT(233);    MKIVCT(234);    MKIVCT(235);
 227  314          MKIVCT(236);    MKIVCT(237);    MKIVCT(238);    MKIVCT(239);
 228  315          MKIVCT(240);    MKIVCT(241);    MKIVCT(242);    MKIVCT(243);
 229  316          MKIVCT(244);    MKIVCT(245);    MKIVCT(246);    MKIVCT(247);
 230  317          MKIVCT(248);    MKIVCT(249);    MKIVCT(250);    MKIVCT(251);
 231  318          MKIVCT(252);    MKIVCT(253);    MKIVCT(254);    MKIVCT(255);
 232  319  
      320 +#if !defined(__xpv)
      321 +.section ".text"
      322 +.align MMU_PAGESIZE
      323 +.global kdi_isr_end
      324 +kdi_isr_end:
      325 +        nop
 233  326  #endif
      327 +
      328 +#endif /* !__lint */
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX