[kvm-unit-tests RFC] x86: Fix "debug" test on AMD uArch

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

 



As per the AMD APM[1], DR6[BusLockDetect] bit is unmodified for any source
of #DB exception other than Bus Lock (and AMD HW is working correctly as
per the spec).

KUT debug test initializes DR6[BusLockDetect] with 0 before executing each
test and thus the bit remains 0 at the #DB exception for sources other
than Bus Lock. Since DR6[BusLockDetect] bit has opposite polarity, as in,
value 0 indicates the condition, KUT tests are interpreting it as #DB due
to Bus Lock and thus they are failing.

Fix this by initializing DR6 with a valid default value before running the
test.

[1]: AMD64 Architecture Programmer's Manual Pub. 40332, Rev. 4.07 - June
     2023, Vol 2, 13.1.3.6 Bus Lock Trap
     https://bugzilla.kernel.org/attachment.cgi?id=304653

Note: Although Intel SDM (December 2024, Vol 3B, 19.2.3 Debug Status
Register (DR6)) stats the same "Other debug exceptions do not modify this
bit", HW seems to be resetting DR6[BusLockDetect] to 1 for #DB with
non-BusLock sources? In any case, initializing DR6 with correct value is
semantically correct on Intel as well, so this should not have any
regression on Intel platforms.

Reported-by: Sean Christopherson <seanjc@xxxxxxxxxx>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219787#c13
Signed-off-by: Ravi Bangoria <ravi.bangoria@xxxxxxx>
---
 x86/debug.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/x86/debug.c b/x86/debug.c
index f493567c..2b1084a2 100644
--- a/x86/debug.c
+++ b/x86/debug.c
@@ -93,7 +93,7 @@ static void __run_single_step_db_test(db_test_fn test, db_report_fn report_fn)
 	bool ign;
 
 	n = 0;
-	write_dr6(0);
+	write_dr6(DR6_ACTIVE_LOW);
 
 	start = test();
 	report_fn(start, "");
@@ -107,7 +107,7 @@ static void __run_single_step_db_test(db_test_fn test, db_report_fn report_fn)
 		return;
 
 	n = 0;
-	write_dr6(0);
+	write_dr6(DR6_ACTIVE_LOW);
 
 	/*
 	 * Run the test in usermode.  Use the expected start RIP from the first
@@ -339,6 +339,7 @@ static noinline unsigned long singlestep_with_movss_blocking_and_dr7_gd(void)
 	 * General Detect #DB.
 	 */
 	asm volatile(
+		"mov $0xffff0ff0, %%rcx\n\t"
 		"xor %0, %0\n\t"
 		"pushf\n\t"
 		"pop %%rax\n\t"
@@ -347,7 +348,7 @@ static noinline unsigned long singlestep_with_movss_blocking_and_dr7_gd(void)
 		"mov %%ss, %%ax\n\t"
 		"popf\n\t"
 		"mov %%ax, %%ss\n\t"
-		"1: mov %0, %%dr6\n\t"
+		"1: mov %%rcx, %%dr6\n\t"
 		"and $~(1<<8),%%rax\n\t"
 		"push %%rax\n\t"
 		"popf\n\t"
@@ -433,7 +434,7 @@ int main(int ac, char **av)
 	write_cr4(cr4 | X86_CR4_DE);
 	read_dr4();
 	report(got_ud, "DR4 read got #UD with CR4.DE == 1");
-	write_dr6(0);
+	write_dr6(DR6_ACTIVE_LOW);
 
 	extern unsigned char sw_bp;
 	asm volatile("int3; sw_bp:");
@@ -460,7 +461,7 @@ int main(int ac, char **av)
 	n = 0;
 	extern unsigned char hw_bp2;
 	write_dr0(&hw_bp2);
-	write_dr6(DR6_BS | DR6_TRAP1);
+	write_dr6(DR6_BS | DR6_TRAP1 | DR6_ACTIVE_LOW);
 	asm volatile("hw_bp2: nop");
 	report(n == 1 &&
 	       db_addr[0] == ((unsigned long)&hw_bp2) &&
@@ -477,7 +478,7 @@ int main(int ac, char **av)
 
 	n = 0;
 	write_dr1((void *)&value);
-	write_dr6(DR6_BS);
+	write_dr6(DR6_BS | DR6_ACTIVE_LOW);
 	write_dr7(0x00d0040a); // 4-byte write
 
 	extern unsigned char hw_wp1;
@@ -491,7 +492,7 @@ int main(int ac, char **av)
 	       "hw watchpoint (test that dr6.BS is not cleared)");
 
 	n = 0;
-	write_dr6(0);
+	write_dr6(DR6_ACTIVE_LOW);
 
 	extern unsigned char hw_wp2;
 	asm volatile(
@@ -504,7 +505,7 @@ int main(int ac, char **av)
 	       "hw watchpoint (test that dr6.BS is not set)");
 
 	n = 0;
-	write_dr6(0);
+	write_dr6(DR6_ACTIVE_LOW);
 	extern unsigned char sw_icebp;
 	asm volatile(".byte 0xf1; sw_icebp:");
 	report(n == 1 &&
-- 
2.43.0





[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