From patchwork Mon Jan 12 08:55:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 427598 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id CF7E8140187 for ; Mon, 12 Jan 2015 19:56:04 +1100 (AEDT) Received: from localhost ([::1]:60930 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YAan4-0000nm-Ts for incoming@patchwork.ozlabs.org; Mon, 12 Jan 2015 03:56:02 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39531) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YAamj-0000XA-RP for qemu-devel@nongnu.org; Mon, 12 Jan 2015 03:55:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YAame-00007S-R6 for qemu-devel@nongnu.org; Mon, 12 Jan 2015 03:55:41 -0500 Received: from mail-wg0-x22b.google.com ([2a00:1450:400c:c00::22b]:40462) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YAame-000073-GG for qemu-devel@nongnu.org; Mon, 12 Jan 2015 03:55:36 -0500 Received: by mail-wg0-f43.google.com with SMTP id k14so17956932wgh.2 for ; Mon, 12 Jan 2015 00:55:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-type:content-transfer-encoding; bh=lP9ZCnMcTZGlMzS88cXEJm+w76TVujVXg3EoKju6GiI=; b=HLccnW1oXaH8vqFKdOTNjj3ktVgQB9XviWtmOp3hBN3Atmgz8+EEtE73ImzHXiRPuK jwuf3iG9nvD1vMX+AN7W1c0xztF3c8SuUUbRioWwjaFOQETTAfCDLm+cP03kr/b4Tidc G047/iANfszj3/meulVx5IKNH+xoIZjmKGFegx96Pi1Ozh3l3vwE/xFpF8fOQXafOBD7 nCRIdWjU2uFwG3MvQlmLTZAV2GrwNK2RfWmxPFgyF4d4gmpSfHepbSYvwRcQggiKObpS RCJJwlhtMphltmKRcuHDREZnIW0gW1+uuwjgawGzegzdBiW182dFsZhYAxUyuOPlkEvd yvfg== X-Received: by 10.180.109.46 with SMTP id hp14mr28469262wib.54.1421052934974; Mon, 12 Jan 2015 00:55:34 -0800 (PST) Received: from [192.168.10.150] (net-37-117-147-67.cust.vodafonedsl.it. [37.117.147.67]) by mx.google.com with ESMTPSA id e4sm20665114wjw.48.2015.01.12.00.55.32 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 12 Jan 2015 00:55:33 -0800 (PST) Message-ID: <54B38C03.9000608@redhat.com> Date: Mon, 12 Jan 2015 09:55:31 +0100 From: Paolo Bonzini User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: Jan Kiszka , Pavel Dovgaluk , qemu-devel@nongnu.org References: <20141022113831.9548.36452.stgit@PASHA-ISP> <54B37FCA.4020805@siemens.com> <000801d02e41$75c1a000$6144e000$@Dovgaluk@ispras.ru> <54B38612.6020903@siemens.com> In-Reply-To: <54B38612.6020903@siemens.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:400c:c00::22b Cc: fred.konrad@greensocs.com, zealot351@gmail.com, maria.klimushenkova@ispras.ru, mark.burton@greensocs.com, batuzovk@ispras.ru Subject: Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org On 12/01/2015 09:30, Jan Kiszka wrote: > I think this would only cure a symptom, but it doesn't explain why we > now hit cpu_handle_guest_debug which we do not before the patch: That means we now exit with EXCP_DEBUG and we didn't before? Something like this would be a more complete fix (it works if you have both gdb and CPU breakpoints), but I'm not sure if it's also a band-aid for the symptoms. diff --git a/cpu-exec.c b/cpu-exec.c index a4f0eff..56139ac 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -302,7 +302,7 @@ static inline TranslationBlock *tb_find_fast(CPUArchState *env) return tb; } -static void cpu_handle_debug_exception(CPUArchState *env) +static int cpu_handle_debug_exception(CPUArchState *env) { CPUState *cpu = ENV_GET_CPU(env); CPUClass *cc = CPU_GET_CLASS(cpu); @@ -314,7 +314,7 @@ static void cpu_handle_debug_exception(CPUArchState *env) } } - cc->debug_excp_handler(cpu); + return cc->debug_excp_handler(cpu); } /* main execution loop */ @@ -375,12 +375,15 @@ int cpu_exec(CPUArchState *env) if (cpu->exception_index >= 0) { if (cpu->exception_index >= EXCP_INTERRUPT) { /* exit request from the cpu execution loop */ - ret = cpu->exception_index; - if (ret == EXCP_DEBUG) { - cpu_handle_debug_exception(env); + if (cpu->exception_index == EXCP_DEBUG) { + ret = cpu_handle_debug_exception(env); + } else { + ret = cpu->exception_index; + } + if (ret >= 0) { + cpu->exception_index = -1; + break; } - cpu->exception_index = -1; - break; } else { #if defined(CONFIG_USER_ONLY) /* if user mode only, we simulate a fake exception diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 2098f1c..c1d6c20 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -95,7 +95,8 @@ struct TranslationBlock; * @get_phys_page_debug: Callback for obtaining a physical address. * @gdb_read_register: Callback for letting GDB read a register. * @gdb_write_register: Callback for letting GDB write a register. - * @debug_excp_handler: Callback for handling debug exceptions. + * @debug_excp_handler: Callback for handling debug exceptions. Should + * return either #EXCP_DEBUG or zero. * @vmsd: State description for migration. * @gdb_num_core_regs: Number of core registers accessible to GDB. * @gdb_core_xml_file: File name for core registers GDB XML description. @@ -140,7 +141,7 @@ typedef struct CPUClass { hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr); int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg); int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg); - void (*debug_excp_handler)(CPUState *cpu); + int (*debug_excp_handler)(CPUState *cpu); int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu, int cpuid, void *opaque); diff --git a/qom/cpu.c b/qom/cpu.c index 9c68fa4..e86fec5 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -193,6 +193,11 @@ static bool cpu_common_virtio_is_big_endian(CPUState *cpu) return target_words_bigendian(); } +static int cpu_common_debug_excp_handler(CPUState *cpu) +{ + return EXCP_DEBUG; +} + static void cpu_common_noop(CPUState *cpu) { } @@ -340,7 +345,7 @@ static void cpu_class_init(ObjectClass *klass, void *data) k->gdb_read_register = cpu_common_gdb_read_register; k->gdb_write_register = cpu_common_gdb_write_register; k->virtio_is_big_endian = cpu_common_virtio_is_big_endian; - k->debug_excp_handler = cpu_common_noop; + k->debug_excp_handler = cpu_common_debug_excp_handler; k->cpu_exec_enter = cpu_common_noop; k->cpu_exec_exit = cpu_common_noop; k->cpu_exec_interrupt = cpu_common_exec_interrupt; diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 2bed914..40b7f79 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -732,7 +732,7 @@ static bool check_breakpoints(ARMCPU *cpu) return false; } -void arm_debug_excp_handler(CPUState *cs) +int arm_debug_excp_handler(CPUState *cs) { /* Called by core code when a watchpoint or breakpoint fires; * need to check which one and raise the appropriate exception. @@ -756,9 +756,9 @@ void arm_debug_excp_handler(CPUState *cs) } env->exception.vaddress = wp_hit->hitaddr; raise_exception(env, EXCP_DATA_ABORT); - } else { - cpu_resume_from_signal(cs, NULL); + return 0; } + cpu_resume_from_signal(cs, NULL); } } else { if (check_breakpoints(cpu)) { @@ -771,8 +771,10 @@ void arm_debug_excp_handler(CPUState *cs) } /* FAR is UNKNOWN, so doesn't need setting */ raise_exception(env, EXCP_PREFETCH_ABORT); + return 0; } } + return EXCP_DEBUG; } /* ??? Flag setting arithmetic is awkward because we need to do comparisons. diff --git a/target-i386/helper.c b/target-i386/helper.c index 4f1ddf7..a313424 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1004,17 +1004,19 @@ bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update) return hit_enabled; } -void breakpoint_handler(CPUState *cs) +int breakpoint_handler(CPUState *cs) { X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; CPUBreakpoint *bp; + int ret = EXCP_DEBUG; if (cs->watchpoint_hit) { if (cs->watchpoint_hit->flags & BP_CPU) { cs->watchpoint_hit = NULL; if (check_hw_breakpoints(env, false)) { raise_exception(env, EXCP01_DB); + ret = 0; } else { cpu_resume_from_signal(cs, NULL); } @@ -1025,11 +1027,13 @@ void breakpoint_handler(CPUState *cs) if (bp->flags & BP_CPU) { check_hw_breakpoints(env, true); raise_exception(env, EXCP01_DB); + ret = 0; } break; } } } + return ret; } typedef struct MCEInjectionParams { diff --git a/target-lm32/helper.c b/target-lm32/helper.c index 7a41f29..088d3fa 100644 --- a/target-lm32/helper.c +++ b/target-lm32/helper.c @@ -125,17 +125,19 @@ static bool check_watchpoints(CPULM32State *env) return false; } -void lm32_debug_excp_handler(CPUState *cs) +int lm32_debug_excp_handler(CPUState *cs) { LM32CPU *cpu = LM32_CPU(cs); CPULM32State *env = &cpu->env; CPUBreakpoint *bp; + int ret = EXCP_DEBUG; if (cs->watchpoint_hit) { if (cs->watchpoint_hit->flags & BP_CPU) { cs->watchpoint_hit = NULL; if (check_watchpoints(env)) { raise_exception(env, EXCP_WATCHPOINT); + ret = 0; } else { cpu_resume_from_signal(cs, NULL); } @@ -145,11 +147,13 @@ void lm32_debug_excp_handler(CPUState *cs) if (bp->pc == env->pc) { if (bp->flags & BP_CPU) { raise_exception(env, EXCP_BREAKPOINT); + ret = 0; } break; } } } + return ret; } void lm32_cpu_do_interrupt(CPUState *cs) diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index d84d259..52f50a2 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -79,7 +79,7 @@ static uint32_t check_hw_breakpoints(CPUXtensaState *env) return 0; } -void xtensa_breakpoint_handler(CPUState *cs) +int xtensa_breakpoint_handler(CPUState *cs) { XtensaCPU *cpu = XTENSA_CPU(cs); CPUXtensaState *env = &cpu->env; @@ -92,10 +92,12 @@ void xtensa_breakpoint_handler(CPUState *cs) cause = check_hw_breakpoints(env); if (cause) { debug_exception_env(env, cause); + return 0; } cpu_resume_from_signal(cs, NULL); } } + return EXCP_DEBUG; } XtensaCPU *cpu_xtensa_init(const char *cpu_model)