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