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.
This commit is contained in:
maxv 2019-10-12 06:31:03 +00:00
parent e46e37d2e1
commit 560337f76b
28 changed files with 225 additions and 362 deletions

View File

@ -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

View File

@ -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, pcb_flags)
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 cpu_info, ci_data.cpu_nsyscall)
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)

View File

@ -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

View File

@ -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) {

View File

@ -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:

View File

@ -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 */

View File

@ -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 **** */
};

View File

@ -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;

View File

@ -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_addr)
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_flag)
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, pcb_onfault)
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(struct cpu_info, ci_want_pmapload)
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)

View File

@ -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

View File

@ -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

View File

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

View File

@ -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)

View File

@ -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_
@ -98,6 +98,22 @@
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.
*
* %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.

View File

@ -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 **** */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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 *);

View File

@ -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 full)
void
cpu_offline_md(void)
{
int s;
s = splhigh();
fpusave_cpu(true);
splx(s);
return;
}
/* XXX joerg restructure and restart CPUs individually */

View File

@ -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 2019/10/04 11:47:08 maxv Exp $");
#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;
return &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;
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_features)
xsaveopt(area, xsave_features);
break;
}
stts();
}
void
@ -254,45 +284,56 @@ fpu_area_restore(void *area, uint64_t xsave_features)
}
}
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_save, uint64_t xstate)
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 x87_cw)
{
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 x87_cw)
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 *s87, struct fxsave *sxmm)
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, const struct fxsave *fpregs)
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, const struct save87 *fpregs)
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, struct fxsave *fpregs)
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, struct save87 *fpregs)
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 xstate *xstate)
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) {

View File

@ -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

View File

@ -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"
@ -139,12 +139,6 @@ cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize,
pcb1 = lwp_getpcb(l1);
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.
*/
@ -158,11 +152,8 @@ cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize,
/* 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);

View File

@ -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 full)
void
cpu_offline_md(void)
{
int s;
s = splhigh();
fpusave_cpu(true);
splx(s);
return;
}
void

View File

@ -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, struct intrframe *intrf)
KASSERT(ci != NULL);
KASSERT(intrf != NULL);
fpusave_cpu(true);
panic("%s: impossible", __func__);
}
#ifdef DDB

View File

@ -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 *mach, struct nvmm_cpu *vcpu,
}
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 *vcpu)
{
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 *vcpu)
}
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, struct nvmm_cpu *vcpu,
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, struct nvmm_cpu *vcpu,
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, struct nvmm_cpu *vcpu,
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);

View File

@ -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 *mach, struct nvmm_cpu *vcpu,
}
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 *vcpu)
{
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 *vcpu)
}
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, struct nvmm_cpu *vcpu,
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, struct nvmm_cpu *vcpu,
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, struct nvmm_cpu *vcpu,
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, struct nvmm_cpu *vcpu,
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);

View File

@ -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__)