[PATCH kvm-unit-tests] x86: Test watchpoints during emulation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux