Module Name:    src
Committed By:   maxv
Date:           Wed May 29 16:54:42 UTC 2019

Modified Files:
        src/sys/arch/amd64/amd64: cpufunc.S genassym.cf
        src/sys/arch/amd64/include: pmap.h
        src/sys/arch/x86/include: cpufunc.h pmap.h specialreg.h
        src/sys/arch/x86/x86: cpu.c svs.c x86_machdep.c

Log Message:
Add PCID support in SVS. This avoids TLB flushes during kernel<->user
transitions, which greatly reduces the performance penalty introduced by
SVS.

We use two ASIDs, 0 (kern) and 1 (user), and use invpcid to flush pages
in both ASIDs.

The read-only machdep.svs.pcid={0,1} sysctl is added, and indicates whether
SVS+PCID is in use.


To generate a diff of this commit:
cvs rdiff -u -r1.40 -r1.41 src/sys/arch/amd64/amd64/cpufunc.S
cvs rdiff -u -r1.75 -r1.76 src/sys/arch/amd64/amd64/genassym.cf
cvs rdiff -u -r1.60 -r1.61 src/sys/arch/amd64/include/pmap.h
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/x86/include/cpufunc.h
cvs rdiff -u -r1.100 -r1.101 src/sys/arch/x86/include/pmap.h
cvs rdiff -u -r1.146 -r1.147 src/sys/arch/x86/include/specialreg.h
cvs rdiff -u -r1.170 -r1.171 src/sys/arch/x86/x86/cpu.c
cvs rdiff -u -r1.28 -r1.29 src/sys/arch/x86/x86/svs.c
cvs rdiff -u -r1.126 -r1.127 src/sys/arch/x86/x86/x86_machdep.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/amd64/cpufunc.S
diff -u src/sys/arch/amd64/amd64/cpufunc.S:1.40 src/sys/arch/amd64/amd64/cpufunc.S:1.41
--- src/sys/arch/amd64/amd64/cpufunc.S:1.40	Sun May 19 08:17:02 2019
+++ src/sys/arch/amd64/amd64/cpufunc.S	Wed May 29 16:54:41 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.S,v 1.40 2019/05/19 08:17:02 maxv Exp $	*/
+/*	$NetBSD: cpufunc.S,v 1.41 2019/05/29 16:54:41 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -41,6 +41,7 @@
 #include <machine/segments.h>
 
 #include "opt_xen.h"
+#include "opt_svs.h"
 
 #include "assym.h"
 
@@ -65,6 +66,17 @@ END(x86_mfence)
 
 #ifndef XENPV
 ENTRY(invlpg)
+#ifdef SVS
+	movb	_C_LABEL(svs_pcid),%al
+	testb	%al,%al
+	jz	1f
+	pushq	%rdi
+	pushq	$PMAP_PCID_USER
+	movq	$INVPCID_ADDRESS,%rax
+	invpcid	(%rsp),%rax
+	addq	$16,%rsp
+1:	/* FALLTHROUGH */
+#endif
 	invlpg	(%rdi)
 	ret
 END(invlpg)
@@ -112,7 +124,7 @@ END(ltr)
 ENTRY(tlbflushg)
 	movq	%cr4, %rax
 	testq	$CR4_PGE, %rax
-	jz	1f
+	jz	tlbflush
 	movq	%rax, %rdx
 	andq	$~CR4_PGE, %rdx
 	movq	%rdx, %cr4
@@ -121,8 +133,19 @@ ENTRY(tlbflushg)
 END(tlbflushg)
 
 ENTRY(tlbflush)
-1:
-	movq	%cr3, %rax
+#ifdef SVS
+	movb	_C_LABEL(svs_pcid),%al
+	testb	%al,%al
+	jz	1f
+	xorq	%rax,%rax
+	pushq	%rax
+	pushq	%rax
+	movq	$INVPCID_ALL_NONGLOBAL,%rax
+	invpcid	(%rsp),%rax
+	addq	$16,%rsp
+	ret
+#endif
+1:	movq	%cr3, %rax
 	movq	%rax, %cr3
 	ret
 END(tlbflush)

Index: src/sys/arch/amd64/amd64/genassym.cf
diff -u src/sys/arch/amd64/amd64/genassym.cf:1.75 src/sys/arch/amd64/amd64/genassym.cf:1.76
--- src/sys/arch/amd64/amd64/genassym.cf:1.75	Mon May 27 17:32:36 2019
+++ src/sys/arch/amd64/amd64/genassym.cf	Wed May 29 16:54:41 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.75 2019/05/27 17:32:36 maxv Exp $
+#	$NetBSD: genassym.cf,v 1.76 2019/05/29 16:54:41 maxv Exp $
 
 #
 # Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -276,6 +276,14 @@ define	ACPI_SUSPEND_CR3	offsetof(struct 
 define	ACPI_SUSPEND_CR4	offsetof(struct cpu_info, ci_suspend_cr4)
 define	ACPI_SUSPEND_CR8	offsetof(struct cpu_info, ci_suspend_cr8)
 
+define	INVPCID_ADDRESS		INVPCID_ADDRESS
+define	INVPCID_CONTEXT		INVPCID_CONTEXT
+define	INVPCID_ALL		INVPCID_ALL
+define	INVPCID_ALL_NONGLOBAL	INVPCID_ALL_NONGLOBAL
+
+define	PMAP_PCID_USER		PMAP_PCID_USER
+define	PMAP_PCID_KERN		PMAP_PCID_KERN
+
 if NIOAPIC > 0
 define		PIC_IOAPIC		offsetof(struct pic, pic_ioapic)
 define		IOAPIC_SC_REG		offsetof(struct ioapic_softc, sc_reg)

Index: src/sys/arch/amd64/include/pmap.h
diff -u src/sys/arch/amd64/include/pmap.h:1.60 src/sys/arch/amd64/include/pmap.h:1.61
--- src/sys/arch/amd64/include/pmap.h:1.60	Sat Mar  9 09:09:56 2019
+++ src/sys/arch/amd64/include/pmap.h	Wed May 29 16:54:41 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.60 2019/03/09 09:09:56 maxv Exp $	*/
+/*	$NetBSD: pmap.h,v 1.61 2019/05/29 16:54:41 maxv Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -179,6 +179,7 @@ void svs_lwp_switch(struct lwp *, struct
 void svs_pdir_switch(struct pmap *);
 void svs_init(void);
 extern bool svs_enabled;
+extern bool svs_pcid;
 
 #include <x86/pmap.h>
 

Index: src/sys/arch/x86/include/cpufunc.h
diff -u src/sys/arch/x86/include/cpufunc.h:1.30 src/sys/arch/x86/include/cpufunc.h:1.31
--- src/sys/arch/x86/include/cpufunc.h:1.30	Sat May 11 13:40:26 2019
+++ src/sys/arch/x86/include/cpufunc.h	Wed May 29 16:54:41 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.h,v 1.30 2019/05/11 13:40:26 christos Exp $	*/
+/*	$NetBSD: cpufunc.h,v 1.31 2019/05/29 16:54:41 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998, 2007, 2019 The NetBSD Foundation, Inc.
@@ -65,6 +65,30 @@ void	invlpg(vaddr_t);
 void	wbinvd(void);
 void	breakpoint(void);
 
+#define INVPCID_ADDRESS		0
+#define INVPCID_CONTEXT		1
+#define INVPCID_ALL		2
+#define INVPCID_ALL_NONGLOBAL	3
+
+static inline void
+invpcid(register_t op, uint64_t pcid, vaddr_t va)
+{
+	struct {
+		uint64_t pcid;
+		uint64_t addr;
+	} desc = {
+		.pcid = pcid,
+		.addr = va
+	};
+
+	asm volatile (
+		"invpcid %[desc],%[op]"
+		:
+		: [desc] "m" (desc), [op] "r" (op)
+		: "memory"
+	);
+}
+
 static inline uint64_t
 rdtsc(void)
 {

Index: src/sys/arch/x86/include/pmap.h
diff -u src/sys/arch/x86/include/pmap.h:1.100 src/sys/arch/x86/include/pmap.h:1.101
--- src/sys/arch/x86/include/pmap.h:1.100	Sun Mar 10 16:30:01 2019
+++ src/sys/arch/x86/include/pmap.h	Wed May 29 16:54:41 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.100 2019/03/10 16:30:01 maxv Exp $	*/
+/*	$NetBSD: pmap.h,v 1.101 2019/05/29 16:54:41 maxv Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -210,6 +210,9 @@ struct pcpu_area {
 
 extern struct pcpu_area *pcpuarea;
 
+#define PMAP_PCID_KERN	0
+#define PMAP_PCID_USER	1
+
 /*
  * pmap data structures: see pmap.c for details of locking.
  */

Index: src/sys/arch/x86/include/specialreg.h
diff -u src/sys/arch/x86/include/specialreg.h:1.146 src/sys/arch/x86/include/specialreg.h:1.147
--- src/sys/arch/x86/include/specialreg.h:1.146	Sat May 18 08:17:39 2019
+++ src/sys/arch/x86/include/specialreg.h	Wed May 29 16:54:41 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: specialreg.h,v 1.146 2019/05/18 08:17:39 maxv Exp $	*/
+/*	$NetBSD: specialreg.h,v 1.147 2019/05/29 16:54:41 maxv Exp $	*/
 
 /*
  * Copyright (c) 2014-2019 The NetBSD Foundation, Inc.
@@ -88,6 +88,13 @@
 #define CCR1_RPL	0x01	/* enables RPLSET and RPLVAL# pins */
 
 /*
+ * CR3
+ */
+#define CR3_PCID		__BITS(11,0)
+#define CR3_PA			__BITS(62,12)
+#define CR3_NO_TLB_FLUSH	__BIT(63)
+
+/*
  * CR4
  */
 #define CR4_VME		0x00000001 /* virtual 8086 mode extension enable */

Index: src/sys/arch/x86/x86/cpu.c
diff -u src/sys/arch/x86/x86/cpu.c:1.170 src/sys/arch/x86/x86/cpu.c:1.171
--- src/sys/arch/x86/x86/cpu.c:1.170	Mon May 27 18:36:37 2019
+++ src/sys/arch/x86/x86/cpu.c	Wed May 29 16:54:41 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.170 2019/05/27 18:36:37 maxv Exp $	*/
+/*	$NetBSD: cpu.c,v 1.171 2019/05/29 16:54:41 maxv Exp $	*/
 
 /*
  * Copyright (c) 2000-2012 NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.170 2019/05/27 18:36:37 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.171 2019/05/29 16:54:41 maxv Exp $");
 
 #include "opt_ddb.h"
 #include "opt_mpbios.h"		/* for MPDEBUG */
@@ -613,6 +613,12 @@ cpu_init(struct cpu_info *ci)
 	if (cpu_feature[5] & CPUID_SEF_SMAP)
 		cr4 |= CR4_SMAP;
 
+#ifdef SVS
+	/* If PCID is supported, enable it */
+	if (svs_pcid)
+		cr4 |= CR4_PCIDE;
+#endif
+
 	if (cr4) {
 		cr4 |= rcr4();
 		lcr4(cr4);

Index: src/sys/arch/x86/x86/svs.c
diff -u src/sys/arch/x86/x86/svs.c:1.28 src/sys/arch/x86/x86/svs.c:1.29
--- src/sys/arch/x86/x86/svs.c:1.28	Mon May 27 18:36:37 2019
+++ src/sys/arch/x86/x86/svs.c	Wed May 29 16:54:41 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: svs.c,v 1.28 2019/05/27 18:36:37 maxv Exp $	*/
+/*	$NetBSD: svs.c,v 1.29 2019/05/29 16:54:41 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.28 2019/05/27 18:36:37 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.29 2019/05/29 16:54:41 maxv Exp $");
 
 #include "opt_svs.h"
 
@@ -228,6 +228,10 @@ __KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.28
  */
 
 bool svs_enabled __read_mostly = false;
+bool svs_pcid __read_mostly = false;
+
+static uint64_t svs_pcid_kcr3 __read_mostly;
+static uint64_t svs_pcid_ucr3 __read_mostly;
 
 struct svs_utls {
 	paddr_t kpdirpa;
@@ -405,6 +409,19 @@ svs_utls_init(struct cpu_info *ci)
 }
 
 static void
+svs_pcid_init(struct cpu_info *ci)
+{
+	if (!svs_pcid) {
+		return;
+	}
+
+	svs_pcid_ucr3 = __SHIFTIN(PMAP_PCID_USER, CR3_PCID) | CR3_NO_TLB_FLUSH;
+	svs_pcid_kcr3 = __SHIFTIN(PMAP_PCID_KERN, CR3_PCID) | CR3_NO_TLB_FLUSH;
+
+	ci->ci_svs_updirpa |= svs_pcid_ucr3;
+}
+
+static void
 svs_range_add(struct cpu_info *ci, vaddr_t va, size_t size, bool global)
 {
 	size_t i, n;
@@ -454,6 +471,8 @@ cpu_svs_init(struct cpu_info *ci)
 
 	svs_rsp0_init(ci);
 	svs_utls_init(ci);
+
+	svs_pcid_init(ci);
 }
 
 void
@@ -523,11 +542,14 @@ svs_lwp_switch(struct lwp *oldlwp, struc
 	utls->scratch = 0;
 
 	/*
-	 * Enter the user rsp0. We don't need to flush the TLB here, since
-	 * the user page tables are not loaded.
+	 * Enter the user rsp0. If we're using PCID we must flush the user VA,
+	 * if we aren't it will be flushed during the next CR3 reload.
 	 */
 	pte = ci->ci_svs_rsp0_pte;
 	*pte = L1_BASE[pl1_i(va)];
+	if (svs_pcid) {
+		invpcid(INVPCID_ADDRESS, PMAP_PCID_USER, ci->ci_svs_rsp0);
+	}
 }
 
 static inline pt_entry_t
@@ -558,7 +580,7 @@ svs_pdir_switch(struct pmap *pmap)
 
 	/* Update the info in the UTLS page */
 	utls = (struct svs_utls *)ci->ci_svs_utls;
-	utls->kpdirpa = pmap_pdirpa(pmap, 0);
+	utls->kpdirpa = pmap_pdirpa(pmap, 0) | svs_pcid_kcr3;
 
 	mutex_enter(&ci->ci_svs_mtx);
 
@@ -569,6 +591,10 @@ svs_pdir_switch(struct pmap *pmap)
 	}
 
 	mutex_exit(&ci->ci_svs_mtx);
+
+	if (svs_pcid) {
+		invpcid(INVPCID_CONTEXT, PMAP_PCID_USER, 0);
+	}
 }
 
 static void
@@ -641,5 +667,11 @@ svs_init(void)
 		}
 	}
 
+	if ((cpu_info_primary.ci_feat_val[1] & CPUID2_PCID) &&
+	    (cpu_info_primary.ci_feat_val[5] & CPUID_SEF_INVPCID)) {
+		svs_pcid = true;
+		lcr4(rcr4() | CR4_PCIDE);
+	}
+
 	svs_enable();
 }

Index: src/sys/arch/x86/x86/x86_machdep.c
diff -u src/sys/arch/x86/x86/x86_machdep.c:1.126 src/sys/arch/x86/x86/x86_machdep.c:1.127
--- src/sys/arch/x86/x86/x86_machdep.c:1.126	Sun May 19 08:17:02 2019
+++ src/sys/arch/x86/x86/x86_machdep.c	Wed May 29 16:54:41 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: x86_machdep.c,v 1.126 2019/05/19 08:17:02 maxv Exp $	*/
+/*	$NetBSD: x86_machdep.c,v 1.127 2019/05/29 16:54:41 maxv Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi,
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.126 2019/05/19 08:17:02 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.127 2019/05/29 16:54:41 maxv Exp $");
 
 #include "opt_modular.h"
 #include "opt_physmem.h"
@@ -1293,12 +1293,18 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysc
 		       CTLTYPE_NODE, "svs", NULL,
 		       NULL, 0, NULL, 0,
 		       CTL_MACHDEP, CTL_CREATE);
-	sysctl_createv(clog, 0, &svs_rnode, &svs_rnode,
+	sysctl_createv(clog, 0, &svs_rnode, NULL,
 		       CTLFLAG_PERMANENT,
 		       CTLTYPE_BOOL, "enabled",
 		       SYSCTL_DESCR("Whether the kernel uses SVS"),
 		       NULL, 0, &svs_enabled, 0,
 		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &svs_rnode, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_BOOL, "pcid",
+		       SYSCTL_DESCR("Whether SVS uses PCID"),
+		       NULL, 0, &svs_pcid, 0,
+		       CTL_CREATE, CTL_EOL);
 #endif
 
 #ifndef XEN

Reply via email to