diff mbox series

[kvm-unit-tests] x86: add CR4.DE test to debug.flat

Message ID 20210203114157.132669-1-pbonzini@redhat.com (mailing list archive)
State New, archived
Headers show
Series [kvm-unit-tests] x86: add CR4.DE test to debug.flat | expand

Commit Message

Paolo Bonzini Feb. 3, 2021, 11:41 a.m. UTC
Check whether reading/writing DR4 generates an undefined opcode exception.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 x86/debug.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)
diff mbox series

Patch

diff --git a/x86/debug.c b/x86/debug.c
index 9798e62..382fdde 100644
--- a/x86/debug.c
+++ b/x86/debug.c
@@ -18,6 +18,14 @@  static volatile unsigned long db_addr[10], dr6[10];
 static volatile unsigned int n;
 static volatile unsigned long value;
 
+static unsigned long get_dr4(void)
+{
+	unsigned long value;
+
+	asm volatile("mov %%dr4, %0" : "=r" (value));
+	return value;
+}
+
 static unsigned long get_dr6(void)
 {
 	unsigned long value;
@@ -36,6 +44,11 @@  static void set_dr1(void *value)
 	asm volatile("mov %0,%%dr1" : : "r" (value));
 }
 
+static void set_dr4(unsigned long value)
+{
+	asm volatile("mov %0,%%dr4" : : "r" (value));
+}
+
 static void set_dr6(unsigned long value)
 {
 	asm volatile("mov %0,%%dr6" : : "r" (value));
@@ -72,12 +85,35 @@  static void handle_bp(struct ex_regs *regs)
 	bp_addr = regs->rip;
 }
 
+bool got_ud;
+static void handle_ud(struct ex_regs *regs)
+{
+	unsigned long cr4 = read_cr4();
+	write_cr4(cr4 & ~X86_CR4_DE);
+	got_ud = 1;
+}
+
 int main(int ac, char **av)
 {
 	unsigned long start;
+	unsigned long cr4;
 
 	handle_exception(DB_VECTOR, handle_db);
 	handle_exception(BP_VECTOR, handle_bp);
+	handle_exception(UD_VECTOR, handle_ud);
+
+	got_ud = 0;
+	cr4 = read_cr4();
+	write_cr4(cr4 & ~X86_CR4_DE);
+	set_dr4(0);
+	set_dr6(0xffff4ff2);
+	report(get_dr4() == 0xffff4ff2 && !got_ud, "reading DR4 with CR4.DE == 0");
+
+	cr4 = read_cr4();
+	write_cr4(cr4 | X86_CR4_DE);
+	get_dr4();
+	report(got_ud, "reading DR4 with CR4.DE == 1");
+	set_dr6(0);
 
 	extern unsigned char sw_bp;
 	asm volatile("int3; sw_bp:");