From patchwork Fri Feb 19 18:22:26 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 80791 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o1JIMxCO028946 for ; Fri, 19 Feb 2010 18:23:04 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755453Ab0BSSXB (ORCPT ); Fri, 19 Feb 2010 13:23:01 -0500 Received: from thoth.sbs.de ([192.35.17.2]:20711 "EHLO thoth.sbs.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755409Ab0BSSXA (ORCPT ); Fri, 19 Feb 2010 13:23:00 -0500 Received: from mail3.siemens.de (localhost [127.0.0.1]) by thoth.sbs.de (8.12.11.20060308/8.12.11) with ESMTP id o1JIMTcS007087; Fri, 19 Feb 2010 19:22:29 +0100 Received: from localhost.localdomain (mchn012c.ww002.siemens.net [139.25.109.167] (may be forged)) by mail3.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id o1JIMRGD025400; Fri, 19 Feb 2010 19:22:29 +0100 From: Jan Kiszka To: Avi Kivity , Marcelo Tosatti Cc: kvm@vger.kernel.org, qemu-devel@nongnu.org, Anthony Liguori , Gleb Natapov Subject: [PATCH 8/9] KVM: Rework of guest debug state writing Date: Fri, 19 Feb 2010 19:22:26 +0100 Message-Id: <68e0d2c45f24b4c183cc1827902afc46d280d89b.1266603744.git.jan.kiszka@siemens.com> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: References: In-Reply-To: References: Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 19 Feb 2010 18:23:05 +0000 (UTC) diff --git a/kvm-all.c b/kvm-all.c index 2237239..f0c5cf6 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -994,10 +994,6 @@ static void kvm_invoke_set_guest_debug(void *data) struct kvm_set_guest_debug_data *dbg_data = data; CPUState *env = dbg_data->env; - if (env->kvm_vcpu_dirty) { - kvm_arch_put_registers(env); - env->kvm_vcpu_dirty = 0; - } dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg); } @@ -1005,12 +1001,12 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap) { struct kvm_set_guest_debug_data data; - data.dbg.control = 0; - if (env->singlestep_enabled) - data.dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP; + data.dbg.control = reinject_trap; + if (env->singlestep_enabled) { + data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP; + } kvm_arch_update_guest_debug(env, &data.dbg); - data.dbg.control |= reinject_trap; data.env = env; on_vcpu(env, kvm_invoke_set_guest_debug, &data); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 8743f32..a4130d4 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -885,6 +885,32 @@ int kvm_arch_put_registers(CPUState *env) if (ret < 0) return ret; + /* + * Kernels before 2.6.33 (which correlates with !kvm_has_vcpu_events()) + * overwrote flags.TF injected via SET_GUEST_DEBUG while updating GP regs. + * Work around this by updating the debug state once again if + * single-stepping is on. + * Another reason to call kvm_update_guest_debug here is a pending debug + * trap raise by the guest. On kernels without SET_VCPU_EVENTS we have to + * reinject them via SET_GUEST_DEBUG. + */ + if (!kvm_has_vcpu_events() && + (env->exception_injected != -1 || env->singlestep_enabled)) { + unsigned long reinject_trap = 0; + + if (env->exception_injected == 1) { + reinject_trap = KVM_GUESTDBG_INJECT_DB; + } else if (env->exception_injected == 3) { + reinject_trap = KVM_GUESTDBG_INJECT_BP; + } + env->exception_injected = -1; + + ret = kvm_update_guest_debug(env, reinject_trap); + if (ret < 0) { + return ret; + } + } + return 0; } @@ -1130,10 +1156,13 @@ int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info) } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc)) handle = 1; - if (!handle) - kvm_update_guest_debug(cpu_single_env, - (arch_info->exception == 1) ? - KVM_GUESTDBG_INJECT_DB : KVM_GUESTDBG_INJECT_BP); + if (!handle) { + cpu_synchronize_state(cpu_single_env); + assert(cpu_single_env->exception_injected == -1); + + cpu_single_env->exception_injected = arch_info->exception; + cpu_single_env->has_error_code = 0; + } return handle; }