[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/2] x86/nmi/64: Giant debugging hack



Signed-off-by: Andy Lutomirski <luto@xxxxxxxxxx>
---
 arch/x86/entry/entry_64.S      | 34 ++++++++++++++++++++++++++++++----
 arch/x86/include/asm/segment.h |  5 ++++-
 arch/x86/kernel/cpu/common.c   |  2 ++
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 70eadb0ea5fa..2f61059dacc3 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -37,6 +37,9 @@
 #include <asm/pgtable_types.h>
 #include <linux/err.h>
 
+#define NMI_NORECURSE_SS (GDT_ENTRY_FOO << 3)
+#define NMI_RECURSIVE_SS (GDT_ENTRY_BAR << 3)
+
 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
 #include <linux/elf-em.h>
 #define AUDIT_ARCH_X86_64                      
(EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
@@ -523,6 +526,10 @@ restore_c_regs_and_iret:
        INTERRUPT_RETURN
 
 ENTRY(native_iret)
+       cmp     $NMI_NORECURSE_SS, 4*8(%rsp)
+       jne 1f
+       ud2
+1:
        /*
         * Are we returning to a stack segment from the LDT?  Note: in
         * 64-bit mode SS:RSP on the exception stack is always valid.
@@ -1113,6 +1120,13 @@ ENTRY(nmi)
        /* Use %rdx as our temp variable throughout */
        pushq   %rdx
 
+       cmpl    $NMI_NORECURSE_SS, 4*8(%rsp)
+       jne     1f
+       ud2
+1:
+       movl    $NMI_NORECURSE_SS, %edx
+       mov     %dx, %ss
+
        testb   $3, CS-RIP+8(%rsp)
        jz      .Lnmi_from_kernel
 
@@ -1158,6 +1172,8 @@ ENTRY(nmi)
         * due to nesting -- we're on the normal thread stack and we're
         * done with the NMI stack.
         */
+       mov     $__KERNEL_DS, %edx
+       mov     %dx, %ss
 
        movq    %rsp, %rdi
        movq    $-1, %rsi
@@ -1240,6 +1256,11 @@ ENTRY(nmi)
        cmpl    $1, -8(%rsp)
        je      nested_nmi
 
+       cmpl    $0, -8(%rsp)
+       je      1f
+       ud2             /* corrupt */
+1:
+
        /*
         * Now test if the previous stack was an NMI stack.  This covers
         * the case where we interrupt an outer NMI after it clears
@@ -1277,7 +1298,7 @@ nested_nmi:
         */
        subq    $8, %rsp
        leaq    -10*8(%rsp), %rdx
-       pushq   $__KERNEL_DS
+       pushq   $NMI_RECURSIVE_SS
        pushq   %rdx
        pushfq
        pushq   $__KERNEL_CS
@@ -1293,6 +1314,11 @@ nested_nmi_out:
        INTERRUPT_RETURN
 
 first_nmi:
+       cmpl    $NMI_RECURSIVE_SS, 4*8(%rsp)
+       jne     1f
+       ud2
+1:
+
        /* Restore rdx. */
        movq    (%rsp), %rdx
 
@@ -1309,12 +1335,12 @@ first_nmi:
 
        /* Everything up to here is safe from nested NMIs */
 
-#ifdef CONFIG_DEBUG_ENTRY
+/*#ifdef CONFIG_DEBUG_ENTRY*/
        /*
         * For ease of testing, unmask NMIs right away.  Disabled by
         * default because IRET is very expensive.
         */
-       pushq   $0              /* SS */
+       pushq   $NMI_RECURSIVE_SS       /* SS */
        pushq   %rsp            /* RSP (minus 8 because of the previous push) */
        addq    $8, (%rsp)      /* Fix up RSP */
        pushfq                  /* RFLAGS */
@@ -1322,7 +1348,7 @@ first_nmi:
        pushq   $1f             /* RIP */
        INTERRUPT_RETURN        /* continues at repeat_nmi below */
 1:
-#endif
+/*#endif*/
 
 repeat_nmi:
        /*
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index 7d5a1929d76b..58473396f290 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -176,6 +176,9 @@
 #define GDT_ENTRY_DEFAULT_USER_DS      5
 #define GDT_ENTRY_DEFAULT_USER_CS      6
 
+#define GDT_ENTRY_FOO                  7
+#define GDT_ENTRY_BAR                  16
+
 /* Needs two entries */
 #define GDT_ENTRY_TSS                  8
 /* Needs two entries */
@@ -190,7 +193,7 @@
 /*
  * Number of entries in the GDT table:
  */
-#define GDT_ENTRIES                    16
+#define GDT_ENTRIES                    17
 
 /*
  * Segment selector values corresponding to the above entries:
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 079d83fc6488..91ddae732a36 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -108,6 +108,8 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { 
.gdt = {
        [GDT_ENTRY_DEFAULT_USER32_CS]   = GDT_ENTRY_INIT(0xc0fb, 0, 0xfffff),
        [GDT_ENTRY_DEFAULT_USER_DS]     = GDT_ENTRY_INIT(0xc0f3, 0, 0xfffff),
        [GDT_ENTRY_DEFAULT_USER_CS]     = GDT_ENTRY_INIT(0xa0fb, 0, 0xfffff),
+       [GDT_ENTRY_FOO]                 = GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
+       [GDT_ENTRY_BAR]                 = GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
 #else
        [GDT_ENTRY_KERNEL_CS]           = GDT_ENTRY_INIT(0xc09a, 0, 0xfffff),
        [GDT_ENTRY_KERNEL_DS]           = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
-- 
2.5.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.