All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] TCG register allocator
@ 2012-01-25 14:24 Xin Tong
  2012-01-25 15:19 ` Peter Maydell
  0 siblings, 1 reply; 16+ messages in thread
From: Xin Tong @ 2012-01-25 14:24 UTC (permalink / raw)
  To: qemu-devel

I am wondering how tcg reg alloc works. Specifically, how do i reserve
a register only for one specific purpose. R14 on tcg i386 is reserved
to point to the cpustate strcuture.  it is assigned in the prologue,
but what code makes sure that it is not clobbered in the middle of a
TB ?


Thanks


Xin

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 14:24 [Qemu-devel] TCG register allocator Xin Tong
@ 2012-01-25 15:19 ` Peter Maydell
  2012-01-25 15:42   ` Xin Tong
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Maydell @ 2012-01-25 15:19 UTC (permalink / raw)
  To: Xin Tong; +Cc: qemu-devel

On 25 January 2012 14:24, Xin Tong <xerox.time.tech@gmail.com> wrote:
> I am wondering how tcg reg alloc works. Specifically, how do i reserve
> a register only for one specific purpose. R14 on tcg i386 is reserved
> to point to the cpustate strcuture.  it is assigned in the prologue,
> but what code makes sure that it is not clobbered in the middle of a
> TB ?

target-i386/translate.c:optimize_flags_init() calls:
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");

which tells TCG that this register always has this value in it.
TCG will then ensure that it doesn't try to use that register
when it's doing allocation later. This is done by having
tcg_global_reg_new_internal() call:
    tcg_regset_set_reg(s->reserved_regs, reg);

We also add a register to the reserved_regs set in tcg/i386/tcg-target.c:
tcg_target_init():
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);

because attempting to allocate a value into ESP would be a bad idea :-)

-- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 15:19 ` Peter Maydell
@ 2012-01-25 15:42   ` Xin Tong
  2012-01-25 15:49     ` Peter Maydell
  0 siblings, 1 reply; 16+ messages in thread
From: Xin Tong @ 2012-01-25 15:42 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

I tried to reserve a register in target-i386 with this code

target-i386/translate.c    tb_env = tcg_global_reg_new_ptr(TCG_AREG1, "env");

i386/tcg-target.h         #define TCG_AREG1 TCG_REG_R13

i386/tcg-target.c         tcg_out_movi(s, TCG_TYPE_PTR, TCG_AREG1, args[0]);

But when i looked into the dynamically generated code, the place which
i use TCG_AREG1 becomes RBP and RBP is not reserved either.

Thanks

Xin



On Wed, Jan 25, 2012 at 10:19 AM, Peter Maydell
<peter.maydell@linaro.org> wrote:
> On 25 January 2012 14:24, Xin Tong <xerox.time.tech@gmail.com> wrote:
>> I am wondering how tcg reg alloc works. Specifically, how do i reserve
>> a register only for one specific purpose. R14 on tcg i386 is reserved
>> to point to the cpustate strcuture.  it is assigned in the prologue,
>> but what code makes sure that it is not clobbered in the middle of a
>> TB ?
>
> target-i386/translate.c:optimize_flags_init() calls:
>    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
>
> which tells TCG that this register always has this value in it.
> TCG will then ensure that it doesn't try to use that register
> when it's doing allocation later. This is done by having
> tcg_global_reg_new_internal() call:
>    tcg_regset_set_reg(s->reserved_regs, reg);
>
> We also add a register to the reserved_regs set in tcg/i386/tcg-target.c:
> tcg_target_init():
>     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
>
> because attempting to allocate a value into ESP would be a bad idea :-)
>
> -- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 15:42   ` Xin Tong
@ 2012-01-25 15:49     ` Peter Maydell
  2012-01-25 15:54       ` Xin Tong
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Maydell @ 2012-01-25 15:49 UTC (permalink / raw)
  To: Xin Tong; +Cc: qemu-devel

On 25 January 2012 15:42, Xin Tong <xerox.time.tech@gmail.com> wrote:
> I tried to reserve a register in target-i386 with this code
>
> target-i386/translate.c    tb_env = tcg_global_reg_new_ptr(TCG_AREG1, "env");

Why do you want to define a second global which holds the environment
variable? Just use TCG_AREG0 for that.

> i386/tcg-target.h         #define TCG_AREG1 TCG_REG_R13
>
> i386/tcg-target.c         tcg_out_movi(s, TCG_TYPE_PTR, TCG_AREG1, args[0]);
>
> But when i looked into the dynamically generated code, the place which
> i use TCG_AREG1 becomes RBP and RBP is not reserved either.

If the reason you're trying to reserve a register is so you can use
it as a temporary in tcg-target.c's codegen, then reserve it in
tcg_target_init(). (But x86-32 is very short on registers as it is,
so really it would be much better not to...)

-- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 15:49     ` Peter Maydell
@ 2012-01-25 15:54       ` Xin Tong
  2012-01-25 15:55         ` Xin Tong
  2012-01-25 16:03         ` Max Filippov
  0 siblings, 2 replies; 16+ messages in thread
From: Xin Tong @ 2012-01-25 15:54 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

I have a bug, it segfaults when executing a translation blocks. when i
disable block chaining, the bug disappears.  However, with block
chaining, i do not know which translation block jumps to the code
which caused the segfault. I want to reserve a register and use it to
record the last translation block executed.  So at entry, i assign the
translation blocks address to the register and when the segfault
happens, I can get the last translation block executed.

Thanks



On Wed, Jan 25, 2012 at 10:49 AM, Peter Maydell
<peter.maydell@linaro.org> wrote:
> On 25 January 2012 15:42, Xin Tong <xerox.time.tech@gmail.com> wrote:
>> I tried to reserve a register in target-i386 with this code
>>
>> target-i386/translate.c    tb_env = tcg_global_reg_new_ptr(TCG_AREG1, "env");
>
> Why do you want to define a second global which holds the environment
> variable? Just use TCG_AREG0 for that.
>
>> i386/tcg-target.h         #define TCG_AREG1 TCG_REG_R13
>>
>> i386/tcg-target.c         tcg_out_movi(s, TCG_TYPE_PTR, TCG_AREG1, args[0]);
>>
>> But when i looked into the dynamically generated code, the place which
>> i use TCG_AREG1 becomes RBP and RBP is not reserved either.
>
> If the reason you're trying to reserve a register is so you can use
> it as a temporary in tcg-target.c's codegen, then reserve it in
> tcg_target_init(). (But x86-32 is very short on registers as it is,
> so really it would be much better not to...)
>
> -- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 15:54       ` Xin Tong
@ 2012-01-25 15:55         ` Xin Tong
  2012-01-25 16:22           ` Peter Maydell
  2012-01-25 16:03         ` Max Filippov
  1 sibling, 1 reply; 16+ messages in thread
From: Xin Tong @ 2012-01-25 15:55 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

The segfault is caused by jumping to the middle of an instruction. so
i want to know which TB jumps here.

Thanks

Xin


On Wed, Jan 25, 2012 at 10:54 AM, Xin Tong <xerox.time.tech@gmail.com> wrote:
> I have a bug, it segfaults when executing a translation blocks. when i
> disable block chaining, the bug disappears.  However, with block
> chaining, i do not know which translation block jumps to the code
> which caused the segfault. I want to reserve a register and use it to
> record the last translation block executed.  So at entry, i assign the
> translation blocks address to the register and when the segfault
> happens, I can get the last translation block executed.
>
> Thanks
>
>
>
> On Wed, Jan 25, 2012 at 10:49 AM, Peter Maydell
> <peter.maydell@linaro.org> wrote:
>> On 25 January 2012 15:42, Xin Tong <xerox.time.tech@gmail.com> wrote:
>>> I tried to reserve a register in target-i386 with this code
>>>
>>> target-i386/translate.c    tb_env = tcg_global_reg_new_ptr(TCG_AREG1, "env");
>>
>> Why do you want to define a second global which holds the environment
>> variable? Just use TCG_AREG0 for that.
>>
>>> i386/tcg-target.h         #define TCG_AREG1 TCG_REG_R13
>>>
>>> i386/tcg-target.c         tcg_out_movi(s, TCG_TYPE_PTR, TCG_AREG1, args[0]);
>>>
>>> But when i looked into the dynamically generated code, the place which
>>> i use TCG_AREG1 becomes RBP and RBP is not reserved either.
>>
>> If the reason you're trying to reserve a register is so you can use
>> it as a temporary in tcg-target.c's codegen, then reserve it in
>> tcg_target_init(). (But x86-32 is very short on registers as it is,
>> so really it would be much better not to...)
>>
>> -- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 15:54       ` Xin Tong
  2012-01-25 15:55         ` Xin Tong
@ 2012-01-25 16:03         ` Max Filippov
  1 sibling, 0 replies; 16+ messages in thread
From: Max Filippov @ 2012-01-25 16:03 UTC (permalink / raw)
  To: Xin Tong; +Cc: Peter Maydell, qemu-devel

> I have a bug, it segfaults when executing a translation blocks. when i
> disable block chaining, the bug disappears.  However, with block
> chaining, i do not know which translation block jumps to the code
> which caused the segfault. I want to reserve a register and use it to
> record the last translation block executed.  So at entry, i assign the
> translation blocks address to the register and when the segfault
> happens, I can get the last translation block executed.

You could inject a helper call at the beginning of each TB that
would record e.g. current program counter into a global variable.

-- 
Thanks.
-- Max

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 15:55         ` Xin Tong
@ 2012-01-25 16:22           ` Peter Maydell
  2012-01-25 18:58             ` Xin Tong
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Maydell @ 2012-01-25 16:22 UTC (permalink / raw)
  To: Xin Tong; +Cc: qemu-devel

On 25 January 2012 15:55, Xin Tong <xerox.time.tech@gmail.com> wrote:
> The segfault is caused by jumping to the middle of an instruction. so
> i want to know which TB jumps here.

(a) Assuming it doesn't take too long to get there, you should
be able to get this information by turning on the debug log
via -d whatever. If it does take too long to get to the crash,
you can use the savevm/loadvm support to save the VM state
at some point slightly before the crash. Then you can run
with the debug log enabled and '-loadvm tag' to start from the
point when you saved the VM state. [disclaimer: depending on the
guest machine you're emulating you might be unlucky and need to
fix save/load first, but that's a worthwhile thing anyway :-)]

(b) Might not be what you're seeing, but there's a class of bug that
can look like a jump to the middle of an instruction that happens
when:
 * step 1: we generate code for a TB
 * a load or store within that TB causes an exception
 * to get CPUState in sync with the point of the exception
   (and in particular to translate the host PC at the exception
   into the guest PC at that point) we call cpu_restore_state()
 * cpu_restore_state() calls gen_intermediate_code_pc() to
   request a retranslation of the TB with extra info to allow
   us to do a host-PC-to-guest-PC lookup
 * Note that gen_intermediate_code_pc() overwrites the generated
   code that already exists in memory, and stops as soon as it
   reaches the point of the exception. This is harmless because
   we are just rewriting the same bytes to memory that were there
   already, but disastrous if...
 * ...due to a bug, gen_intermediate_code_pc() generates different
   code to that generated back in step 1; this tends to result
   in writing half an instruction at the point where it stops
 * subsequent attempts to execute that TB tend to result in
   weird crashes, often looking like an attempt to jump into
   the middle of an instruction

This is why it's critical that gen_intermediate_code()+TCG always
deterministically generates exactly the same native code every
time.

-- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 16:22           ` Peter Maydell
@ 2012-01-25 18:58             ` Xin Tong
  2012-01-25 19:10               ` Xin Tong
  2012-01-31  3:09               ` 陳韋任
  0 siblings, 2 replies; 16+ messages in thread
From: Xin Tong @ 2012-01-25 18:58 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

I am working on extending coremu (parallel version of qemu).
Currently, the code cache in coremu is private, I am working towards
to make it shared by all cores. I think the add_tb_jump may not be
atomic.

Thanks

Xin

On Wed, Jan 25, 2012 at 11:22 AM, Peter Maydell
<peter.maydell@linaro.org> wrote:
> On 25 January 2012 15:55, Xin Tong <xerox.time.tech@gmail.com> wrote:
>> The segfault is caused by jumping to the middle of an instruction. so
>> i want to know which TB jumps here.
>
> (a) Assuming it doesn't take too long to get there, you should
> be able to get this information by turning on the debug log
> via -d whatever. If it does take too long to get to the crash,
> you can use the savevm/loadvm support to save the VM state
> at some point slightly before the crash. Then you can run
> with the debug log enabled and '-loadvm tag' to start from the
> point when you saved the VM state. [disclaimer: depending on the
> guest machine you're emulating you might be unlucky and need to
> fix save/load first, but that's a worthwhile thing anyway :-)]
>
> (b) Might not be what you're seeing, but there's a class of bug that
> can look like a jump to the middle of an instruction that happens
> when:
>  * step 1: we generate code for a TB
>  * a load or store within that TB causes an exception
>  * to get CPUState in sync with the point of the exception
>   (and in particular to translate the host PC at the exception
>   into the guest PC at that point) we call cpu_restore_state()
>  * cpu_restore_state() calls gen_intermediate_code_pc() to
>   request a retranslation of the TB with extra info to allow
>   us to do a host-PC-to-guest-PC lookup
>  * Note that gen_intermediate_code_pc() overwrites the generated
>   code that already exists in memory, and stops as soon as it
>   reaches the point of the exception. This is harmless because
>   we are just rewriting the same bytes to memory that were there
>   already, but disastrous if...
>  * ...due to a bug, gen_intermediate_code_pc() generates different
>   code to that generated back in step 1; this tends to result
>   in writing half an instruction at the point where it stops
>  * subsequent attempts to execute that TB tend to result in
>   weird crashes, often looking like an attempt to jump into
>   the middle of an instruction
>
> This is why it's critical that gen_intermediate_code()+TCG always
> deterministically generates exactly the same native code every
> time.
>
> -- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 18:58             ` Xin Tong
@ 2012-01-25 19:10               ` Xin Tong
  2012-01-25 19:18                 ` James Greensky
  2012-01-25 19:23                 ` Peter Maydell
  2012-01-31  3:09               ` 陳韋任
  1 sibling, 2 replies; 16+ messages in thread
From: Xin Tong @ 2012-01-25 19:10 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

cpu_restore_state() calls gen_intermediate_code_pc() to
request a retranslation of the TB with extra info to allow
us to do a host-PC-to-guest-PC lookup
 * Note that gen_intermediate_code_pc() overwrites the generated
code that already exists in memory, and stops as soon as it
reaches the point of the exception. This is harmless because
we are just rewriting the same bytes to memory that were there
already, but disastrous if...


in the case you described above, which code guarantees that the
re-generated code is laid down in the place where the old code is.
This has to be do somewhere in tcg.


Xin


On Wed, Jan 25, 2012 at 1:58 PM, Xin Tong <xerox.time.tech@gmail.com> wrote:
> I am working on extending coremu (parallel version of qemu).
> Currently, the code cache in coremu is private, I am working towards
> to make it shared by all cores. I think the add_tb_jump may not be
> atomic.
>
> Thanks
>
> Xin
>
> On Wed, Jan 25, 2012 at 11:22 AM, Peter Maydell
> <peter.maydell@linaro.org> wrote:
>> On 25 January 2012 15:55, Xin Tong <xerox.time.tech@gmail.com> wrote:
>>> The segfault is caused by jumping to the middle of an instruction. so
>>> i want to know which TB jumps here.
>>
>> (a) Assuming it doesn't take too long to get there, you should
>> be able to get this information by turning on the debug log
>> via -d whatever. If it does take too long to get to the crash,
>> you can use the savevm/loadvm support to save the VM state
>> at some point slightly before the crash. Then you can run
>> with the debug log enabled and '-loadvm tag' to start from the
>> point when you saved the VM state. [disclaimer: depending on the
>> guest machine you're emulating you might be unlucky and need to
>> fix save/load first, but that's a worthwhile thing anyway :-)]
>>
>> (b) Might not be what you're seeing, but there's a class of bug that
>> can look like a jump to the middle of an instruction that happens
>> when:
>>  * step 1: we generate code for a TB
>>  * a load or store within that TB causes an exception
>>  * to get CPUState in sync with the point of the exception
>>   (and in particular to translate the host PC at the exception
>>   into the guest PC at that point) we call cpu_restore_state()
>>  * cpu_restore_state() calls gen_intermediate_code_pc() to
>>   request a retranslation of the TB with extra info to allow
>>   us to do a host-PC-to-guest-PC lookup
>>  * Note that gen_intermediate_code_pc() overwrites the generated
>>   code that already exists in memory, and stops as soon as it
>>   reaches the point of the exception. This is harmless because
>>   we are just rewriting the same bytes to memory that were there
>>   already, but disastrous if...
>>  * ...due to a bug, gen_intermediate_code_pc() generates different
>>   code to that generated back in step 1; this tends to result
>>   in writing half an instruction at the point where it stops
>>  * subsequent attempts to execute that TB tend to result in
>>   weird crashes, often looking like an attempt to jump into
>>   the middle of an instruction
>>
>> This is why it's critical that gen_intermediate_code()+TCG always
>> deterministically generates exactly the same native code every
>> time.
>>
>> -- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 19:10               ` Xin Tong
@ 2012-01-25 19:18                 ` James Greensky
  2012-01-25 19:19                   ` Xin Tong
  2012-01-25 19:23                 ` Peter Maydell
  1 sibling, 1 reply; 16+ messages in thread
From: James Greensky @ 2012-01-25 19:18 UTC (permalink / raw)
  To: Xin Tong; +Cc: qemu-devel

On Wed, Jan 25, 2012 at 11:10 AM, Xin Tong <xerox.time.tech@gmail.com> wrote:
> cpu_restore_state() calls gen_intermediate_code_pc() to
> request a retranslation of the TB with extra info to allow
> us to do a host-PC-to-guest-PC lookup
>  * Note that gen_intermediate_code_pc() overwrites the generated
> code that already exists in memory, and stops as soon as it
> reaches the point of the exception. This is harmless because
> we are just rewriting the same bytes to memory that were there
> already, but disastrous if...
>
>
> in the case you described above, which code guarantees that the
> re-generated code is laid down in the place where the old code is.
> This has to be do somewhere in tcg.
>
>
> Xin
>
>
> On Wed, Jan 25, 2012 at 1:58 PM, Xin Tong <xerox.time.tech@gmail.com> wrote:
>> I am working on extending coremu (parallel version of qemu).
>> Currently, the code cache in coremu is private, I am working towards
>> to make it shared by all cores. I think the add_tb_jump may not be
>> atomic.
>>
>> Thanks
>>
>> Xin
>>
>> On Wed, Jan 25, 2012 at 11:22 AM, Peter Maydell
>> <peter.maydell@linaro.org> wrote:
>>> On 25 January 2012 15:55, Xin Tong <xerox.time.tech@gmail.com> wrote:
>>>> The segfault is caused by jumping to the middle of an instruction. so
>>>> i want to know which TB jumps here.
>>>
>>> (a) Assuming it doesn't take too long to get there, you should
>>> be able to get this information by turning on the debug log
>>> via -d whatever. If it does take too long to get to the crash,
>>> you can use the savevm/loadvm support to save the VM state
>>> at some point slightly before the crash. Then you can run
>>> with the debug log enabled and '-loadvm tag' to start from the
>>> point when you saved the VM state. [disclaimer: depending on the
>>> guest machine you're emulating you might be unlucky and need to
>>> fix save/load first, but that's a worthwhile thing anyway :-)]
>>>
>>> (b) Might not be what you're seeing, but there's a class of bug that
>>> can look like a jump to the middle of an instruction that happens
>>> when:
>>>  * step 1: we generate code for a TB
>>>  * a load or store within that TB causes an exception
>>>  * to get CPUState in sync with the point of the exception
>>>   (and in particular to translate the host PC at the exception
>>>   into the guest PC at that point) we call cpu_restore_state()
>>>  * cpu_restore_state() calls gen_intermediate_code_pc() to
>>>   request a retranslation of the TB with extra info to allow
>>>   us to do a host-PC-to-guest-PC lookup
>>>  * Note that gen_intermediate_code_pc() overwrites the generated
>>>   code that already exists in memory, and stops as soon as it
>>>   reaches the point of the exception. This is harmless because
>>>   we are just rewriting the same bytes to memory that were there
>>>   already, but disastrous if...
>>>  * ...due to a bug, gen_intermediate_code_pc() generates different
>>>   code to that generated back in step 1; this tends to result
>>>   in writing half an instruction at the point where it stops
>>>  * subsequent attempts to execute that TB tend to result in
>>>   weird crashes, often looking like an attempt to jump into
>>>   the middle of an instruction
>>>
>>> This is why it's critical that gen_intermediate_code()+TCG always
>>> deterministically generates exactly the same native code every
>>> time.
>>>
>>> -- PMM
>

cpu_restore_state of translate-all.c.

j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr);

Maybe I don't understand your question.

-Jim

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 19:18                 ` James Greensky
@ 2012-01-25 19:19                   ` Xin Tong
  0 siblings, 0 replies; 16+ messages in thread
From: Xin Tong @ 2012-01-25 19:19 UTC (permalink / raw)
  To: James Greensky; +Cc: qemu-devel

you understood it correctly, I saw the code just after i sent out the email.

Thanks

Xin


On Wed, Jan 25, 2012 at 2:18 PM, James Greensky <gsky51@gmail.com> wrote:
> On Wed, Jan 25, 2012 at 11:10 AM, Xin Tong <xerox.time.tech@gmail.com> wrote:
>> cpu_restore_state() calls gen_intermediate_code_pc() to
>> request a retranslation of the TB with extra info to allow
>> us to do a host-PC-to-guest-PC lookup
>>  * Note that gen_intermediate_code_pc() overwrites the generated
>> code that already exists in memory, and stops as soon as it
>> reaches the point of the exception. This is harmless because
>> we are just rewriting the same bytes to memory that were there
>> already, but disastrous if...
>>
>>
>> in the case you described above, which code guarantees that the
>> re-generated code is laid down in the place where the old code is.
>> This has to be do somewhere in tcg.
>>
>>
>> Xin
>>
>>
>> On Wed, Jan 25, 2012 at 1:58 PM, Xin Tong <xerox.time.tech@gmail.com> wrote:
>>> I am working on extending coremu (parallel version of qemu).
>>> Currently, the code cache in coremu is private, I am working towards
>>> to make it shared by all cores. I think the add_tb_jump may not be
>>> atomic.
>>>
>>> Thanks
>>>
>>> Xin
>>>
>>> On Wed, Jan 25, 2012 at 11:22 AM, Peter Maydell
>>> <peter.maydell@linaro.org> wrote:
>>>> On 25 January 2012 15:55, Xin Tong <xerox.time.tech@gmail.com> wrote:
>>>>> The segfault is caused by jumping to the middle of an instruction. so
>>>>> i want to know which TB jumps here.
>>>>
>>>> (a) Assuming it doesn't take too long to get there, you should
>>>> be able to get this information by turning on the debug log
>>>> via -d whatever. If it does take too long to get to the crash,
>>>> you can use the savevm/loadvm support to save the VM state
>>>> at some point slightly before the crash. Then you can run
>>>> with the debug log enabled and '-loadvm tag' to start from the
>>>> point when you saved the VM state. [disclaimer: depending on the
>>>> guest machine you're emulating you might be unlucky and need to
>>>> fix save/load first, but that's a worthwhile thing anyway :-)]
>>>>
>>>> (b) Might not be what you're seeing, but there's a class of bug that
>>>> can look like a jump to the middle of an instruction that happens
>>>> when:
>>>>  * step 1: we generate code for a TB
>>>>  * a load or store within that TB causes an exception
>>>>  * to get CPUState in sync with the point of the exception
>>>>   (and in particular to translate the host PC at the exception
>>>>   into the guest PC at that point) we call cpu_restore_state()
>>>>  * cpu_restore_state() calls gen_intermediate_code_pc() to
>>>>   request a retranslation of the TB with extra info to allow
>>>>   us to do a host-PC-to-guest-PC lookup
>>>>  * Note that gen_intermediate_code_pc() overwrites the generated
>>>>   code that already exists in memory, and stops as soon as it
>>>>   reaches the point of the exception. This is harmless because
>>>>   we are just rewriting the same bytes to memory that were there
>>>>   already, but disastrous if...
>>>>  * ...due to a bug, gen_intermediate_code_pc() generates different
>>>>   code to that generated back in step 1; this tends to result
>>>>   in writing half an instruction at the point where it stops
>>>>  * subsequent attempts to execute that TB tend to result in
>>>>   weird crashes, often looking like an attempt to jump into
>>>>   the middle of an instruction
>>>>
>>>> This is why it's critical that gen_intermediate_code()+TCG always
>>>> deterministically generates exactly the same native code every
>>>> time.
>>>>
>>>> -- PMM
>>
>
> cpu_restore_state of translate-all.c.
>
> j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr);
>
> Maybe I don't understand your question.
>
> -Jim

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 19:10               ` Xin Tong
  2012-01-25 19:18                 ` James Greensky
@ 2012-01-25 19:23                 ` Peter Maydell
  2012-01-25 19:25                   ` Xin Tong
  1 sibling, 1 reply; 16+ messages in thread
From: Peter Maydell @ 2012-01-25 19:23 UTC (permalink / raw)
  To: Xin Tong; +Cc: qemu-devel

On 25 January 2012 19:10, Xin Tong <xerox.time.tech@gmail.com> wrote:
Peter Maydell wrote:
>> cpu_restore_state() calls gen_intermediate_code_pc() to
>> request a retranslation of the TB with extra info to allow
>> us to do a host-PC-to-guest-PC lookup
>>  * Note that gen_intermediate_code_pc() overwrites the generated
>> code that already exists in memory, and stops as soon as it
>> reaches the point of the exception. This is harmless because
>> we are just rewriting the same bytes to memory that were there
>> already, but disastrous if...

> in the case you described above, which code guarantees that the
> re-generated code is laid down in the place where the old code is.
> This has to be do somewhere in tcg.

Actually, it's not in TCG but in the bit of QEMU which calls TCG.

When we first translate a block of code we decide where its
generated code will sit (in exec.c:tb_gen_code()) and set tb->tc_ptr
to point at this location. Then when translate-all.c:cpu_gen_code()
does this first translation it passes tcg_gen_code() a gen_code_buf
argument which is this tb->tc_ptr.
Later if we need to do a restore, translate-all.c:cpu_restore_state()
calls tcg_gen_code_search_pc(), and again it passes a gen_code_buf
argument for where generated code should be written. It uses tb->tc_ptr
for the TranslationBlock, so it will always be at the same place.

-- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 19:23                 ` Peter Maydell
@ 2012-01-25 19:25                   ` Xin Tong
  2012-01-25 19:33                     ` Peter Maydell
  0 siblings, 1 reply; 16+ messages in thread
From: Xin Tong @ 2012-01-25 19:25 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

as I mentioned. In my current implementation of coremu, the code could
be executed when it is modified. so the modifications need to be
atomic. I think I need a scratch area in which the restore_cpu_state
needs to be generated while leaving the already generated code in
tact. would this solve the problem ?

Thanks

Xin


On Wed, Jan 25, 2012 at 2:23 PM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 25 January 2012 19:10, Xin Tong <xerox.time.tech@gmail.com> wrote:
> Peter Maydell wrote:
>>> cpu_restore_state() calls gen_intermediate_code_pc() to
>>> request a retranslation of the TB with extra info to allow
>>> us to do a host-PC-to-guest-PC lookup
>>>  * Note that gen_intermediate_code_pc() overwrites the generated
>>> code that already exists in memory, and stops as soon as it
>>> reaches the point of the exception. This is harmless because
>>> we are just rewriting the same bytes to memory that were there
>>> already, but disastrous if...
>
>> in the case you described above, which code guarantees that the
>> re-generated code is laid down in the place where the old code is.
>> This has to be do somewhere in tcg.
>
> Actually, it's not in TCG but in the bit of QEMU which calls TCG.
>
> When we first translate a block of code we decide where its
> generated code will sit (in exec.c:tb_gen_code()) and set tb->tc_ptr
> to point at this location. Then when translate-all.c:cpu_gen_code()
> does this first translation it passes tcg_gen_code() a gen_code_buf
> argument which is this tb->tc_ptr.
> Later if we need to do a restore, translate-all.c:cpu_restore_state()
> calls tcg_gen_code_search_pc(), and again it passes a gen_code_buf
> argument for where generated code should be written. It uses tb->tc_ptr
> for the TranslationBlock, so it will always be at the same place.
>
> -- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 19:25                   ` Xin Tong
@ 2012-01-25 19:33                     ` Peter Maydell
  0 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2012-01-25 19:33 UTC (permalink / raw)
  To: Xin Tong; +Cc: qemu-devel

On 25 January 2012 19:25, Xin Tong <xerox.time.tech@gmail.com> wrote:
> as I mentioned. In my current implementation of coremu, the code could
> be executed when it is modified. so the modifications need to be
> atomic. I think I need a scratch area in which the restore_cpu_state
> needs to be generated while leaving the already generated code in
> tact. would this solve the problem ?

No, the code must be regenerated at the same absolute address,
because the TCG code generation routines might otherwise produce
different (different size!) output. Consider the case of a jump
instruction, where for example on x86 we might generate a short
or a longer instruction depending on how far the target was from
where we were writing the code.

It should be entirely fine to have code being executed while it
is being "modified", because the cpu_restore_state can only ever
write exactly identical bytes to memory that were there to start
with, so there will never be an issue with a core executing code
finding half an instruction, or with icache/dcache incoherence
on architectures which need explicit cache maintenance (ie non-x86).

-- PMM

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

* Re: [Qemu-devel] TCG register allocator
  2012-01-25 18:58             ` Xin Tong
  2012-01-25 19:10               ` Xin Tong
@ 2012-01-31  3:09               ` 陳韋任
  1 sibling, 0 replies; 16+ messages in thread
From: 陳韋任 @ 2012-01-31  3:09 UTC (permalink / raw)
  To: Xin Tong; +Cc: Peter Maydell, qemu-devel

On Wed, Jan 25, 2012 at 01:58:10PM -0500, Xin Tong wrote:
> I am working on extending coremu (parallel version of qemu).
> Currently, the code cache in coremu is private, I am working towards
> to make it shared by all cores. I think the add_tb_jump may not be
> atomic.

  If you're talking about [1], maybe you can seek for help on their mailing list
too.

[1] http://sourceforge.net/p/coremu/home/Home/

Regards,
chenwj

-- 
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj

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

end of thread, other threads:[~2012-01-31  3:09 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-25 14:24 [Qemu-devel] TCG register allocator Xin Tong
2012-01-25 15:19 ` Peter Maydell
2012-01-25 15:42   ` Xin Tong
2012-01-25 15:49     ` Peter Maydell
2012-01-25 15:54       ` Xin Tong
2012-01-25 15:55         ` Xin Tong
2012-01-25 16:22           ` Peter Maydell
2012-01-25 18:58             ` Xin Tong
2012-01-25 19:10               ` Xin Tong
2012-01-25 19:18                 ` James Greensky
2012-01-25 19:19                   ` Xin Tong
2012-01-25 19:23                 ` Peter Maydell
2012-01-25 19:25                   ` Xin Tong
2012-01-25 19:33                     ` Peter Maydell
2012-01-31  3:09               ` 陳韋任
2012-01-25 16:03         ` Max Filippov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.