Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/intel/ia32/os/sysi86.c
          +++ new/usr/src/uts/intel/ia32/os/sysi86.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright 2018 Joyent, Inc.
  23   24   */
  24   25  
  25   26  /*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
  26   27  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T   */
  27   28  /*        All Rights Reserved   */
  28   29  
  29   30  /*      Copyright (c) 1987, 1988 Microsoft Corporation  */
  30   31  /*        All Rights Reserved   */
  31   32  
  32   33  #include <sys/param.h>
↓ open down ↓ 20 lines elided ↑ open up ↑
  53   54  #include <sys/archsystm.h>
  54   55  #include <vm/hat.h>
  55   56  #include <vm/as.h>
  56   57  #include <vm/seg.h>
  57   58  #include <vm/seg_kmem.h>
  58   59  #include <vm/faultcode.h>
  59   60  #include <sys/fp.h>
  60   61  #include <sys/cmn_err.h>
  61   62  #include <sys/segments.h>
  62   63  #include <sys/clock.h>
       64 +#include <vm/hat_i86.h>
  63   65  #if defined(__xpv)
  64   66  #include <sys/hypervisor.h>
  65   67  #include <sys/note.h>
  66   68  #endif
  67   69  
  68   70  static void ldt_alloc(proc_t *, uint_t);
  69   71  static void ldt_free(proc_t *);
  70   72  static void ldt_dup(proc_t *, proc_t *);
  71   73  static void ldt_grow(proc_t *, uint_t);
  72   74  
↓ open down ↓ 266 lines elided ↑ open up ↑
 339  341  /*
 340  342   * Load LDT register with the current process's LDT.
 341  343   */
 342  344  static void
 343  345  ldt_load(void)
 344  346  {
 345  347  #if defined(__xpv)
 346  348          xen_set_ldt(get_ssd_base(&curproc->p_ldt_desc),
 347  349              curproc->p_ldtlimit + 1);
 348  350  #else
 349      -        *((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = curproc->p_ldt_desc;
      351 +        size_t len;
      352 +        system_desc_t desc;
      353 +
      354 +        /*
      355 +         * Before we can use the LDT on this CPU, we must install the LDT in the
      356 +         * user mapping table.
      357 +         */
      358 +        len = (curproc->p_ldtlimit + 1) * sizeof (user_desc_t);
      359 +        bcopy(curproc->p_ldt, CPU->cpu_m.mcpu_ldt, len);
      360 +        CPU->cpu_m.mcpu_ldt_len = len;
      361 +        set_syssegd(&desc, CPU->cpu_m.mcpu_ldt, len - 1, SDT_SYSLDT, SEL_KPL);
      362 +        *((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = desc;
      363 +
 350  364          wr_ldtr(ULDT_SEL);
 351  365  #endif
 352  366  }
 353  367  
 354  368  /*
 355  369   * Store a NULL selector in the LDTR. All subsequent illegal references to
 356  370   * the LDT will result in a #gp.
 357  371   */
 358  372  void
 359  373  ldt_unload(void)
 360  374  {
 361  375  #if defined(__xpv)
 362  376          xen_set_ldt(NULL, 0);
 363  377  #else
 364  378          *((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = null_sdesc;
 365  379          wr_ldtr(0);
      380 +
      381 +        bzero(CPU->cpu_m.mcpu_ldt, CPU->cpu_m.mcpu_ldt_len);
      382 +        CPU->cpu_m.mcpu_ldt_len = 0;
 366  383  #endif
 367  384  }
 368  385  
 369  386  /*ARGSUSED*/
 370  387  static void
 371  388  ldt_savectx(proc_t *p)
 372  389  {
 373  390          ASSERT(p->p_ldt != NULL);
 374  391          ASSERT(p == curproc);
 375  392  
↓ open down ↓ 331 lines elided ↑ open up ↑
 707  724  {
 708  725          user_desc_t     *ldt;
 709  726          size_t          ldtsz;
 710  727          uint_t          nsels;
 711  728  
 712  729          ASSERT(MUTEX_HELD(&pp->p_ldtlock));
 713  730          ASSERT(pp->p_ldt == NULL);
 714  731          ASSERT(pp->p_ldtlimit == 0);
 715  732  
 716  733          /*
 717      -         * Allocate new LDT just large enough to contain seli.
      734 +         * Allocate new LDT just large enough to contain seli. The LDT must
      735 +         * always be allocated in units of pages for KPTI.
 718  736           */
 719  737          ldtsz = P2ROUNDUP((seli + 1) * sizeof (user_desc_t), PAGESIZE);
 720  738          nsels = ldtsz / sizeof (user_desc_t);
 721  739          ASSERT(nsels >= MINNLDT && nsels <= MAXNLDT);
 722  740  
 723  741          ldt = kmem_zalloc(ldtsz, KM_SLEEP);
 724  742          ASSERT(IS_P2ALIGNED(ldt, PAGESIZE));
 725  743  
 726  744  #if defined(__xpv)
 727  745          if (xen_ldt_setprot(ldt, ldtsz, PROT_READ))
↓ open down ↓ 97 lines elided ↑ open up ↑
 825  843  {
 826  844          user_desc_t     *oldt, *nldt;
 827  845          uint_t          nsels;
 828  846          size_t          oldtsz, nldtsz;
 829  847  
 830  848          ASSERT(MUTEX_HELD(&pp->p_ldtlock));
 831  849          ASSERT(pp->p_ldt != NULL);
 832  850          ASSERT(pp->p_ldtlimit != 0);
 833  851  
 834  852          /*
 835      -         * Allocate larger LDT just large enough to contain seli.
      853 +         * Allocate larger LDT just large enough to contain seli. The LDT must
      854 +         * always be allocated in units of pages for KPTI.
 836  855           */
 837  856          nldtsz = P2ROUNDUP((seli + 1) * sizeof (user_desc_t), PAGESIZE);
 838  857          nsels = nldtsz / sizeof (user_desc_t);
 839  858          ASSERT(nsels >= MINNLDT && nsels <= MAXNLDT);
 840  859          ASSERT(nsels > pp->p_ldtlimit);
 841  860  
 842  861          oldt = pp->p_ldt;
 843  862          oldtsz = (pp->p_ldtlimit + 1) * sizeof (user_desc_t);
 844  863  
 845  864          nldt = kmem_zalloc(nldtsz, KM_SLEEP);
↓ open down ↓ 40 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX