Print this page
11787 Kernel needs to be built with retpolines
11788 Kernel needs to generally use RSB stuffing
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: John Levon <john.levon@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/i86pc/ml/mpcore.s
          +++ new/usr/src/uts/i86pc/ml/mpcore.s
↓ open down ↓ 17 lines elided ↑ open up ↑
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   */
  24   24  /*
  25   25   * Copyright (c) 2010, Intel Corporation.
  26   26   * All rights reserved.
  27   27   *
  28      - * Copyright 2018 Joyent, Inc.
       28 + * Copyright 2019 Joyent, Inc.
  29   29   */
  30      -        
       30 +
  31   31  #include <sys/asm_linkage.h>
  32   32  #include <sys/asm_misc.h>
  33   33  #include <sys/regset.h>
  34   34  #include <sys/privregs.h>
  35   35  #include <sys/x86_archext.h>
  36   36  
  37   37  #if !defined(__lint)
  38   38  #include <sys/segments.h>
  39   39  #include "assym.h"
  40   40  #endif
↓ open down ↓ 39 lines elided ↑ open up ↑
  80   80  
  81   81          ENTRY_NP(real_mode_start_cpu)
  82   82  
  83   83          /*
  84   84           * NOTE:  The GNU assembler automatically does the right thing to
  85   85           *        generate data size operand prefixes based on the code size
  86   86           *        generation mode (e.g. .code16, .code32, .code64) and as such
  87   87           *        prefixes need not be used on instructions EXCEPT in the case
  88   88           *        of address prefixes for code for which the reference is not
  89   89           *        automatically of the default operand size.
  90      -         */      
       90 +         */
  91   91          .code16
  92   92          cli
  93   93          movw            %cs, %ax
  94   94          movw            %ax, %ds        /* load cs into ds */
  95   95          movw            %ax, %ss        /* and into ss */
  96   96  
  97   97          /*
  98   98           * Helps in debugging by giving us the fault address.
  99   99           *
 100  100           * Remember to patch a hlt (0xf4) at cmntrap to get a good stack.
↓ open down ↓ 8 lines elided ↑ open up ↑
 109  109          movl            %eax, %cr0
 110  110  
 111  111          /*
 112  112           * Do a jmp immediately after writing to cr0 when enabling protected
 113  113           * mode to clear the real mode prefetch queue (per Intel's docs)
 114  114           */
 115  115          jmp             pestart
 116  116  
 117  117  pestart:
 118  118          /*
 119      -         * 16-bit protected mode is now active, so prepare to turn on long
      119 +         * 16-bit protected mode is now active, so prepare to turn on long
 120  120           * mode.
 121  121           *
 122  122           * Note that we currently assume that if we're attempting to run a
 123  123           * kernel compiled with (__amd64) #defined, the target CPU has long
 124  124           * mode support.
 125  125           */
 126  126  
 127  127  #if 0
 128  128          /*
 129  129           * If there's a chance this might not be true, the following test should
 130  130           * be done, with the no_long_mode branch then doing something
 131  131           * appropriate:
 132  132           */
 133  133  
 134  134          movl            $0x80000000, %eax       /* get largest extended CPUID */
 135  135          cpuid
 136  136          cmpl            $0x80000000, %eax       /* check if > 0x80000000 */
 137  137          jbe             no_long_mode            /* nope, no long mode */
 138      -        movl            $0x80000001, %eax       
      138 +        movl            $0x80000001, %eax
 139  139          cpuid                                   /* get extended feature flags */
 140  140          btl             $29, %edx               /* check for long mode */
 141  141          jnc             no_long_mode            /* long mode not supported */
 142  142  #endif
 143  143  
 144  144          /*
 145      -         * Add any initial cr4 bits
      145 +         * Add any initial cr4 bits
 146  146           */
 147  147          movl            %cr4, %eax
 148  148          addr32 orl      CR4OFF, %eax
 149  149  
 150  150          /*
 151  151           * Enable PAE mode (CR4.PAE)
 152  152           */
 153  153          orl             $CR4_PAE, %eax
 154  154          movl            %eax, %cr4
 155  155  
↓ open down ↓ 35 lines elided ↑ open up ↑
 191  191           * We have to load an intermediate GDT and IDT here that we know are
 192  192           * in 32-bit space before we can use the kernel's GDT and IDT, which
 193  193           * may be in the 64-bit address space, and since we're in compatability
 194  194           * mode, we only have access to 16 and 32-bit instructions at the
 195  195           * moment.
 196  196           */
 197  197          addr32 lgdtl    TEMPGDTOFF      /* load temporary GDT */
 198  198          addr32 lidtl    TEMPIDTOFF      /* load temporary IDT */
 199  199  
 200  200          /*
 201      -         * Do a far transfer to 64-bit mode.  Set the CS selector to a 64-bit
      201 +         * Do a far transfer to 64-bit mode.  Set the CS selector to a 64-bit
 202  202           * long mode selector (CS.L=1) in the temporary 32-bit GDT and jump
 203  203           * to the real mode platter address of long_mode 64 as until the 64-bit
 204  204           * CS is in place we don't have access to 64-bit instructions and thus
 205  205           * can't reference a 64-bit %rip.
 206  206           */
 207      -        pushl           $TEMP_CS64_SEL
      207 +        pushl           $TEMP_CS64_SEL
 208  208          addr32 pushl    LM64OFF
 209  209          lretl
 210  210  
 211  211          .globl  long_mode_64
 212  212  long_mode_64:
 213  213          .code64
 214  214          /*
 215  215           * We are now running in long mode with a 64-bit CS (EFER.LMA=1,
 216  216           * CS.L=1) so we now have access to 64-bit instructions.
 217  217           *
↓ open down ↓ 88 lines elided ↑ open up ↑
 306  306          pushq   $0              /* null return address */
 307  307          pushq   $0              /* null frame pointer terminates stack trace */
 308  308          movq    %rsp, %rbp      /* stack aligned on 16-byte boundary */
 309  309  
 310  310          movq    %cr0, %rax
 311  311          andq    $~(CR0_TS|CR0_EM), %rax /* clear emulate math chip bit */
 312  312          orq     $(CR0_MP|CR0_NE), %rax
 313  313          movq    %rax, %cr0              /* set machine status word */
 314  314  
 315  315          /*
 316      -         * Before going any further, enable usage of page table NX bit if 
      316 +         * Before going any further, enable usage of page table NX bit if
 317  317           * that's how our page tables are set up.
 318  318           */
 319  319          bt      $X86FSET_NX, x86_featureset(%rip)
 320  320          jnc     1f
 321  321          movl    $MSR_AMD_EFER, %ecx
 322  322          rdmsr
 323  323          orl     $AMD_EFER_NXE, %eax
 324  324          wrmsr
 325  325  1:
 326  326  
 327  327          /*
 328  328           * Complete the rest of the setup and call mp_startup().
 329  329           */
 330  330          movq    %gs:CPU_THREAD, %rax    /* get thread ptr */
 331      -        call    *T_PC(%rax)             /* call mp_startup_boot */
      331 +        movq    T_PC(%rax), %rax
      332 +        INDIRECT_CALL_REG(rax)          /* call mp_startup_boot */
 332  333          /* not reached */
 333  334          int     $20                     /* whoops, returned somehow! */
 334  335  
 335  336          SET_SIZE(real_mode_start_cpu)
 336  337  
 337  338  #elif defined(__i386)
 338  339  
 339  340          ENTRY_NP(real_mode_start_cpu)
 340  341  
 341  342  #if !defined(__GNUC_AS__)
↓ open down ↓ 3 lines elided ↑ open up ↑
 345  346          movw            %eax, %ds       /* load cs into ds */
 346  347          movw            %eax, %ss       /* and into ss */
 347  348  
 348  349          /*
 349  350           * Helps in debugging by giving us the fault address.
 350  351           *
 351  352           * Remember to patch a hlt (0xf4) at cmntrap to get a good stack.
 352  353           */
 353  354          D16 movl        $0xffc, %esp
 354  355  
 355      -        D16 A16 lgdt    %cs:GDTROFF
 356      -        D16 A16 lidt    %cs:IDTROFF
      356 +        D16 A16 lgdt    %cs:GDTROFF
      357 +        D16 A16 lidt    %cs:IDTROFF
 357  358          D16 A16 movl    %cs:CR4OFF, %eax        /* set up CR4, if desired */
 358  359          D16 andl        %eax, %eax
 359  360          D16 A16 je      no_cr4
 360  361  
 361  362          D16 movl        %eax, %ecx
 362  363          D16 movl        %cr4, %eax
 363  364          D16 orl         %ecx, %eax
 364  365          D16 movl        %eax, %cr4
 365  366  no_cr4:
 366  367          D16 A16 movl    %cs:CR3OFF, %eax
↓ open down ↓ 38 lines elided ↑ open up ↑
 405  406          movw    $KTSS_SEL,%ax
 406  407          ltr     %ax
 407  408          xorw    %ax, %ax                /* clear LDTR */
 408  409          lldt    %ax
 409  410          movl    %cr0,%edx
 410  411          andl    $-1![CR0_TS|CR0_EM],%edx  /* clear emulate math chip bit */
 411  412          orl     $[CR0_MP|CR0_NE],%edx
 412  413          movl    %edx,%cr0                 /* set machine status word */
 413  414  
 414  415          /*
 415      -         * Before going any further, enable usage of page table NX bit if 
      416 +         * Before going any further, enable usage of page table NX bit if
 416  417           * that's how our page tables are set up.
 417  418           */
 418  419          bt      $X86FSET_NX, x86_featureset
 419  420          jnc     1f
 420  421          movl    %cr4, %ecx
 421  422          andl    $CR4_PAE, %ecx
 422  423          jz      1f
 423  424          movl    $MSR_AMD_EFER, %ecx
 424  425          rdmsr
 425  426          orl     $AMD_EFER_NXE, %eax
↓ open down ↓ 70 lines elided ↑ open up ↑
 496  497          mov     $(KTSS_SEL), %ax
 497  498          ltr     %ax
 498  499          xorw    %ax, %ax                /* clear LDTR */
 499  500          lldt    %ax
 500  501          mov     %cr0, %edx
 501  502          and     $~(CR0_TS|CR0_EM), %edx /* clear emulate math chip bit */
 502  503          or      $(CR0_MP|CR0_NE), %edx
 503  504          mov     %edx, %cr0              /* set machine status word */
 504  505  
 505  506          /*
 506      -         * Before going any farther, enable usage of page table NX bit if 
      507 +         * Before going any farther, enable usage of page table NX bit if
 507  508           * that's how our page tables are set up.  (PCIDE is enabled later on).
 508  509           */
 509  510          bt      $X86FSET_NX, x86_featureset
 510  511          jnc     1f
 511  512          movl    %cr4, %ecx
 512  513          andl    $CR4_PAE, %ecx
 513  514          jz      1f
 514  515          movl    $MSR_AMD_EFER, %ecx
 515  516          rdmsr
 516  517          orl     $AMD_EFER_NXE, %eax
↓ open down ↓ 34 lines elided ↑ open up ↑
 551  552  
 552  553  #else   /* __GNUC_AS__ */
 553  554  
 554  555          /*
 555  556           * NOTE:  The GNU assembler automatically does the right thing to
 556  557           *        generate data size operand prefixes based on the code size
 557  558           *        generation mode (e.g. .code16, .code32, .code64) and as such
 558  559           *        prefixes need not be used on instructions EXCEPT in the case
 559  560           *        of address prefixes for code for which the reference is not
 560  561           *        automatically of the default operand size.
 561      -         */      
      562 +         */
 562  563          .code16
 563  564          cli
 564  565          movw            %cs, %ax
 565  566          movw            %ax, %ds        /* load cs into ds */
 566  567          movw            %ax, %ss        /* and into ss */
 567  568  
 568  569          /*
 569  570           * Jump to the stage 2 code in the rm_platter_va->rm_cpu_halt_code
 570  571           */
 571  572          movw            $CPUHALTCODEOFF, %ax
↓ open down ↓ 28 lines elided ↑ open up ↑
 600  601  
 601  602          cli
 602  603          mov             %cs, %ax
 603  604          mov             %eax, %ds       /* load cs into ds */
 604  605          mov             %eax, %ss       /* and into ss */
 605  606  
 606  607          /*
 607  608           * Jump to the stage 2 code in the rm_platter_va->rm_cpu_halt_code
 608  609           */
 609  610          movw            $CPUHALTCODEOFF, %ax
      611 +        /*
      612 +         * The following indirect call is executed as part of starting up a CPU.
      613 +         * As such nothing else should be running on it or executing in the
      614 +         * system such that it is a viable Spectre v2 branch target injection
      615 +         * location. At least, in theory.
      616 +         */
 610  617          jmp             *%ax
 611  618  
 612  619  #endif  /* !__GNUC_AS__ */
 613  620  
 614  621          .globl real_mode_stop_cpu_stage1_end
 615  622  real_mode_stop_cpu_stage1_end:
 616  623          nop
 617  624  
 618  625          SET_SIZE(real_mode_stop_cpu_stage1)
 619  626  
↓ open down ↓ 22 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX