Proper FPU exeptions support for Xen. Should fix FPU issues reported by
various users.
This commit is contained in:
parent
f0fae83846
commit
fe0fcf52f5
@ -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);
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user