Skip to content

Commit 82b3277

Browse files
anadavbonzini
authored andcommitted
KVM: x86: Breakpoints do not consider CS.base
x86 debug registers hold a linear address. Therefore, breakpoints detection should consider CS.base, and check whether instruction linear address equals (CS.base + RIP). This patch introduces a function to evaluate RIP linear address and uses it for breakpoints detection. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 7305eb5 commit 82b3277

File tree

3 files changed

+18
-16
lines changed

3 files changed

+18
-16
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,7 @@ void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
10671067
void kvm_define_shared_msr(unsigned index, u32 msr);
10681068
int kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
10691069

1070+
unsigned long kvm_get_linear_rip(struct kvm_vcpu *vcpu);
10701071
bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip);
10711072

10721073
void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,

arch/x86/kvm/vmx.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5118,9 +5118,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
51185118
if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
51195119
vcpu->run->debug.arch.dr6 = vcpu->arch.dr6;
51205120
vcpu->run->debug.arch.dr7 = dr7;
5121-
vcpu->run->debug.arch.pc =
5122-
vmcs_readl(GUEST_CS_BASE) +
5123-
vmcs_readl(GUEST_RIP);
5121+
vcpu->run->debug.arch.pc = kvm_get_linear_rip(vcpu);
51245122
vcpu->run->debug.arch.exception = DB_VECTOR;
51255123
vcpu->run->exit_reason = KVM_EXIT_DEBUG;
51265124
return 0;

arch/x86/kvm/x86.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5207,21 +5207,17 @@ static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, unsigned long rflag
52075207

52085208
static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
52095209
{
5210-
struct kvm_run *kvm_run = vcpu->run;
5211-
unsigned long eip = vcpu->arch.emulate_ctxt.eip;
5212-
u32 dr6 = 0;
5213-
52145210
if (unlikely(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) &&
52155211
(vcpu->arch.guest_debug_dr7 & DR7_BP_EN_MASK)) {
5216-
dr6 = kvm_vcpu_check_hw_bp(eip, 0,
5212+
struct kvm_run *kvm_run = vcpu->run;
5213+
unsigned long eip = kvm_get_linear_rip(vcpu);
5214+
u32 dr6 = kvm_vcpu_check_hw_bp(eip, 0,
52175215
vcpu->arch.guest_debug_dr7,
52185216
vcpu->arch.eff_db);
52195217

52205218
if (dr6 != 0) {
52215219
kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1 | DR6_RTM;
5222-
kvm_run->debug.arch.pc = kvm_rip_read(vcpu) +
5223-
get_segment_base(vcpu, VCPU_SREG_CS);
5224-
5220+
kvm_run->debug.arch.pc = eip;
52255221
kvm_run->debug.arch.exception = DB_VECTOR;
52265222
kvm_run->exit_reason = KVM_EXIT_DEBUG;
52275223
*r = EMULATE_USER_EXIT;
@@ -5231,7 +5227,8 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
52315227

52325228
if (unlikely(vcpu->arch.dr7 & DR7_BP_EN_MASK) &&
52335229
!(kvm_get_rflags(vcpu) & X86_EFLAGS_RF)) {
5234-
dr6 = kvm_vcpu_check_hw_bp(eip, 0,
5230+
unsigned long eip = kvm_get_linear_rip(vcpu);
5231+
u32 dr6 = kvm_vcpu_check_hw_bp(eip, 0,
52355232
vcpu->arch.dr7,
52365233
vcpu->arch.db);
52375234

@@ -7538,12 +7535,18 @@ int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
75387535
return kvm_x86_ops->interrupt_allowed(vcpu);
75397536
}
75407537

7541-
bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip)
7538+
unsigned long kvm_get_linear_rip(struct kvm_vcpu *vcpu)
75427539
{
7543-
unsigned long current_rip = kvm_rip_read(vcpu) +
7544-
get_segment_base(vcpu, VCPU_SREG_CS);
7540+
if (is_64_bit_mode(vcpu))
7541+
return kvm_rip_read(vcpu);
7542+
return (u32)(get_segment_base(vcpu, VCPU_SREG_CS) +
7543+
kvm_rip_read(vcpu));
7544+
}
7545+
EXPORT_SYMBOL_GPL(kvm_get_linear_rip);
75457546

7546-
return current_rip == linear_rip;
7547+
bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip)
7548+
{
7549+
return kvm_get_linear_rip(vcpu) == linear_rip;
75477550
}
75487551
EXPORT_SYMBOL_GPL(kvm_is_linear_rip);
75497552

0 commit comments

Comments
 (0)