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


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.

  23  */
  24 
  25 /*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
  26 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T       */
  27 /*        All Rights Reserved   */
  28 
  29 /*      Copyright (c) 1987, 1988 Microsoft Corporation  */
  30 /*        All Rights Reserved   */
  31 
  32 #include <sys/param.h>
  33 #include <sys/types.h>
  34 #include <sys/sysmacros.h>
  35 #include <sys/systm.h>
  36 #include <sys/signal.h>
  37 #include <sys/errno.h>
  38 #include <sys/fault.h>
  39 #include <sys/syscall.h>
  40 #include <sys/cpuvar.h>
  41 #include <sys/sysi86.h>
  42 #include <sys/psw.h>
  43 #include <sys/cred.h>
  44 #include <sys/policy.h>
  45 #include <sys/thread.h>
  46 #include <sys/debug.h>
  47 #include <sys/ontrap.h>
  48 #include <sys/privregs.h>
  49 #include <sys/x86_archext.h>
  50 #include <sys/vmem.h>
  51 #include <sys/kmem.h>
  52 #include <sys/mman.h>
  53 #include <sys/archsystm.h>
  54 #include <vm/hat.h>
  55 #include <vm/as.h>
  56 #include <vm/seg.h>
  57 #include <vm/seg_kmem.h>
  58 #include <vm/faultcode.h>
  59 #include <sys/fp.h>
  60 #include <sys/cmn_err.h>
  61 #include <sys/segments.h>
  62 #include <sys/clock.h>

  63 #if defined(__xpv)
  64 #include <sys/hypervisor.h>
  65 #include <sys/note.h>
  66 #endif
  67 
  68 static void ldt_alloc(proc_t *, uint_t);
  69 static void ldt_free(proc_t *);
  70 static void ldt_dup(proc_t *, proc_t *);
  71 static void ldt_grow(proc_t *, uint_t);
  72 
  73 /*
  74  * sysi86 System Call
  75  */
  76 
  77 /* ARGSUSED */
  78 int
  79 sysi86(short cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
  80 {
  81         struct ssd ssd;
  82         int error = 0;


 329         sgd->sgd_type = ssd->acc1;
 330         sgd->sgd_dpl = ssd->acc1 >> 5;
 331         sgd->sgd_p = ssd->acc1 >> 7;
 332         ASSERT(sgd->sgd_type == SDT_SYSCGT);
 333         ASSERT(sgd->sgd_dpl == SEL_UPL);
 334         sgd->sgd_stkcpy = 0;
 335 }
 336 
 337 #endif  /* __i386 */
 338 
 339 /*
 340  * Load LDT register with the current process's LDT.
 341  */
 342 static void
 343 ldt_load(void)
 344 {
 345 #if defined(__xpv)
 346         xen_set_ldt(get_ssd_base(&curproc->p_ldt_desc),
 347             curproc->p_ldtlimit + 1);
 348 #else
 349         *((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = curproc->p_ldt_desc;












 350         wr_ldtr(ULDT_SEL);
 351 #endif
 352 }
 353 
 354 /*
 355  * Store a NULL selector in the LDTR. All subsequent illegal references to
 356  * the LDT will result in a #gp.
 357  */
 358 void
 359 ldt_unload(void)
 360 {
 361 #if defined(__xpv)
 362         xen_set_ldt(NULL, 0);
 363 #else
 364         *((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = null_sdesc;
 365         wr_ldtr(0);



 366 #endif
 367 }
 368 
 369 /*ARGSUSED*/
 370 static void
 371 ldt_savectx(proc_t *p)
 372 {
 373         ASSERT(p->p_ldt != NULL);
 374         ASSERT(p == curproc);
 375 
 376 #if defined(__amd64)
 377         /*
 378          * The 64-bit kernel must be sure to clear any stale ldt
 379          * selectors when context switching away from a process that
 380          * has a private ldt. Consider the following example:
 381          *
 382          *      Wine creats a ldt descriptor and points a segment register
 383          *      to it.
 384          *
 385          *      We then context switch away from wine lwp to kernel


 697 
 698 /*
 699  * Allocate new LDT for process just large enough to contain seli.
 700  * Note we allocate and grow LDT in PAGESIZE chunks. We do this
 701  * to simplify the implementation and because on the hypervisor it's
 702  * required, since the LDT must live on pages that have PROT_WRITE
 703  * removed and which are given to the hypervisor.
 704  */
 705 static void
 706 ldt_alloc(proc_t *pp, uint_t seli)
 707 {
 708         user_desc_t     *ldt;
 709         size_t          ldtsz;
 710         uint_t          nsels;
 711 
 712         ASSERT(MUTEX_HELD(&pp->p_ldtlock));
 713         ASSERT(pp->p_ldt == NULL);
 714         ASSERT(pp->p_ldtlimit == 0);
 715 
 716         /*
 717          * Allocate new LDT just large enough to contain seli.

 718          */
 719         ldtsz = P2ROUNDUP((seli + 1) * sizeof (user_desc_t), PAGESIZE);
 720         nsels = ldtsz / sizeof (user_desc_t);
 721         ASSERT(nsels >= MINNLDT && nsels <= MAXNLDT);
 722 
 723         ldt = kmem_zalloc(ldtsz, KM_SLEEP);
 724         ASSERT(IS_P2ALIGNED(ldt, PAGESIZE));
 725 
 726 #if defined(__xpv)
 727         if (xen_ldt_setprot(ldt, ldtsz, PROT_READ))
 728                 panic("ldt_alloc:xen_ldt_setprot(PROT_READ) failed");
 729 #endif
 730 
 731         pp->p_ldt = ldt;
 732         pp->p_ldtlimit = nsels - 1;
 733         set_syssegd(&pp->p_ldt_desc, ldt, ldtsz - 1, SDT_SYSLDT, SEL_KPL);
 734 
 735         if (pp == curproc) {
 736                 kpreempt_disable();
 737                 ldt_load();


 815         if (xen_ldt_setprot(cp->p_ldt, ldtsz, PROT_READ))
 816                 panic("ldt_dup:xen_ldt_setprot(PROT_READ) failed");
 817 #endif
 818         mutex_exit(&cp->p_ldtlock);
 819         mutex_exit(&pp->p_ldtlock);
 820 
 821 }
 822 
 823 static void
 824 ldt_grow(proc_t *pp, uint_t seli)
 825 {
 826         user_desc_t     *oldt, *nldt;
 827         uint_t          nsels;
 828         size_t          oldtsz, nldtsz;
 829 
 830         ASSERT(MUTEX_HELD(&pp->p_ldtlock));
 831         ASSERT(pp->p_ldt != NULL);
 832         ASSERT(pp->p_ldtlimit != 0);
 833 
 834         /*
 835          * Allocate larger LDT just large enough to contain seli.

 836          */
 837         nldtsz = P2ROUNDUP((seli + 1) * sizeof (user_desc_t), PAGESIZE);
 838         nsels = nldtsz / sizeof (user_desc_t);
 839         ASSERT(nsels >= MINNLDT && nsels <= MAXNLDT);
 840         ASSERT(nsels > pp->p_ldtlimit);
 841 
 842         oldt = pp->p_ldt;
 843         oldtsz = (pp->p_ldtlimit + 1) * sizeof (user_desc_t);
 844 
 845         nldt = kmem_zalloc(nldtsz, KM_SLEEP);
 846         ASSERT(IS_P2ALIGNED(nldt, PAGESIZE));
 847 
 848         bcopy(oldt, nldt, oldtsz);
 849 
 850         /*
 851          * unload old ldt.
 852          */
 853         kpreempt_disable();
 854         ldt_unload();
 855         kpreempt_enable();




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018 Joyent, Inc.
  24  */
  25 
  26 /*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
  27 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T       */
  28 /*        All Rights Reserved   */
  29 
  30 /*      Copyright (c) 1987, 1988 Microsoft Corporation  */
  31 /*        All Rights Reserved   */
  32 
  33 #include <sys/param.h>
  34 #include <sys/types.h>
  35 #include <sys/sysmacros.h>
  36 #include <sys/systm.h>
  37 #include <sys/signal.h>
  38 #include <sys/errno.h>
  39 #include <sys/fault.h>
  40 #include <sys/syscall.h>
  41 #include <sys/cpuvar.h>
  42 #include <sys/sysi86.h>
  43 #include <sys/psw.h>
  44 #include <sys/cred.h>
  45 #include <sys/policy.h>
  46 #include <sys/thread.h>
  47 #include <sys/debug.h>
  48 #include <sys/ontrap.h>
  49 #include <sys/privregs.h>
  50 #include <sys/x86_archext.h>
  51 #include <sys/vmem.h>
  52 #include <sys/kmem.h>
  53 #include <sys/mman.h>
  54 #include <sys/archsystm.h>
  55 #include <vm/hat.h>
  56 #include <vm/as.h>
  57 #include <vm/seg.h>
  58 #include <vm/seg_kmem.h>
  59 #include <vm/faultcode.h>
  60 #include <sys/fp.h>
  61 #include <sys/cmn_err.h>
  62 #include <sys/segments.h>
  63 #include <sys/clock.h>
  64 #include <vm/hat_i86.h>
  65 #if defined(__xpv)
  66 #include <sys/hypervisor.h>
  67 #include <sys/note.h>
  68 #endif
  69 
  70 static void ldt_alloc(proc_t *, uint_t);
  71 static void ldt_free(proc_t *);
  72 static void ldt_dup(proc_t *, proc_t *);
  73 static void ldt_grow(proc_t *, uint_t);
  74 
  75 /*
  76  * sysi86 System Call
  77  */
  78 
  79 /* ARGSUSED */
  80 int
  81 sysi86(short cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
  82 {
  83         struct ssd ssd;
  84         int error = 0;


 331         sgd->sgd_type = ssd->acc1;
 332         sgd->sgd_dpl = ssd->acc1 >> 5;
 333         sgd->sgd_p = ssd->acc1 >> 7;
 334         ASSERT(sgd->sgd_type == SDT_SYSCGT);
 335         ASSERT(sgd->sgd_dpl == SEL_UPL);
 336         sgd->sgd_stkcpy = 0;
 337 }
 338 
 339 #endif  /* __i386 */
 340 
 341 /*
 342  * Load LDT register with the current process's LDT.
 343  */
 344 static void
 345 ldt_load(void)
 346 {
 347 #if defined(__xpv)
 348         xen_set_ldt(get_ssd_base(&curproc->p_ldt_desc),
 349             curproc->p_ldtlimit + 1);
 350 #else
 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 
 364         wr_ldtr(ULDT_SEL);
 365 #endif
 366 }
 367 
 368 /*
 369  * Store a NULL selector in the LDTR. All subsequent illegal references to
 370  * the LDT will result in a #gp.
 371  */
 372 void
 373 ldt_unload(void)
 374 {
 375 #if defined(__xpv)
 376         xen_set_ldt(NULL, 0);
 377 #else
 378         *((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = null_sdesc;
 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;
 383 #endif
 384 }
 385 
 386 /*ARGSUSED*/
 387 static void
 388 ldt_savectx(proc_t *p)
 389 {
 390         ASSERT(p->p_ldt != NULL);
 391         ASSERT(p == curproc);
 392 
 393 #if defined(__amd64)
 394         /*
 395          * The 64-bit kernel must be sure to clear any stale ldt
 396          * selectors when context switching away from a process that
 397          * has a private ldt. Consider the following example:
 398          *
 399          *      Wine creats a ldt descriptor and points a segment register
 400          *      to it.
 401          *
 402          *      We then context switch away from wine lwp to kernel


 714 
 715 /*
 716  * Allocate new LDT for process just large enough to contain seli.
 717  * Note we allocate and grow LDT in PAGESIZE chunks. We do this
 718  * to simplify the implementation and because on the hypervisor it's
 719  * required, since the LDT must live on pages that have PROT_WRITE
 720  * removed and which are given to the hypervisor.
 721  */
 722 static void
 723 ldt_alloc(proc_t *pp, uint_t seli)
 724 {
 725         user_desc_t     *ldt;
 726         size_t          ldtsz;
 727         uint_t          nsels;
 728 
 729         ASSERT(MUTEX_HELD(&pp->p_ldtlock));
 730         ASSERT(pp->p_ldt == NULL);
 731         ASSERT(pp->p_ldtlimit == 0);
 732 
 733         /*
 734          * Allocate new LDT just large enough to contain seli. The LDT must
 735          * always be allocated in units of pages for KPTI.
 736          */
 737         ldtsz = P2ROUNDUP((seli + 1) * sizeof (user_desc_t), PAGESIZE);
 738         nsels = ldtsz / sizeof (user_desc_t);
 739         ASSERT(nsels >= MINNLDT && nsels <= MAXNLDT);
 740 
 741         ldt = kmem_zalloc(ldtsz, KM_SLEEP);
 742         ASSERT(IS_P2ALIGNED(ldt, PAGESIZE));
 743 
 744 #if defined(__xpv)
 745         if (xen_ldt_setprot(ldt, ldtsz, PROT_READ))
 746                 panic("ldt_alloc:xen_ldt_setprot(PROT_READ) failed");
 747 #endif
 748 
 749         pp->p_ldt = ldt;
 750         pp->p_ldtlimit = nsels - 1;
 751         set_syssegd(&pp->p_ldt_desc, ldt, ldtsz - 1, SDT_SYSLDT, SEL_KPL);
 752 
 753         if (pp == curproc) {
 754                 kpreempt_disable();
 755                 ldt_load();


 833         if (xen_ldt_setprot(cp->p_ldt, ldtsz, PROT_READ))
 834                 panic("ldt_dup:xen_ldt_setprot(PROT_READ) failed");
 835 #endif
 836         mutex_exit(&cp->p_ldtlock);
 837         mutex_exit(&pp->p_ldtlock);
 838 
 839 }
 840 
 841 static void
 842 ldt_grow(proc_t *pp, uint_t seli)
 843 {
 844         user_desc_t     *oldt, *nldt;
 845         uint_t          nsels;
 846         size_t          oldtsz, nldtsz;
 847 
 848         ASSERT(MUTEX_HELD(&pp->p_ldtlock));
 849         ASSERT(pp->p_ldt != NULL);
 850         ASSERT(pp->p_ldtlimit != 0);
 851 
 852         /*
 853          * Allocate larger LDT just large enough to contain seli. The LDT must
 854          * always be allocated in units of pages for KPTI.
 855          */
 856         nldtsz = P2ROUNDUP((seli + 1) * sizeof (user_desc_t), PAGESIZE);
 857         nsels = nldtsz / sizeof (user_desc_t);
 858         ASSERT(nsels >= MINNLDT && nsels <= MAXNLDT);
 859         ASSERT(nsels > pp->p_ldtlimit);
 860 
 861         oldt = pp->p_ldt;
 862         oldtsz = (pp->p_ldtlimit + 1) * sizeof (user_desc_t);
 863 
 864         nldt = kmem_zalloc(nldtsz, KM_SLEEP);
 865         ASSERT(IS_P2ALIGNED(nldt, PAGESIZE));
 866 
 867         bcopy(oldt, nldt, oldtsz);
 868 
 869         /*
 870          * unload old ldt.
 871          */
 872         kpreempt_disable();
 873         ldt_unload();
 874         kpreempt_enable();