aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@web.de>2009-10-02 18:31:21 -0400
committerAvi Kivity <avi@redhat.com>2009-12-03 02:32:14 -0500
commit355be0b9300579e02275d7d19374806a974ce622 (patch)
treefaa52bac7a0d1d83c7a0a8f1bec01088b77a68fb /arch/x86
parent201d945bcfb0d53e67c9c081f7c28532eb4669c7 (diff)
KVM: x86: Refactor guest debug IOCTL handling
Much of so far vendor-specific code for setting up guest debug can actually be handled by the generic code. This also fixes a minor deficit in the SVM part /wrt processing KVM_GUESTDBG_ENABLE. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/kvm_host.h4
-rw-r--r--arch/x86/kvm/svm.c14
-rw-r--r--arch/x86/kvm/vmx.c18
-rw-r--r--arch/x86/kvm/x86.c28
4 files changed, 26 insertions, 38 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 295c7c4d9c90..e7f870832603 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -475,8 +475,8 @@ struct kvm_x86_ops {
475 void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu); 475 void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu);
476 void (*vcpu_put)(struct kvm_vcpu *vcpu); 476 void (*vcpu_put)(struct kvm_vcpu *vcpu);
477 477
478 int (*set_guest_debug)(struct kvm_vcpu *vcpu, 478 void (*set_guest_debug)(struct kvm_vcpu *vcpu,
479 struct kvm_guest_debug *dbg); 479 struct kvm_guest_debug *dbg);
480 int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata); 480 int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata);
481 int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); 481 int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
482 u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg); 482 u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 02a4269be645..279a2ae21b4f 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1065,26 +1065,16 @@ static void update_db_intercept(struct kvm_vcpu *vcpu)
1065 vcpu->guest_debug = 0; 1065 vcpu->guest_debug = 0;
1066} 1066}
1067 1067
1068static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) 1068static void svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
1069{ 1069{
1070 int old_debug = vcpu->guest_debug;
1071 struct vcpu_svm *svm = to_svm(vcpu); 1070 struct vcpu_svm *svm = to_svm(vcpu);
1072 1071
1073 vcpu->guest_debug = dbg->control;
1074
1075 update_db_intercept(vcpu);
1076
1077 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) 1072 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
1078 svm->vmcb->save.dr7 = dbg->arch.debugreg[7]; 1073 svm->vmcb->save.dr7 = dbg->arch.debugreg[7];
1079 else 1074 else
1080 svm->vmcb->save.dr7 = vcpu->arch.dr7; 1075 svm->vmcb->save.dr7 = vcpu->arch.dr7;
1081 1076
1082 if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) 1077 update_db_intercept(vcpu);
1083 svm->vmcb->save.rflags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
1084 else if (old_debug & KVM_GUESTDBG_SINGLESTEP)
1085 svm->vmcb->save.rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
1086
1087 return 0;
1088} 1078}
1089 1079
1090static void load_host_msrs(struct kvm_vcpu *vcpu) 1080static void load_host_msrs(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 97f4265cda38..70020e505c22 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1096,30 +1096,14 @@ static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
1096 } 1096 }
1097} 1097}
1098 1098
1099static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) 1099static void set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
1100{ 1100{
1101 int old_debug = vcpu->guest_debug;
1102 unsigned long flags;
1103
1104 vcpu->guest_debug = dbg->control;
1105 if (!(vcpu->guest_debug & KVM_GUESTDBG_ENABLE))
1106 vcpu->guest_debug = 0;
1107
1108 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) 1101 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
1109 vmcs_writel(GUEST_DR7, dbg->arch.debugreg[7]); 1102 vmcs_writel(GUEST_DR7, dbg->arch.debugreg[7]);
1110 else 1103 else
1111 vmcs_writel(GUEST_DR7, vcpu->arch.dr7); 1104 vmcs_writel(GUEST_DR7, vcpu->arch.dr7);
1112 1105
1113 flags = vmcs_readl(GUEST_RFLAGS);
1114 if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
1115 flags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
1116 else if (old_debug & KVM_GUESTDBG_SINGLESTEP)
1117 flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
1118 vmcs_writel(GUEST_RFLAGS, flags);
1119
1120 update_exception_bitmap(vcpu); 1106 update_exception_bitmap(vcpu);
1121
1122 return 0;
1123} 1107}
1124 1108
1125static __init int cpu_has_kvm_support(void) 1109static __init int cpu_has_kvm_support(void)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 5f44d565cc9b..a06f88e66c89 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4472,12 +4472,19 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
4472int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, 4472int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
4473 struct kvm_guest_debug *dbg) 4473 struct kvm_guest_debug *dbg)
4474{ 4474{
4475 int i, r; 4475 unsigned long rflags;
4476 int old_debug;
4477 int i;
4476 4478
4477 vcpu_load(vcpu); 4479 vcpu_load(vcpu);
4478 4480
4479 if ((dbg->control & (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP)) == 4481 old_debug = vcpu->guest_debug;
4480 (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP)) { 4482
4483 vcpu->guest_debug = dbg->control;
4484 if (!(vcpu->guest_debug & KVM_GUESTDBG_ENABLE))
4485 vcpu->guest_debug = 0;
4486
4487 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
4481 for (i = 0; i < KVM_NR_DB_REGS; ++i) 4488 for (i = 0; i < KVM_NR_DB_REGS; ++i)
4482 vcpu->arch.eff_db[i] = dbg->arch.debugreg[i]; 4489 vcpu->arch.eff_db[i] = dbg->arch.debugreg[i];
4483 vcpu->arch.switch_db_regs = 4490 vcpu->arch.switch_db_regs =
@@ -4488,16 +4495,23 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
4488 vcpu->arch.switch_db_regs = (vcpu->arch.dr7 & DR7_BP_EN_MASK); 4495 vcpu->arch.switch_db_regs = (vcpu->arch.dr7 & DR7_BP_EN_MASK);
4489 } 4496 }
4490 4497
4491 r = kvm_x86_ops->set_guest_debug(vcpu, dbg); 4498 rflags = kvm_x86_ops->get_rflags(vcpu);
4499 if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
4500 rflags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
4501 else if (old_debug & KVM_GUESTDBG_SINGLESTEP)
4502 rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
4503 kvm_x86_ops->set_rflags(vcpu, rflags);
4492 4504
4493 if (dbg->control & KVM_GUESTDBG_INJECT_DB) 4505 kvm_x86_ops->set_guest_debug(vcpu, dbg);
4506
4507 if (vcpu->guest_debug & KVM_GUESTDBG_INJECT_DB)
4494 kvm_queue_exception(vcpu, DB_VECTOR); 4508 kvm_queue_exception(vcpu, DB_VECTOR);
4495 else if (dbg->control & KVM_GUESTDBG_INJECT_BP) 4509 else if (vcpu->guest_debug & KVM_GUESTDBG_INJECT_BP)
4496 kvm_queue_exception(vcpu, BP_VECTOR); 4510 kvm_queue_exception(vcpu, BP_VECTOR);
4497 4511
4498 vcpu_put(vcpu); 4512 vcpu_put(vcpu);
4499 4513
4500 return r; 4514 return 0;
4501} 4515}
4502 4516
4503/* 4517/*