Proper FPU exeptions support for Xen. Should fix FPU issues reported by

various users.
This commit is contained in:
bouyer 2008-06-29 21:00:08 +00:00
parent f0fae83846
commit fe0fcf52f5
3 changed files with 36 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: fpu.c,v 1.25 2008/05/30 12:17:11 ad Exp $ */
/* $NetBSD: fpu.c,v 1.26 2008/06/29 21:00:08 bouyer Exp $ */
/*-
* Copyright (c) 1991 The Regents of the University of California.
@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.25 2008/05/30 12:17:11 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.26 2008/06/29 21:00:08 bouyer Exp $");
#include "opt_multiprocessor.h"
@ -101,6 +101,12 @@ __KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.25 2008/05/30 12:17:11 ad Exp $");
#include <dev/isa/isavar.h>
#endif
#ifdef XEN
#define clts() HYPERVISOR_fpu_taskswitch(0)
#define stts() HYPERVISOR_fpu_taskswitch(1)
#endif
/*
* We do lazy initialization and switching using the TS bit in cr0 and the
* MDP_USEDFPU bit in mdproc.
@ -122,6 +128,7 @@ __KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.25 2008/05/30 12:17:11 ad Exp $");
void fpudna(struct cpu_info *);
static int x86fpflags_to_ksiginfo(uint32_t);
#ifndef XEN
/*
* Init the FPU.
*/
@ -132,6 +139,7 @@ fpuinit(struct cpu_info *ci)
fninit();
lcr0(rcr0() | (CR0_TS));
}
#endif
/*
* Record the FPU state and reinitialize it all except for the control word.
@ -239,6 +247,20 @@ fpudna(struct cpu_info *ci)
* Initialize the FPU state to clear any exceptions. If someone else
* was using the FPU, save their state.
*/
#ifdef XEN
/*
* it seems we can get there on Xen even if we didn't switch lwp.
* in this case do nothing
*/
if (ci->ci_fpcurlwp == l) {
KDASSERT(l->l_addr->u_pcb.pcb_fpcpu == ci);
splx(s);
l->l_addr->u_pcb.pcb_cr0 &= ~CR0_TS;
clts();
kpreempt_enable();
return;
}
#endif
KDASSERT(ci->ci_fpcurlwp != l);
if (ci->ci_fpcurlwp != 0)
fpusave_cpu(true);

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.95 2008/06/05 21:44:31 ad Exp $ */
/* $NetBSD: machdep.c,v 1.96 2008/06/29 21:00:08 bouyer Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008
@ -112,7 +112,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.95 2008/06/05 21:44:31 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.96 2008/06/29 21:00:08 bouyer Exp $");
/* #define XENDEBUG_LOW */
@ -394,10 +394,6 @@ x86_64_switch_context(struct pcb *new)
{
struct cpu_info *ci;
ci = curcpu();
if (/* XXX ! ci->ci_fpused */ 1) {
HYPERVISOR_fpu_taskswitch(0);
/* XXX ci->ci_fpused = 0; */
}
HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL), new->pcb_rsp0);
if (xen_start_info.flags & SIF_PRIVILEGED) {
struct physdev_op physop;
@ -405,6 +401,9 @@ x86_64_switch_context(struct pcb *new)
physop.u.set_iopl.iopl = new->pcb_iopl;
HYPERVISOR_physdev_op(&physop);
}
if (new->pcb_fpcpu != ci) {
HYPERVISOR_fpu_taskswitch(1);
}
}
#endif
@ -436,7 +435,7 @@ x86_64_proc0_tss_ldt_init(void)
#else
xen_set_ldt((vaddr_t) ldtstore, LDT_SIZE >> 3);
/* Reset TS bit and set kernel stack for interrupt handlers */
HYPERVISOR_fpu_taskswitch(0);
HYPERVISOR_fpu_taskswitch(1);
HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL), pcb->pcb_rsp0);
#endif /* XEN */
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: vector.S,v 1.27 2008/06/01 21:24:15 ad Exp $ */
/* $NetBSD: vector.S,v 1.28 2008/06/29 21:00:08 bouyer Exp $ */
/*-
* Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@ -99,6 +99,7 @@
/*****************************************************************************/
#ifndef XEN
#define PRE_TRAP
#define TRAP(a) pushq $(a) ; jmp _C_LABEL(alltraps)
#define ZTRAP(a) pushq $0 ; TRAP(a)
#else
@ -160,15 +161,14 @@ IDTVEC(trap05)
IDTVEC(trap06)
ZTRAP(T_PRIVINFLT)
IDTVEC(trap07)
PRE_TRAP;
pushq $0 # dummy error code
pushq $T_ASTFLT
INTRENTRY
#ifdef DIAGNOSTIC
movl CPUVAR(ILEVEL),%ebx
#endif /* DIAGNOSTIC */
#ifdef XEN
STI(si)
#endif
movq CPUVAR(SELF),%rdi
call _C_LABEL(fpudna)
jmp .Lalltraps_checkusr
@ -188,6 +188,7 @@ IDTVEC(trap0e)
TRAP(T_PAGEFLT)
IDTVEC(intrspurious)
IDTVEC(trap0f)
PRE_TRAP;
pushq $0 # dummy error code
pushq $T_ASTFLT
INTRENTRY
@ -196,6 +197,7 @@ IDTVEC(trap0f)
#endif /* DIAGNOSTIC */
jmp .Lalltraps_checkusr
IDTVEC(trap10)
PRE_TRAP;
pushq $0 # dummy error code
pushq $T_ARITHTRAP
.Ldo_fputrap:
@ -216,6 +218,7 @@ IDTVEC(trap11)
IDTVEC(trap12)
ZTRAP(T_MCA)
IDTVEC(trap13)
PRE_TRAP;
pushq $0 # dummy error code
pushq $T_XMM
jmp .Ldo_fputrap