Skip to content

Commit 45981de

Browse files
committed
KVM: VMX: pass correct DR6 for GD userspace exit
When KVM_EXIT_DEBUG is raised for the disabled-breakpoints case (DR7.GD), DR6 was incorrectly copied from the value in the VM. Instead, DR6.BD should be set in order to catch this case. On AMD this does not need any special code because the processor triggers a #DB exception that is intercepted. However, the testcase would fail without the previous patch because both DR6.BS and DR6.BD would be set. Signed-off-by: Paolo Bonzini <[email protected]>
1 parent d67668e commit 45981de

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

arch/x86/kvm/vmx/vmx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4927,7 +4927,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
49274927
* guest debugging itself.
49284928
*/
49294929
if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
4930-
vcpu->run->debug.arch.dr6 = vcpu->arch.dr6;
4930+
vcpu->run->debug.arch.dr6 = DR6_BD | DR6_RTM | DR6_FIXED_1;
49314931
vcpu->run->debug.arch.dr7 = dr7;
49324932
vcpu->run->debug.arch.pc = kvm_get_linear_rip(vcpu);
49334933
vcpu->run->debug.arch.exception = DB_VECTOR;

tools/testing/selftests/kvm/x86_64/debug_regs.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111

1212
#define VCPU_ID 0
1313

14+
#define DR6_BD (1 << 13)
15+
#define DR7_GD (1 << 13)
16+
1417
/* For testing data access debug BP */
1518
uint32_t guest_value;
1619

17-
extern unsigned char sw_bp, hw_bp, write_data, ss_start;
20+
extern unsigned char sw_bp, hw_bp, write_data, ss_start, bd_start;
1821

1922
static void guest_code(void)
2023
{
@@ -43,6 +46,8 @@ static void guest_code(void)
4346
"rdmsr\n\t"
4447
: : : "rax", "ecx");
4548

49+
/* DR6.BD test */
50+
asm volatile("bd_start: mov %%dr0, %%rax" : : : "rax");
4651
GUEST_DONE();
4752
}
4853

@@ -165,6 +170,23 @@ int main(void)
165170
target_dr6);
166171
}
167172

173+
/* Finally test global disable */
174+
CLEAR_DEBUG();
175+
debug.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
176+
debug.arch.debugreg[7] = 0x400 | DR7_GD;
177+
APPLY_DEBUG();
178+
vcpu_run(vm, VCPU_ID);
179+
target_dr6 = 0xffff0ff0 | DR6_BD;
180+
TEST_ASSERT(run->exit_reason == KVM_EXIT_DEBUG &&
181+
run->debug.arch.exception == DB_VECTOR &&
182+
run->debug.arch.pc == CAST_TO_RIP(bd_start) &&
183+
run->debug.arch.dr6 == target_dr6,
184+
"DR7.GD: exit %d exception %d rip 0x%llx "
185+
"(should be 0x%llx) dr6 0x%llx (should be 0x%llx)",
186+
run->exit_reason, run->debug.arch.exception,
187+
run->debug.arch.pc, target_rip, run->debug.arch.dr6,
188+
target_dr6);
189+
168190
/* Disable all debug controls, run to the end */
169191
CLEAR_DEBUG();
170192
APPLY_DEBUG();

0 commit comments

Comments
 (0)