Skip to content

Commit

Permalink
KVM: VMX: pass correct DR6 for GD userspace exit
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
bonzini committed May 8, 2020
1 parent d67668e commit 45981de
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
2 changes: 1 addition & 1 deletion arch/x86/kvm/vmx/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -4927,7 +4927,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
* guest debugging itself.
*/
if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
vcpu->run->debug.arch.dr6 = vcpu->arch.dr6;
vcpu->run->debug.arch.dr6 = DR6_BD | DR6_RTM | DR6_FIXED_1;
vcpu->run->debug.arch.dr7 = dr7;
vcpu->run->debug.arch.pc = kvm_get_linear_rip(vcpu);
vcpu->run->debug.arch.exception = DB_VECTOR;
Expand Down
24 changes: 23 additions & 1 deletion tools/testing/selftests/kvm/x86_64/debug_regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@

#define VCPU_ID 0

#define DR6_BD (1 << 13)
#define DR7_GD (1 << 13)

/* For testing data access debug BP */
uint32_t guest_value;

extern unsigned char sw_bp, hw_bp, write_data, ss_start;
extern unsigned char sw_bp, hw_bp, write_data, ss_start, bd_start;

static void guest_code(void)
{
Expand Down Expand Up @@ -43,6 +46,8 @@ static void guest_code(void)
"rdmsr\n\t"
: : : "rax", "ecx");

/* DR6.BD test */
asm volatile("bd_start: mov %%dr0, %%rax" : : : "rax");
GUEST_DONE();
}

Expand Down Expand Up @@ -165,6 +170,23 @@ int main(void)
target_dr6);
}

/* Finally test global disable */
CLEAR_DEBUG();
debug.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
debug.arch.debugreg[7] = 0x400 | DR7_GD;
APPLY_DEBUG();
vcpu_run(vm, VCPU_ID);
target_dr6 = 0xffff0ff0 | DR6_BD;
TEST_ASSERT(run->exit_reason == KVM_EXIT_DEBUG &&
run->debug.arch.exception == DB_VECTOR &&
run->debug.arch.pc == CAST_TO_RIP(bd_start) &&
run->debug.arch.dr6 == target_dr6,
"DR7.GD: exit %d exception %d rip 0x%llx "
"(should be 0x%llx) dr6 0x%llx (should be 0x%llx)",
run->exit_reason, run->debug.arch.exception,
run->debug.arch.pc, target_rip, run->debug.arch.dr6,
target_dr6);

/* Disable all debug controls, run to the end */
CLEAR_DEBUG();
APPLY_DEBUG();
Expand Down

0 comments on commit 45981de

Please sign in to comment.