Module Name: src
Committed By: maxv
Date: Sat Oct 12 06:31:04 UTC 2019
Modified Files:
src/sys/arch/amd64/amd64: amd64_trap.S genassym.cf locore.S machdep.c
spl.S
src/sys/arch/amd64/include: frameasm.h pcb.h proc.h
src/sys/arch/i386/i386: genassym.cf i386_trap.S locore.S machdep.c
spl.S
src/sys/arch/i386/include: frameasm.h pcb.h proc.h
src/sys/arch/x86/acpi: acpi_wakeup.c
src/sys/arch/x86/include: cpu.h fpu.h
src/sys/arch/x86/x86: cpu.c fpu.c ipi.c vm_machdep.c
src/sys/arch/xen/x86: cpu.c xen_ipi.c
src/sys/dev/nvmm/x86: nvmm_x86_svm.c nvmm_x86_vmx.c
src/sys/sys: param.h
Log Message:
Rewrite the FPU code on x86. This greatly simplifies the logic and removes
the dependency on IPL_HIGH. NVMM is updated accordingly. Posted on
port-amd64 a week ago.
Bump the kernel version to 9.99.16.
To generate a diff of this commit:
cvs rdiff -u -r1.48 -r1.49 src/sys/arch/amd64/amd64/amd64_trap.S
cvs rdiff -u -r1.76 -r1.77 src/sys/arch/amd64/amd64/genassym.cf
cvs rdiff -u -r1.188 -r1.189 src/sys/arch/amd64/amd64/locore.S
cvs rdiff -u -r1.336 -r1.337 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.40 -r1.41 src/sys/arch/amd64/amd64/spl.S
cvs rdiff -u -r1.44 -r1.45 src/sys/arch/amd64/include/frameasm.h
cvs rdiff -u -r1.29 -r1.30 src/sys/arch/amd64/include/pcb.h
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/amd64/include/proc.h
cvs rdiff -u -r1.113 -r1.114 src/sys/arch/i386/i386/genassym.cf
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/i386/i386/i386_trap.S
cvs rdiff -u -r1.171 -r1.172 src/sys/arch/i386/i386/locore.S
cvs rdiff -u -r1.820 -r1.821 src/sys/arch/i386/i386/machdep.c
cvs rdiff -u -r1.48 -r1.49 src/sys/arch/i386/i386/spl.S
cvs rdiff -u -r1.28 -r1.29 src/sys/arch/i386/include/frameasm.h
cvs rdiff -u -r1.58 -r1.59 src/sys/arch/i386/include/pcb.h
cvs rdiff -u -r1.45 -r1.46 src/sys/arch/i386/include/proc.h
cvs rdiff -u -r1.50 -r1.51 src/sys/arch/x86/acpi/acpi_wakeup.c
cvs rdiff -u -r1.109 -r1.110 src/sys/arch/x86/include/cpu.h
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/x86/include/fpu.h
cvs rdiff -u -r1.172 -r1.173 src/sys/arch/x86/x86/cpu.c
cvs rdiff -u -r1.57 -r1.58 src/sys/arch/x86/x86/fpu.c
cvs rdiff -u -r1.27 -r1.28 src/sys/arch/x86/x86/ipi.c
cvs rdiff -u -r1.37 -r1.38 src/sys/arch/x86/x86/vm_machdep.c
cvs rdiff -u -r1.129 -r1.130 src/sys/arch/xen/x86/cpu.c
cvs rdiff -u -r1.32 -r1.33 src/sys/arch/xen/x86/xen_ipi.c
cvs rdiff -u -r1.49 -r1.50 src/sys/dev/nvmm/x86/nvmm_x86_svm.c
cvs rdiff -u -r1.38 -r1.39 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c
cvs rdiff -u -r1.616 -r1.617 src/sys/sys/param.h
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/amd64_trap.S
diff -u src/sys/arch/amd64/amd64/amd64_trap.S:1.48 src/sys/arch/amd64/amd64/amd64_trap.S:1.49
--- src/sys/arch/amd64/amd64/amd64_trap.S:1.48 Sat May 18 13:32:12 2019
+++ src/sys/arch/amd64/amd64/amd64_trap.S Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: amd64_trap.S,v 1.48 2019/05/18 13:32:12 maxv Exp $ */
+/* $NetBSD: amd64_trap.S,v 1.49 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 1998, 2007, 2008, 2017 The NetBSD Foundation, Inc.
@@ -672,6 +672,7 @@ calltrap:
jmp .Lalltraps_checkast /* re-check ASTs */
3: CHECK_DEFERRED_SWITCH
jnz 9f
+ HANDLE_DEFERRED_FPU
6:
#ifdef DIAGNOSTIC
Index: src/sys/arch/amd64/amd64/genassym.cf
diff -u src/sys/arch/amd64/amd64/genassym.cf:1.76 src/sys/arch/amd64/amd64/genassym.cf:1.77
--- src/sys/arch/amd64/amd64/genassym.cf:1.76 Wed May 29 16:54:41 2019
+++ src/sys/arch/amd64/amd64/genassym.cf Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-# $NetBSD: genassym.cf,v 1.76 2019/05/29 16:54:41 maxv Exp $
+# $NetBSD: genassym.cf,v 1.77 2019/10/12 06:31:03 maxv Exp $
#
# Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -164,6 +164,7 @@ define PAGE_SIZE PAGE_SIZE
define MDL_IRET MDL_IRET
define MDL_COMPAT32 MDL_COMPAT32
+define MDL_FPU_IN_CPU MDL_FPU_IN_CPU
define P_FLAG offsetof(struct proc, p_flag)
define P_RASLIST offsetof(struct proc, p_raslist)
@@ -188,6 +189,7 @@ define PCB_FLAGS offsetof(struct pcb, p
define PCB_COMPAT32 PCB_COMPAT32
define PCB_FS offsetof(struct pcb, pcb_fs)
define PCB_GS offsetof(struct pcb, pcb_gs)
+define PCB_SAVEFPU offsetof(struct pcb, pcb_savefpu)
define TF_RDI offsetof(struct trapframe, tf_rdi)
define TF_RSI offsetof(struct trapframe, tf_rsi)
@@ -244,7 +246,6 @@ define CPU_INFO_NSYSCALL offsetof(struct
define CPU_INFO_NTRAP offsetof(struct cpu_info, ci_data.cpu_ntrap)
define CPU_INFO_NINTR offsetof(struct cpu_info, ci_data.cpu_nintr)
define CPU_INFO_CURPRIORITY offsetof(struct cpu_info, ci_schedstate.spc_curpriority)
-define CPU_INFO_FPCURLWP offsetof(struct cpu_info, ci_fpcurlwp)
define CPU_INFO_GDT offsetof(struct cpu_info, ci_gdt)
define CPU_INFO_ILEVEL offsetof(struct cpu_info, ci_ilevel)
Index: src/sys/arch/amd64/amd64/locore.S
diff -u src/sys/arch/amd64/amd64/locore.S:1.188 src/sys/arch/amd64/amd64/locore.S:1.189
--- src/sys/arch/amd64/amd64/locore.S:1.188 Fri Oct 4 11:47:07 2019
+++ src/sys/arch/amd64/amd64/locore.S Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.S,v 1.188 2019/10/04 11:47:07 maxv Exp $ */
+/* $NetBSD: locore.S,v 1.189 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright-o-rama!
@@ -1170,29 +1170,10 @@ ENTRY(cpu_switchto)
movq %rax,TF_RIP(%rbx)
.Lno_RAS:
- /*
- * Restore cr0 including FPU state (may have CR0_TS set). Note that
- * IPL_SCHED prevents from FPU interrupt altering the LWP's saved cr0.
- */
#ifndef XENPV
+ /* Raise the IPL to IPL_HIGH. Dropping the priority is deferred until
+ * mi_switch(), when cpu_switchto() returns. XXX Still needed? */
movl $IPL_HIGH,CPUVAR(ILEVEL)
- movl PCB_CR0(%r14),%ecx /* has CR0_TS clear */
- movq %cr0,%rdx
-
- /*
- * If our floating point registers are on a different CPU,
- * set CR0_TS so we'll trap rather than reuse bogus state.
- */
- cmpq CPUVAR(FPCURLWP),%r12
- je .Lskip_TS
- orq $CR0_TS,%rcx
-.Lskip_TS:
-
- /* Reloading CR0 is very expensive - avoid if possible. */
- cmpq %rdx,%rcx
- je .Lskip_CR0
- movq %rcx,%cr0
-.Lskip_CR0:
/* The 32bit LWPs are handled differently. */
testl $PCB_COMPAT32,PCB_FLAGS(%r14)
@@ -1305,6 +1286,8 @@ ENTRY(handle_syscall)
jne .Lspl_error
#endif
+ HANDLE_DEFERRED_FPU
+
/*
* Decide if we need to take a slow path. That's the case when we
* want to reload %cs and %ss on a 64bit LWP (MDL_IRET set), or when
Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.336 src/sys/arch/amd64/amd64/machdep.c:1.337
--- src/sys/arch/amd64/amd64/machdep.c:1.336 Wed Aug 21 20:30:36 2019
+++ src/sys/arch/amd64/amd64/machdep.c Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.336 2019/08/21 20:30:36 skrll Exp $ */
+/* $NetBSD: machdep.c,v 1.337 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -110,7 +110,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.336 2019/08/21 20:30:36 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.337 2019/10/12 06:31:03 maxv Exp $");
#include "opt_modular.h"
#include "opt_user_ldt.h"
@@ -442,18 +442,9 @@ x86_64_tls_switch(struct lwp *l)
uint64_t zero = 0;
/*
- * Raise the IPL to IPL_HIGH.
- * FPU IPIs can alter the LWP's saved cr0. Dropping the priority
- * is deferred until mi_switch(), when cpu_switchto() returns.
+ * Raise the IPL to IPL_HIGH. XXX Still needed?
*/
(void)splhigh();
- /*
- * If our floating point registers are on a different CPU,
- * set CR0_TS so we'll trap rather than reuse bogus state.
- */
- if (l != ci->ci_fpcurlwp) {
- HYPERVISOR_fpu_taskswitch(1);
- }
/* Update segment registers */
if (pcb->pcb_flags & PCB_COMPAT32) {
Index: src/sys/arch/amd64/amd64/spl.S
diff -u src/sys/arch/amd64/amd64/spl.S:1.40 src/sys/arch/amd64/amd64/spl.S:1.41
--- src/sys/arch/amd64/amd64/spl.S:1.40 Thu Feb 14 08:18:25 2019
+++ src/sys/arch/amd64/amd64/spl.S Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: spl.S,v 1.40 2019/02/14 08:18:25 cherry Exp $ */
+/* $NetBSD: spl.S,v 1.41 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 2003 Wasabi Systems, Inc.
@@ -397,6 +397,7 @@ LABEL(doreti_checkast)
3:
CHECK_DEFERRED_SWITCH
jnz 9f
+ HANDLE_DEFERRED_FPU
6:
INTRFASTEXIT
9:
Index: src/sys/arch/amd64/include/frameasm.h
diff -u src/sys/arch/amd64/include/frameasm.h:1.44 src/sys/arch/amd64/include/frameasm.h:1.45
--- src/sys/arch/amd64/include/frameasm.h:1.44 Sat May 18 13:32:12 2019
+++ src/sys/arch/amd64/include/frameasm.h Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: frameasm.h,v 1.44 2019/05/18 13:32:12 maxv Exp $ */
+/* $NetBSD: frameasm.h,v 1.45 2019/10/12 06:31:03 maxv Exp $ */
#ifndef _AMD64_MACHINE_FRAMEASM_H
#define _AMD64_MACHINE_FRAMEASM_H
@@ -246,4 +246,18 @@
#define CHECK_ASTPENDING(reg) cmpl $0, L_MD_ASTPENDING(reg)
#define CLEAR_ASTPENDING(reg) movl $0, L_MD_ASTPENDING(reg)
+/*
+ * If the FPU state is not in the CPU, restore it. Executed with interrupts
+ * disabled.
+ *
+ * %r14 is curlwp, must not be modified
+ * %rbx must not be modified
+ */
+#define HANDLE_DEFERRED_FPU \
+ testl $MDL_FPU_IN_CPU,L_MD_FLAGS(%r14) ; \
+ jnz 1f ; \
+ call _C_LABEL(fpu_handle_deferred) ; \
+ orl $MDL_FPU_IN_CPU,L_MD_FLAGS(%r14) ; \
+1:
+
#endif /* _AMD64_MACHINE_FRAMEASM_H */
Index: src/sys/arch/amd64/include/pcb.h
diff -u src/sys/arch/amd64/include/pcb.h:1.29 src/sys/arch/amd64/include/pcb.h:1.30
--- src/sys/arch/amd64/include/pcb.h:1.29 Thu Jul 26 09:29:08 2018
+++ src/sys/arch/amd64/include/pcb.h Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: pcb.h,v 1.29 2018/07/26 09:29:08 maxv Exp $ */
+/* $NetBSD: pcb.h,v 1.30 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -96,7 +96,6 @@ struct pcb {
uint32_t pcb_unused[8]; /* unused */
- struct cpu_info *pcb_fpcpu; /* cpu holding our fp state. */
union savefpu pcb_savefpu __aligned(64); /* floating point state */
/* **** DO NOT ADD ANYTHING HERE **** */
};
Index: src/sys/arch/amd64/include/proc.h
diff -u src/sys/arch/amd64/include/proc.h:1.22 src/sys/arch/amd64/include/proc.h:1.23
--- src/sys/arch/amd64/include/proc.h:1.22 Sat Feb 25 13:34:21 2017
+++ src/sys/arch/amd64/include/proc.h Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: proc.h,v 1.22 2017/02/25 13:34:21 kamil Exp $ */
+/* $NetBSD: proc.h,v 1.23 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 1991 Regents of the University of California.
@@ -55,6 +55,7 @@ struct mdlwp {
#define MDL_COMPAT32 0x0008 /* i386, always return via iret */
#define MDL_IRET 0x0010 /* force return via iret, not sysret */
+#define MDL_FPU_IN_CPU 0x0020 /* the FPU state is in the CPU */
struct mdproc {
int md_flags;
Index: src/sys/arch/i386/i386/genassym.cf
diff -u src/sys/arch/i386/i386/genassym.cf:1.113 src/sys/arch/i386/i386/genassym.cf:1.114
--- src/sys/arch/i386/i386/genassym.cf:1.113 Sat Mar 9 08:42:25 2019
+++ src/sys/arch/i386/i386/genassym.cf Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-# $NetBSD: genassym.cf,v 1.113 2019/03/09 08:42:25 maxv Exp $
+# $NetBSD: genassym.cf,v 1.114 2019/10/12 06:31:03 maxv Exp $
#
# Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -165,6 +165,7 @@ define L_PCB offsetof(struct lwp, l_ad
define L_FLAG offsetof(struct lwp, l_flag)
define L_PROC offsetof(struct lwp, l_proc)
define L_MD_REGS offsetof(struct lwp, l_md.md_regs)
+define L_MD_FLAGS offsetof(struct lwp, l_md.md_flags)
define L_CTXSWTCH offsetof(struct lwp, l_ctxswtch)
define L_MD_ASTPENDING offsetof(struct lwp, l_md.md_astpending)
define L_CPU offsetof(struct lwp, l_cpu)
@@ -176,6 +177,8 @@ define P_FLAG offsetof(struct proc, p_
define P_RASLIST offsetof(struct proc, p_raslist)
define P_MD_SYSCALL offsetof(struct proc, p_md.md_syscall)
+define MDL_FPU_IN_CPU MDL_FPU_IN_CPU
+
define LW_SYSTEM LW_SYSTEM
define GUFS_SEL GUFS_SEL
@@ -200,6 +203,7 @@ define PCB_ONFAULT offsetof(struct pcb,
define PCB_FSD offsetof(struct pcb, pcb_fsd)
define PCB_GSD offsetof(struct pcb, pcb_gsd)
define PCB_IOMAP offsetof(struct pcb, pcb_iomap)
+define PCB_SAVEFPU offsetof(struct pcb, pcb_savefpu)
define TF_CS offsetof(struct trapframe, tf_cs)
define TF_EIP offsetof(struct trapframe, tf_eip)
@@ -251,7 +255,6 @@ define CPU_INFO_WANT_PMAPLOAD offsetof(s
define CPU_INFO_TLBSTATE offsetof(struct cpu_info, ci_tlbstate)
define TLBSTATE_VALID TLBSTATE_VALID
define CPU_INFO_CURLWP offsetof(struct cpu_info, ci_curlwp)
-define CPU_INFO_FPCURLWP offsetof(struct cpu_info, ci_fpcurlwp)
define CPU_INFO_CURLDT offsetof(struct cpu_info, ci_curldt)
define CPU_INFO_IDLELWP offsetof(struct cpu_info, ci_data.cpu_idlelwp)
define CPU_INFO_PMAP offsetof(struct cpu_info, ci_pmap)
Index: src/sys/arch/i386/i386/i386_trap.S
diff -u src/sys/arch/i386/i386/i386_trap.S:1.19 src/sys/arch/i386/i386/i386_trap.S:1.20
--- src/sys/arch/i386/i386/i386_trap.S:1.19 Fri Oct 4 15:28:00 2019
+++ src/sys/arch/i386/i386/i386_trap.S Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: i386_trap.S,v 1.19 2019/10/04 15:28:00 maxv Exp $ */
+/* $NetBSD: i386_trap.S,v 1.20 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright 2002 (c) Wasabi Systems, Inc.
@@ -66,7 +66,7 @@
#if 0
#include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: i386_trap.S,v 1.19 2019/10/04 15:28:00 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i386_trap.S,v 1.20 2019/10/12 06:31:03 maxv Exp $");
#endif
/*
@@ -436,10 +436,10 @@ calltrap:
#ifdef XEN
STIC(%eax)
- jz 6f
+ jz 22f
call _C_LABEL(stipending)
testl %eax,%eax
- jz 6f
+ jz 22f
/* process pending interrupts */
CLI(%eax)
movl CPUVAR(ILEVEL),%ebx
@@ -448,15 +448,18 @@ calltrap:
movl %ebx,%eax /* get cpl */
movl CPUVAR(XUNMASK)(,%eax,4),%eax
andl CPUVAR(XPENDING),%eax /* any non-masked bits left? */
- jz 7f
+ jz 11f
bsrl %eax,%eax
btrl %eax,CPUVAR(XPENDING)
movl CPUVAR(XSOURCES)(,%eax,4),%eax
jmp *IS_RESUME(%eax)
-7: movl %ebx,CPUVAR(ILEVEL) /* restore cpl */
+11: movl %ebx,CPUVAR(ILEVEL) /* restore cpl */
jmp .Lalltraps_checkusr
+22:
#endif
+ HANDLE_DEFERRED_FPU
+
6:
#ifdef DIAGNOSTIC
cmpl CPUVAR(ILEVEL),%ebx
Index: src/sys/arch/i386/i386/locore.S
diff -u src/sys/arch/i386/i386/locore.S:1.171 src/sys/arch/i386/i386/locore.S:1.172
--- src/sys/arch/i386/i386/locore.S:1.171 Fri Oct 4 15:28:00 2019
+++ src/sys/arch/i386/i386/locore.S Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.S,v 1.171 2019/10/04 15:28:00 maxv Exp $ */
+/* $NetBSD: locore.S,v 1.172 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright-o-rama!
@@ -128,7 +128,7 @@
*/
#include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.171 2019/10/04 15:28:00 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.172 2019/10/12 06:31:03 maxv Exp $");
#include "opt_copy_symtab.h"
#include "opt_ddb.h"
@@ -1187,33 +1187,14 @@ skip_save:
movl %eax,TF_EIP(%ecx)
no_RAS:
- /*
- * Restore cr0 (including FPU state). Raise the IPL to IPL_HIGH.
- * FPU IPIs can alter the LWP's saved cr0. Dropping the priority
- * is deferred until mi_switch(), when cpu_switchto() returns.
- */
#ifdef XENPV
pushl %edi
call _C_LABEL(i386_tls_switch)
addl $4,%esp
#else
+ /* Raise the IPL to IPL_HIGH. Dropping the priority is deferred until
+ * mi_switch(), when cpu_switchto() returns. XXX Still needed? */
movl $IPL_HIGH,CPUVAR(ILEVEL)
- movl PCB_CR0(%ebx),%ecx /* has CR0_TS clear */
- movl %cr0,%edx
-
- /*
- * If our floating point registers are on a different CPU,
- * set CR0_TS so we'll trap rather than reuse bogus state.
- */
- cmpl CPUVAR(FPCURLWP),%edi
- je skip_TS
- orl $CR0_TS,%ecx
-skip_TS:
-
- /* Reloading CR0 is very expensive - avoid if possible. */
- cmpl %edx,%ecx
- je switch_return
- movl %ecx,%cr0
#endif
switch_return:
@@ -1322,6 +1303,8 @@ IDTVEC(syscall)
jne 3f
#endif
+ HANDLE_DEFERRED_FPU
+
INTRFASTEXIT
#ifdef DIAGNOSTIC
Index: src/sys/arch/i386/i386/machdep.c
diff -u src/sys/arch/i386/i386/machdep.c:1.820 src/sys/arch/i386/i386/machdep.c:1.821
--- src/sys/arch/i386/i386/machdep.c:1.820 Sun May 19 08:46:15 2019
+++ src/sys/arch/i386/i386/machdep.c Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.820 2019/05/19 08:46:15 maxv Exp $ */
+/* $NetBSD: machdep.c,v 1.821 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009, 2017
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.820 2019/05/19 08:46:15 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.821 2019/10/12 06:31:03 maxv Exp $");
#include "opt_beep.h"
#include "opt_compat_freebsd.h"
@@ -509,20 +509,10 @@ i386_tls_switch(lwp_t *l)
struct pcb *pcb = lwp_getpcb(l);
/*
- * Raise the IPL to IPL_HIGH.
- * FPU IPIs can alter the LWP's saved cr0. Dropping the priority
- * is deferred until mi_switch(), when cpu_switchto() returns.
+ * Raise the IPL to IPL_HIGH. XXX Still needed?
*/
(void)splhigh();
- /*
- * If our floating point registers are on a different CPU,
- * set CR0_TS so we'll trap rather than reuse bogus state.
- */
- if (l != ci->ci_fpcurlwp) {
- HYPERVISOR_fpu_taskswitch(1);
- }
-
/* Update TLS segment pointers */
update_descriptor(&ci->ci_gdt[GUFS_SEL],
(union descriptor *)&pcb->pcb_fsd);
Index: src/sys/arch/i386/i386/spl.S
diff -u src/sys/arch/i386/i386/spl.S:1.48 src/sys/arch/i386/i386/spl.S:1.49
--- src/sys/arch/i386/i386/spl.S:1.48 Fri Oct 4 15:28:00 2019
+++ src/sys/arch/i386/i386/spl.S Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: spl.S,v 1.48 2019/10/04 15:28:00 maxv Exp $ */
+/* $NetBSD: spl.S,v 1.49 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: spl.S,v 1.48 2019/10/04 15:28:00 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spl.S,v 1.49 2019/10/12 06:31:03 maxv Exp $");
#include "opt_ddb.h"
#include "opt_spldebug.h"
@@ -326,6 +326,7 @@ END(doreti_checkast)
3:
CHECK_DEFERRED_SWITCH
jnz 9f
+ HANDLE_DEFERRED_FPU
6:
#ifdef XEN
STIC(%eax)
Index: src/sys/arch/i386/include/frameasm.h
diff -u src/sys/arch/i386/include/frameasm.h:1.28 src/sys/arch/i386/include/frameasm.h:1.29
--- src/sys/arch/i386/include/frameasm.h:1.28 Thu Feb 14 08:18:25 2019
+++ src/sys/arch/i386/include/frameasm.h Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: frameasm.h,v 1.28 2019/02/14 08:18:25 cherry Exp $ */
+/* $NetBSD: frameasm.h,v 1.29 2019/10/12 06:31:03 maxv Exp $ */
#ifndef _I386_FRAMEASM_H_
#define _I386_FRAMEASM_H_
@@ -99,6 +99,22 @@
#define CLEAR_ASTPENDING(reg) movl $0, L_MD_ASTPENDING(reg)
/*
+ * If the FPU state is not in the CPU, restore it. Executed with interrupts
+ * disabled.
+ *
+ * %ebx must not be modified
+ */
+#define HANDLE_DEFERRED_FPU \
+ movl CPUVAR(CURLWP),%eax ; \
+ testl $MDL_FPU_IN_CPU,L_MD_FLAGS(%eax) ; \
+ jnz 1f ; \
+ pushl %eax ; \
+ call _C_LABEL(fpu_handle_deferred) ; \
+ popl %eax ; \
+ orl $MDL_FPU_IN_CPU,L_MD_FLAGS(%eax) ; \
+1:
+
+/*
* IDEPTH_INCR:
* increase ci_idepth and switch to the interrupt stack if necessary.
* note that the initial value of ci_idepth is -1.
Index: src/sys/arch/i386/include/pcb.h
diff -u src/sys/arch/i386/include/pcb.h:1.58 src/sys/arch/i386/include/pcb.h:1.59
--- src/sys/arch/i386/include/pcb.h:1.58 Thu Jul 26 09:29:08 2018
+++ src/sys/arch/i386/include/pcb.h Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: pcb.h,v 1.58 2018/07/26 09:29:08 maxv Exp $ */
+/* $NetBSD: pcb.h,v 1.59 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 1998, 2009 The NetBSD Foundation, Inc.
@@ -99,7 +99,6 @@ struct pcb {
int not_used[15];
/* floating point state */
- struct cpu_info *pcb_fpcpu; /* cpu holding our fp state. */
union savefpu pcb_savefpu __aligned(64);
/* **** DO NOT ADD ANYTHING HERE **** */
Index: src/sys/arch/i386/include/proc.h
diff -u src/sys/arch/i386/include/proc.h:1.45 src/sys/arch/i386/include/proc.h:1.46
--- src/sys/arch/i386/include/proc.h:1.45 Sat Feb 25 13:34:21 2017
+++ src/sys/arch/i386/include/proc.h Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: proc.h,v 1.45 2017/02/25 13:34:21 kamil Exp $ */
+/* $NetBSD: proc.h,v 1.46 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 1991 Regents of the University of California.
@@ -43,6 +43,8 @@
struct pmap;
struct vm_page;
+#define MDL_FPU_IN_CPU 0x0020 /* the FPU state is in the CPU */
+
struct mdlwp {
struct trapframe *md_regs; /* registers on current frame */
int md_flags; /* machine-dependent flags */
Index: src/sys/arch/x86/acpi/acpi_wakeup.c
diff -u src/sys/arch/x86/acpi/acpi_wakeup.c:1.50 src/sys/arch/x86/acpi/acpi_wakeup.c:1.51
--- src/sys/arch/x86/acpi/acpi_wakeup.c:1.50 Mon Jun 17 16:34:02 2019
+++ src/sys/arch/x86/acpi/acpi_wakeup.c Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_wakeup.c,v 1.50 2019/06/17 16:34:02 jmcneill Exp $ */
+/* $NetBSD: acpi_wakeup.c,v 1.51 2019/10/12 06:31:03 maxv Exp $ */
/*-
* Copyright (c) 2002, 2011 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.50 2019/06/17 16:34:02 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.51 2019/10/12 06:31:03 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -249,7 +249,7 @@ acpi_cpu_sleep(struct cpu_info *ci)
KASSERT(ci == curcpu());
s = splhigh();
- fpusave_cpu(true);
+ fpu_save();
x86_disable_intr();
/*
@@ -313,7 +313,7 @@ acpi_md_sleep(int state)
AcpiSetFirmwareWakingVector(acpi_wakeup_paddr, 0);
s = splhigh();
- fpusave_cpu(true);
+ fpu_save();
x86_disable_intr();
#ifdef MULTIPROCESSOR
Index: src/sys/arch/x86/include/cpu.h
diff -u src/sys/arch/x86/include/cpu.h:1.109 src/sys/arch/x86/include/cpu.h:1.110
--- src/sys/arch/x86/include/cpu.h:1.109 Thu Oct 3 05:06:29 2019
+++ src/sys/arch/x86/include/cpu.h Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.109 2019/10/03 05:06:29 maxv Exp $ */
+/* $NetBSD: cpu.h,v 1.110 2019/10/12 06:31:03 maxv Exp $ */
/*
* Copyright (c) 1990 The Regents of the University of California.
@@ -119,7 +119,6 @@ struct cpu_info {
*/
struct cpu_info *ci_next; /* next cpu */
struct lwp *ci_curlwp; /* current owner of the processor */
- struct lwp *ci_fpcurlwp; /* current owner of the FPU */
cpuid_t ci_cpuid; /* our CPU ID */
uint32_t ci_acpiid; /* our ACPI/MADT ID */
uint32_t ci_initapicid; /* our initial APIC ID */
Index: src/sys/arch/x86/include/fpu.h
diff -u src/sys/arch/x86/include/fpu.h:1.18 src/sys/arch/x86/include/fpu.h:1.19
--- src/sys/arch/x86/include/fpu.h:1.18 Fri Oct 4 11:47:08 2019
+++ src/sys/arch/x86/include/fpu.h Sat Oct 12 06:31:03 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu.h,v 1.18 2019/10/04 11:47:08 maxv Exp $ */
+/* $NetBSD: fpu.h,v 1.19 2019/10/12 06:31:03 maxv Exp $ */
#ifndef _X86_FPU_H_
#define _X86_FPU_H_
@@ -17,8 +17,7 @@ void fpuinit_mxcsr_mask(void);
void fpu_area_save(void *, uint64_t);
void fpu_area_restore(void *, uint64_t);
-void fpusave_lwp(struct lwp *, bool);
-void fpusave_cpu(bool);
+void fpu_save(void);
void fpu_set_default_cw(struct lwp *, unsigned int);
@@ -28,7 +27,8 @@ void fpudna(struct trapframe *);
void fpu_clear(struct lwp *, unsigned int);
void fpu_sigreset(struct lwp *);
-void fpu_save_area_fork(struct pcb *, const struct pcb *);
+void fpu_lwp_fork(struct lwp *, struct lwp *);
+void fpu_lwp_abandon(struct lwp *l);
void process_write_fpregs_xmm(struct lwp *, const struct fxsave *);
void process_write_fpregs_s87(struct lwp *, const struct save87 *);
Index: src/sys/arch/x86/x86/cpu.c
diff -u src/sys/arch/x86/x86/cpu.c:1.172 src/sys/arch/x86/x86/cpu.c:1.173
--- src/sys/arch/x86/x86/cpu.c:1.172 Fri Aug 30 07:53:47 2019
+++ src/sys/arch/x86/x86/cpu.c Sat Oct 12 06:31:04 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.172 2019/08/30 07:53:47 mrg Exp $ */
+/* $NetBSD: cpu.c,v 1.173 2019/10/12 06:31:04 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.172 2019/08/30 07:53:47 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.173 2019/10/12 06:31:04 maxv Exp $");
#include "opt_ddb.h"
#include "opt_mpbios.h" /* for MPDEBUG */
@@ -986,15 +986,14 @@ cpu_debug_dump(void)
"";
db_printf("addr %sdev id flags ipis curlwp "
- "fpcurlwp\n", sixtyfour64space);
+ "\n", sixtyfour64space);
for (CPU_INFO_FOREACH(cii, ci)) {
- db_printf("%p %s %ld %x %x %10p %10p\n",
+ db_printf("%p %s %ld %x %x %10p\n",
ci,
ci->ci_dev == NULL ? "BOOT" : device_xname(ci->ci_dev),
(long)ci->ci_cpuid,
ci->ci_flags, ci->ci_ipis,
- ci->ci_curlwp,
- ci->ci_fpcurlwp);
+ ci->ci_curlwp);
}
}
#endif
@@ -1159,11 +1158,7 @@ cpu_init_msrs(struct cpu_info *ci, bool
void
cpu_offline_md(void)
{
- int s;
-
- s = splhigh();
- fpusave_cpu(true);
- splx(s);
+ return;
}
/* XXX joerg restructure and restart CPUs individually */
Index: src/sys/arch/x86/x86/fpu.c
diff -u src/sys/arch/x86/x86/fpu.c:1.57 src/sys/arch/x86/x86/fpu.c:1.58
--- src/sys/arch/x86/x86/fpu.c:1.57 Fri Oct 4 11:47:08 2019
+++ src/sys/arch/x86/x86/fpu.c Sat Oct 12 06:31:04 2019
@@ -1,11 +1,11 @@
-/* $NetBSD: fpu.c,v 1.57 2019/10/04 11:47:08 maxv Exp $ */
+/* $NetBSD: fpu.c,v 1.58 2019/10/12 06:31:04 maxv Exp $ */
/*
- * Copyright (c) 2008 The NetBSD Foundation, Inc. All
+ * Copyright (c) 2008, 2019 The NetBSD Foundation, Inc. All
* rights reserved.
*
* This code is derived from software developed for The NetBSD Foundation
- * by Andrew Doran.
+ * by Andrew Doran and Maxime Villard.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -96,7 +96,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.57 2019/10/04 11:47:08 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.58 2019/10/12 06:31:04 maxv Exp $");
#include "opt_multiprocessor.h"
@@ -126,14 +126,44 @@ __KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.57
#define stts() HYPERVISOR_fpu_taskswitch(1)
#endif
+void fpu_handle_deferred(void);
+void fpu_switch(struct lwp *, struct lwp *);
+
uint32_t x86_fpu_mxcsr_mask __read_mostly = 0;
static inline union savefpu *
-lwp_fpuarea(struct lwp *l)
+fpu_lwp_area(struct lwp *l)
+{
+ struct pcb *pcb = lwp_getpcb(l);
+ union savefpu *area = &pcb->pcb_savefpu;
+
+ KASSERT((l->l_flag & LW_SYSTEM) == 0);
+ if (l == curlwp) {
+ fpu_save();
+ }
+ KASSERT(!(l->l_md.md_flags & MDL_FPU_IN_CPU));
+
+ return area;
+}
+
+/*
+ * Bring curlwp's FPU state in memory. It will get installed back in the CPU
+ * when returning to userland.
+ */
+void
+fpu_save(void)
{
+ struct lwp *l = curlwp;
struct pcb *pcb = lwp_getpcb(l);
+ union savefpu *area = &pcb->pcb_savefpu;
- return &pcb->pcb_savefpu;
+ kpreempt_disable();
+ if (l->l_md.md_flags & MDL_FPU_IN_CPU) {
+ KASSERT((l->l_flag & LW_SYSTEM) == 0);
+ fpu_area_save(area, x86_xsave_features);
+ l->l_md.md_flags &= ~MDL_FPU_IN_CPU;
+ }
+ kpreempt_enable();
}
void
@@ -213,8 +243,6 @@ fpu_errata_amd(void)
void
fpu_area_save(void *area, uint64_t xsave_features)
{
- clts();
-
switch (x86_fpu_save) {
case FPU_SAVE_FSAVE:
fnsave(area);
@@ -229,6 +257,8 @@ fpu_area_save(void *area, uint64_t xsave
xsaveopt(area, xsave_features);
break;
}
+
+ stts();
}
void
@@ -254,45 +284,56 @@ fpu_area_restore(void *area, uint64_t xs
}
}
-static void
-fpu_lwp_install(struct lwp *l)
+void
+fpu_handle_deferred(void)
{
- struct pcb *pcb = lwp_getpcb(l);
- struct cpu_info *ci = curcpu();
-
- KASSERT(ci->ci_fpcurlwp == NULL);
- KASSERT(pcb->pcb_fpcpu == NULL);
- ci->ci_fpcurlwp = l;
- pcb->pcb_fpcpu = ci;
+ struct pcb *pcb = lwp_getpcb(curlwp);
fpu_area_restore(&pcb->pcb_savefpu, x86_xsave_features);
}
-void fpu_switch(struct lwp *, struct lwp *);
-
void
fpu_switch(struct lwp *oldlwp, struct lwp *newlwp)
{
- int s;
+ struct pcb *pcb;
- s = splhigh();
-#ifdef DIAGNOSTIC
- if (oldlwp != NULL) {
- struct pcb *pcb = lwp_getpcb(oldlwp);
- struct cpu_info *ci = curcpu();
- if (pcb->pcb_fpcpu == NULL) {
- KASSERT(ci->ci_fpcurlwp != oldlwp);
- } else if (pcb->pcb_fpcpu == ci) {
- KASSERT(ci->ci_fpcurlwp == oldlwp);
- } else {
- panic("%s: oldlwp's state installed elsewhere",
- __func__);
- }
+ if ((oldlwp != NULL) && (oldlwp->l_md.md_flags & MDL_FPU_IN_CPU)) {
+ KASSERT(!(oldlwp->l_flag & LW_SYSTEM));
+ pcb = lwp_getpcb(oldlwp);
+ fpu_area_save(&pcb->pcb_savefpu, x86_xsave_features);
+ oldlwp->l_md.md_flags &= ~MDL_FPU_IN_CPU;
}
-#endif
- fpusave_cpu(true);
- if (!(newlwp->l_flag & LW_SYSTEM))
- fpu_lwp_install(newlwp);
- splx(s);
+ KASSERT(!(newlwp->l_md.md_flags & MDL_FPU_IN_CPU));
+}
+
+void
+fpu_lwp_fork(struct lwp *l1, struct lwp *l2)
+{
+ struct pcb *pcb2 = lwp_getpcb(l2);
+ union savefpu *fpu_save;
+
+ /* Kernel threads have no FPU. */
+ if (__predict_false(l2->l_flag & LW_SYSTEM)) {
+ return;
+ }
+ /* For init(8). */
+ if (__predict_false(l1->l_flag & LW_SYSTEM)) {
+ memset(&pcb2->pcb_savefpu, 0, x86_fpu_save_size);
+ return;
+ }
+
+ fpu_save = fpu_lwp_area(l1);
+ memcpy(&pcb2->pcb_savefpu, fpu_save, x86_fpu_save_size);
+ l2->l_md.md_flags &= ~MDL_FPU_IN_CPU;
+}
+
+void
+fpu_lwp_abandon(struct lwp *l)
+{
+ KASSERT(l == curlwp);
+ kpreempt_disable();
+ l->l_md.md_flags &= ~MDL_FPU_IN_CPU;
+ stts();
+ kpreempt_enable();
}
/* -------------------------------------------------------------------------- */
@@ -399,11 +440,7 @@ fputrap(struct trapframe *frame)
panic("fpu trap from kernel, trapframe %p\n", frame);
}
- /*
- * At this point, fpcurlwp should be curlwp. If it wasn't, the TS bit
- * should be set, and we should have gotten a DNA exception.
- */
- KASSERT(curcpu()->ci_fpcurlwp == curlwp);
+ KASSERT(curlwp->l_md.md_flags & MDL_FPU_IN_CPU);
if (frame->tf_trapno == T_XMM) {
uint32_t mxcsr;
@@ -440,104 +477,16 @@ fputrap(struct trapframe *frame)
(*curlwp->l_proc->p_emul->e_trapsignal)(curlwp, &ksi);
}
-/*
- * Implement device not available (DNA) exception. Called with interrupts still
- * disabled.
- */
void
fpudna(struct trapframe *frame)
{
- struct cpu_info *ci = curcpu();
- int s;
-
- if (!USERMODE(frame->tf_cs)) {
- panic("fpudna from kernel, ip %p, trapframe %p\n",
- (void *)X86_TF_RIP(frame), frame);
- }
-
- /* Install the LWP's FPU state. */
- s = splhigh();
- fpu_lwp_install(ci->ci_curlwp);
- splx(s);
+ panic("fpudna from %s, ip %p, trapframe %p",
+ USERMODE(frame->tf_cs) ? "userland" : "kernel",
+ (void *)X86_TF_RIP(frame), frame);
}
/* -------------------------------------------------------------------------- */
-/*
- * Save current CPU's FPU state. Must be called at IPL_HIGH.
- */
-void
-fpusave_cpu(bool save)
-{
- struct cpu_info *ci;
- struct pcb *pcb;
- struct lwp *l;
-
- KASSERT(curcpu()->ci_ilevel == IPL_HIGH);
-
- ci = curcpu();
- l = ci->ci_fpcurlwp;
- if (l == NULL) {
- return;
- }
- pcb = lwp_getpcb(l);
-
- if (save) {
- fpu_area_save(&pcb->pcb_savefpu, x86_xsave_features);
- }
-
- stts();
- pcb->pcb_fpcpu = NULL;
- ci->ci_fpcurlwp = NULL;
-}
-
-/*
- * Save l's FPU state, which may be on this processor or another processor.
- * It may take some time, so we avoid disabling preemption where possible.
- * Caller must know that the target LWP is stopped, otherwise this routine
- * may race against it.
- */
-void
-fpusave_lwp(struct lwp *l, bool save)
-{
- struct pcb *pcb = lwp_getpcb(l);
- struct cpu_info *oci;
- int s, spins, ticks;
-
- spins = 0;
- ticks = hardclock_ticks;
- for (;;) {
- s = splhigh();
- oci = pcb->pcb_fpcpu;
- if (oci == NULL) {
- splx(s);
- break;
- }
- if (oci == curcpu()) {
- KASSERT(oci->ci_fpcurlwp == l);
- fpusave_cpu(save);
- splx(s);
- break;
- }
- splx(s);
-#ifdef XENPV
- if (xen_send_ipi(oci, XEN_IPI_SYNCH_FPU) != 0) {
- panic("xen_send_ipi(%s, XEN_IPI_SYNCH_FPU) failed.",
- cpu_name(oci));
- }
-#else
- x86_send_ipi(oci, X86_IPI_SYNCH_FPU);
-#endif
- while (pcb->pcb_fpcpu == oci && ticks == hardclock_ticks) {
- x86_pause();
- spins++;
- }
- if (spins > 100000000) {
- panic("fpusave_lwp: did not");
- }
- }
-}
-
static inline void
fpu_xstate_reload(union savefpu *fpu_save, uint64_t xstate)
{
@@ -552,7 +501,7 @@ fpu_xstate_reload(union savefpu *fpu_sav
void
fpu_set_default_cw(struct lwp *l, unsigned int x87_cw)
{
- union savefpu *fpu_save = lwp_fpuarea(l);
+ union savefpu *fpu_save = fpu_lwp_area(l);
struct pcb *pcb = lwp_getpcb(l);
if (i386_use_fxsave) {
@@ -571,18 +520,9 @@ fpu_clear(struct lwp *l, unsigned int x8
{
union savefpu *fpu_save;
struct pcb *pcb;
- int s;
KASSERT(l == curlwp);
- KASSERT((l->l_flag & LW_SYSTEM) == 0);
- fpu_save = lwp_fpuarea(l);
- pcb = lwp_getpcb(l);
-
- s = splhigh();
-
- KASSERT(pcb->pcb_fpcpu == NULL || pcb->pcb_fpcpu == curcpu());
- fpusave_cpu(false);
- KASSERT(pcb->pcb_fpcpu == NULL);
+ fpu_save = fpu_lwp_area(l);
switch (x86_fpu_save) {
case FPU_SAVE_FSAVE:
@@ -608,16 +548,14 @@ fpu_clear(struct lwp *l, unsigned int x8
break;
}
+ pcb = lwp_getpcb(l);
pcb->pcb_fpu_dflt_cw = x87_cw;
-
- fpu_lwp_install(l);
- splx(s);
}
void
fpu_sigreset(struct lwp *l)
{
- union savefpu *fpu_save = lwp_fpuarea(l);
+ union savefpu *fpu_save = fpu_lwp_area(l);
struct pcb *pcb = lwp_getpcb(l);
/*
@@ -635,17 +573,6 @@ fpu_sigreset(struct lwp *l)
}
}
-void
-fpu_save_area_fork(struct pcb *pcb2, const struct pcb *pcb1)
-{
- const uint8_t *src = (const uint8_t *)&pcb1->pcb_savefpu;
- uint8_t *dst = (uint8_t *)&pcb2->pcb_savefpu;
-
- memcpy(dst, src, x86_fpu_save_size);
-
- KASSERT(pcb2->pcb_fpcpu == NULL);
-}
-
/* -------------------------------------------------------------------------- */
static void
@@ -769,10 +696,7 @@ process_s87_to_xmm(const struct save87 *
void
process_write_fpregs_xmm(struct lwp *l, const struct fxsave *fpregs)
{
- union savefpu *fpu_save;
-
- fpusave_lwp(l, true);
- fpu_save = lwp_fpuarea(l);
+ union savefpu *fpu_save = fpu_lwp_area(l);
if (i386_use_fxsave) {
memcpy(&fpu_save->sv_xmm, fpregs, sizeof(fpu_save->sv_xmm));
@@ -792,17 +716,12 @@ process_write_fpregs_xmm(struct lwp *l,
void
process_write_fpregs_s87(struct lwp *l, const struct save87 *fpregs)
{
- union savefpu *fpu_save;
+ union savefpu *fpu_save = fpu_lwp_area(l);
if (i386_use_fxsave) {
- /* Save so we don't lose the xmm registers */
- fpusave_lwp(l, true);
- fpu_save = lwp_fpuarea(l);
process_s87_to_xmm(fpregs, &fpu_save->sv_xmm);
fpu_xstate_reload(fpu_save, XCR0_X87 | XCR0_SSE);
} else {
- fpusave_lwp(l, false);
- fpu_save = lwp_fpuarea(l);
memcpy(&fpu_save->sv_87, fpregs, sizeof(fpu_save->sv_87));
}
}
@@ -810,10 +729,7 @@ process_write_fpregs_s87(struct lwp *l,
void
process_read_fpregs_xmm(struct lwp *l, struct fxsave *fpregs)
{
- union savefpu *fpu_save;
-
- fpusave_lwp(l, true);
- fpu_save = lwp_fpuarea(l);
+ union savefpu *fpu_save = fpu_lwp_area(l);
if (i386_use_fxsave) {
memcpy(fpregs, &fpu_save->sv_xmm, sizeof(fpu_save->sv_xmm));
@@ -826,10 +742,7 @@ process_read_fpregs_xmm(struct lwp *l, s
void
process_read_fpregs_s87(struct lwp *l, struct save87 *fpregs)
{
- union savefpu *fpu_save;
-
- fpusave_lwp(l, true);
- fpu_save = lwp_fpuarea(l);
+ union savefpu *fpu_save = fpu_lwp_area(l);
if (i386_use_fxsave) {
memset(fpregs, 0, sizeof(*fpregs));
@@ -842,10 +755,7 @@ process_read_fpregs_s87(struct lwp *l, s
int
process_read_xstate(struct lwp *l, struct xstate *xstate)
{
- union savefpu *fpu_save;
-
- fpusave_lwp(l, true);
- fpu_save = lwp_fpuarea(l);
+ union savefpu *fpu_save = fpu_lwp_area(l);
if (x86_fpu_save == FPU_SAVE_FSAVE) {
/* Convert from legacy FSAVE format. */
@@ -924,10 +834,7 @@ process_verify_xstate(const struct xstat
int
process_write_xstate(struct lwp *l, const struct xstate *xstate)
{
- union savefpu *fpu_save;
-
- fpusave_lwp(l, true);
- fpu_save = lwp_fpuarea(l);
+ union savefpu *fpu_save = fpu_lwp_area(l);
/* Convert data into legacy FSAVE format. */
if (x86_fpu_save == FPU_SAVE_FSAVE) {
Index: src/sys/arch/x86/x86/ipi.c
diff -u src/sys/arch/x86/x86/ipi.c:1.27 src/sys/arch/x86/x86/ipi.c:1.28
--- src/sys/arch/x86/x86/ipi.c:1.27 Wed Feb 8 10:08:26 2017
+++ src/sys/arch/x86/x86/ipi.c Sat Oct 12 06:31:04 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ipi.c,v 1.27 2017/02/08 10:08:26 maxv Exp $ */
+/* $NetBSD: ipi.c,v 1.28 2019/10/12 06:31:04 maxv Exp $ */
/*-
* Copyright (c) 2000, 2008, 2009 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipi.c,v 1.27 2017/02/08 10:08:26 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipi.c,v 1.28 2019/10/12 06:31:04 maxv Exp $");
#include "opt_mtrr.h"
@@ -176,7 +176,7 @@ static void
x86_ipi_synch_fpu(struct cpu_info *ci)
{
- fpusave_cpu(true);
+ panic("%s: impossible", __func__);
}
#ifdef MTRR
Index: src/sys/arch/x86/x86/vm_machdep.c
diff -u src/sys/arch/x86/x86/vm_machdep.c:1.37 src/sys/arch/x86/x86/vm_machdep.c:1.38
--- src/sys/arch/x86/x86/vm_machdep.c:1.37 Mon Feb 11 14:59:33 2019
+++ src/sys/arch/x86/x86/vm_machdep.c Sat Oct 12 06:31:04 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: vm_machdep.c,v 1.37 2019/02/11 14:59:33 cherry Exp $ */
+/* $NetBSD: vm_machdep.c,v 1.38 2019/10/12 06:31:04 maxv Exp $ */
/*-
* Copyright (c) 1982, 1986 The Regents of the University of California.
@@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.37 2019/02/11 14:59:33 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.38 2019/10/12 06:31:04 maxv Exp $");
#include "opt_mtrr.h"
@@ -140,12 +140,6 @@ cpu_lwp_fork(struct lwp *l1, struct lwp
pcb2 = lwp_getpcb(l2);
/*
- * If parent LWP was using FPU, then we have to save the FPU h/w
- * state to PCB so that we can copy it.
- */
- fpusave_lwp(l1, true);
-
- /*
* Sync the PCB before we copy it.
*/
if (l1 == curlwp) {
@@ -158,11 +152,8 @@ cpu_lwp_fork(struct lwp *l1, struct lwp
/* Copy the PCB from parent, except the FPU state. */
memcpy(pcb2, pcb1, offsetof(struct pcb, pcb_savefpu));
- /* FPU state not installed. */
- pcb2->pcb_fpcpu = NULL;
-
- /* Copy FPU state. */
- fpu_save_area_fork(pcb2, pcb1);
+ /* Fork the FPU state. */
+ fpu_lwp_fork(l1, l2);
/* Never inherit CPU Debug Registers */
pcb2->pcb_dbregs = NULL;
@@ -260,8 +251,8 @@ void
cpu_lwp_free(struct lwp *l, int proc)
{
- /* If we were using the FPU, forget about it. */
- fpusave_lwp(l, false);
+ /* Abandon the FPU state. */
+ fpu_lwp_abandon(l);
/* Abandon the dbregs state. */
x86_dbregs_abandon(l);
Index: src/sys/arch/xen/x86/cpu.c
diff -u src/sys/arch/xen/x86/cpu.c:1.129 src/sys/arch/xen/x86/cpu.c:1.130
--- src/sys/arch/xen/x86/cpu.c:1.129 Sat Mar 9 08:42:25 2019
+++ src/sys/arch/xen/x86/cpu.c Sat Oct 12 06:31:04 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.129 2019/03/09 08:42:25 maxv Exp $ */
+/* $NetBSD: cpu.c,v 1.130 2019/10/12 06:31:04 maxv Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.129 2019/03/09 08:42:25 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.130 2019/10/12 06:31:04 maxv Exp $");
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
@@ -759,15 +759,14 @@ cpu_debug_dump(void)
struct cpu_info *ci;
CPU_INFO_ITERATOR cii;
- db_printf("addr dev id flags ipis curlwp fpcurlwp\n");
+ db_printf("addr dev id flags ipis curlwp\n");
for (CPU_INFO_FOREACH(cii, ci)) {
- db_printf("%p %s %ld %x %x %10p %10p\n",
+ db_printf("%p %s %ld %x %x %10p\n",
ci,
ci->ci_dev == NULL ? "BOOT" : device_xname(ci->ci_dev),
(long)ci->ci_cpuid,
ci->ci_flags, ci->ci_ipis,
- ci->ci_curlwp,
- ci->ci_fpcurlwp);
+ ci->ci_curlwp);
}
}
#endif /* DDB */
@@ -1066,11 +1065,7 @@ cpu_init_msrs(struct cpu_info *ci, bool
void
cpu_offline_md(void)
{
- int s;
-
- s = splhigh();
- fpusave_cpu(true);
- splx(s);
+ return;
}
void
Index: src/sys/arch/xen/x86/xen_ipi.c
diff -u src/sys/arch/xen/x86/xen_ipi.c:1.32 src/sys/arch/xen/x86/xen_ipi.c:1.33
--- src/sys/arch/xen/x86/xen_ipi.c:1.32 Sat Feb 2 12:32:55 2019
+++ src/sys/arch/xen/x86/xen_ipi.c Sat Oct 12 06:31:04 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: xen_ipi.c,v 1.32 2019/02/02 12:32:55 cherry Exp $ */
+/* $NetBSD: xen_ipi.c,v 1.33 2019/10/12 06:31:04 maxv Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
@@ -33,10 +33,10 @@
/*
* Based on: x86/ipi.c
- * __KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.32 2019/02/02 12:32:55 cherry Exp $");
+ * __KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.33 2019/10/12 06:31:04 maxv Exp $");
*/
-__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.32 2019/02/02 12:32:55 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.33 2019/10/12 06:31:04 maxv Exp $");
#include "opt_ddb.h"
@@ -237,7 +237,7 @@ xen_ipi_synch_fpu(struct cpu_info *ci, s
KASSERT(ci != NULL);
KASSERT(intrf != NULL);
- fpusave_cpu(true);
+ panic("%s: impossible", __func__);
}
#ifdef DDB
Index: src/sys/dev/nvmm/x86/nvmm_x86_svm.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.49 src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.50
--- src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.49 Fri Oct 4 12:17:05 2019
+++ src/sys/dev/nvmm/x86/nvmm_x86_svm.c Sat Oct 12 06:31:04 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_x86_svm.c,v 1.49 2019/10/04 12:17:05 maxv Exp $ */
+/* $NetBSD: nvmm_x86_svm.c,v 1.50 2019/10/12 06:31:04 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.49 2019/10/04 12:17:05 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.50 2019/10/12 06:31:04 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -541,8 +541,6 @@ struct svm_cpudata {
uint64_t sfmask;
uint64_t fsbase;
uint64_t kernelgsbase;
- bool ts_set;
- struct xsave_header hfpu __aligned(64);
/* Intr state */
bool int_window_exit;
@@ -1137,6 +1135,9 @@ svm_exit_xsetbv(struct nvmm_machine *mac
}
cpudata->gxcr0 = val;
+ if (svm_xcr0_mask != 0) {
+ wrxcr(0, cpudata->gxcr0);
+ }
svm_inkernel_advance(cpudata->vmcb);
return;
@@ -1159,9 +1160,7 @@ svm_vcpu_guest_fpu_enter(struct nvmm_cpu
{
struct svm_cpudata *cpudata = vcpu->cpudata;
- cpudata->ts_set = (rcr0() & CR0_TS) != 0;
-
- fpu_area_save(&cpudata->hfpu, svm_xcr0_mask);
+ fpu_save();
fpu_area_restore(&cpudata->gfpu, svm_xcr0_mask);
if (svm_xcr0_mask != 0) {
@@ -1181,11 +1180,6 @@ svm_vcpu_guest_fpu_leave(struct nvmm_cpu
}
fpu_area_save(&cpudata->gfpu, svm_xcr0_mask);
- fpu_area_restore(&cpudata->hfpu, svm_xcr0_mask);
-
- if (cpudata->ts_set) {
- stts();
- }
}
static void
@@ -1327,6 +1321,7 @@ svm_vcpu_run(struct nvmm_machine *mach,
svm_vcpu_guest_dbregs_enter(vcpu);
svm_vcpu_guest_misc_enter(vcpu);
+ svm_vcpu_guest_fpu_enter(vcpu);
while (1) {
if (cpudata->gtlb_want_flush) {
@@ -1342,9 +1337,7 @@ svm_vcpu_run(struct nvmm_machine *mach,
s = splhigh();
machgen = svm_htlb_flush(machdata, cpudata);
- svm_vcpu_guest_fpu_enter(vcpu);
svm_vmrun(cpudata->vmcb_pa, cpudata->gprs);
- svm_vcpu_guest_fpu_leave(vcpu);
svm_htlb_flush_ack(cpudata, machgen);
splx(s);
@@ -1437,6 +1430,7 @@ svm_vcpu_run(struct nvmm_machine *mach,
cpudata->gtsc = rdtsc() + vmcb->ctrl.tsc_offset;
+ svm_vcpu_guest_fpu_leave(vcpu);
svm_vcpu_guest_misc_leave(vcpu);
svm_vcpu_guest_dbregs_leave(vcpu);
Index: src/sys/dev/nvmm/x86/nvmm_x86_vmx.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.38 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.39
--- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.38 Fri Oct 4 12:17:05 2019
+++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Sat Oct 12 06:31:04 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_x86_vmx.c,v 1.38 2019/10/04 12:17:05 maxv Exp $ */
+/* $NetBSD: nvmm_x86_vmx.c,v 1.39 2019/10/12 06:31:04 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.38 2019/10/04 12:17:05 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.39 2019/10/12 06:31:04 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -733,8 +733,6 @@ struct vmx_cpudata {
uint64_t cstar;
uint64_t sfmask;
uint64_t kernelgsbase;
- bool ts_set;
- struct xsave_header hfpu __aligned(64);
/* Intr state */
bool int_window_exit;
@@ -1659,6 +1657,9 @@ vmx_exit_xsetbv(struct nvmm_machine *mac
}
cpudata->gxcr0 = val;
+ if (vmx_xcr0_mask != 0) {
+ wrxcr(0, cpudata->gxcr0);
+ }
vmx_inkernel_advance();
return;
@@ -1703,9 +1704,7 @@ vmx_vcpu_guest_fpu_enter(struct nvmm_cpu
{
struct vmx_cpudata *cpudata = vcpu->cpudata;
- cpudata->ts_set = (rcr0() & CR0_TS) != 0;
-
- fpu_area_save(&cpudata->hfpu, vmx_xcr0_mask);
+ fpu_save();
fpu_area_restore(&cpudata->gfpu, vmx_xcr0_mask);
if (vmx_xcr0_mask != 0) {
@@ -1725,11 +1724,6 @@ vmx_vcpu_guest_fpu_leave(struct nvmm_cpu
}
fpu_area_save(&cpudata->gfpu, vmx_xcr0_mask);
- fpu_area_restore(&cpudata->hfpu, vmx_xcr0_mask);
-
- if (cpudata->ts_set) {
- stts();
- }
}
static void
@@ -1911,6 +1905,7 @@ vmx_vcpu_run(struct nvmm_machine *mach,
vmx_vcpu_guest_dbregs_enter(vcpu);
vmx_vcpu_guest_misc_enter(vcpu);
+ vmx_vcpu_guest_fpu_enter(vcpu);
while (1) {
if (cpudata->gtlb_want_flush) {
@@ -1927,7 +1922,6 @@ vmx_vcpu_run(struct nvmm_machine *mach,
s = splhigh();
machgen = vmx_htlb_flush(machdata, cpudata);
- vmx_vcpu_guest_fpu_enter(vcpu);
lcr2(cpudata->gcr2);
if (launched) {
ret = vmx_vmresume(cpudata->gprs);
@@ -1935,7 +1929,6 @@ vmx_vcpu_run(struct nvmm_machine *mach,
ret = vmx_vmlaunch(cpudata->gprs);
}
cpudata->gcr2 = rcr2();
- vmx_vcpu_guest_fpu_leave(vcpu);
vmx_htlb_flush_ack(cpudata, machgen);
splx(s);
@@ -2039,6 +2032,7 @@ vmx_vcpu_run(struct nvmm_machine *mach,
cpudata->gtsc = vmx_vmread(VMCS_TSC_OFFSET) + rdtsc();
+ vmx_vcpu_guest_fpu_leave(vcpu);
vmx_vcpu_guest_misc_leave(vcpu);
vmx_vcpu_guest_dbregs_leave(vcpu);
Index: src/sys/sys/param.h
diff -u src/sys/sys/param.h:1.616 src/sys/sys/param.h:1.617
--- src/sys/sys/param.h:1.616 Mon Sep 30 21:18:00 2019
+++ src/sys/sys/param.h Sat Oct 12 06:31:04 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: param.h,v 1.616 2019/09/30 21:18:00 kamil Exp $ */
+/* $NetBSD: param.h,v 1.617 2019/10/12 06:31:04 maxv Exp $ */
/*-
* Copyright (c) 1982, 1986, 1989, 1993
@@ -67,7 +67,7 @@
* 2.99.9 (299000900)
*/
-#define __NetBSD_Version__ 999001500 /* NetBSD 9.99.15 */
+#define __NetBSD_Version__ 999001600 /* NetBSD 9.99.16 */
#define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__)