From: Jan Kiszka <jan.kis...@siemens.com>

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

Signed-off-by: Jan Kiszka <jan.kis...@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 --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.kis...@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
-- 
1.8.1.1.298.ge7eed54

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to