[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