# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID b5903c9aeda56523b6676163e06b7db5cf4cd93d
# Parent 07aa5213d8119f9889f49cd79cc9a2a3ae787881
Fix floating-point corruption (a nasty race in fp task-switch
exception handling).
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r 07aa5213d811 -r b5903c9aeda5
linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S Sun Oct 30 08:39:55 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S Sun Oct 30 09:45:49 2005
@@ -653,7 +653,7 @@
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
diff -r 07aa5213d811 -r b5903c9aeda5
linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Sun Oct 30 08:39:55 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Sun Oct 30 09:45:49 2005
@@ -647,6 +647,12 @@
do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
}
#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.
@@ -680,11 +686,9 @@
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 @@
#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 },
diff -r 07aa5213d811 -r b5903c9aeda5 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Sun Oct 30 08:39:55 2005
+++ b/xen/arch/x86/traps.c Sun Oct 30 09:45:49 2005
@@ -1147,6 +1147,9 @@
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 @@
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 @@
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 @@
/* 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;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|