qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] Confusion regarding temporaries with branch conditional
@ 2016-11-30  7:00 Nikunj A Dadhania
  2016-11-30  7:24 ` Peter Maydell
  2016-11-30 16:55 ` Alex Bennée
  0 siblings, 2 replies; 9+ messages in thread
From: Nikunj A Dadhania @ 2016-11-30  7:00 UTC (permalink / raw)
  To: rth, qemu-devel


Hi,

I was writing one instruction and hit following issue:

[snip]/qemu/tcg/tcg.c:2039: tcg fatal error
qemu-ppc64le: [snip]/qemu/translate-all.c:175: tb_lock: Assertion `!have_tb_lock' failed.
Segmentation fault (core dumped)

Debugging deeper found that its something to do with the variable type:

    TCGv nb = tcg_temp_new();
    tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
    tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
    [ Do something here]
    gen_set_label(l1);
    tcg_temp_free(nb);

If I change the variable as "local temporary", the code works fine:

    TCGv nb = tcg_temp_local_new();
    tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
    tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
    [ Do something here]
    gen_set_label(l1);
    tcg_temp_free(nb);

I see lot of code that is using temporaries for similar operations,
example target-ppc/translate.c:gen_check_align(). How is that working,
is this a bug there as well?

Regards,
Nikunj

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

* Re: [Qemu-devel] Confusion regarding temporaries with branch conditional
  2016-11-30  7:00 [Qemu-devel] Confusion regarding temporaries with branch conditional Nikunj A Dadhania
@ 2016-11-30  7:24 ` Peter Maydell
  2016-11-30  7:56   ` Nikunj A Dadhania
  2016-11-30 16:55 ` Alex Bennée
  1 sibling, 1 reply; 9+ messages in thread
From: Peter Maydell @ 2016-11-30  7:24 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: Richard Henderson, QEMU Developers

On 30 November 2016 at 07:00, Nikunj A Dadhania
<nikunj@linux.vnet.ibm.com> wrote:
>
> Hi,
>
> I was writing one instruction and hit following issue:
>
> [snip]/qemu/tcg/tcg.c:2039: tcg fatal error
> qemu-ppc64le: [snip]/qemu/translate-all.c:175: tb_lock: Assertion `!have_tb_lock' failed.
> Segmentation fault (core dumped)
>
> Debugging deeper found that its something to do with the variable type:
>
>     TCGv nb = tcg_temp_new();
>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
>     [ Do something here]
>     gen_set_label(l1);
>     tcg_temp_free(nb);
>
> If I change the variable as "local temporary", the code works fine:
>
>     TCGv nb = tcg_temp_local_new();
>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
>     [ Do something here]
>     gen_set_label(l1);
>     tcg_temp_free(nb);
>
> I see lot of code that is using temporaries for similar operations,
> example target-ppc/translate.c:gen_check_align(). How is that working,
> is this a bug there as well?

You don't say what your "do something" code is doing, which
is the critical question for whether you need a plain
temporary or a local temporary. (See tcg/README.)
The plain temporary is only valid to the end of a basic
block, and brcond ends a basic block. So you can free
the temp after the brcond but you can't do anything
else with it. (This is what the PPC gen_check_align() does.)
If you want to use 'nb' in the "do something" code then
it must remain valid over the end of the basic block
and you need a local temporary.

thanks
-- PMM

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

* Re: [Qemu-devel] Confusion regarding temporaries with branch conditional
  2016-11-30  7:24 ` Peter Maydell
@ 2016-11-30  7:56   ` Nikunj A Dadhania
  2016-11-30 17:08     ` Richard Henderson
  0 siblings, 1 reply; 9+ messages in thread
From: Nikunj A Dadhania @ 2016-11-30  7:56 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Richard Henderson, QEMU Developers

Peter Maydell <peter.maydell@linaro.org> writes:

> On 30 November 2016 at 07:00, Nikunj A Dadhania
> <nikunj@linux.vnet.ibm.com> wrote:
>>
>> Hi,
>>
>> I was writing one instruction and hit following issue:
>>
>> [snip]/qemu/tcg/tcg.c:2039: tcg fatal error
>> qemu-ppc64le: [snip]/qemu/translate-all.c:175: tb_lock: Assertion `!have_tb_lock' failed.
>> Segmentation fault (core dumped)
>>
>> Debugging deeper found that its something to do with the variable type:
>>
>>     TCGv nb = tcg_temp_new();
>>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
>>     [ Do something here]
>>     gen_set_label(l1);
>>     tcg_temp_free(nb);
>>
>> If I change the variable as "local temporary", the code works fine:
>>
>>     TCGv nb = tcg_temp_local_new();
>>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
>>     [ Do something here]
>>     gen_set_label(l1);
>>     tcg_temp_free(nb);
>>
>> I see lot of code that is using temporaries for similar operations,
>> example target-ppc/translate.c:gen_check_align(). How is that working,
>> is this a bug there as well?
>
> You don't say what your "do something" code is doing, which
> is the critical question for whether you need a plain
> temporary or a local temporary. (See tcg/README.)

Lets bring full example here.

    TCGv nb = tcg_temp_new();
    tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
    tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);

    /* do something */
    gen_set_access_type(ctx, ACCESS_INT);
    EA = tcg_temp_new();
    gen_addr_register(ctx, EA);
    tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_LEQ);
    tcg_gen_addi_tl(EA, EA, 8);
    tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_LEQ);
    opc = tcg_const_i32(ctx->opcode);
    gen_helper_lxvl(cpu_env, opc, nb);      /* <--- That uses nb */
    tcg_temp_free_i32(opc);
    tcg_temp_free(EA);

    gen_set_label(l1);
    tcg_temp_free(nb);

> The plain temporary is only valid to the end of a basic
> block, and brcond ends a basic block. So you can free
> the temp after the brcond but you can't do anything
> else with it.

In the above case, assuming that nb is a plain temporary, case nb != 0
worked fine (by fluke?), i.e. no branch.

While when nb == 0, failed, i.e. branch taken to l1, and just free nb. I
am not using "nb" in this case.

> (This is what the PPC gen_check_align() does.)
> If you want to use 'nb' in the "do something" code then
> it must remain valid over the end of the basic block
> and you need a local temporary.

Understood, I need nb in that code, so I will use local temporary.

Regards
Nikunj

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

* Re: [Qemu-devel] Confusion regarding temporaries with branch conditional
  2016-11-30  7:00 [Qemu-devel] Confusion regarding temporaries with branch conditional Nikunj A Dadhania
  2016-11-30  7:24 ` Peter Maydell
@ 2016-11-30 16:55 ` Alex Bennée
  2016-11-30 17:03   ` Richard Henderson
  1 sibling, 1 reply; 9+ messages in thread
From: Alex Bennée @ 2016-11-30 16:55 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: rth, qemu-devel


Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> writes:

> Hi,
>
> I was writing one instruction and hit following issue:
>
> [snip]/qemu/tcg/tcg.c:2039: tcg fatal error
> qemu-ppc64le: [snip]/qemu/translate-all.c:175: tb_lock: Assertion `!have_tb_lock' failed.
> Segmentation fault (core dumped)

This is confusing because something is trying to take the tb_lock while
you are in code generation. tb_lock is held for code generation to
ensure serialisation of generation.

>
> Debugging deeper found that its something to do with the variable type:
>
>     TCGv nb = tcg_temp_new();
>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
>     [ Do something here]
>     gen_set_label(l1);
>     tcg_temp_free(nb);
>
> If I change the variable as "local temporary", the code works fine:
>
>     TCGv nb = tcg_temp_local_new();
>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
>     [ Do something here]
>     gen_set_label(l1);
>     tcg_temp_free(nb);
>
> I see lot of code that is using temporaries for similar operations,
> example target-ppc/translate.c:gen_check_align(). How is that working,
> is this a bug there as well?

Well that is odd. Are you sure there is no side effect that is
attempting to modify run state during generation? I'm thinking of
changing memory maps or other such stuff. A back trace at the assert
would make things clearer.

>
> Regards,
> Nikunj


--
Alex Bennée

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

* Re: [Qemu-devel] Confusion regarding temporaries with branch conditional
  2016-11-30 16:55 ` Alex Bennée
@ 2016-11-30 17:03   ` Richard Henderson
  2016-11-30 18:12     ` Alex Bennée
  0 siblings, 1 reply; 9+ messages in thread
From: Richard Henderson @ 2016-11-30 17:03 UTC (permalink / raw)
  To: Alex Bennée, Nikunj A Dadhania; +Cc: qemu-devel

On 11/30/2016 08:55 AM, Alex Bennée wrote:
> 
> Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> writes:
> 
>> Hi,
>>
>> I was writing one instruction and hit following issue:
>>
>> [snip]/qemu/tcg/tcg.c:2039: tcg fatal error
>> qemu-ppc64le: [snip]/qemu/translate-all.c:175: tb_lock: Assertion `!have_tb_lock' failed.
>> Segmentation fault (core dumped)
> 
> This is confusing because something is trying to take the tb_lock while
> you are in code generation. tb_lock is held for code generation to
> ensure serialisation of generation.

Yes, I've seen this myself.  I never got around to reporting the "problem"
properly.  It's a confusing side effect of a SIGSEGV arriving during tcg code
generation.  The signal handler longjmps back with unexpected locks held.

Probably we should simply crash earlier and less confusingly.


r~

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

* Re: [Qemu-devel] Confusion regarding temporaries with branch conditional
  2016-11-30  7:56   ` Nikunj A Dadhania
@ 2016-11-30 17:08     ` Richard Henderson
  2016-12-01  4:44       ` Nikunj A Dadhania
  0 siblings, 1 reply; 9+ messages in thread
From: Richard Henderson @ 2016-11-30 17:08 UTC (permalink / raw)
  To: Nikunj A Dadhania, Peter Maydell; +Cc: QEMU Developers

On 11/29/2016 11:56 PM, Nikunj A Dadhania wrote:
> Lets bring full example here.
> 
>     TCGv nb = tcg_temp_new();
>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
> 
>     /* do something */
>     gen_set_access_type(ctx, ACCESS_INT);
>     EA = tcg_temp_new();
>     gen_addr_register(ctx, EA);
>     tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_LEQ);
>     tcg_gen_addi_tl(EA, EA, 8);
>     tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_LEQ);
>     opc = tcg_const_i32(ctx->opcode);
>     gen_helper_lxvl(cpu_env, opc, nb);      /* <--- That uses nb */
>     tcg_temp_free_i32(opc);
>     tcg_temp_free(EA);
> 
>     gen_set_label(l1);
>     tcg_temp_free(nb);
> 
>> The plain temporary is only valid to the end of a basic
>> block, and brcond ends a basic block. So you can free
>> the temp after the brcond but you can't do anything
>> else with it.
> 
> In the above case, assuming that nb is a plain temporary, case nb != 0
> worked fine (by fluke?), i.e. no branch.
> 
> While when nb == 0, failed, i.e. branch taken to l1, and just free nb. I
> am not using "nb" in this case.

This is also a good example of why you should preferentially avoid branches
within the tcg opcode stream.

In the case of lxvl, I strongly suggest that you push *everything* into the
helper.  In particular:

 (1) Passing the full instruction opcode means you've got to re-parse.
     Why are you not passing a pointer to the XT register like other
     VSX helpers?

 (2) As I read it, this is wrong, since when NB == 0, XT is assigned 0.
     Which you are not doing, having skipped over the helper.

 (3) Use cpu_ldq_data_ra within the helper to perform the memory loads.


r~

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

* Re: [Qemu-devel] Confusion regarding temporaries with branch conditional
  2016-11-30 17:03   ` Richard Henderson
@ 2016-11-30 18:12     ` Alex Bennée
  2016-11-30 20:09       ` Richard Henderson
  0 siblings, 1 reply; 9+ messages in thread
From: Alex Bennée @ 2016-11-30 18:12 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Nikunj A Dadhania, qemu-devel


Richard Henderson <rth@twiddle.net> writes:

> On 11/30/2016 08:55 AM, Alex Bennée wrote:
>>
>> Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> writes:
>>
>>> Hi,
>>>
>>> I was writing one instruction and hit following issue:
>>>
>>> [snip]/qemu/tcg/tcg.c:2039: tcg fatal error
>>> qemu-ppc64le: [snip]/qemu/translate-all.c:175: tb_lock: Assertion `!have_tb_lock' failed.
>>> Segmentation fault (core dumped)
>>
>> This is confusing because something is trying to take the tb_lock while
>> you are in code generation. tb_lock is held for code generation to
>> ensure serialisation of generation.
>
> Yes, I've seen this myself.  I never got around to reporting the "problem"
> properly.  It's a confusing side effect of a SIGSEGV arriving during tcg code
> generation.  The signal handler longjmps back with unexpected locks
> held.

So this is a SEGV which belongs to the translation code rather than the
guest?

There are places in the cpu loop where we exit that should reset the
locks on a restart - see tb_lock_reset() so I'm not quite sure what has
happened here.

>
> Probably we should simply crash earlier and less confusingly.
>
>
> r~


--
Alex Bennée

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

* Re: [Qemu-devel] Confusion regarding temporaries with branch conditional
  2016-11-30 18:12     ` Alex Bennée
@ 2016-11-30 20:09       ` Richard Henderson
  0 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2016-11-30 20:09 UTC (permalink / raw)
  To: Alex Bennée; +Cc: Nikunj A Dadhania, qemu-devel

On 11/30/2016 10:12 AM, Alex Bennée wrote:
> 
> Richard Henderson <rth@twiddle.net> writes:
> 
>> On 11/30/2016 08:55 AM, Alex Bennée wrote:
>>>
>>> Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> writes:
>>>
>>>> Hi,
>>>>
>>>> I was writing one instruction and hit following issue:
>>>>
>>>> [snip]/qemu/tcg/tcg.c:2039: tcg fatal error
>>>> qemu-ppc64le: [snip]/qemu/translate-all.c:175: tb_lock: Assertion `!have_tb_lock' failed.
>>>> Segmentation fault (core dumped)
>>>
>>> This is confusing because something is trying to take the tb_lock while
>>> you are in code generation. tb_lock is held for code generation to
>>> ensure serialisation of generation.
>>
>> Yes, I've seen this myself.  I never got around to reporting the "problem"
>> properly.  It's a confusing side effect of a SIGSEGV arriving during tcg code
>> generation.  The signal handler longjmps back with unexpected locks
>> held.
> 
> So this is a SEGV which belongs to the translation code rather than the
> guest?

Yes.

> There are places in the cpu loop where we exit that should reset the
> locks on a restart - see tb_lock_reset() so I'm not quite sure what has
> happened here.

It should be easy enough to force a segv from within the compile step to
reproduce this.


r~

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

* Re: [Qemu-devel] Confusion regarding temporaries with branch conditional
  2016-11-30 17:08     ` Richard Henderson
@ 2016-12-01  4:44       ` Nikunj A Dadhania
  0 siblings, 0 replies; 9+ messages in thread
From: Nikunj A Dadhania @ 2016-12-01  4:44 UTC (permalink / raw)
  To: Richard Henderson, Peter Maydell; +Cc: QEMU Developers

Richard Henderson <rth@twiddle.net> writes:

> On 11/29/2016 11:56 PM, Nikunj A Dadhania wrote:
>> Lets bring full example here.
>> 
>>     TCGv nb = tcg_temp_new();
>>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
>> 
>>     /* do something */
>>     gen_set_access_type(ctx, ACCESS_INT);
>>     EA = tcg_temp_new();
>>     gen_addr_register(ctx, EA);
>>     tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_LEQ);
>>     tcg_gen_addi_tl(EA, EA, 8);
>>     tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_LEQ);
>>     opc = tcg_const_i32(ctx->opcode);
>>     gen_helper_lxvl(cpu_env, opc, nb);      /* <--- That uses nb */
>>     tcg_temp_free_i32(opc);
>>     tcg_temp_free(EA);
>> 
>>     gen_set_label(l1);
>>     tcg_temp_free(nb);
>> 
>>> The plain temporary is only valid to the end of a basic
>>> block, and brcond ends a basic block. So you can free
>>> the temp after the brcond but you can't do anything
>>> else with it.
>> 
>> In the above case, assuming that nb is a plain temporary, case nb != 0
>> worked fine (by fluke?), i.e. no branch.
>> 
>> While when nb == 0, failed, i.e. branch taken to l1, and just free nb. I
>> am not using "nb" in this case.
>
> This is also a good example of why you should preferentially avoid branches
> within the tcg opcode stream.
>
> In the case of lxvl, I strongly suggest that you push *everything* into the
> helper.  In particular:
>
>  (1) Passing the full instruction opcode means you've got to re-parse.
>      Why are you not passing a pointer to the XT register like other
>      VSX helpers?

Sure, I can do that. No particular reason though.

>  (2) As I read it, this is wrong, since when NB == 0, XT is assigned 0.
>      Which you are not doing, having skipped over the helper.

I am doing that in my code. Didn't want to complicate the example code
above.

>  (3) Use cpu_ldq_data_ra within the helper to perform the memory
>  loads.

Let me try that.

Regards
Nikunj

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

end of thread, other threads:[~2016-12-01  4:44 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-11-30  7:00 [Qemu-devel] Confusion regarding temporaries with branch conditional Nikunj A Dadhania
2016-11-30  7:24 ` Peter Maydell
2016-11-30  7:56   ` Nikunj A Dadhania
2016-11-30 17:08     ` Richard Henderson
2016-12-01  4:44       ` Nikunj A Dadhania
2016-11-30 16:55 ` Alex Bennée
2016-11-30 17:03   ` Richard Henderson
2016-11-30 18:12     ` Alex Bennée
2016-11-30 20:09       ` Richard Henderson

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