diff mbox

[13/13] x86: Add debug facility test case

Message ID 9b5cf4498bf00c4be5338ffd3324fdd7b138b20f.1388858359.git.jan.kiszka@web.de (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Kiszka Jan. 4, 2014, 5:59 p.m. UTC
From: Jan Kiszka <jan.kiszka@siemens.com>

This adds a basic test for INT3/#BP, hardware breakpoints, hardware
watchpoints and single-stepping.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 config-x86-common.mak |   2 +
 config-x86_64.mak     |   2 +-
 lib/x86/desc.h        |   2 +
 x86/debug.c           | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++
 x86/unittests.cfg     |   3 ++
 5 files changed, 121 insertions(+), 1 deletion(-)
 create mode 100644 x86/debug.c
diff mbox

Patch

diff --git a/config-x86-common.mak b/config-x86-common.mak
index 32da7fb..aa5a439 100644
--- a/config-x86-common.mak
+++ b/config-x86-common.mak
@@ -103,6 +103,8 @@  $(TEST_DIR)/pcid.elf: $(cstart.o) $(TEST_DIR)/pcid.o
 
 $(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o
 
+$(TEST_DIR)/debug.elf: $(cstart.o) $(TEST_DIR)/debug.o
+
 arch_clean:
 	$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
 	$(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o
diff --git a/config-x86_64.mak b/config-x86_64.mak
index bb8ee89..a9a2a9e 100644
--- a/config-x86_64.mak
+++ b/config-x86_64.mak
@@ -7,7 +7,7 @@  CFLAGS += -D__x86_64__
 tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
 	  $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
 	  $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \
-	  $(TEST_DIR)/pcid.flat
+	  $(TEST_DIR)/pcid.flat $(TEST_DIR)/debug.flat
 tests += $(TEST_DIR)/svm.flat
 tests += $(TEST_DIR)/vmx.flat
 
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index 5c850b2..b795aad 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -66,6 +66,8 @@  typedef struct {
     ".popsection \n\t"                                  \
     "1111:"
 
+#define DB_VECTOR   1
+#define BP_VECTOR   3
 #define UD_VECTOR   6
 #define GP_VECTOR   13
 
diff --git a/x86/debug.c b/x86/debug.c
new file mode 100644
index 0000000..154c7fe
--- /dev/null
+++ b/x86/debug.c
@@ -0,0 +1,113 @@ 
+/*
+ * Test for x86 debugging facilities
+ *
+ * Copyright (c) Siemens AG, 2014
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ */
+
+#include "libcflat.h"
+#include "desc.h"
+
+static volatile unsigned long bp_addr[10], dr6[10];
+static volatile unsigned int n;
+static volatile unsigned long value;
+
+static unsigned long get_dr6(void)
+{
+	unsigned long value;
+
+	asm volatile("mov %%dr6,%0" : "=r" (value));
+	return value;
+}
+
+static void set_dr0(void *value)
+{
+	asm volatile("mov %0,%%dr0" : : "r" (value));
+}
+
+static void set_dr1(void *value)
+{
+	asm volatile("mov %0,%%dr1" : : "r" (value));
+}
+
+static void set_dr7(unsigned long value)
+{
+	asm volatile("mov %0,%%dr7" : : "r" (value));
+}
+
+static void handle_db(struct ex_regs *regs)
+{
+	bp_addr[n] = regs->rip;
+	dr6[n] = get_dr6();
+
+	if (dr6[n] & 0x1)
+		regs->rflags |= (1 << 16);
+
+	if (++n >= 10) {
+		regs->rflags &= ~(1 << 8);
+		set_dr7(0x00000400);
+	}
+}
+
+static void handle_bp(struct ex_regs *regs)
+{
+	bp_addr[0] = regs->rip;
+}
+
+int main(int ac, char **av)
+{
+	unsigned long start;
+
+	setup_idt();
+	handle_exception(DB_VECTOR, handle_db);
+	handle_exception(BP_VECTOR, handle_bp);
+
+sw_bp:
+	asm volatile("int3");
+	report("#BP", bp_addr[0] == (unsigned long)&&sw_bp + 1);
+
+	set_dr0(&&hw_bp);
+	set_dr7(0x00000402);
+hw_bp:
+	asm volatile("nop");
+	report("hw breakpoint",
+	       n == 1 &&
+	       bp_addr[0] == ((unsigned long)&&hw_bp) && dr6[0] == 0xffff0ff1);
+
+	n = 0;
+	asm volatile(
+		"pushf\n\t"
+		"pop %%rax\n\t"
+		"or $(1<<8),%%rax\n\t"
+		"push %%rax\n\t"
+		"lea (%%rip),%0\n\t"
+		"popf\n\t"
+		"and $~(1<<8),%%rax\n\t"
+		"push %%rax\n\t"
+		"popf\n\t"
+		: "=g" (start) : : "rax");
+	report("single step",
+	       n == 3 &&
+	       bp_addr[0] == start+1+6 && dr6[0] == 0xffff4ff0 &&
+	       bp_addr[1] == start+1+6+1 && dr6[1] == 0xffff4ff0 &&
+	       bp_addr[2] == start+1+6+1+1 && dr6[2] == 0xffff4ff0);
+
+	n = 0;
+	set_dr1((void *)&value);
+	set_dr7(0x00d0040a);
+
+	asm volatile(
+		"mov $42,%%rax\n\t"
+		"mov %%rax,%0\n\t"
+		: "=m" (value) : : "rax");
+hw_wp:
+	report("hw watchpoint",
+	       n == 1 &&
+	       bp_addr[0] == ((unsigned long)&&hw_wp) && dr6[0] == 0xffff4ff2);
+
+	return 0;
+}
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 85c36aa..7930c02 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -155,3 +155,6 @@  file = vmx.flat
 extra_params = -cpu host,+vmx
 arch = x86_64
 
+[debug]
+file = debug.flag
+arch = x86_64