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

@@ -18,10 +18,11 @@
  *
  * CDDL HEADER END
  */
 /*
  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
 
 /*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T   */
 /*        All Rights Reserved   */

@@ -58,10 +59,11 @@
 #include <vm/faultcode.h>
 #include <sys/fp.h>
 #include <sys/cmn_err.h>
 #include <sys/segments.h>
 #include <sys/clock.h>
+#include <vm/hat_i86.h>
 #if defined(__xpv)
 #include <sys/hypervisor.h>
 #include <sys/note.h>
 #endif
 

@@ -344,11 +346,23 @@
 {
 #if defined(__xpv)
         xen_set_ldt(get_ssd_base(&curproc->p_ldt_desc),
             curproc->p_ldtlimit + 1);
 #else
-        *((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = curproc->p_ldt_desc;
+        size_t len;
+        system_desc_t desc;
+
+        /*
+         * Before we can use the LDT on this CPU, we must install the LDT in the
+         * user mapping table.
+         */
+        len = (curproc->p_ldtlimit + 1) * sizeof (user_desc_t);
+        bcopy(curproc->p_ldt, CPU->cpu_m.mcpu_ldt, len);
+        CPU->cpu_m.mcpu_ldt_len = len;
+        set_syssegd(&desc, CPU->cpu_m.mcpu_ldt, len - 1, SDT_SYSLDT, SEL_KPL);
+        *((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = desc;
+
         wr_ldtr(ULDT_SEL);
 #endif
 }
 
 /*

@@ -361,10 +375,13 @@
 #if defined(__xpv)
         xen_set_ldt(NULL, 0);
 #else
         *((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = null_sdesc;
         wr_ldtr(0);
+
+        bzero(CPU->cpu_m.mcpu_ldt, CPU->cpu_m.mcpu_ldt_len);
+        CPU->cpu_m.mcpu_ldt_len = 0;
 #endif
 }
 
 /*ARGSUSED*/
 static void

@@ -712,11 +729,12 @@
         ASSERT(MUTEX_HELD(&pp->p_ldtlock));
         ASSERT(pp->p_ldt == NULL);
         ASSERT(pp->p_ldtlimit == 0);
 
         /*
-         * Allocate new LDT just large enough to contain seli.
+         * Allocate new LDT just large enough to contain seli. The LDT must
+         * always be allocated in units of pages for KPTI.
          */
         ldtsz = P2ROUNDUP((seli + 1) * sizeof (user_desc_t), PAGESIZE);
         nsels = ldtsz / sizeof (user_desc_t);
         ASSERT(nsels >= MINNLDT && nsels <= MAXNLDT);
 

@@ -830,11 +848,12 @@
         ASSERT(MUTEX_HELD(&pp->p_ldtlock));
         ASSERT(pp->p_ldt != NULL);
         ASSERT(pp->p_ldtlimit != 0);
 
         /*
-         * Allocate larger LDT just large enough to contain seli.
+         * Allocate larger LDT just large enough to contain seli. The LDT must
+         * always be allocated in units of pages for KPTI.
          */
         nldtsz = P2ROUNDUP((seli + 1) * sizeof (user_desc_t), PAGESIZE);
         nsels = nldtsz / sizeof (user_desc_t);
         ASSERT(nsels >= MINNLDT && nsels <= MAXNLDT);
         ASSERT(nsels > pp->p_ldtlimit);