xcp-1.6-updates/xen-4.1.hg

changeset 23308:0b947d466e3e

x86_64: Fix off-by-one error setting up the Interrupt Stack Tables

The Interrupt Stack Table entries in a 64bit TSS are a 1 based data
structure as far as hardware is concerned. As a result, the code
setting up stacks in subarch_percpu_traps_init() fills in the wrong
IST entries.

The result is that the MCE handler executes on the stack set up for
NMIs; the NMI handler executes on a stack set up for Double Faults,
and Double Faults are executed with a stack pointer set to 0.

Once the #DF handler starts to execute, it will usually take a page
fault looking up the address at 0xfffffffffffffff8, which will cause a
triple fault. If a guest has mapped a page in that location, then it
will have some state overwritten, but as the #DF handler always calls
panic(), this is not a problem the guest will have time to care about.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Committed-by: Keir Fraser <keir@xen.org>
xen-unstable changeset: 25271:54da0329e259
xen-unstable date: Thu May 10 11:04:32 2012 +0100
author Andrew Cooper <andrew.cooper3@citrix.com>
date Tue Jul 03 13:48:58 2012 +0100 (2012-07-03)
parents 32ab8989df67
children ce1b489f0543
files xen/arch/x86/x86_64/traps.c xen/include/asm-x86/processor.h
line diff
     1.1 --- a/xen/arch/x86/x86_64/traps.c	Tue Jul 03 13:48:07 2012 +0100
     1.2 +++ b/xen/arch/x86/x86_64/traps.c	Tue Jul 03 13:48:58 2012 +0100
     1.3 @@ -385,13 +385,13 @@ void __devinit subarch_percpu_traps_init
     1.4      BUILD_BUG_ON((IST_MAX + 2) * PAGE_SIZE + PRIMARY_STACK_SIZE > STACK_SIZE);
     1.5  
     1.6      /* Machine Check handler has its own per-CPU 4kB stack. */
     1.7 -    this_cpu(init_tss).ist[IST_MCE] = (unsigned long)&stack[IST_MCE * PAGE_SIZE];
     1.8 +    this_cpu(init_tss).ist[IST_MCE-1] = (unsigned long)&stack[IST_MCE * PAGE_SIZE];
     1.9  
    1.10      /* Double-fault handler has its own per-CPU 4kB stack. */
    1.11 -    this_cpu(init_tss).ist[IST_DF] = (unsigned long)&stack[IST_DF * PAGE_SIZE];
    1.12 +    this_cpu(init_tss).ist[IST_DF-1] = (unsigned long)&stack[IST_DF * PAGE_SIZE];
    1.13  
    1.14      /* NMI handler has its own per-CPU 4kB stack. */
    1.15 -    this_cpu(init_tss).ist[IST_NMI] = (unsigned long)&stack[IST_NMI * PAGE_SIZE];
    1.16 +    this_cpu(init_tss).ist[IST_NMI-1] = (unsigned long)&stack[IST_NMI * PAGE_SIZE];
    1.17  
    1.18      /* Trampoline for SYSCALL entry from long mode. */
    1.19      stack = &stack[IST_MAX * PAGE_SIZE]; /* Skip the IST stacks. */
     2.1 --- a/xen/include/asm-x86/processor.h	Tue Jul 03 13:48:07 2012 +0100
     2.2 +++ b/xen/include/asm-x86/processor.h	Tue Jul 03 13:48:58 2012 +0100
     2.3 @@ -427,7 +427,9 @@ struct tss_struct {
     2.4      union { u64 rsp1, esp1; };
     2.5      union { u64 rsp2, esp2; };
     2.6      u64 reserved1;
     2.7 -    u64 ist[7];
     2.8 +    u64 ist[7]; /* Interrupt Stack Table is 1-based so tss->ist[0]
     2.9 +                 * corresponds to an IST value of 1 in an Interrupt
    2.10 +                 * Descriptor */
    2.11      u64 reserved2;
    2.12      u16 reserved3;
    2.13  #else