qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
@ 2014-10-22 11:38 Pavel Dovgalyuk
  2014-10-22 12:53 ` Frederic Konrad
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Pavel Dovgalyuk @ 2014-10-22 11:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: mark.burton, batuzovk, maria.klimushenkova, pavel.dovgaluk,
	pbonzini, zealot351, fred.konrad

This patch fixes instructions counting when execution is stopped on
breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
and icount is incremented by invalid value (which equals to number of
executed instructions + 1).

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 target-i386/translate.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 1284173..193cf9f 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8000,7 +8000,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);
-                    break;
+                    goto done_generating;
                 }
             }
         }
@@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
             break;
         }
     }
+done_generating:
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
     gen_tb_end(tb, num_insns);

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  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-31 15:41 ` Paolo Bonzini
  2015-01-12  8:03 ` Jan Kiszka
  2 siblings, 1 reply; 14+ messages in thread
From: Frederic Konrad @ 2014-10-22 12:53 UTC (permalink / raw)
  To: Pavel Dovgalyuk, qemu-devel
  Cc: pbonzini, zealot351, maria.klimushenkova, mark.burton, batuzovk

On 22/10/2014 13:38, Pavel Dovgalyuk wrote:

Hi Pavel,
> This patch fixes instructions counting when execution is stopped on
> breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
> and icount is incremented by invalid value (which equals to number of
> executed instructions + 1).
>
> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> ---
>   target-i386/translate.c |    3 ++-
>   1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/target-i386/translate.c b/target-i386/translate.c
> index 1284173..193cf9f 100644
> --- a/target-i386/translate.c
> +++ b/target-i386/translate.c
> @@ -8000,7 +8000,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);
> -                    break;
> +                    goto done_generating;
This makes sense to me.
But I don't see why you don't just "break" like the other instruction in 
this loop?

>                   }
>               }
>           }
> @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
>               break;
>           }
>       }
> +done_generating:
>       if (tb->cflags & CF_LAST_IO)
>           gen_io_end();
Is there any reason why you don't jump over this two lines in case of a
breakpoint?

>       gen_tb_end(tb, num_insns);
>
>

I'll give it a try later and I'll let you know.

Thanks,
Fred

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2014-10-22 12:53 ` Frederic Konrad
@ 2014-10-23  5:57   ` Pavel Dovgaluk
  2014-10-23  7:39     ` Frederic Konrad
  0 siblings, 1 reply; 14+ messages in thread
From: Pavel Dovgaluk @ 2014-10-23  5:57 UTC (permalink / raw)
  To: 'Frederic Konrad', qemu-devel
  Cc: pbonzini, zealot351, maria.klimushenkova, mark.burton, batuzovk

> From: Frederic Konrad [mailto:fred.konrad@greensocs.com]
> On 22/10/2014 13:38, Pavel Dovgalyuk wrote:
> 
> Hi Pavel,
> > This patch fixes instructions counting when execution is stopped on
> > breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
> > and icount is incremented by invalid value (which equals to number of
> > executed instructions + 1).
> >
> > Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> > ---
> >   target-i386/translate.c |    3 ++-
> >   1 files changed, 2 insertions(+), 1 deletions(-)
> >
> > diff --git a/target-i386/translate.c b/target-i386/translate.c
> > index 1284173..193cf9f 100644
> > --- a/target-i386/translate.c
> > +++ b/target-i386/translate.c
> > @@ -8000,7 +8000,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);
> > -                    break;
> > +                    goto done_generating;
> This makes sense to me.
> But I don't see why you don't just "break" like the other instruction in
> this loop?

Single break will just exit the breakpoints iteration loop. I'll need an additional flag
to break the translation loop. ARM does the same thing, anyway :)

> >                   }
> >               }
> >           }
> > @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
> >               break;
> >           }
> >       }
> > +done_generating:
> >       if (tb->cflags & CF_LAST_IO)
> >           gen_io_end();
> Is there any reason why you don't jump over this two lines in case of a
> breakpoint?

Shouldn't we switch off can_do_io flag if it was switched on?

> 
> >       gen_tb_end(tb, num_insns);
> >
> >
> 
> I'll give it a try later and I'll let you know.

Thanks.

Pavel Dovgalyuk

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2014-10-23  5:57   ` Pavel Dovgaluk
@ 2014-10-23  7:39     ` Frederic Konrad
  2014-10-23  7:52       ` Pavel Dovgaluk
  0 siblings, 1 reply; 14+ messages in thread
From: Frederic Konrad @ 2014-10-23  7:39 UTC (permalink / raw)
  To: Pavel Dovgaluk, qemu-devel
  Cc: pbonzini, zealot351, maria.klimushenkova, mark.burton, batuzovk

On 23/10/2014 07:57, Pavel Dovgaluk wrote:
>> From: Frederic Konrad [mailto:fred.konrad@greensocs.com]
>> On 22/10/2014 13:38, Pavel Dovgalyuk wrote:
>>
>> Hi Pavel,
>>> This patch fixes instructions counting when execution is stopped on
>>> breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
>>> and icount is incremented by invalid value (which equals to number of
>>> executed instructions + 1).
>>>
>>> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
>>> ---
>>>    target-i386/translate.c |    3 ++-
>>>    1 files changed, 2 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/target-i386/translate.c b/target-i386/translate.c
>>> index 1284173..193cf9f 100644
>>> --- a/target-i386/translate.c
>>> +++ b/target-i386/translate.c
>>> @@ -8000,7 +8000,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);
>>> -                    break;
>>> +                    goto done_generating;
>> This makes sense to me.
>> But I don't see why you don't just "break" like the other instruction in
>> this loop?
> Single break will just exit the breakpoints iteration loop. I'll need an additional flag
> to break the translation loop. ARM does the same thing, anyway :)

Yes that's what I mentioned.
>
>>>                    }
>>>                }
>>>            }
>>> @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
>>>                break;
>>>            }
>>>        }
>>> +done_generating:
>>>        if (tb->cflags & CF_LAST_IO)
>>>            gen_io_end();
>> Is there any reason why you don't jump over this two lines in case of a
>> breakpoint?
> Shouldn't we switch off can_do_io flag if it was switched on?

Yes but can we switch on can_do_io if we have a breakpoint?

The code is not shown in this patch but there is:

         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();

I think you can't reach this code if you exit the translation loop?

Fred
>
>>>        gen_tb_end(tb, num_insns);
>>>
>>>
>> I'll give it a try later and I'll let you know.
> Thanks.
>
> Pavel Dovgalyuk
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2014-10-23  7:39     ` Frederic Konrad
@ 2014-10-23  7:52       ` Pavel Dovgaluk
  2014-10-23  8:47         ` Frederic Konrad
  0 siblings, 1 reply; 14+ messages in thread
From: Pavel Dovgaluk @ 2014-10-23  7:52 UTC (permalink / raw)
  To: 'Frederic Konrad', qemu-devel
  Cc: pbonzini, zealot351, maria.klimushenkova, mark.burton, batuzovk

> From: Frederic Konrad [mailto:fred.konrad@greensocs.com]
> On 23/10/2014 07:57, Pavel Dovgaluk wrote:
> >> From: Frederic Konrad [mailto:fred.konrad@greensocs.com]
> >> On 22/10/2014 13:38, Pavel Dovgalyuk wrote:
> >>
> >> Hi Pavel,
> >>> This patch fixes instructions counting when execution is stopped on
> >>> breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
> >>> and icount is incremented by invalid value (which equals to number of
> >>> executed instructions + 1).
> >>>
> >>> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> >>> ---
> >>>    target-i386/translate.c |    3 ++-
> >>>    1 files changed, 2 insertions(+), 1 deletions(-)
> >>>
> >>> diff --git a/target-i386/translate.c b/target-i386/translate.c
> >>> index 1284173..193cf9f 100644
> >>> --- a/target-i386/translate.c
> >>> +++ b/target-i386/translate.c
> >>> @@ -8000,7 +8000,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);
> >>> -                    break;
> >>> +                    goto done_generating;
> >> This makes sense to me.
> >> But I don't see why you don't just "break" like the other instruction in
> >> this loop?
> > Single break will just exit the breakpoints iteration loop. I'll need an additional flag
> > to break the translation loop. ARM does the same thing, anyway :)
> 
> Yes that's what I mentioned.
> >
> >>>                    }
> >>>                }
> >>>            }
> >>> @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
> >>>                break;
> >>>            }
> >>>        }
> >>> +done_generating:
> >>>        if (tb->cflags & CF_LAST_IO)
> >>>            gen_io_end();
> >> Is there any reason why you don't jump over this two lines in case of a
> >> breakpoint?
> > Shouldn't we switch off can_do_io flag if it was switched on?
> 
> Yes but can we switch on can_do_io if we have a breakpoint?
> 
> The code is not shown in this patch but there is:
> 
>          if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
>              gen_io_start();
> 
> I think you can't reach this code if you exit the translation loop?

This is not the only gen_io_start call. It is called from some of the instructions'
translation functions, that could precede the breakpoint.

Pavel Dovgalyuk

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2014-10-23  7:52       ` Pavel Dovgaluk
@ 2014-10-23  8:47         ` Frederic Konrad
  2014-10-23  9:58           ` Pavel Dovgaluk
  0 siblings, 1 reply; 14+ messages in thread
From: Frederic Konrad @ 2014-10-23  8:47 UTC (permalink / raw)
  To: Pavel Dovgaluk, qemu-devel
  Cc: pbonzini, zealot351, maria.klimushenkova, mark.burton, batuzovk

On 23/10/2014 09:52, Pavel Dovgaluk wrote:
>> From: Frederic Konrad [mailto:fred.konrad@greensocs.com]
>> On 23/10/2014 07:57, Pavel Dovgaluk wrote:
>>>> From: Frederic Konrad [mailto:fred.konrad@greensocs.com]
>>>> On 22/10/2014 13:38, Pavel Dovgalyuk wrote:
>>>>
>>>> Hi Pavel,
>>>>> This patch fixes instructions counting when execution is stopped on
>>>>> breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
>>>>> and icount is incremented by invalid value (which equals to number of
>>>>> executed instructions + 1).
>>>>>
>>>>> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
>>>>> ---
>>>>>     target-i386/translate.c |    3 ++-
>>>>>     1 files changed, 2 insertions(+), 1 deletions(-)
>>>>>
>>>>> diff --git a/target-i386/translate.c b/target-i386/translate.c
>>>>> index 1284173..193cf9f 100644
>>>>> --- a/target-i386/translate.c
>>>>> +++ b/target-i386/translate.c
>>>>> @@ -8000,7 +8000,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);
>>>>> -                    break;
>>>>> +                    goto done_generating;
>>>> This makes sense to me.
>>>> But I don't see why you don't just "break" like the other instruction in
>>>> this loop?
>>> Single break will just exit the breakpoints iteration loop. I'll need an additional flag
>>> to break the translation loop. ARM does the same thing, anyway :)
>> Yes that's what I mentioned.
>>>>>                     }
>>>>>                 }
>>>>>             }
>>>>> @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
>>>>>                 break;
>>>>>             }
>>>>>         }
>>>>> +done_generating:
>>>>>         if (tb->cflags & CF_LAST_IO)
>>>>>             gen_io_end();
>>>> Is there any reason why you don't jump over this two lines in case of a
>>>> breakpoint?
>>> Shouldn't we switch off can_do_io flag if it was switched on?
>> Yes but can we switch on can_do_io if we have a breakpoint?
>>
>> The code is not shown in this patch but there is:
>>
>>           if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
>>               gen_io_start();
>>
>> I think you can't reach this code if you exit the translation loop?
> This is not the only gen_io_start call. It is called from some of the instructions'
> translation functions, that could precede the breakpoint.
>
> Pavel Dovgalyuk
>
>
True, there are 8 others place where gen_io_start is called in this 
file, but they
seems to be each time followed by a gen_io_end?

eg:

static inline void gen_ins(DisasContext *s, TCGMemOp ot)
{
     if (use_icount)
         gen_io_start();
     gen_string_movl_A0_EDI(s);
     /* Note: we must do this dummy write first to be restartable in
        case of page fault. */
     tcg_gen_movi_tl(cpu_T[0], 0);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
     tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
     gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_EDI);
     if (use_icount)
         gen_io_end();
}

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2014-10-23  8:47         ` Frederic Konrad
@ 2014-10-23  9:58           ` Pavel Dovgaluk
  0 siblings, 0 replies; 14+ messages in thread
From: Pavel Dovgaluk @ 2014-10-23  9:58 UTC (permalink / raw)
  To: 'Frederic Konrad', qemu-devel
  Cc: pbonzini, zealot351, maria.klimushenkova, mark.burton, batuzovk

> From: Frederic Konrad [mailto:fred.konrad@greensocs.com]
> On 23/10/2014 09:52, Pavel Dovgaluk wrote:
> >> From: Frederic Konrad [mailto:fred.konrad@greensocs.com]
> >> On 23/10/2014 07:57, Pavel Dovgaluk wrote:
> >>>> From: Frederic Konrad [mailto:fred.konrad@greensocs.com]
> >>>> On 22/10/2014 13:38, Pavel Dovgalyuk wrote:
> >>>>
> >>>> Hi Pavel,
> >>>>> This patch fixes instructions counting when execution is stopped on
> >>>>> breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
> >>>>> and icount is incremented by invalid value (which equals to number of
> >>>>> executed instructions + 1).
> >>>>>
> >>>>> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> >>>>> ---
> >>>>>     target-i386/translate.c |    3 ++-
> >>>>>     1 files changed, 2 insertions(+), 1 deletions(-)
> >>>>>
> >>>>> diff --git a/target-i386/translate.c b/target-i386/translate.c
> >>>>> index 1284173..193cf9f 100644
> >>>>> --- a/target-i386/translate.c
> >>>>> +++ b/target-i386/translate.c
> >>>>> @@ -8000,7 +8000,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);
> >>>>> -                    break;
> >>>>> +                    goto done_generating;
> >>>> This makes sense to me.
> >>>> But I don't see why you don't just "break" like the other instruction in
> >>>> this loop?
> >>> Single break will just exit the breakpoints iteration loop. I'll need an additional flag
> >>> to break the translation loop. ARM does the same thing, anyway :)
> >> Yes that's what I mentioned.
> >>>>>                     }
> >>>>>                 }
> >>>>>             }
> >>>>> @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
> >>>>>                 break;
> >>>>>             }
> >>>>>         }
> >>>>> +done_generating:
> >>>>>         if (tb->cflags & CF_LAST_IO)
> >>>>>             gen_io_end();
> >>>> Is there any reason why you don't jump over this two lines in case of a
> >>>> breakpoint?
> >>> Shouldn't we switch off can_do_io flag if it was switched on?
> >> Yes but can we switch on can_do_io if we have a breakpoint?
> >>
> >> The code is not shown in this patch but there is:
> >>
> >>           if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
> >>               gen_io_start();
> >>
> >> I think you can't reach this code if you exit the translation loop?
> > This is not the only gen_io_start call. It is called from some of the instructions'
> > translation functions, that could precede the breakpoint.
> >
> > Pavel Dovgalyuk
> >
> >
> True, there are 8 others place where gen_io_start is called in this
> file, but they
> seems to be each time followed by a gen_io_end?

Right. Here is the updated patch:

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 1284173..4d5dfb3 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8000,7 +8000,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);
-                    break;
+                    goto done_generating;
                 }
             }
         }
@@ -8051,6 +8051,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
     }
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
+done_generating:
     gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     /* we don't forget to fill the last values */

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  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-31 15:41 ` Paolo Bonzini
  2015-01-12  8:03 ` Jan Kiszka
  2 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2014-10-31 15:41 UTC (permalink / raw)
  To: Pavel Dovgalyuk, qemu-devel
  Cc: fred.konrad, zealot351, maria.klimushenkova, mark.burton,
	batuzovk

On 22/10/2014 13:38, Pavel Dovgalyuk wrote:
> This patch fixes instructions counting when execution is stopped on
> breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
> and icount is incremented by invalid value (which equals to number of
> executed instructions + 1).
> 
> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> ---
>  target-i386/translate.c |    3 ++-
>  1 files changed, 2 insertions(+), 1 deletions(-)
> 
> diff --git a/target-i386/translate.c b/target-i386/translate.c
> index 1284173..193cf9f 100644
> --- a/target-i386/translate.c
> +++ b/target-i386/translate.c
> @@ -8000,7 +8000,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);
> -                    break;
> +                    goto done_generating;
>                  }
>              }
>          }
> @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
>              break;
>          }
>      }
> +done_generating:
>      if (tb->cflags & CF_LAST_IO)
>          gen_io_end();
>      gen_tb_end(tb, num_insns);
> 

Applied, thanks.

Paolo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  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-31 15:41 ` Paolo Bonzini
@ 2015-01-12  8:03 ` Jan Kiszka
  2015-01-12  8:26   ` Pavel Dovgaluk
  2 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2015-01-12  8:03 UTC (permalink / raw)
  To: Pavel Dovgalyuk, qemu-devel
  Cc: mark.burton, batuzovk, maria.klimushenkova, pbonzini, zealot351,
	fred.konrad

On 2014-10-22 13:38, Pavel Dovgalyuk wrote:
> This patch fixes instructions counting when execution is stopped on
> breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
> and icount is incremented by invalid value (which equals to number of
> executed instructions + 1).
> 
> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> ---
>  target-i386/translate.c |    3 ++-
>  1 files changed, 2 insertions(+), 1 deletions(-)
> 
> diff --git a/target-i386/translate.c b/target-i386/translate.c
> index 1284173..193cf9f 100644
> --- a/target-i386/translate.c
> +++ b/target-i386/translate.c
> @@ -8000,7 +8000,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);
> -                    break;
> +                    goto done_generating;
>                  }
>              }
>          }
> @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
>              break;
>          }
>      }
> +done_generating:
>      if (tb->cflags & CF_LAST_IO)
>          gen_io_end();
>      gen_tb_end(tb, num_insns);
> 
> 
> 

Didn't looked into why, just bisected that this patch breaks at least
certain guest-originated break- or watchpoints in TCG mode. Can be
triggered by booting a Linux kernel with kgdb self-tests enabled. The
result is some false reporting of a host-originated debug stop to
gdb_set_stop_cpu while gdbserver_state is NULL -> SEGV.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SES-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2015-01-12  8:03 ` Jan Kiszka
@ 2015-01-12  8:26   ` Pavel Dovgaluk
  2015-01-12  8:30     ` Jan Kiszka
  0 siblings, 1 reply; 14+ messages in thread
From: Pavel Dovgaluk @ 2015-01-12  8:26 UTC (permalink / raw)
  To: 'Jan Kiszka', qemu-devel
  Cc: mark.burton, batuzovk, maria.klimushenkova, pbonzini, zealot351,
	fred.konrad

> From: Jan Kiszka [mailto:jan.kiszka@siemens.com]
> On 2014-10-22 13:38, Pavel Dovgalyuk wrote:
> > This patch fixes instructions counting when execution is stopped on
> > breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
> > and icount is incremented by invalid value (which equals to number of
> > executed instructions + 1).
> >
> > Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> > ---
> >  target-i386/translate.c |    3 ++-
> >  1 files changed, 2 insertions(+), 1 deletions(-)
> >
> > diff --git a/target-i386/translate.c b/target-i386/translate.c
> > index 1284173..193cf9f 100644
> > --- a/target-i386/translate.c
> > +++ b/target-i386/translate.c
> > @@ -8000,7 +8000,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);
> > -                    break;
> > +                    goto done_generating;
> >                  }
> >              }
> >          }
> > @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
> >              break;
> >          }
> >      }
> > +done_generating:
> >      if (tb->cflags & CF_LAST_IO)
> >          gen_io_end();
> >      gen_tb_end(tb, num_insns);
> >
> >
> >
> 
> Didn't looked into why, just bisected that this patch breaks at least
> certain guest-originated break- or watchpoints in TCG mode. Can be
> triggered by booting a Linux kernel with kgdb self-tests enabled. The
> result is some false reporting of a host-originated debug stop to
> gdb_set_stop_cpu while gdbserver_state is NULL -> SEGV.

It seems that kernel sets some hardware breakpoints and QEMU tries to process 
them with GDB stub. Modifying gdb_set_stop_cpu should help:

diff --git a/gdbstub.c b/gdbstub.c
index e4a1a79..e8ef546 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1202,8 +1202,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
 
 void gdb_set_stop_cpu(CPUState *cpu)
 {
-    gdbserver_state->c_cpu = cpu;
-    gdbserver_state->g_cpu = cpu;
+    if (gdbserver_state) {
+        gdbserver_state->c_cpu = cpu;
+        gdbserver_state->g_cpu = cpu;
+    }
 }
 
 #ifndef CONFIG_USER_ONLY

Pavel Dovgalyuk

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2015-01-12  8:26   ` Pavel Dovgaluk
@ 2015-01-12  8:30     ` Jan Kiszka
  2015-01-12  8:55       ` Paolo Bonzini
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2015-01-12  8:30 UTC (permalink / raw)
  To: Pavel Dovgaluk, qemu-devel
  Cc: mark.burton, batuzovk, maria.klimushenkova, pbonzini, zealot351,
	fred.konrad

On 2015-01-12 09:26, Pavel Dovgaluk wrote:
>> From: Jan Kiszka [mailto:jan.kiszka@siemens.com]
>> On 2014-10-22 13:38, Pavel Dovgalyuk wrote:
>>> This patch fixes instructions counting when execution is stopped on
>>> breakpoint (e.g. set from gdb). Without a patch extra instruction is translated
>>> and icount is incremented by invalid value (which equals to number of
>>> executed instructions + 1).
>>>
>>> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
>>> ---
>>>  target-i386/translate.c |    3 ++-
>>>  1 files changed, 2 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/target-i386/translate.c b/target-i386/translate.c
>>> index 1284173..193cf9f 100644
>>> --- a/target-i386/translate.c
>>> +++ b/target-i386/translate.c
>>> @@ -8000,7 +8000,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);
>>> -                    break;
>>> +                    goto done_generating;
>>>                  }
>>>              }
>>>          }
>>> @@ -8049,6 +8049,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
>>>              break;
>>>          }
>>>      }
>>> +done_generating:
>>>      if (tb->cflags & CF_LAST_IO)
>>>          gen_io_end();
>>>      gen_tb_end(tb, num_insns);
>>>
>>>
>>>
>>
>> Didn't looked into why, just bisected that this patch breaks at least
>> certain guest-originated break- or watchpoints in TCG mode. Can be
>> triggered by booting a Linux kernel with kgdb self-tests enabled. The
>> result is some false reporting of a host-originated debug stop to
>> gdb_set_stop_cpu while gdbserver_state is NULL -> SEGV.
> 
> It seems that kernel sets some hardware breakpoints and QEMU tries to process 
> them with GDB stub. Modifying gdb_set_stop_cpu should help:
> 
> diff --git a/gdbstub.c b/gdbstub.c
> index e4a1a79..e8ef546 100644
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -1202,8 +1202,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
>  
>  void gdb_set_stop_cpu(CPUState *cpu)
>  {
> -    gdbserver_state->c_cpu = cpu;
> -    gdbserver_state->g_cpu = cpu;
> +    if (gdbserver_state) {
> +        gdbserver_state->c_cpu = cpu;
> +        gdbserver_state->g_cpu = cpu;
> +    }
>  }
>  
>  #ifndef CONFIG_USER_ONLY

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:

(gdb) bt
#0  gdb_set_stop_cpu (cpu=cpu@entry=0x55555663ac40) at /data/qemu/gdbstub.c:1193
#1  0x000055555562dfdf in cpu_handle_guest_debug (cpu=0x55555663ac40) at /data/qemu/cpus.c:636
#2  tcg_exec_all () at /data/qemu/cpus.c:1389
#3  qemu_tcg_cpu_thread_fn (arg=<optimized out>) at /data/qemu/cpus.c:1033
#4  0x00007ffff2c3d0a4 in start_thread () from /lib64/libpthread.so.0
#5  0x00007fffeea4a7fd in clone () from /lib64/libc.so.6

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SES-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2015-01-12  8:30     ` Jan Kiszka
@ 2015-01-12  8:55       ` Paolo Bonzini
  2015-05-24 14:43         ` Jan Kiszka
  0 siblings, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2015-01-12  8:55 UTC (permalink / raw)
  To: Jan Kiszka, Pavel Dovgaluk, qemu-devel
  Cc: fred.konrad, zealot351, maria.klimushenkova, mark.burton,
	batuzovk



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)

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2015-01-12  8:55       ` Paolo Bonzini
@ 2015-05-24 14:43         ` Jan Kiszka
  2015-05-26 14:56           ` Paolo Bonzini
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2015-05-24 14:43 UTC (permalink / raw)
  To: Paolo Bonzini, Pavel Dovgaluk, qemu-devel
  Cc: batuzovk, zealot351, maria.klimushenkova, mark.burton,
	fred.konrad

[-- 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 --]

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH] i386: fix breakpoints handling in icount mode
  2015-05-24 14:43         ` Jan Kiszka
@ 2015-05-26 14:56           ` Paolo Bonzini
  0 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2015-05-26 14:56 UTC (permalink / raw)
  To: Jan Kiszka, Pavel Dovgaluk, qemu-devel
  Cc: batuzovk, zealot351, maria.klimushenkova, mark.burton,
	fred.konrad



On 24/05/2015 16:43, Jan Kiszka wrote:
> 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.

So when a breakpoint is removed at address X, you have to also remove 
translation blocks that end exactly at X?  That is:

diff --git a/translate-all.c b/translate-all.c
index 536008f..6e50b8f 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1113,7 +1116,7 @@
             tb_start = tb->page_addr[1];
             tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
         }
-        if (!(tb_end <= start || tb_start >= end)) {
+        if (tb_start < end && tb_end >= start) {
 #ifdef TARGET_HAS_PRECISE_SMC
             if (current_tb_not_found) {
                 current_tb_not_found = 0;

Does this fix the bug?  Is there any other case where this
is desirable?  Should tb_invalidate_phys_page_range grow another
argument to choose between "tb_end > start" and "tb_end >= start"?

Paolo

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-05-26 14:56 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2015-05-26 14:56           ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).