KVM: SVM: Fix reading of DR6
PATCH 1/1 KVM: SVM: Fix reading of DR6
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.
---
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(-)
arch/x86/include/asm/kvm_host.h +1 -0
@@ -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);
arch/x86/kvm/svm.c +9 -0
@@ -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,
arch/x86/kvm/vmx.c +6 -0
@@ -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,
arch/x86/kvm/x86.c +1 -1
@@ -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 ))
Signature · 1 line
1.8.1.1.298.ge7eed54
Quoted 95 lines · Jan Kiszka
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 <[email protected]>---
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(-)arch/x86/include/asm/kvm_host.h +1
-0@@ -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);arch/x86/kvm/svm.c +9
-0@@ -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,arch/x86/kvm/vmx.c +6
-0@@ -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,arch/x86/kvm/x86.c +1
-1@@ -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 ))Signature · 1 line
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).
PATCH v2 1/1 KVM: SVM: Fix reading of DR6
Quoted 99 lines · Marcelo Tosatti
Quoted 95 lines · Jan Kiszka
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 <[email protected]>---
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(-)arch/x86/include/asm/kvm_host.h +1
-0@@ -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);arch/x86/kvm/svm.c +9
-0@@ -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,arch/x86/kvm/vmx.c +6
-0@@ -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,arch/x86/kvm/x86.c +1
-1@@ -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 ))Signature · 1 line
1.8.1.1.298.ge7eed54It allows
Quoted 6 lines
kvm_set_dr(a)
val =kvm_get_dr()to have 'val' different than a.
Is this OK ? (its certainly counter intuitive).
No, it's not ok. We also need to sync the guest-visible state to the VMCB on updates.
----8<----
From: Jan Kiszka <[email protected]>
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. And as SVM now picks the DR6 state from its VMCB, we also need a set callback in order to write updates of DR6 back.
Fixes a regression of 020df0794f.
--- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/svm.c | 18 ++++++++++++++++++ arch/x86/kvm/vmx.c | 11 +++++++++++ arch/x86/kvm/x86.c | 3 ++- 4 files changed, 33 insertions(+), 1 deletion(-)
arch/x86/include/asm/kvm_host.h +2 -0
@@ -699,6 +699,8 @@ 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_dr6)(struct kvm_vcpu *vcpu,unsigned long value);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);
arch/x86/kvm/svm.c +18 -0
@@ -1671,6 +1671,22 @@ 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_dr6 (struct kvm_vcpu *vcpu,unsigned long value) +{ +struct vcpu_svm *svm =to_svm (vcpu); + + svm->vmcb->save.dr6 = value; +mark_dirty (svm->vmcb,VMCB_DR ); +} +static void svm_set_dr7 (struct kvm_vcpu *vcpu,unsigned long value) {struct vcpu_svm *svm =to_svm (vcpu);
@@ -4286,6 +4302,8 @@ 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_dr6 = svm_set_dr6, .set_dr7 = svm_set_dr7, .cache_reg = svm_cache_reg, .get_rflags = svm_get_rflags,
arch/x86/kvm/vmx.c +11 -0
@@ -5153,6 +5153,15 @@ 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_dr6 (struct kvm_vcpu *vcpu,unsigned long val) +{ +} +static void vmx_set_dr7 (struct kvm_vcpu *vcpu,unsigned long val) {vmcs_writel (GUEST_DR7 , val);
@@ -8573,6 +8582,8 @@ 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_dr6 = vmx_set_dr6, .set_dr7 = vmx_set_dr7, .cache_reg = vmx_cache_reg, .get_rflags = vmx_get_rflags,
arch/x86/kvm/x86.c +2 -1
@@ -747,6 +747,7 @@ static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)if (val &0xffffffff00000000ULL )return -1 ;/* #GP */ vcpu->arch.dr6 = (val &DR6_VOLATILE ) |DR6_FIXED_1 ; + kvm_x86_ops->set_dr6 (vcpu, vcpu->arch.dr6);break ;case 5 :if (kvm_read_cr4_bits (vcpu,X86_CR4_DE ))
@@ -788,7 +789,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 ))
Signature · 1 line
1.8.1.1.298.ge7eed54
Paolo Bonzini
maintainerIl 27/12/2013 19:17, Jan Kiszka ha scritto:
Quoted 44 lines
From: Jan Kiszka <[email protected]>
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. And as SVM now picks the DR6 state from its VMCB, we also need a set callback in order to write updates of DR6 back.
Fixes a regression of
020df0794f.Signed-off-by Jan Kiszka <[email protected]>--- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/svm.c | 18 ++++++++++++++++++ arch/x86/kvm/vmx.c | 11 +++++++++++ arch/x86/kvm/x86.c | 3 ++- 4 files changed, 33 insertions(+), 1 deletion(-)arch/x86/include/asm/kvm_host.h +2
-0@@ -699,6 +699,8 @@ 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_dr6)(struct kvm_vcpu *vcpu,unsigned long value);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);arch/x86/kvm/svm.c +4
-0@@ -1671,6 +1671,22 @@ 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;
arch/x86/kvm/svm.c static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) · line 1687
Quoted 10 lines
arch/x86/kvm/svm.c +10
-0+else +return to_svm (vcpu)->vmcb->save.dr6; +} + +static void svm_set_dr6 (struct kvm_vcpu *vcpu,unsigned long value) +{ +struct vcpu_svm *svm =to_svm (vcpu); + + svm->vmcb->save.dr6 = value; +mark_dirty (svm->vmcb,VMCB_DR );
The code here is a bit different from the existing DR7 hooks. Why isn't get_dr7 needed? I cannot find anything in the AMD manuals that suggests a difference between DR6 and DR7.
Also, set_dr7 is only called when !(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP). I think it makes sense to do the same for all the new hooks you need to introduce (get_dr6, set_dr6 and possibly get_dr7).
And finally, is it necessary to write to both vcpu->arch.dr6/7 and svm->vmcb->save.dr6/7, or is it simply okay to do that?
Paolo
Quoted 64 lines
arch/x86/kvm/svm.c +4
-0+} +static void svm_set_dr7 (struct kvm_vcpu *vcpu,unsigned long value) {struct vcpu_svm *svm =to_svm (vcpu);@@ -4286,6 +4302,8 @@ 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_dr6 = svm_set_dr6, .set_dr7 = svm_set_dr7, .cache_reg = svm_cache_reg, .get_rflags = svm_get_rflags,arch/x86/kvm/vmx.c +11
-0@@ -5153,6 +5153,15 @@ 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_dr6 (struct kvm_vcpu *vcpu,unsigned long val) +{ +} +static void vmx_set_dr7 (struct kvm_vcpu *vcpu,unsigned long val) {vmcs_writel (GUEST_DR7 , val);@@ -8573,6 +8582,8 @@ 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_dr6 = vmx_set_dr6, .set_dr7 = vmx_set_dr7, .cache_reg = vmx_cache_reg, .get_rflags = vmx_get_rflags,arch/x86/kvm/x86.c +2
-1@@ -747,6 +747,7 @@ static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)if (val &0xffffffff00000000ULL )return -1 ;/* #GP */ vcpu->arch.dr6 = (val &DR6_VOLATILE ) |DR6_FIXED_1 ; + kvm_x86_ops->set_dr6 (vcpu, vcpu->arch.dr6);break ;case 5 :if (kvm_read_cr4_bits (vcpu,X86_CR4_DE ))@@ -788,7 +789,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 ))
Quoted 51 lines · Paolo Bonzini
Il 27/12/2013 19:17, Jan Kiszka ha scritto:
Quoted 50 lines
From: Jan Kiszka <[email protected]>
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. And as SVM now picks the DR6 state from its VMCB, we also need a set callback in order to write updates of DR6 back.
Fixes a regression of
020df0794f.Signed-off-by Jan Kiszka <[email protected]>--- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/svm.c | 18 ++++++++++++++++++ arch/x86/kvm/vmx.c | 11 +++++++++++ arch/x86/kvm/x86.c | 3 ++- 4 files changed, 33 insertions(+), 1 deletion(-)arch/x86/include/asm/kvm_host.h +2
-0@@ -699,6 +699,8 @@ 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_dr6)(struct kvm_vcpu *vcpu,unsigned long value);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);arch/x86/kvm/svm.c +10
-0@@ -1671,6 +1671,22 @@ 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_dr6 (struct kvm_vcpu *vcpu,unsigned long value) +{
Quoted 8 lines
arch/x86/kvm/svm.c static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) · line 1687
Quoted 4 lines
arch/x86/kvm/svm.c +4
-0+struct vcpu_svm *svm =to_svm (vcpu); + + svm->vmcb->save.dr6 = value; +mark_dirty (svm->vmcb,VMCB_DR );The code here is a bit different from the existing DR7 hooks. Why isn't
get_dr7needed? I cannot find anything in the AMD manuals that suggests a difference between DR6 and DR7.
DR7 doesn't change while the guest is running, only when the guest writes to it, and we intercept that.
Quoted 4 lines
Also,
set_dr7is only called when !(vcpu->guest_debug &KVM_GUESTDBG_USE_HW_BP). I think it makes sense to do the same for all the new hooks you need to introduce (get_dr6,set_dr6and possiblyget_dr7).
We could make set_dr6 conditional, but it doesn't make a difference in practice. If guest debugging is enabled, we effectively only use DR6 when leaving the guest, i.e. when the hardware defined DR6.
Hmm, SVM is not updating kvm_run::debug.arch.dr6/7... There might be more broken, need to check. But that would not be guest visible then.
Quoted 3 lines
And finally, is it necessary to write to both vcpu->arch.dr6/7 and svm->vmcb->save.dr6/7, or is it simply okay to do that?
arch.dr6/7 holds the guest visible state, save.dr6/7 the effective one.
Jan
PS: I'll look into a kvm unit test for hardware debugging features these days. Guest-side at least, no idea yet how to implement host-side debugging with unit tests.
Paolo Bonzini
maintainer-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Il 31/12/2013 18:29, Jan Kiszka ha scritto:
Quoted 7 lines
Quoted 4 lines
Also,
set_dr7is only called when !(vcpu->guest_debug &KVM_GUESTDBG_USE_HW_BP). I think it makes sense to do the same for all the new hooks you need to introduce (get_dr6,set_dr6and possiblyget_dr7).We could make
set_dr6conditional, but it doesn't make a difference in practice.
No, it doesn't indeed. It's just a matter of consistency.
Quoted 11 lines
If guest debugging is enabled, we effectively only use DR6 when leaving the guest, i.e. when the hardware defined DR6.
Hmm, SVM is not updating kvm_run::debug.arch.dr6/7... There might be more broken, need to check. But that would not be guest visible then.
Quoted 3 lines
And finally, is it necessary to write to both vcpu->arch.dr6/7 and svm->vmcb->save.dr6/7, or is it simply okay to do that?
Quoted 8 lines
arch.dr6/7 holds the guest visible state, save.dr6/7 the effective one.
Jan
PS: I'll look into a kvm unit test for hardware debugging features these days. Guest-side at least, no idea yet how to implement host-side debugging with unit tests.
It would be possible to do it with infrastructure like qtest or autotest. You could speak the gdbserver protocol yourself, or open a pty to gdb. But guest-side is already an improvement over nothing!
Paolo
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iQIcBAEBAgAGBQJSxSI0AAoJEBvWZb6bTYbyoiYP/REKgPL/dUwJoSA8AEm7h6Ip wkXlaxBcyBiKlIzfiN3abBXBOZvDy7dSzNfXUZ4bY6DitQIJZYSVc93XfvWYRToY ORC6qZej+P/bD/rNwATpvVhGG6RbRpmihmVgkoX5w5J3GWZ52QREcyoW7mZEhIoR fCMJmNCq2l9vxa5hhXLAuiLYtq7mto6hQpFE8TXG81PyzE+c3WWK1D5vy/2cpv48 qabaVsJs7aj0KV2rVDvyQkO+GSdm+8SDpf4GyJcLo1Y1yYjPW97xC0Ey4ZyEXXWf 37zb3oOoH9NPPXtt1oJhUFCFZ34v1MxW2j0IIGvtUfRPSjphW+T/nQ5y17GG+efQ TbKnSlibNP0L7fX/xa/sytaYcslIJVIKvvq0Wz9a3Ka1OHNufgtBIreUjtAPvSmy TLxTm2w2s0S/mD3yMDK62uAtQMV/FW7qV6WHTHHZzj8VJpgfAAO0j4gkN0PlLB91 XfuR8ANmYoAKm9yafOSlr6Xw4uzHh41ZODMIY9w/pwB6nGB8SMRVBUWAILkyiyoN btJdVCFdmxTlUmszAeHGTkd4VMtOMqva8MmgnV5isVEUy5A6gJZwNSZ8KJCdny+J N+jRLj/j3SUlxGFnsK4FPBlMQzK1DDYS3C2QKd+Z5No42kZg4w2g4n0zQamDi2XR 2lcuexvRePHTZglNkP82
=dDQc
-----END PGP SIGNATURE-----