From: Jan Kiszka <jan.kiszka@xxxxxxxxxxx> This adds a basic test for INT3/#BP, hardware breakpoints, hardware watchpoints and single-stepping. Signed-off-by: Jan Kiszka <jan.kiszka@xxxxxxxxxxx> --- 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.kiszka@xxxxxxxxxxx> + * + * 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html