Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Add support for USER_LDT in SVS. This allows us to ...



details:   https://anonhg.NetBSD.org/src/rev/2b9c18cc1768
branches:  trunk
changeset: 463049:2b9c18cc1768
user:      maxv <maxv%NetBSD.org@localhost>
date:      Wed Aug 07 06:23:48 2019 +0000

description:
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).

diffstat:

 sys/arch/amd64/include/pmap.h |   3 ++-
 sys/arch/x86/include/cpu.h    |   4 ++--
 sys/arch/x86/include/pmap.h   |   3 ++-
 sys/arch/x86/x86/pmap.c       |  14 ++++++++++++--
 sys/arch/x86/x86/svs.c        |  33 +++++++++++++++++++++++++++------
 5 files changed, 45 insertions(+), 12 deletions(-)

diffs (172 lines):

diff -r 64bde05b69df -r 2b9c18cc1768 sys/arch/amd64/include/pmap.h
--- a/sys/arch/amd64/include/pmap.h     Wed Aug 07 01:47:18 2019 +0000
+++ b/sys/arch/amd64/include/pmap.h     Wed Aug 07 06:23:48 2019 +0000
@@ -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 @@
 #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);
diff -r 64bde05b69df -r 2b9c18cc1768 sys/arch/x86/include/cpu.h
--- a/sys/arch/x86/include/cpu.h        Wed Aug 07 01:47:18 2019 +0000
+++ b/sys/arch/x86/include/cpu.h        Wed Aug 07 06:23:48 2019 +0000
@@ -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 @@
 #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;
diff -r 64bde05b69df -r 2b9c18cc1768 sys/arch/x86/include/pmap.h
--- a/sys/arch/x86/include/pmap.h       Wed Aug 07 01:47:18 2019 +0000
+++ b/sys/arch/x86/include/pmap.h       Wed Aug 07 06:23:48 2019 +0000
@@ -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 @@
 
 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];
diff -r 64bde05b69df -r 2b9c18cc1768 sys/arch/x86/x86/pmap.c
--- a/sys/arch/x86/x86/pmap.c   Wed Aug 07 01:47:18 2019 +0000
+++ b/sys/arch/x86/x86/pmap.c   Wed Aug 07 06:23:48 2019 +0000
@@ -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 @@
        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 @@
 #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);
diff -r 64bde05b69df -r 2b9c18cc1768 sys/arch/x86/x86/svs.c
--- a/sys/arch/x86/x86/svs.c    Wed Aug 07 01:47:18 2019 +0000
+++ b/sys/arch/x86/x86/svs.c    Wed Aug 07 06:23:48 2019 +0000
@@ -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 @@
 #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 @@
  *
  *  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 @@
 
        svs_rsp0_init(ci);
        svs_utls_init(ci);
+       svs_pcid_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 @@
 }
 
 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();



Home | Main Index | Thread Index | Old Index