From patchwork Tue Jul 30 15:11:35 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 2835733 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id A8A609F7D6 for ; Tue, 30 Jul 2013 15:12:44 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6DAFC2017E for ; Tue, 30 Jul 2013 15:12:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B28E920157 for ; Tue, 30 Jul 2013 15:12:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755067Ab3G3PMQ (ORCPT ); Tue, 30 Jul 2013 11:12:16 -0400 Received: from mail-ee0-f51.google.com ([74.125.83.51]:53878 "EHLO mail-ee0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753332Ab3G3PLr (ORCPT ); Tue, 30 Jul 2013 11:11:47 -0400 Received: by mail-ee0-f51.google.com with SMTP id c1so3612113eek.38 for ; Tue, 30 Jul 2013 08:11:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=93gAwdsRoY8dFh8W9Giv2wDVS56LdT0eQxsPcmXmuXY=; b=Ursr7ipDgHfbJBT7RFQrCcWf0kCZgTk5fYBrXpkusSr3vQy2PmvEja5+1UGjs0Xwvk MxDjGNzjtfzt2CjKPAGc16UX9wtzwMr5DoJ1/AYSQlXdG8CmVKN8BPwxbRoZxeqqyini E11PdPUjQ7JsmOEaakfTn3G0UI9lB0oQGQUnSYuJRNEnBCEg0mu+jpAZ9igYoVBQuQbf twB+0mEvamzpbPBhdX7D1xGOCwArrAqJ6i0eT4k3JY0o1NyKHBCNeAyk4Z4Ycayz3bsn KqQgLhCHn/eZqpYA8DRSZ+bl1nR5SArbE0T0lK2+O40HcPRb8KTQKKkwv+VHyPIEPzum NcpQ== X-Received: by 10.15.91.69 with SMTP id r45mr65053334eez.79.1375197105604; Tue, 30 Jul 2013 08:11:45 -0700 (PDT) Received: from playground.station (net-2-39-8-162.cust.dsl.vodafone.it. [2.39.8.162]) by mx.google.com with ESMTPSA id cg12sm111276799eeb.7.2013.07.30.08.11.43 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 30 Jul 2013 08:11:44 -0700 (PDT) From: Paolo Bonzini To: linux-kernel@vger.kernel.org Cc: gnatapov@redhat.com, kvm@vger.kernel.org Subject: [PATCH 2/3] KVM: x86: handle hardware breakpoints during emulation Date: Tue, 30 Jul 2013 17:11:35 +0200 Message-Id: <1375197096-2454-3-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1375197096-2454-1-git-send-email-pbonzini@redhat.com> References: <1375197096-2454-1-git-send-email-pbonzini@redhat.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-8.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This lets debugging work better during emulation of invalid guest state. The check is done before emulating the instruction, and (in the case of guest debugging) reuses EMULATE_DO_MMIO to exit with KVM_EXIT_DEBUG. Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c2a0674..1368cf5 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, static int complete_emulated_mmio(struct kvm_vcpu *vcpu); static int complete_emulated_pio(struct kvm_vcpu *vcpu); +static int kvm_vcpu_check_hw_bp(unsigned long addr, u32 type, u32 dr7, + unsigned long *db) +{ + u32 dr6 = 0; + int i; + u32 enable, rwlen; + + enable = dr7; + rwlen = dr7 >> 16; + for (i = 0; i < 4; i++, enable >>= 2, rwlen >>= 4) + if ((enable & 3) && (rwlen & 15) == type && db[i] == addr) + dr6 |= (1 << i); + return dr6; +} + +static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r) +{ + struct kvm_run *kvm_run = vcpu->run; + unsigned long eip = vcpu->arch.emulate_ctxt.eip; + u32 dr6 = 0; + + if (unlikely(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) && + (vcpu->arch.guest_debug_dr7 & DR7_BP_EN_MASK)) { + dr6 = kvm_vcpu_check_hw_bp(eip, 0, + vcpu->arch.guest_debug_dr7, + vcpu->arch.eff_db); + + if (dr6 != 0) { + kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1; + kvm_run->debug.arch.pc = kvm_rip_read(vcpu) + + get_segment_base(vcpu, VCPU_SREG_CS); + + kvm_run->debug.arch.exception = DB_VECTOR; + kvm_run->exit_reason = KVM_EXIT_DEBUG; + *r = EMULATE_USER_EXIT; + return true; + } + } + + if (unlikely(vcpu->arch.dr7 & DR7_BP_EN_MASK)) { + dr6 = kvm_vcpu_check_hw_bp(eip, 0, + vcpu->arch.dr7, + vcpu->arch.db); + + if (dr6 != 0) { + vcpu->arch.dr6 &= ~15; + vcpu->arch.dr6 |= dr6; + kvm_queue_exception(vcpu, DB_VECTOR); + *r = EMULATE_DONE; + return true; + } + } + + return false; +} + int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2, int emulation_type, @@ -4976,6 +5032,16 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, if (!(emulation_type & EMULTYPE_NO_DECODE)) { init_emulate_ctxt(vcpu); + + /* + * We will reenter on the same instruction since + * we do not set complete_userspace_io. This does not + * handle watchpoints yet, those would be handled in + * the emulate_ops. + */ + if (kvm_vcpu_check_breakpoint(vcpu, &r)) + return r; + ctxt->interruptibility = 0; ctxt->have_exception = false; ctxt->perm_ok = false;