Module Name: src Committed By: maxv Date: Wed Aug 7 06:23:48 UTC 2019
Modified Files: src/sys/arch/amd64/include: pmap.h src/sys/arch/x86/include: cpu.h pmap.h src/sys/arch/x86/x86: pmap.c svs.c Log Message: Add support for USER_LDT in SVS. This allows us to have both enabled at the same time. We allocate an LDT for each CPU in the GDT and map an area for it, in addition to the default LDT already present. In context switches between different processes, we choose between the default or the per-cpu LDT selector: if the user set specific LDT entries, we memcpy them to the per-cpu LDT and load the per-cpu selector. Tested by Naveen Narayanan (with Wine on amd64). To generate a diff of this commit: cvs rdiff -u -r1.61 -r1.62 src/sys/arch/amd64/include/pmap.h cvs rdiff -u -r1.107 -r1.108 src/sys/arch/x86/include/cpu.h cvs rdiff -u -r1.101 -r1.102 src/sys/arch/x86/include/pmap.h cvs rdiff -u -r1.334 -r1.335 src/sys/arch/x86/x86/pmap.c cvs rdiff -u -r1.29 -r1.30 src/sys/arch/x86/x86/svs.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/include/pmap.h diff -u src/sys/arch/amd64/include/pmap.h:1.61 src/sys/arch/amd64/include/pmap.h:1.62 --- src/sys/arch/amd64/include/pmap.h:1.61 Wed May 29 16:54:41 2019 +++ src/sys/arch/amd64/include/pmap.h Wed Aug 7 06:23:48 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.h,v 1.61 2019/05/29 16:54:41 maxv Exp $ */ +/* $NetBSD: pmap.h,v 1.62 2019/08/07 06:23:48 maxv Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -175,6 +175,7 @@ extern pt_entry_t *pte_base; #define PG_X PTE_X void svs_pmap_sync(struct pmap *, int); +void svs_ldt_sync(struct pmap *); void svs_lwp_switch(struct lwp *, struct lwp *); void svs_pdir_switch(struct pmap *); void svs_init(void); Index: src/sys/arch/x86/include/cpu.h diff -u src/sys/arch/x86/include/cpu.h:1.107 src/sys/arch/x86/include/cpu.h:1.108 --- src/sys/arch/x86/include/cpu.h:1.107 Wed Jun 26 12:29:00 2019 +++ src/sys/arch/x86/include/cpu.h Wed Aug 7 06:23:48 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.107 2019/06/26 12:29:00 mgorny Exp $ */ +/* $NetBSD: cpu.h,v 1.108 2019/08/07 06:23:48 maxv Exp $ */ /* * Copyright (c) 1990 The Regents of the University of California. @@ -245,7 +245,7 @@ struct cpu_info { #ifdef SVS pd_entry_t * ci_svs_updir; paddr_t ci_svs_updirpa; - paddr_t ci_unused; + int ci_svs_ldt_sel; kmutex_t ci_svs_mtx; pd_entry_t * ci_svs_rsp0_pte; vaddr_t ci_svs_rsp0; Index: src/sys/arch/x86/include/pmap.h diff -u src/sys/arch/x86/include/pmap.h:1.101 src/sys/arch/x86/include/pmap.h:1.102 --- src/sys/arch/x86/include/pmap.h:1.101 Wed May 29 16:54:41 2019 +++ src/sys/arch/x86/include/pmap.h Wed Aug 7 06:23:48 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.h,v 1.101 2019/05/29 16:54:41 maxv Exp $ */ +/* $NetBSD: pmap.h,v 1.102 2019/08/07 06:23:48 maxv Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -191,6 +191,7 @@ extern struct slotspace slotspace; struct pcpu_entry { uint8_t gdt[MAXGDTSIZ]; + uint8_t ldt[MAXGDTSIZ]; uint8_t tss[PAGE_SIZE]; uint8_t ist0[PAGE_SIZE]; uint8_t ist1[PAGE_SIZE]; Index: src/sys/arch/x86/x86/pmap.c diff -u src/sys/arch/x86/x86/pmap.c:1.334 src/sys/arch/x86/x86/pmap.c:1.335 --- src/sys/arch/x86/x86/pmap.c:1.334 Sat Jun 1 08:12:26 2019 +++ src/sys/arch/x86/x86/pmap.c Wed Aug 7 06:23:48 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.334 2019/06/01 08:12:26 maxv Exp $ */ +/* $NetBSD: pmap.c,v 1.335 2019/08/07 06:23:48 maxv Exp $ */ /* * Copyright (c) 2008, 2010, 2016, 2017 The NetBSD Foundation, Inc. @@ -130,7 +130,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.334 2019/06/01 08:12:26 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.335 2019/08/07 06:23:48 maxv Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -2710,6 +2710,11 @@ pmap_ldt_xcall(void *arg1, void *arg2) kpreempt_disable(); pm = arg1; if (curcpu()->ci_pmap == pm) { +#if defined(SVS) && defined(USER_LDT) + if (svs_enabled) { + svs_ldt_sync(pm); + } else +#endif lldt(pm->pm_ldt_sel); } kpreempt_enable(); @@ -2947,6 +2952,11 @@ pmap_load(void) #endif #endif +#if defined(SVS) && defined(USER_LDT) + if (svs_enabled) { + svs_ldt_sync(pmap); + } else +#endif lldt(pmap->pm_ldt_sel); cpu_load_pmap(pmap, oldpmap); Index: src/sys/arch/x86/x86/svs.c diff -u src/sys/arch/x86/x86/svs.c:1.29 src/sys/arch/x86/x86/svs.c:1.30 --- src/sys/arch/x86/x86/svs.c:1.29 Wed May 29 16:54:41 2019 +++ src/sys/arch/x86/x86/svs.c Wed Aug 7 06:23:48 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: svs.c,v 1.29 2019/05/29 16:54:41 maxv Exp $ */ +/* $NetBSD: svs.c,v 1.30 2019/08/07 06:23:48 maxv Exp $ */ /* * Copyright (c) 2018-2019 The NetBSD Foundation, Inc. @@ -30,9 +30,10 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.29 2019/05/29 16:54:41 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.30 2019/08/07 06:23:48 maxv Exp $"); #include "opt_svs.h" +#include "opt_user_ldt.h" #include <sys/param.h> #include <sys/systm.h> @@ -46,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.29 #include <x86/cputypes.h> #include <machine/cpuvar.h> #include <machine/frameasm.h> +#include <machine/gdt.h> #include <uvm/uvm.h> #include <uvm/uvm_page.h> @@ -222,9 +224,6 @@ __KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.29 * * o Narrow down the entry points: hide the 'jmp handler' instructions. This * makes sense on GENERIC_KASLR kernels. - * - * o Right now there is only one global LDT, and that's not compatible with - * USER_LDT. */ bool svs_enabled __read_mostly = false; @@ -471,8 +470,13 @@ cpu_svs_init(struct cpu_info *ci) svs_rsp0_init(ci); svs_utls_init(ci); - svs_pcid_init(ci); + +#ifdef USER_LDT + mutex_enter(&cpu_lock); + ci->ci_svs_ldt_sel = ldt_alloc(&pcpuarea->ent[cid].ldt, MAXGDTSIZ); + mutex_exit(&cpu_lock); +#endif } void @@ -505,6 +509,23 @@ svs_pmap_sync(struct pmap *pmap, int ind } void +svs_ldt_sync(struct pmap *pmap) +{ + struct cpu_info *ci = curcpu(); + int sel = pmap->pm_ldt_sel; + + KASSERT(kpreempt_disabled()); + + if (__predict_false(sel != GSYSSEL(GLDT_SEL, SEL_KPL))) { + memcpy(&pcpuarea->ent[cpu_index(ci)].ldt, pmap->pm_ldt, + pmap->pm_ldt_len); + sel = ci->ci_svs_ldt_sel; + } + + lldt(sel); +} + +void svs_lwp_switch(struct lwp *oldlwp, struct lwp *newlwp) { struct cpu_info *ci = curcpu();