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);