* [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).