diff options
author | Andrew Cooper <andrew.cooper3@citrix.com> | 2012-07-03 13:50:51 +0100 |
---|---|---|
committer | Andrew Cooper <andrew.cooper3@citrix.com> | 2012-07-03 13:50:51 +0100 |
commit | d358f56e36f79e565d764c3728a9c999e8913df2 (patch) | |
tree | 17b559343150c001ad954cee4a3921fd9953c194 | |
parent | c0d8fe164dc5e917b80ca506ba04c3e16f6a8185 (diff) | |
download | xen-d358f56e36f79e565d764c3728a9c999e8913df2.tar.gz xen-d358f56e36f79e565d764c3728a9c999e8913df2.tar.bz2 xen-d358f56e36f79e565d764c3728a9c999e8913df2.zip |
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
-rw-r--r-- | xen/arch/x86/x86_64/traps.c | 6 | ||||
-rw-r--r-- | xen/include/asm-x86/processor.h | 4 |
2 files changed, 6 insertions, 4 deletions
diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 2373435f29..fe4bc8ceaf 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -385,13 +385,13 @@ void __devinit subarch_percpu_traps_init(void) BUILD_BUG_ON((IST_MAX + 2) * PAGE_SIZE + PRIMARY_STACK_SIZE > STACK_SIZE); /* Machine Check handler has its own per-CPU 4kB stack. */ - this_cpu(init_tss).ist[IST_MCE] = (unsigned long)&stack[IST_MCE * PAGE_SIZE]; + this_cpu(init_tss).ist[IST_MCE-1] = (unsigned long)&stack[IST_MCE * PAGE_SIZE]; /* Double-fault handler has its own per-CPU 4kB stack. */ - this_cpu(init_tss).ist[IST_DF] = (unsigned long)&stack[IST_DF * PAGE_SIZE]; + this_cpu(init_tss).ist[IST_DF-1] = (unsigned long)&stack[IST_DF * PAGE_SIZE]; /* NMI handler has its own per-CPU 4kB stack. */ - this_cpu(init_tss).ist[IST_NMI] = (unsigned long)&stack[IST_NMI * PAGE_SIZE]; + this_cpu(init_tss).ist[IST_NMI-1] = (unsigned long)&stack[IST_NMI * PAGE_SIZE]; /* Trampoline for SYSCALL entry from long mode. */ stack = &stack[IST_MAX * PAGE_SIZE]; /* Skip the IST stacks. */ diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index df9f612e5f..9da4124c19 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -417,7 +417,9 @@ struct tss_struct { union { u64 rsp1, esp1; }; union { u64 rsp2, esp2; }; u64 reserved1; - u64 ist[7]; + u64 ist[7]; /* Interrupt Stack Table is 1-based so tss->ist[0] + * corresponds to an IST value of 1 in an Interrupt + * Descriptor */ u64 reserved2; u16 reserved3; #else |