From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Cooper Subject: x86_64: Fix off-by-one error setting up the Interrupt Stack Tables Date: Wed, 9 May 2012 11:22:12 +0100 Message-ID: <4FAA4554.3080005@citrix.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------000003060208070400050109" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: "xen-devel@lists.xen.org" , Keir Fraser , Jan Beulich List-Id: xen-devel@lists.xenproject.org --------------000003060208070400050109 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit This affects every version of Xen at least as back as 3.4 -- Andrew Cooper - Dom0 Kernel Engineer, Citrix XenServer T: +44 (0)1223 225 900, http://www.citrix.com --------------000003060208070400050109 Content-Type: text/x-patch; name="x86_64-ist-off-by-one-error.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="x86_64-ist-off-by-one-error.patch" # HG changeset patch # Parent 8f1e0cc4a507a52a49a2eb7832a57ecc7e032dce 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 diff -r 8f1e0cc4a507 xen/arch/x86/x86_64/traps.c --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -386,13 +386,13 @@ void __devinit subarch_percpu_traps_init 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 -r 8f1e0cc4a507 xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -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 --------------000003060208070400050109 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel --------------000003060208070400050109--