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

Reply via email to