mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Fix floating-point corruption (a nasty race in fp task-switch
exception handling). Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
e16adc291f
commit
80e5f07b52
3 files changed
+33
-14
No files matched your search
@@ -653,7 +653,7 @@ ENTRY(simd_coprocessor_error)
|
||||
ENTRY(device_not_available)
|
||||
pushl $-1 # mark this as an int
|
||||
SAVE_ALL
|
||||
preempt_stop
|
||||
#preempt_stop /* This is already an interrupt gate on Xen. */
|
||||
call math_state_restore
|
||||
jmp ret_from_exception
|
||||
|
||||
|
||||
@@ -648,6 +648,12 @@ fastcall void do_int3(struct pt_regs *regs, long error_code)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void conditional_sti(struct pt_regs *regs)
|
||||
{
|
||||
if ((uint8_t)(regs->xcs >> 16) == 0)
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Our handling of the processor debug registers is non-trivial.
|
||||
* We do not clear them on entry and exit from the kernel. Therefore
|
||||
@@ -680,11 +686,9 @@ fastcall void do_debug(struct pt_regs * regs, long error_code)
|
||||
if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
|
||||
SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
#if 0
|
||||
|
||||
/* It's safe to allow irq's after DR6 has been saved */
|
||||
if (regs->eflags & X86_EFLAGS_IF)
|
||||
local_irq_enable();
|
||||
#endif
|
||||
conditional_sti(regs);
|
||||
|
||||
/* Mask out spurious debug traps due to lazy DR7 setting */
|
||||
if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
|
||||
@@ -967,15 +971,18 @@ void __init trap_init_f00f_bug(void)
|
||||
#endif
|
||||
|
||||
|
||||
/* NB. All these are "trap gates" (i.e. events_mask isn't cleared). */
|
||||
/*
|
||||
* NB. All these are "trap gates" (i.e. events_mask isn't cleared) except
|
||||
* for those that specify <dpl>|4 in the second field.
|
||||
*/
|
||||
static trap_info_t trap_table[] = {
|
||||
{ 0, 0, __KERNEL_CS, (unsigned long)divide_error },
|
||||
{ 1, 0, __KERNEL_CS, (unsigned long)debug },
|
||||
{ 3, 3, __KERNEL_CS, (unsigned long)int3 },
|
||||
{ 1, 0|4, __KERNEL_CS, (unsigned long)debug },
|
||||
{ 3, 3|4, __KERNEL_CS, (unsigned long)int3 },
|
||||
{ 4, 3, __KERNEL_CS, (unsigned long)overflow },
|
||||
{ 5, 3, __KERNEL_CS, (unsigned long)bounds },
|
||||
{ 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
|
||||
{ 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
|
||||
{ 7, 0|4, __KERNEL_CS, (unsigned long)device_not_available },
|
||||
{ 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
|
||||
{ 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
|
||||
{ 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
|
||||
|
||||
+17
-5
@@ -1147,6 +1147,9 @@ asmlinkage void do_nmi(struct cpu_user_regs *regs, unsigned long reason)
|
||||
|
||||
asmlinkage int math_state_restore(struct cpu_user_regs *regs)
|
||||
{
|
||||
struct trap_bounce *tb;
|
||||
trap_info_t *ti;
|
||||
|
||||
/* Prevent recursion. */
|
||||
clts();
|
||||
|
||||
@@ -1154,10 +1157,15 @@ asmlinkage int math_state_restore(struct cpu_user_regs *regs)
|
||||
|
||||
if ( current->arch.guest_context.ctrlreg[0] & X86_CR0_TS )
|
||||
{
|
||||
struct trap_bounce *tb = ¤t->arch.trap_bounce;
|
||||
tb = ¤t->arch.trap_bounce;
|
||||
ti = ¤t->arch.guest_context.trap_ctxt[TRAP_no_device];
|
||||
|
||||
tb->flags = TBF_EXCEPTION;
|
||||
tb->cs = current->arch.guest_context.trap_ctxt[7].cs;
|
||||
tb->eip = current->arch.guest_context.trap_ctxt[7].address;
|
||||
tb->cs = ti->cs;
|
||||
tb->eip = ti->address;
|
||||
if ( TI_GET_IF(ti) )
|
||||
tb->flags |= TBF_INTERRUPT;
|
||||
|
||||
current->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS;
|
||||
}
|
||||
|
||||
@@ -1169,6 +1177,7 @@ asmlinkage int do_debug(struct cpu_user_regs *regs)
|
||||
unsigned long condition;
|
||||
struct vcpu *v = current;
|
||||
struct trap_bounce *tb = &v->arch.trap_bounce;
|
||||
trap_info_t *ti;
|
||||
|
||||
__asm__ __volatile__("mov %%db6,%0" : "=r" (condition));
|
||||
|
||||
@@ -1198,9 +1207,12 @@ asmlinkage int do_debug(struct cpu_user_regs *regs)
|
||||
/* Save debug status register where guest OS can peek at it */
|
||||
v->arch.guest_context.debugreg[6] = condition;
|
||||
|
||||
ti = &v->arch.guest_context.trap_ctxt[TRAP_debug];
|
||||
tb->flags = TBF_EXCEPTION;
|
||||
tb->cs = v->arch.guest_context.trap_ctxt[TRAP_debug].cs;
|
||||
tb->eip = v->arch.guest_context.trap_ctxt[TRAP_debug].address;
|
||||
tb->cs = ti->cs;
|
||||
tb->eip = ti->address;
|
||||
if ( TI_GET_IF(ti) )
|
||||
tb->flags |= TBF_INTERRUPT;
|
||||
|
||||
out:
|
||||
return EXCRET_not_a_fault;
|
||||
|
||||