From: Rami Burstein& Anrey Isakov <ramibot@xxxxxxxxx> This adds a test for data and port watchpoints during instruction emulation. Signed-off-by: Rami Burstein <ramibot@xxxxxxxxx> Signed-off-by: Andrey Isakov <andreyisakov7@xxxxxxxxx> --- This unit tests are based on old kvm-unit-tests version and are only delivered for reference. They are certainly bloated in their current form. --- x86/debug.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 374 insertions(+) diff --git a/x86/debug.c b/x86/debug.c index 34e56fb..43a2777 100644 --- a/x86/debug.c +++ b/x86/debug.c @@ -11,10 +11,24 @@ #include "libcflat.h" #include "desc.h" +#include "vm.h" + +#define TESTDEV_IO_PORT 0xe0 static volatile unsigned long bp_addr[10], dr6[10]; static volatile unsigned int n; static volatile unsigned long value; +static volatile char st1[] = "abcdefghijklmnop"; + +static void set_dr2(void *value) +{ + asm volatile("mov %0,%%dr2" : : "r" (value)); +} + +static void set_dr3(void *value) +{ + asm volatile("mov %0,%%dr3" : : "r" (value)); +} static unsigned long get_dr6(void) { @@ -58,6 +72,360 @@ static void handle_bp(struct ex_regs *regs) bp_addr[0] = regs->rip; } +static void test_port_io_bp() +{ + unsigned char r = 0; + unsigned short port_in = 0; + unsigned int port_din = 0; + + n = 0; + set_dr0((void*)TESTDEV_IO_PORT); + set_dr1((void*)TESTDEV_IO_PORT); + set_dr2((void*)TESTDEV_IO_PORT); + set_dr3((void*)TESTDEV_IO_PORT); + set_dr7(0x00020402); + + // Set DE flag. + write_cr4(read_cr4() | 0x8); + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)TESTDEV_IO_PORT),"S"(st1)); + asm volatile("inb %1, %0\n\t" : "=a"(r) : "i"((short)TESTDEV_IO_PORT)); +io_0: + report("em_IO out_in 1 byte bp through dr0", + n == 2 && bp_addr[n-1] == ((unsigned long)&&io_0) && + dr6[n-1] == 0xffff4ff1); + + set_dr7(0x00200408); + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)TESTDEV_IO_PORT), "S"(st1)); + asm volatile("inb %1, %0\n\t" : "=a"(r) + : "i"((short)TESTDEV_IO_PORT)); +io_1: + report("em_IO out_in 1 byte bp through dr1", + n == 4 && bp_addr[n-1] == ((unsigned long)&&io_1) && + dr6[n-1] == 0xffff4ff2); + + set_dr7(0x02000420); + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)TESTDEV_IO_PORT), "S"(st1)); + asm volatile("inb %1, %0\n\t" : "=a"(r) + : "i"((short)TESTDEV_IO_PORT)); +io_2: + report("em_IO out_in 1 byte bp through dr2", + n == 6 && bp_addr[n-1] == ((unsigned long)&&io_2) && + dr6[n-1] == 0xffff4ff4); + + set_dr7(0x20000480); + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)TESTDEV_IO_PORT), "S"(st1)); + asm volatile("inb %1, %0\n\t" : "=a"(r) + : "i"((short)TESTDEV_IO_PORT)); +io_3: + report("em_IO out_in 1 byte bp through dr3", + n == 8 && bp_addr[n-1] == ((unsigned long)&&io_3) && + dr6[n-1] == 0xffff4ff8); + + n=0; + set_dr7(0x60000480); + asm volatile("movw %0, %%dx \n\t" "outsw \n\t" + : : "i"((short)TESTDEV_IO_PORT), "S"(st1)); + asm volatile("inw %1, %0\n\t" : "=r"(port_in) + : "i"((short)TESTDEV_IO_PORT)); +io_w: + report("em_IO out_in 2 byte bp through dr3", + n == 2 && bp_addr[n-1] == ((unsigned long)&&io_w) && + dr6[n-1] == 0xffff4ff8); + + set_dr7(0xe0000480); + asm volatile("movw %0, %%dx \n\t" "outsl \n\t" + : : "i"((short)TESTDEV_IO_PORT), "S"(st1)); + asm volatile ("insl;" :"+D" (port_din) + : "i" ((short)TESTDEV_IO_PORT) : "memory"); +io_dw: + report("em_IO out_in 4 byte bp through dr3", + n == 4 && bp_addr[n-1] == ((unsigned long)&&io_dw) + && dr6[n-1] == 0xffff4ff8); +} +static void test_port_io_aligned_bp(){ + + unsigned char r = 0; + unsigned short port_in = 0; + unsigned int port_din = 0; + + n = 0; + write_cr4(read_cr4() | 0x8); + + set_dr7(0x00020402); + set_dr0((void*)(TESTDEV_IO_PORT )); + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)TESTDEV_IO_PORT),"S"(st1)); + asm volatile("inb %1, %0\n\t" : "=a"(r) + : "i"((short)TESTDEV_IO_PORT)); +aio_0: + report("em_IO aligned out_in 1 byte bp through dr0", + n == 2 && bp_addr[n-1] == ((unsigned long)&&aio_0) && + dr6[n-1] == 0xffff4ff1); + + set_dr7(0x00060402); + set_dr0((void*)(TESTDEV_IO_PORT + 1)); + asm volatile("movw %0, %%dx \n\t" "outsw \n\t" + : : "i"((short)TESTDEV_IO_PORT),"S"(st1)); + asm volatile("inw %1, %0\n\t" : "=a"(port_in) + : "i"((short)TESTDEV_IO_PORT)); +aio_1: + report("em_IO aligned out_in 2 byte bp through dr0", + n == 4 && bp_addr[n-1] == ((unsigned long)&&aio_1) && + dr6[n-1] == 0xffff4ff1); + + set_dr7(0x000e0402); + set_dr0((void*)(TESTDEV_IO_PORT + 2)); + asm volatile("movw %0, %%dx \n\t" "outsl \n\t" + : : "i"((short)TESTDEV_IO_PORT),"S"(st1)); + asm volatile("inl %1, %0\n\t" : "=a"(port_din) + : "i"((short)TESTDEV_IO_PORT)); +aio_2: + report("em_IO aligned out_in 4 byte bp through dr0", + n == 6 && bp_addr[n-1] == ((unsigned long)&&aio_2) && + dr6[n-1] == 0xffff4ff1); + + set_dr7(0x00320402); + set_dr0((void*)(TESTDEV_IO_PORT + 3)); + asm volatile("movw %0, %%dx \n\t" "outsl \n\t" + : : "i"((short)TESTDEV_IO_PORT),"S"(st1)); + asm volatile("inl %1, %0\n\t" : "=a"(port_din) + : "i"((short)TESTDEV_IO_PORT)); +aio_3: + report("em_IO aligned out_in 4 byte bp through dr0", + n == 8 && bp_addr[n-1] == ((unsigned long)&&aio_3) && + dr6[n-1] == 0xffff4ff1); + + n=0; + set_dr7(0x000e0402); + set_dr0((void*)(TESTDEV_IO_PORT)); + asm volatile("movw %0, %%dx \n\t" "outsw \n\t" + : : "i"((short)(TESTDEV_IO_PORT + 1)),"S"(st1)); + asm volatile("inw %1, %0\n\t" : "=a"(port_in) + : "i"((short)(TESTDEV_IO_PORT + 1))); +aio_4: + report("em_IO aligned out_in 2 byte bp through dr0", + n == 2 && bp_addr[1] == ((unsigned long)&&aio_4) && + dr6[1] == 0xffff4ff1); + + set_dr7(0x000e0402); + set_dr0((void*)(TESTDEV_IO_PORT)); + asm volatile("movw %0, %%dx \n\t" "outsl \n\t" + : : "i"((short)(TESTDEV_IO_PORT + 1)),"S"(st1)); + asm volatile("inl %1, %0\n\t" : "=a"(port_din) + : "i"((short)(TESTDEV_IO_PORT + 1))); +aio_5: + report("em_IO aligned out_in 2 byte bp through dr0", + n == 4 && bp_addr[n-1] == ((unsigned long)&&aio_5) && + dr6[n-1] == 0xffff4ff1); +} + +static void test_data_read_bp() { + char st2[] = "abcdefghijklmnop"; + n = 0; + + set_dr1(&st2); + set_dr7(0x00300408); + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(st2)); +datars_b_0: + report("Data em_read 1 byte bp through dr1", + n == 1 && bp_addr[n-1] == ((unsigned long)&&datars_b_0) && + dr6[n-1] == 0xffff4ff2); + + set_dr2(&st2); + set_dr7(0x07000420); + asm volatile("movw %0, %%dx \n\t" "outsw \n\t" + : : "i"((short)TESTDEV_IO_PORT), "S"(st2)); +datars_b_1: + report("Data em_read 2 byte bp through dr2", + n == 2 && bp_addr[n-1] == ((unsigned long)&&datars_b_1) && + dr6[n-1] == 0xffff4ff4); + + set_dr3(&st2); + set_dr7(0xf0000480); + asm volatile("movw %0, %%dx \n\t" "outsl \n\t" + : : "i"((short)TESTDEV_IO_PORT), "S"(st2)); +datar_b_2: + report("Data em_read 4 byte bp through dr3", + n == 3 && + bp_addr[n-1] == ((unsigned long)&&datar_b_2) + && dr6[n-1] == 0xffff4ff8); +} + +static void test_data_write_bp() { + uint8_t mem[4] = {1, 2, 3, 4}; + n=0; + + set_dr0(mem); + set_dr7(0x00030402); + asm volatile("insb" : : "d" (TESTDEV_IO_PORT), "D" (mem)); + +dataw_b_1: + report("Data em_write 1 byte bp through dr0", + n == 1 && bp_addr[n-1] == ((unsigned long)&&dataw_b_1) && + dr6[n-1] == 0xffff4ff1); + + set_dr1(&mem); + set_dr7(0x00700408); + asm volatile ("insw" : : "d" (TESTDEV_IO_PORT), "D" (mem)); + +dataw_b_2: + report("Data em_write 2 byte bp through dr1", + n == 2 && bp_addr[n-1] == ((unsigned long)&&dataw_b_2) && + dr6[n-1] == 0xffff4ff2); + + set_dr2(&mem); + set_dr7(0x0F000420); + asm volatile ("insl" : : "d" (TESTDEV_IO_PORT), "D" (mem)); + +dataw_b_3: + report("Data em_write 4 byte bp through dr2", + n == 3 && bp_addr[n-1] == ((unsigned long)&&dataw_b_3) && + dr6[n-1] == 0xffff4ff4); + + asm volatile("outl %0,%1 \n\t" : : "a"(0x33221100), "i"(TESTDEV_IO_PORT)); + + set_dr0(mem); + set_dr7(0x00010402); + asm volatile ("insb" : : "d" (TESTDEV_IO_PORT), "D" (mem)); + +dataow_b_1: + report("Data em_write_only 1 byte bp through dr0", + n == 4 && bp_addr[n-1] == ((unsigned long)&&dataow_b_1) && + dr6[n-1] == 0xffff4ff1); + + set_dr1(&mem); + set_dr7(0x00500408); + asm volatile ("insw" : : "d" (TESTDEV_IO_PORT), "D" (mem)); + +dataow_b_2: + report("Data em_write_only 2 byte bp through dr1", + n == 5 && bp_addr[n-1] == ((unsigned long)&&dataow_b_2) && + dr6[n-1] == 0xffff4ff2); + + set_dr3(&mem); + set_dr7(0xd0000480); + asm volatile ("insl" : : "d" (TESTDEV_IO_PORT), "D" (mem)); + +dataow_b_3: + report("Data em_write_only 4 byte bp through dr3", + n == 6 && bp_addr[n-1] == ((unsigned long)&&dataow_b_3) && + dr6[n-1] == 0xffff4ff8); +} + +static void test_data_aligned_rw_bp() { + unsigned char mm1[8]; + unsigned char mm2[8]; + unsigned char mm3[8]; + + n = 0; + set_dr0(mm1 + 1); + set_dr1(mm1 + 2); + set_dr2(mm2 + 2); + set_dr3(mm3); + set_dr7(0xD71304AA); + + asm volatile("insb" : : "d" (TESTDEV_IO_PORT), "D" (mm1 + 1)); + report("Data align em_write 1 byte bp through dr0", + n == 1 && dr6[n-1] == 0xffff4ff1); + + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm1 + 1)); + report("Data align em_read 1 byte bp through dr0", + n == 2 && dr6[n-1] == 0xffff4ff1); + + asm volatile("insw" : : "d" (TESTDEV_IO_PORT), "D" (mm1 + 1)); + report("Data align em_write 2 byte bp through dr0", + n == 3 && dr6[n-1] == 0xffff4ff3); + + asm volatile("movw %0, %%dx \n\t" "outsw \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm1 + 1)); + report("Data align em_read 2 byte bp through dr0", + n == 4 && dr6[n-1] == 0xffff4ff1); + + asm volatile("insb" : : "d" (TESTDEV_IO_PORT), "D" (mm1 + 2)); + report("Data align em_write 1 byte bp through dr0", + n == 5 && dr6[n-1] == 0xffff4ff2); + + asm volatile("insw" : : "d" (TESTDEV_IO_PORT), "D" (mm1 + 2)); + report("Data align em_write 2 byte bp through dr0", + n == 6 && dr6[n-1] == 0xffff4ff2); + + n=0; + asm volatile("insl" : : "d" (TESTDEV_IO_PORT), "D" (mm2 + 2)); + report("Data align em_write 4 byte bp through dr2", + n == 1 && dr6[n-1] == 0xffff4ff4); + + asm volatile("movw %0, %%dx \n\t" "outsl \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm2 + 2)); + report("Data align em_read 4 byte bp through dr2", + n == 2 && dr6[n-1] == 0xffff4ff4); + + asm volatile("insb" : : "d" (TESTDEV_IO_PORT), "D" (mm2 + 2)); + report("Data align em_write 1 byte bp through dr2", + n == 3 && dr6[n-1] == 0xffff4ff4); + + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm2 + 2)); + report("Data align em_read 1 byte bp through dr2", + n == 4 && dr6[n-1] == 0xffff4ff4); + + asm volatile("insw" : : "d" (TESTDEV_IO_PORT), "D" (mm2 + 1)); + report("Data align em_write 2 byte bp through dr2", + n == 5 && dr6[n-1] == 0xffff4ff4); + + asm volatile("movw %0, %%dx \n\t" "outsw \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm2 + 1)); + report("Data align em_read 2 byte bp through dr2", + n == 6 && dr6[n-1] == 0xffff4ff4); + + asm volatile("insl" : : "d" (TESTDEV_IO_PORT), "D" (mm3)); + report("Data align em_write 4 byte bp through dr3", + n == 7 && dr6[n-1] == 0xffff4ff8); + + asm volatile("insw" : : "d" (TESTDEV_IO_PORT), "D" (mm3 + 3)); + report("Data align em_write 2 byte bp through dr3", + n == 8 && dr6[n-1] == 0xffff4ff8); + + asm volatile("insb" : : "d" (TESTDEV_IO_PORT), "D" (mm3 + 1)); + report("Data align em_write 1 byte bp through dr3", + n == 9 && dr6[n-1] == 0xffff4ff8); + + n=0; + asm volatile("insb" : : "d" (TESTDEV_IO_PORT), "D" (mm1)); + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm1)); + report("Data operations that do not trap", n == 0); + + asm volatile("movw %0, %%dx \n\t" "outsb \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm1 + 2)); + report("Data operations that do not trap", n == 0); + + asm volatile("insl" : : "d" (TESTDEV_IO_PORT), "D" (mm1 + 3)); + asm volatile("movw %0, %%dx \n\t" "outsl \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm1 + 3)); + report("Data operations that do not trap", n == 0); + + asm volatile("insw" : : "d" (TESTDEV_IO_PORT), "D" (mm2)); + asm volatile("movw %0, %%dx \n\t" "outsw \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm2)); + report("Data operations that do not trap", n == 0); + + asm volatile("movw %0, %%dx \n\t" "outsw \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm3)); + report("Data operations that do not trap", n == 0); + + asm volatile("insl" : : "d" (TESTDEV_IO_PORT), "D" (mm3 + 4)); + asm volatile("movw %0, %%dx \n\t" "outsl \n\t" + : : "i"((short)(TESTDEV_IO_PORT)), "S"(mm3 + 4)); + report("Data operations that do not trap", n == 0); + +} + int main(int ac, char **av) { unsigned long start; @@ -109,5 +477,11 @@ hw_wp: n == 1 && bp_addr[0] == ((unsigned long)&&hw_wp) && dr6[0] == 0xffff4ff2); + test_port_io_bp(); + test_port_io_aligned_bp(); + test_data_read_bp(); + test_data_write_bp(); + test_data_aligned_rw_bp(); + return report_summary(); } -- 2.1.4 -- 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