From patchwork Wed Feb 3 08:53:38 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 44371 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 154A0B7D4A for ; Wed, 3 Feb 2010 21:05:54 +1100 (EST) Received: from localhost ([127.0.0.1]:49937 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ncc5h-0002A9-D7 for incoming@patchwork.ozlabs.org; Wed, 03 Feb 2010 05:04:09 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Ncbkf-0000bQ-Gj for qemu-devel@nongnu.org; Wed, 03 Feb 2010 04:42:25 -0500 Received: from [199.232.76.173] (port=51810 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ncbke-0000b4-MG for qemu-devel@nongnu.org; Wed, 03 Feb 2010 04:42:24 -0500 Received: from Debian-exim by monty-python.gnu.org with spam-scanned (Exim 4.60) (envelope-from ) id 1Ncbkb-0003Yv-L4 for qemu-devel@nongnu.org; Wed, 03 Feb 2010 04:42:24 -0500 Received: from thoth.sbs.de ([192.35.17.2]:15018) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NcbkY-0003Yj-N4 for qemu-devel@nongnu.org; Wed, 03 Feb 2010 04:42:21 -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 o138rtoc025967; Wed, 3 Feb 2010 09:53:55 +0100 Received: from localhost.localdomain ([139.25.173.28]) by mail3.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id o138rkCE012112; Wed, 3 Feb 2010 09:53:54 +0100 From: Jan Kiszka To: Avi Kivity , Marcelo Tosatti Date: Wed, 3 Feb 2010 09:53:38 +0100 Message-Id: <169a38d67bc88e10426818e79c889cee388a555b.1265187223.git.jan.kiszka@siemens.com> 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: Anthony Liguori , Glauber Costa , Alexander Graf , kvm@vger.kernel.org, qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH v2 13/21] qemu-kvm: Use upstream guest debug code 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 Code was absolute identical except for previous cleanup in upstream. Signed-off-by: Jan Kiszka --- kvm-all.c | 7 +- kvm.h | 4 - qemu-kvm-x86.c | 178 ++-------------------------------------------------- qemu-kvm.c | 44 ------------- qemu-kvm.h | 37 ----------- target-i386/kvm.c | 2 +- 6 files changed, 11 insertions(+), 261 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index 9c921cc..f3cfa2c 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -919,7 +919,9 @@ static void on_vcpu(CPUState *env, void (*func)(void *data), void *data) func(data); #endif } -#endif /* KVM_UPSTREAM */ +#else /* !KVM_UPSTREAM */ +static void on_vcpu(CPUState *env, void (*func)(void *data), void *data); +#endif /* !KVM_UPSTREAM */ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env, target_ulong pc) @@ -938,8 +940,6 @@ int kvm_sw_breakpoints_active(CPUState *env) return !QTAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints); } -#ifdef KVM_UPSTREAM - struct kvm_set_guest_debug_data { struct kvm_guest_debug dbg; CPUState *env; @@ -969,7 +969,6 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap) on_vcpu(env, kvm_invoke_set_guest_debug, &data); return data.err; } -#endif int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr, target_ulong len, int type) diff --git a/kvm.h b/kvm.h index 253b45d..740fd1a 100644 --- a/kvm.h +++ b/kvm.h @@ -61,14 +61,12 @@ void kvm_setup_guest_memory(void *start, size_t size); int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); -#ifdef KVM_UPSTREAM int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr, target_ulong len, int type); int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr, target_ulong len, int type); void kvm_remove_all_breakpoints(CPUState *current_env); int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap); -#endif /* KVM_UPSTREAM */ int kvm_pit_in_kernel(void); int kvm_irqchip_in_kernel(void); @@ -101,7 +99,6 @@ int kvm_arch_init(KVMState *s, int smp_cpus); int kvm_arch_init_vcpu(CPUState *env); void kvm_arch_reset_vcpu(CPUState *env); -#ifdef KVM_UPSTREAM struct kvm_guest_debug; struct kvm_debug_exit_arch; @@ -133,7 +130,6 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr, void kvm_arch_remove_all_hw_breakpoints(void); void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg); -#endif int kvm_check_extension(KVMState *s, unsigned int extension); diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index 2b36c22..36d805a 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -837,6 +837,13 @@ void kvm_arch_load_regs(CPUState *env) kvm_set_regs(env, ®s); + /* + * Kernels before 2.6.33 overwrote flags.TF injected via SET_GUEST_DEBUG + * while updating GP regs. Work around this by updating the debug state + * once again. + */ + kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &env->kvm_guest_debug); + memset(&fpu, 0, sizeof fpu); fpu.fsw = env->fpus & ~(7 << 11); fpu.fsw |= (env->fpstt & 7) << 11; @@ -1376,177 +1383,6 @@ void kvm_arch_cpu_reset(CPUState *env) } } -int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp) -{ - uint8_t int3 = 0xcc; - - if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) || - cpu_memory_rw_debug(env, bp->pc, &int3, 1, 1)) - return -EINVAL; - return 0; -} - -int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp) -{ - uint8_t int3; - - if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc || - cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) - return -EINVAL; - return 0; -} - -#ifdef KVM_CAP_SET_GUEST_DEBUG -static struct { - target_ulong addr; - int len; - int type; -} hw_breakpoint[4]; - -static int nb_hw_breakpoint; - -static int find_hw_breakpoint(target_ulong addr, int len, int type) -{ - int n; - - for (n = 0; n < nb_hw_breakpoint; n++) - if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type && - (hw_breakpoint[n].len == len || len == -1)) - return n; - return -1; -} - -int kvm_arch_insert_hw_breakpoint(target_ulong addr, - target_ulong len, int type) -{ - switch (type) { - case GDB_BREAKPOINT_HW: - len = 1; - break; - case GDB_WATCHPOINT_WRITE: - case GDB_WATCHPOINT_ACCESS: - switch (len) { - case 1: - break; - case 2: - case 4: - case 8: - if (addr & (len - 1)) - return -EINVAL; - break; - default: - return -EINVAL; - } - break; - default: - return -ENOSYS; - } - - if (nb_hw_breakpoint == 4) - return -ENOBUFS; - - if (find_hw_breakpoint(addr, len, type) >= 0) - return -EEXIST; - - hw_breakpoint[nb_hw_breakpoint].addr = addr; - hw_breakpoint[nb_hw_breakpoint].len = len; - hw_breakpoint[nb_hw_breakpoint].type = type; - nb_hw_breakpoint++; - - return 0; -} - -int kvm_arch_remove_hw_breakpoint(target_ulong addr, - target_ulong len, int type) -{ - int n; - - n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type); - if (n < 0) - return -ENOENT; - - nb_hw_breakpoint--; - hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint]; - - return 0; -} - -void kvm_arch_remove_all_hw_breakpoints(void) -{ - nb_hw_breakpoint = 0; -} - -static CPUWatchpoint hw_watchpoint; - -int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info) -{ - int handle = 0; - int n; - - if (arch_info->exception == 1) { - if (arch_info->dr6 & (1 << 14)) { - if (cpu_single_env->singlestep_enabled) - handle = 1; - } else { - for (n = 0; n < 4; n++) - if (arch_info->dr6 & (1 << n)) - switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) { - case 0x0: - handle = 1; - break; - case 0x1: - handle = 1; - cpu_single_env->watchpoint_hit = &hw_watchpoint; - hw_watchpoint.vaddr = hw_breakpoint[n].addr; - hw_watchpoint.flags = BP_MEM_WRITE; - break; - case 0x3: - handle = 1; - cpu_single_env->watchpoint_hit = &hw_watchpoint; - hw_watchpoint.vaddr = hw_breakpoint[n].addr; - hw_watchpoint.flags = BP_MEM_ACCESS; - break; - } - } - } 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); - - return handle; -} - -void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg) -{ - const uint8_t type_code[] = { - [GDB_BREAKPOINT_HW] = 0x0, - [GDB_WATCHPOINT_WRITE] = 0x1, - [GDB_WATCHPOINT_ACCESS] = 0x3 - }; - const uint8_t len_code[] = { - [1] = 0x0, [2] = 0x1, [4] = 0x3, [8] = 0x2 - }; - int n; - - if (kvm_sw_breakpoints_active(env)) - dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; - - if (nb_hw_breakpoint > 0) { - dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; - dbg->arch.debugreg[7] = 0x0600; - for (n = 0; n < nb_hw_breakpoint; n++) { - dbg->arch.debugreg[n] = hw_breakpoint[n].addr; - dbg->arch.debugreg[7] |= (2 << (n * 2)) | - (type_code[hw_breakpoint[n].type] << (16 + n*4)) | - (len_code[hw_breakpoint[n].len] << (18 + n*4)); - } - } -} -#endif - #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT void kvm_arch_do_ioperm(void *_data) { diff --git a/qemu-kvm.c b/qemu-kvm.c index 6a72b89..d90c8e3 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -1016,13 +1016,6 @@ int kvm_inject_irq(CPUState *env, unsigned irq) return kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr); } -#ifdef KVM_CAP_SET_GUEST_DEBUG -int kvm_set_guest_debug(CPUState *env, struct kvm_guest_debug *dbg) -{ - return kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, dbg); -} -#endif - int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset) { struct kvm_signal_mask *sigmask; @@ -2318,43 +2311,6 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size, return; } -#ifdef KVM_CAP_SET_GUEST_DEBUG - -struct kvm_set_guest_debug_data { - struct kvm_guest_debug dbg; - int err; -}; - -static void kvm_invoke_set_guest_debug(void *data) -{ - struct kvm_set_guest_debug_data *dbg_data = data; - - if (cpu_single_env->kvm_vcpu_dirty) { - kvm_arch_save_regs(cpu_single_env); - cpu_single_env->kvm_vcpu_dirty = 0; - } - dbg_data->err = - kvm_set_guest_debug(cpu_single_env, - &dbg_data->dbg); -} - -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; - - kvm_arch_update_guest_debug(env, &data.dbg); - data.dbg.control |= reinject_trap; - - on_vcpu(env, kvm_invoke_set_guest_debug, &data); - return data.err; -} - -#endif - /* * dirty pages logging */ diff --git a/qemu-kvm.h b/qemu-kvm.h index a84f7c8..3a7a9ba 100644 --- a/qemu-kvm.h +++ b/qemu-kvm.h @@ -323,10 +323,6 @@ static inline int kvm_reset_mpstate(CPUState *env) */ int kvm_inject_irq(CPUState *env, unsigned irq); -#ifdef KVM_CAP_SET_GUEST_DEBUG -int kvm_set_guest_debug(CPUState *env, struct kvm_guest_debug *dbg); -#endif - #if defined(__i386__) || defined(__x86_64__) /*! * \brief Setup a vcpu's cpuid instruction emulation @@ -880,12 +876,6 @@ int kvm_init_ap(void); int kvm_vcpu_inited(CPUState *env); void kvm_load_mpstate(CPUState *env); void kvm_save_mpstate(CPUState *env); -int kvm_insert_breakpoint(CPUState * current_env, target_ulong addr, - target_ulong len, int type); -int kvm_remove_breakpoint(CPUState * current_env, target_ulong addr, - target_ulong len, int type); -void kvm_remove_all_breakpoints(CPUState * current_env); -int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap); void kvm_apic_init(CPUState *env); /* called from vcpu initialization */ void qemu_kvm_load_lapic(CPUState *env); @@ -928,33 +918,6 @@ void kvm_arch_push_nmi(void *opaque); void kvm_arch_cpu_reset(CPUState *env); int kvm_set_boot_cpu_id(uint32_t id); -struct kvm_guest_debug; -struct kvm_debug_exit_arch; - -struct kvm_sw_breakpoint { - target_ulong pc; - target_ulong saved_insn; - int use_count; - QTAILQ_ENTRY(kvm_sw_breakpoint) entry; -}; - -QTAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint); - -int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info); -int kvm_sw_breakpoints_active(CPUState *env); -struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env, - target_ulong pc); -int kvm_arch_insert_sw_breakpoint(CPUState * current_env, - struct kvm_sw_breakpoint *bp); -int kvm_arch_remove_sw_breakpoint(CPUState * current_env, - struct kvm_sw_breakpoint *bp); -int kvm_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, - int type); -int kvm_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len, - int type); -void kvm_arch_remove_all_hw_breakpoints(void); -void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg); - void qemu_kvm_aio_wait_start(void); void qemu_kvm_aio_wait(void); void qemu_kvm_aio_wait_end(void); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 5ac12a8..e1ae15d 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1003,6 +1003,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run) return ret; } +#endif #ifdef KVM_CAP_SET_GUEST_DEBUG int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp) @@ -1176,6 +1177,5 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg) memcpy(&env->kvm_guest_debug, dbg, sizeof(env->kvm_guest_debug)); } #endif /* KVM_CAP_SET_GUEST_DEBUG */ -#endif #include "qemu-kvm-x86.c"