aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/x86.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8589cc02789e..89313187d7f7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4956,6 +4956,62 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
4956static int complete_emulated_mmio(struct kvm_vcpu *vcpu); 4956static int complete_emulated_mmio(struct kvm_vcpu *vcpu);
4957static int complete_emulated_pio(struct kvm_vcpu *vcpu); 4957static int complete_emulated_pio(struct kvm_vcpu *vcpu);
4958 4958
4959static int kvm_vcpu_check_hw_bp(unsigned long addr, u32 type, u32 dr7,
4960 unsigned long *db)
4961{
4962 u32 dr6 = 0;
4963 int i;
4964 u32 enable, rwlen;
4965
4966 enable = dr7;
4967 rwlen = dr7 >> 16;
4968 for (i = 0; i < 4; i++, enable >>= 2, rwlen >>= 4)
4969 if ((enable & 3) && (rwlen & 15) == type && db[i] == addr)
4970 dr6 |= (1 << i);
4971 return dr6;
4972}
4973
4974static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
4975{
4976 struct kvm_run *kvm_run = vcpu->run;
4977 unsigned long eip = vcpu->arch.emulate_ctxt.eip;
4978 u32 dr6 = 0;
4979
4980 if (unlikely(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) &&
4981 (vcpu->arch.guest_debug_dr7 & DR7_BP_EN_MASK)) {
4982 dr6 = kvm_vcpu_check_hw_bp(eip, 0,
4983 vcpu->arch.guest_debug_dr7,
4984 vcpu->arch.eff_db);
4985
4986 if (dr6 != 0) {
4987 kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1;
4988 kvm_run->debug.arch.pc = kvm_rip_read(vcpu) +
4989 get_segment_base(vcpu, VCPU_SREG_CS);
4990
4991 kvm_run->debug.arch.exception = DB_VECTOR;
4992 kvm_run->exit_reason = KVM_EXIT_DEBUG;
4993 *r = EMULATE_USER_EXIT;
4994 return true;
4995 }
4996 }
4997
4998 if (unlikely(vcpu->arch.dr7 & DR7_BP_EN_MASK)) {
4999 dr6 = kvm_vcpu_check_hw_bp(eip, 0,
5000 vcpu->arch.dr7,
5001 vcpu->arch.db);
5002
5003 if (dr6 != 0) {
5004 vcpu->arch.dr6 &= ~15;
5005 vcpu->arch.dr6 |= dr6;
5006 kvm_queue_exception(vcpu, DB_VECTOR);
5007 *r = EMULATE_DONE;
5008 return true;
5009 }
5010 }
5011
5012 return false;
5013}
5014
4959int x86_emulate_instruction(struct kvm_vcpu *vcpu, 5015int x86_emulate_instruction(struct kvm_vcpu *vcpu,
4960 unsigned long cr2, 5016 unsigned long cr2,
4961 int emulation_type, 5017 int emulation_type,
@@ -4976,6 +5032,16 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
4976 5032
4977 if (!(emulation_type & EMULTYPE_NO_DECODE)) { 5033 if (!(emulation_type & EMULTYPE_NO_DECODE)) {
4978 init_emulate_ctxt(vcpu); 5034 init_emulate_ctxt(vcpu);
5035
5036 /*
5037 * We will reenter on the same instruction since
5038 * we do not set complete_userspace_io. This does not
5039 * handle watchpoints yet, those would be handled in
5040 * the emulate_ops.
5041 */
5042 if (kvm_vcpu_check_breakpoint(vcpu, &r))
5043 return r;
5044
4979 ctxt->interruptibility = 0; 5045 ctxt->interruptibility = 0;
4980 ctxt->have_exception = false; 5046 ctxt->have_exception = false;
4981 ctxt->perm_ok = false; 5047 ctxt->perm_ok = false;