[Lguest] [PATCH 1/2] x86/nmi/64: Giant debugging hack

Andy Lutomirski luto at kernel.org
Tue Mar 1 10:45:24 AEDT 2016


Signed-off-by: Andy Lutomirski <luto at kernel.org>
---
 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



More information about the Lguest mailing list