Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-8]: src/sys/arch Pull up the following, via patch, requested by m...
details: https://anonhg.NetBSD.org/src/rev/aaa1550ec99e
branches: netbsd-8
changeset: 435086:aaa1550ec99e
user: martin <martin%NetBSD.org@localhost>
date: Sat Jun 23 11:39:01 2018 +0000
description:
Pull up the following, via patch, requested by maxv in ticket #897:
sys/arch/amd64/amd64/locore.S 1.166 (patch)
sys/arch/i386/i386/locore.S 1.157 (patch)
sys/arch/x86/include/cpu.h 1.92 (patch)
sys/arch/x86/include/fpu.h 1.9 (patch)
sys/arch/x86/x86/fpu.c 1.33-1.39 (patch)
sys/arch/x86/x86/identcpu.c 1.72 (patch)
sys/arch/x86/x86/vm_machdep.c 1.34 (patch)
sys/arch/x86/x86/x86_machdep.c 1.116,1.117 (patch)
Support eager fpu switch, to work around INTEL-SA-00145.
Provide a sysctl machdep.fpu_eager, which gets automatically
initialized to 1 on affected CPUs.
diffstat:
sys/arch/amd64/amd64/locore.S | 16 ++-
sys/arch/i386/i386/locore.S | 17 ++-
sys/arch/x86/include/cpu.h | 3 +-
sys/arch/x86/include/fpu.h | 4 +-
sys/arch/x86/x86/fpu.c | 268 +++++++++++++++++++++++++++++++++++-----
sys/arch/x86/x86/identcpu.c | 52 +++++++-
sys/arch/x86/x86/vm_machdep.c | 8 +-
sys/arch/x86/x86/x86_machdep.c | 9 +-
8 files changed, 329 insertions(+), 48 deletions(-)
diffs (truncated from 602 to 300 lines):
diff -r d8aa027c8b98 -r aaa1550ec99e sys/arch/amd64/amd64/locore.S
--- a/sys/arch/amd64/amd64/locore.S Sat Jun 23 11:14:23 2018 +0000
+++ b/sys/arch/amd64/amd64/locore.S Sat Jun 23 11:39:01 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.S,v 1.123.6.6 2018/05/05 15:00:29 martin Exp $ */
+/* $NetBSD: locore.S,v 1.123.6.7 2018/06/23 11:39:01 martin Exp $ */
/*
* Copyright-o-rama!
@@ -1094,6 +1094,20 @@
popq %rdx
#endif
+#ifndef XEN
+ /* RDI/RSI got clobbered. */
+ movq %r13,%rdi
+ movq %r12,%rsi
+
+ pushq %rdx
+ movb _C_LABEL(x86_fpu_eager),%dl
+ testb %dl,%dl
+ jz .Lno_eagerfpu
+ callq _C_LABEL(fpu_eagerswitch)
+.Lno_eagerfpu:
+ popq %rdx
+#endif
+
/* Switch to newlwp's stack. */
movq L_PCB(%r12),%r14
movq PCB_RSP(%r14),%rsp
diff -r d8aa027c8b98 -r aaa1550ec99e sys/arch/i386/i386/locore.S
--- a/sys/arch/i386/i386/locore.S Sat Jun 23 11:14:23 2018 +0000
+++ b/sys/arch/i386/i386/locore.S Sat Jun 23 11:39:01 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.S,v 1.145.6.3 2018/03/13 15:47:44 martin Exp $ */
+/* $NetBSD: locore.S,v 1.145.6.4 2018/06/23 11:39:02 martin Exp $ */
/*
* Copyright-o-rama!
@@ -128,7 +128,7 @@
*/
#include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.145.6.3 2018/03/13 15:47:44 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.145.6.4 2018/06/23 11:39:02 martin Exp $");
#include "opt_compat_oldboot.h"
#include "opt_copy_symtab.h"
@@ -1089,6 +1089,19 @@
movl %ebp,PCB_EBP(%eax)
skip_save:
+#ifndef XEN
+ pushl %edx
+ movb _C_LABEL(x86_fpu_eager),%dl
+ testb %dl,%dl
+ jz .Lno_eagerfpu
+ pushl %edi
+ pushl %esi
+ call _C_LABEL(fpu_eagerswitch)
+ addl $8,%esp
+.Lno_eagerfpu:
+ popl %edx
+#endif
+
/* Switch to newlwp's stack. */
movl L_PCB(%edi),%ebx
movl PCB_EBP(%ebx),%ebp
diff -r d8aa027c8b98 -r aaa1550ec99e sys/arch/x86/include/cpu.h
--- a/sys/arch/x86/include/cpu.h Sat Jun 23 11:14:23 2018 +0000
+++ b/sys/arch/x86/include/cpu.h Sat Jun 23 11:39:01 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.71.2.6 2018/06/09 15:12:21 martin Exp $ */
+/* $NetBSD: cpu.h,v 1.71.2.7 2018/06/23 11:39:02 martin Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -424,6 +424,7 @@
#define FPU_SAVE_XSAVEOPT 3
extern unsigned int x86_fpu_save_size;
extern uint64_t x86_xsave_features;
+extern bool x86_fpu_eager;
extern void (*x86_cpu_idle)(void);
#define cpu_idle() (*x86_cpu_idle)()
diff -r d8aa027c8b98 -r aaa1550ec99e sys/arch/x86/include/fpu.h
--- a/sys/arch/x86/include/fpu.h Sat Jun 23 11:14:23 2018 +0000
+++ b/sys/arch/x86/include/fpu.h Sat Jun 23 11:39:01 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu.h,v 1.6 2014/02/25 22:16:52 dsl Exp $ */
+/* $NetBSD: fpu.h,v 1.6.28.1 2018/06/23 11:39:02 martin Exp $ */
#ifndef _X86_FPU_H_
#define _X86_FPU_H_
@@ -15,6 +15,8 @@
void fpusave_lwp(struct lwp *, bool);
void fpusave_cpu(bool);
+void fpu_eagerswitch(struct lwp *, struct lwp *);
+
void fpu_set_default_cw(struct lwp *, unsigned int);
void fputrap(struct trapframe *);
diff -r d8aa027c8b98 -r aaa1550ec99e sys/arch/x86/x86/fpu.c
--- a/sys/arch/x86/x86/fpu.c Sat Jun 23 11:14:23 2018 +0000
+++ b/sys/arch/x86/x86/fpu.c Sat Jun 23 11:39:01 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu.c,v 1.12.8.1 2017/12/21 19:33:15 snj Exp $ */
+/* $NetBSD: fpu.c,v 1.12.8.2 2018/06/23 11:39:02 martin Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc. All
@@ -96,7 +96,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.12.8.1 2017/12/21 19:33:15 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.12.8.2 2018/06/23 11:39:02 martin Exp $");
#include "opt_multiprocessor.h"
@@ -107,6 +107,8 @@
#include <sys/file.h>
#include <sys/proc.h>
#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/xcall.h>
#include <machine/cpu.h>
#include <machine/intr.h>
@@ -125,6 +127,8 @@
#define stts() HYPERVISOR_fpu_taskswitch(1)
#endif
+bool x86_fpu_eager __read_mostly = false;
+
static inline union savefpu *
process_fpframe(struct lwp *lwp)
{
@@ -228,6 +232,89 @@
}
static void
+fpu_clear_amd(void)
+{
+ /*
+ * AMD FPUs do not restore FIP, FDP, and FOP on fxrstor and xrstor
+ * when FSW.ES=0, leaking other threads' execution history.
+ *
+ * Clear them manually by loading a zero (fldummy). We do this
+ * unconditionally, regardless of FSW.ES.
+ *
+ * Before that, clear the ES bit in the x87 status word if it is
+ * currently set, in order to avoid causing a fault in the
+ * upcoming load.
+ *
+ * Newer generations of AMD CPUs have CPUID_Fn80000008_EBX[2],
+ * which indicates that FIP/FDP/FOP are restored (same behavior
+ * as Intel). We're not using it though.
+ */
+ if (fngetsw() & 0x80)
+ fnclex();
+ fldummy();
+}
+
+static void
+fpu_save(struct lwp *l)
+{
+ struct pcb *pcb = lwp_getpcb(l);
+
+ if (i386_use_fxsave) {
+ if (x86_xsave_features != 0)
+ xsave(&pcb->pcb_savefpu, x86_xsave_features);
+ else
+ fxsave(&pcb->pcb_savefpu);
+ } else {
+ fnsave(&pcb->pcb_savefpu);
+ }
+}
+
+static void
+fpu_restore(struct lwp *l)
+{
+ struct pcb *pcb = lwp_getpcb(l);
+
+ if (i386_use_fxsave) {
+ if (x86_xsave_features != 0) {
+ xrstor(&pcb->pcb_savefpu, x86_xsave_features);
+ } else {
+ fpu_clear_amd();
+ fxrstor(&pcb->pcb_savefpu);
+ }
+ } else {
+ frstor(&pcb->pcb_savefpu);
+ }
+}
+
+static void
+fpu_eagerrestore(struct lwp *l)
+{
+ struct pcb *pcb = lwp_getpcb(l);
+ struct cpu_info *ci = curcpu();
+
+ clts();
+ KASSERT(ci->ci_fpcurlwp == NULL);
+ KASSERT(pcb->pcb_fpcpu == NULL);
+ ci->ci_fpcurlwp = l;
+ pcb->pcb_fpcpu = ci;
+ fpu_restore(l);
+}
+
+void
+fpu_eagerswitch(struct lwp *oldlwp, struct lwp *newlwp)
+{
+ int s;
+
+ s = splhigh();
+ fpusave_cpu(true);
+ if (!(newlwp->l_flag & LW_SYSTEM))
+ fpu_eagerrestore(newlwp);
+ splx(s);
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void
send_sigill(void *rip)
{
/* No fpu (486SX) - send SIGILL */
@@ -358,6 +445,11 @@
pcb = lwp_getpcb(l);
fl = ci->ci_fpcurlwp;
if (fl != NULL) {
+ if (__predict_false(x86_fpu_eager)) {
+ panic("%s: FPU busy with EagerFPU enabled",
+ __func__);
+ }
+
/*
* It seems we can get here on Xen even if we didn't
* switch lwp. In this case do nothing
@@ -373,6 +465,11 @@
/* Save our state if on a remote CPU. */
if (pcb->pcb_fpcpu != NULL) {
+ if (__predict_false(x86_fpu_eager)) {
+ panic("%s: LWP busy with EagerFPU enabled",
+ __func__);
+ }
+
/* Explicitly disable preemption before dropping spl. */
kpreempt_disable();
splx(s);
@@ -394,28 +491,7 @@
ci->ci_fpcurlwp = l;
pcb->pcb_fpcpu = ci;
- if (i386_use_fxsave) {
- if (x86_xsave_features != 0) {
- xrstor(&pcb->pcb_savefpu, x86_xsave_features);
- } else {
- /*
- * AMD FPU's do not restore FIP, FDP, and FOP on
- * fxrstor, leaking other process's execution history.
- * Clear them manually by loading a zero.
- *
- * Clear the ES bit in the x87 status word if it is
- * currently set, in order to avoid causing a fault
- * in the upcoming load.
- */
- if (fngetsw() & 0x80)
- fnclex();
- fldummy();
-
- fxrstor(&pcb->pcb_savefpu);
- }
- } else {
- frstor(&pcb->pcb_savefpu);
- }
+ fpu_restore(l);
KASSERT(ci == curcpu());
splx(s);
@@ -442,14 +518,7 @@
if (save) {
clts();
- if (i386_use_fxsave) {
- if (x86_xsave_features != 0)
- xsave(&pcb->pcb_savefpu, x86_xsave_features);
- else
- fxsave(&pcb->pcb_savefpu);
- } else {
- fnsave(&pcb->pcb_savefpu);
- }
+ fpu_save(l);
}
stts();
@@ -516,17 +585,28 @@
Home |
Main Index |
Thread Index |
Old Index