From patchwork Mon Mar 1 17:17:20 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 46573 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E2375B7D9D for ; Tue, 2 Mar 2010 04:37:56 +1100 (EST) Received: from localhost ([127.0.0.1]:40137 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Nm9Y6-0000yw-KA for incoming@patchwork.ozlabs.org; Mon, 01 Mar 2010 12:36:54 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Nm9Fk-0000DY-FL for qemu-devel@nongnu.org; Mon, 01 Mar 2010 12:17:56 -0500 Received: from [199.232.76.173] (port=41209 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Nm9Fi-0000Cn-Sl for qemu-devel@nongnu.org; Mon, 01 Mar 2010 12:17:54 -0500 Received: from Debian-exim by monty-python.gnu.org with spam-scanned (Exim 4.60) (envelope-from ) id 1Nm9FR-0004KT-JQ for qemu-devel@nongnu.org; Mon, 01 Mar 2010 12:17:53 -0500 Received: from david.siemens.de ([192.35.17.14]:23124) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Nm9FO-0004Ip-OH for qemu-devel@nongnu.org; Mon, 01 Mar 2010 12:17:36 -0500 Received: from mail2.siemens.de (localhost [127.0.0.1]) by david.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id o21HHUr4020540; Mon, 1 Mar 2010 18:17:30 +0100 Received: from localhost.localdomain (mchn012c.mchp.siemens.de [139.25.109.167] (may be forged)) by mail2.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id o21HHUx0000935; Mon, 1 Mar 2010 18:17:30 +0100 From: Jan Kiszka To: Avi Kivity , Marcelo Tosatti Date: Mon, 1 Mar 2010 18:17:20 +0100 Message-Id: X-Mailer: git-send-email 1.6.0.2 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.4-2.6 Cc: Gleb Natapov , qemu-devel@nongnu.org, kvm@vger.kernel.org Subject: [Qemu-devel] [PATCH v4 01/10] qemu-kvm: Add KVM_CAP_X86_ROBUST_SINGLESTEP-awareness X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This add-on patch to recent guest debugging refactorings adds the requested awareness for KVM_CAP_X86_ROBUST_SINGLESTEP to both the upstream as well as qemu-kvm's own code. Fortunately, code sharing increased once again. Signed-off-by: Jan Kiszka --- kvm-all.c | 12 ++++++++++ kvm.h | 1 + qemu-kvm-x86.c | 27 +---------------------- qemu-kvm.h | 1 + target-i386/kvm.c | 60 ++++++++++++++++++++++++++++++---------------------- 5 files changed, 51 insertions(+), 50 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index d1542e3..06708a5 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -65,6 +65,7 @@ struct KVMState int broken_set_mem_region; int migration_log; int vcpu_events; + int robust_singlestep; #ifdef KVM_CAP_SET_GUEST_DEBUG struct kvm_sw_breakpoint_head kvm_sw_breakpoints; #endif @@ -673,6 +674,12 @@ int kvm_init(int smp_cpus) s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS); #endif + s->robust_singlestep = 0; +#ifdef KVM_CAP_X86_ROBUST_SINGLESTEP + s->robust_singlestep = + kvm_check_extension(s, KVM_CAP_X86_ROBUST_SINGLESTEP); +#endif + ret = kvm_arch_init(s, smp_cpus); if (ret < 0) goto err; @@ -933,6 +940,11 @@ int kvm_has_vcpu_events(void) return kvm_state->vcpu_events; } +int kvm_has_robust_singlestep(void) +{ + return kvm_state->robust_singlestep; +} + void kvm_setup_guest_memory(void *start, size_t size) { if (!kvm_has_sync_mmu()) { diff --git a/kvm.h b/kvm.h index 1b498d7..888dfcb 100644 --- a/kvm.h +++ b/kvm.h @@ -43,6 +43,7 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size); int kvm_has_sync_mmu(void); int kvm_has_vcpu_events(void); +int kvm_has_robust_singlestep(void); int kvm_put_vcpu_events(CPUState *env); int kvm_get_vcpu_events(CPUState *env); diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index 5af9ce1..5db95f8 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -922,31 +922,8 @@ void kvm_arch_load_regs(CPUState *env) if (rc == -1) perror("kvm_set_msrs FAILED"); - /* - * 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; - - rc = kvm_update_guest_debug(env, reinject_trap); - if (rc < 0) { - perror("kvm_update_guest_debug FAILED"); - } - } + /* must be last */ + kvm_guest_debug_workarounds(env); } void kvm_load_tsc(CPUState *env) diff --git a/qemu-kvm.h b/qemu-kvm.h index ecb52c1..ed00665 100644 --- a/qemu-kvm.h +++ b/qemu-kvm.h @@ -1012,6 +1012,7 @@ struct KVMState { int broken_set_mem_region; int migration_log; int vcpu_events; + int robust_singlestep; #ifdef KVM_CAP_SET_GUEST_DEBUG QTAILQ_HEAD(, kvm_sw_breakpoint) kvm_sw_breakpoints; #endif diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 4e1358c..dd636f1 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -861,6 +861,37 @@ int kvm_get_vcpu_events(CPUState *env) return 0; } +static int kvm_guest_debug_workarounds(CPUState *env) +{ + int ret = 0; +#ifdef KVM_CAP_SET_GUEST_DEBUG + unsigned long reinject_trap = 0; + + if (!kvm_has_vcpu_events()) { + 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; + } + + /* + * Kernels before KVM_CAP_X86_ROBUST_SINGLESTEP 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 (reinject_trap || + (!kvm_has_robust_singlestep() && env->singlestep_enabled)) { + ret = kvm_update_guest_debug(env, reinject_trap); + } +#endif /* KVM_CAP_SET_GUEST_DEBUG */ + return ret; +} + #ifdef KVM_UPSTREAM int kvm_arch_put_registers(CPUState *env) { @@ -890,31 +921,10 @@ 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; - } - } + /* must be last */ + ret = kvm_guest_debug_workarounds(env); + if (ret < 0) + return ret; return 0; }