From: Rami Burstein& Anrey Isakov <[email protected]>

This adds a test for data and port watchpoints during instruction emulation.

Signed-off-by: Rami Burstein <[email protected]>
Signed-off-by: Andrey Isakov <[email protected]>

---

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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to