Message ID | 52B2F3AB.9050101@siemens.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Dec 19, 2013 at 02:24:59PM +0100, Jan Kiszka wrote: > In contrast to VMX, SVM dose not automatically transfer DR6 into the > VCPU's arch.dr6. So if we face a DR6 read, we must consult a new vendor > hook to obtain the current value. > > Fixes a regression of 020df0794f. > > Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> > --- > > Should go to stable as well. > > arch/x86/include/asm/kvm_host.h | 1 + > arch/x86/kvm/svm.c | 9 +++++++++ > arch/x86/kvm/vmx.c | 6 ++++++ > arch/x86/kvm/x86.c | 2 +- > 4 files changed, 17 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index ae5d783..f115f46 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -699,6 +699,7 @@ struct kvm_x86_ops { > void (*set_idt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); > void (*get_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); > void (*set_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); > + u64 (*get_dr6)(struct kvm_vcpu *vcpu); > void (*set_dr7)(struct kvm_vcpu *vcpu, unsigned long value); > void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); > unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); > diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c > index c7168a5..48fa63e 100644 > --- a/arch/x86/kvm/svm.c > +++ b/arch/x86/kvm/svm.c > @@ -1671,6 +1671,14 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) > mark_dirty(svm->vmcb, VMCB_ASID); > } > > +static u64 svm_get_dr6(struct kvm_vcpu *vcpu) > +{ > + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) > + return vcpu->arch.dr6; > + else > + return to_svm(vcpu)->vmcb->save.dr6; > +} > + > static void svm_set_dr7(struct kvm_vcpu *vcpu, unsigned long value) > { > struct vcpu_svm *svm = to_svm(vcpu); > @@ -4286,6 +4294,7 @@ static struct kvm_x86_ops svm_x86_ops = { > .set_idt = svm_set_idt, > .get_gdt = svm_get_gdt, > .set_gdt = svm_set_gdt, > + .get_dr6 = svm_get_dr6, > .set_dr7 = svm_set_dr7, > .cache_reg = svm_cache_reg, > .get_rflags = svm_get_rflags, > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c > index ee3bf54..c5c7e62 100644 > --- a/arch/x86/kvm/vmx.c > +++ b/arch/x86/kvm/vmx.c > @@ -5153,6 +5153,11 @@ static int handle_dr(struct kvm_vcpu *vcpu) > return 1; > } > > +static u64 vmx_get_dr6(struct kvm_vcpu *vcpu) > +{ > + return vcpu->arch.dr6; > +} > + > static void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val) > { > vmcs_writel(GUEST_DR7, val); > @@ -8573,6 +8578,7 @@ static struct kvm_x86_ops vmx_x86_ops = { > .set_idt = vmx_set_idt, > .get_gdt = vmx_get_gdt, > .set_gdt = vmx_set_gdt, > + .get_dr6 = vmx_get_dr6, > .set_dr7 = vmx_set_dr7, > .cache_reg = vmx_cache_reg, > .get_rflags = vmx_get_rflags, > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 1dc0359..8fe227c 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -788,7 +788,7 @@ static int _kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val) > return 1; > /* fall through */ > case 6: > - *val = vcpu->arch.dr6; > + *val = kvm_x86_ops->get_dr6(vcpu); > break; > case 5: > if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) > -- > 1.8.1.1.298.ge7eed54 It allows kvm_set_dr(a) val = kvm_get_dr() to have 'val' different than a. Is this OK ? (its certainly counter intuitive). -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index ae5d783..f115f46 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -699,6 +699,7 @@ struct kvm_x86_ops { void (*set_idt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); void (*get_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); void (*set_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); + u64 (*get_dr6)(struct kvm_vcpu *vcpu); void (*set_dr7)(struct kvm_vcpu *vcpu, unsigned long value); void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index c7168a5..48fa63e 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1671,6 +1671,14 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) mark_dirty(svm->vmcb, VMCB_ASID); } +static u64 svm_get_dr6(struct kvm_vcpu *vcpu) +{ + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) + return vcpu->arch.dr6; + else + return to_svm(vcpu)->vmcb->save.dr6; +} + static void svm_set_dr7(struct kvm_vcpu *vcpu, unsigned long value) { struct vcpu_svm *svm = to_svm(vcpu); @@ -4286,6 +4294,7 @@ static struct kvm_x86_ops svm_x86_ops = { .set_idt = svm_set_idt, .get_gdt = svm_get_gdt, .set_gdt = svm_set_gdt, + .get_dr6 = svm_get_dr6, .set_dr7 = svm_set_dr7, .cache_reg = svm_cache_reg, .get_rflags = svm_get_rflags, diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ee3bf54..c5c7e62 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5153,6 +5153,11 @@ static int handle_dr(struct kvm_vcpu *vcpu) return 1; } +static u64 vmx_get_dr6(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.dr6; +} + static void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val) { vmcs_writel(GUEST_DR7, val); @@ -8573,6 +8578,7 @@ static struct kvm_x86_ops vmx_x86_ops = { .set_idt = vmx_set_idt, .get_gdt = vmx_get_gdt, .set_gdt = vmx_set_gdt, + .get_dr6 = vmx_get_dr6, .set_dr7 = vmx_set_dr7, .cache_reg = vmx_cache_reg, .get_rflags = vmx_get_rflags, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1dc0359..8fe227c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -788,7 +788,7 @@ static int _kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val) return 1; /* fall through */ case 6: - *val = vcpu->arch.dr6; + *val = kvm_x86_ops->get_dr6(vcpu); break; case 5: if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
In contrast to VMX, SVM dose not automatically transfer DR6 into the VCPU's arch.dr6. So if we face a DR6 read, we must consult a new vendor hook to obtain the current value. Fixes a regression of 020df0794f. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> --- Should go to stable as well. arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/svm.c | 9 +++++++++ arch/x86/kvm/vmx.c | 6 ++++++ arch/x86/kvm/x86.c | 2 +- 4 files changed, 17 insertions(+), 1 deletion(-)