From: Jan Kiszka <jan.kiszka@web.de>
To: Paolo Bonzini <pbonzini@redhat.com>,
Pavel Dovgaluk <Pavel.Dovgaluk@ispras.ru>,
qemu-devel@nongnu.org
Cc: batuzovk@ispras.ru, zealot351@gmail.com,
maria.klimushenkova@ispras.ru, mark.burton@greensocs.com,
fred.konrad@greensocs.com
Subject: Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
Date: Sun, 24 May 2015 16:43:12 +0200 [thread overview]
Message-ID: <5561E380.5010003@web.de> (raw)
In-Reply-To: <54B38C03.9000608@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 10322 bytes --]
On 2015-01-12 09:55, Paolo Bonzini wrote:
> 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) {
This condition is always true for both 0 and EXCP_DEBUG.
> + 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)
>
>
Lost track of this: This doesn't build (EXCP_DEBUG not available to
qom/cpu.c, wrong breakpoint_handler prototype) and then, when the build
issues are fixed, it doesn't work.
Playing a bit with the code, I found out that this cures the issue:
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 305ce50..57b607d 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8006,6 +8006,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
if (bp->pc == pc_ptr &&
!((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
gen_debug(dc, pc_ptr - dc->cs_base);
+ pc_ptr = disas_insn(env, dc, pc_ptr);
goto done_generating;
}
}
pc_ptr is used at the end of the function to calculate the tb size. I
suspect that the difference prevents that the breakpoint event is
associated with the stored location. Can someone explain this more
properly? Then I would happily pass patch credits.
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
next prev parent reply other threads:[~2015-05-24 14:43 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-22 11:38 [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode Pavel Dovgalyuk
2014-10-22 12:53 ` Frederic Konrad
2014-10-23 5:57 ` Pavel Dovgaluk
2014-10-23 7:39 ` Frederic Konrad
2014-10-23 7:52 ` Pavel Dovgaluk
2014-10-23 8:47 ` Frederic Konrad
2014-10-23 9:58 ` Pavel Dovgaluk
2014-10-31 15:41 ` Paolo Bonzini
2015-01-12 8:03 ` Jan Kiszka
2015-01-12 8:26 ` Pavel Dovgaluk
2015-01-12 8:30 ` Jan Kiszka
2015-01-12 8:55 ` Paolo Bonzini
2015-05-24 14:43 ` Jan Kiszka [this message]
2015-05-26 14:56 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5561E380.5010003@web.de \
--to=jan.kiszka@web.de \
--cc=Pavel.Dovgaluk@ispras.ru \
--cc=batuzovk@ispras.ru \
--cc=fred.konrad@greensocs.com \
--cc=maria.klimushenkova@ispras.ru \
--cc=mark.burton@greensocs.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=zealot351@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.