diff options
author | Jan Kiszka <jan.kiszka@web.de> | 2009-10-02 18:31:21 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-03 02:32:14 -0500 |
commit | 355be0b9300579e02275d7d19374806a974ce622 (patch) | |
tree | faa52bac7a0d1d83c7a0a8f1bec01088b77a68fb /arch | |
parent | 201d945bcfb0d53e67c9c081f7c28532eb4669c7 (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')
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 4 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 14 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 18 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 28 |
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 | ||
1068 | static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) | 1068 | static 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 | ||
1090 | static void load_host_msrs(struct kvm_vcpu *vcpu) | 1080 | static 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 | ||
1099 | static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) | 1099 | static 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 | ||
1125 | static __init int cpu_has_kvm_support(void) | 1109 | static __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, | |||
4472 | int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, | 4472 | int 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 | /* |