mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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>
This commit is contained in:
1 parent
f0b5db91de
commit
d47e6a744e
2 files changed
+6
-4
No files matched your search
@@ -386,13 +386,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. */
|
||||
|
||||
@@ -424,7 +424,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
|
||||
|
||||