qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] classic emulator Vs QEMU-TCG
@ 2010-12-16 15:20 Stefano Bonifazi
  2010-12-16 15:41 ` Peter Maydell
  2010-12-16 15:57 ` Mulyadi Santosa
  0 siblings, 2 replies; 7+ messages in thread
From: Stefano Bonifazi @ 2010-12-16 15:20 UTC (permalink / raw)
  To: qemu-devel

Hi all!
     I am a student, trying to understand QEMU, specifically TCG 
translation/execution.
After spending much time on the code I still have big doubts. I think my 
doubts are due to the classic idea I have of an emulator.
Actually as a student, I've never developed even a simple classic 
emulator myself, but in my idea it should follow this flow:
1) Fetch target instruction
  i.e. PC(0x532652) : 0x104265 (I am just inventing)
2) Decode
  Opcode 0x10 :  ADD,  R1: 0x42, R2: 0x65
3) Look up instruction function table:
  switch(opcode)
   case add :
    add(R1, R2)
   break;
4) Execution
  void add(int R1, int R2)
  { env->reg[R1] = env->reg[R1] + env[R2];}

Now all of that would be compiled offline for the host machine and at 
runtime the host macine would just execute the binary host code for the 
instruction  "env->reg[R1] = env->reg[R1] + env[R2];" (its host binary 
translation)

In QEMU/TCG, thanks to the help of Mr. Blue Swirl, I understood there is 
a runtime creation of host binary, starting from the loaded target binary..
My big doubt is, how can I execute that new binary? .. Shall TCG put it 
in some memory location, and then make the process branch to that 
address (and then back) ?
I really can't see how that happens in the code :(

in cpu-exec.c : cpu_exec_nocache i find:

> /* execute the generated code */
>     next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
and in cpu-exec.c : cpu_exec

> /* execute the generated code */
>
>                     next_tb = tcg_qemu_tb_exec(tc_ptr);
so I thought tcg_qemu_tb_exec "function" should do the work of executing 
the translated binary in the host.
But then I found out it is just a define in tcg.h:

> #define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void 
> *))code_gen_prologue)(tb_ptr)
and again in exec.c

> uint8_t code_gen_prologue[1024] code_gen_section;
Maybe I have some problems with that C syntax, but I really don't 
understand what happens there.. how the execution happens!

I think for all of you working for so long on QEMU, with a long 
successful experience in this field should be very easy.. but atm I 
really can't figure it out alone.. I can't find good documents 
explaining it, and I can't understand myself from the code!
Thank you very very much for any help! :)
Stefano B.

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

* Re: [Qemu-devel] classic emulator Vs QEMU-TCG
  2010-12-16 15:20 [Qemu-devel] classic emulator Vs QEMU-TCG Stefano Bonifazi
@ 2010-12-16 15:41 ` Peter Maydell
  2010-12-17 13:49   ` Stefano Bonifazi
  2010-12-16 15:57 ` Mulyadi Santosa
  1 sibling, 1 reply; 7+ messages in thread
From: Peter Maydell @ 2010-12-16 15:41 UTC (permalink / raw)
  To: Stefano Bonifazi; +Cc: qemu-devel

On 16 December 2010 15:20, Stefano Bonifazi <stefboombastic@gmail.com> wrote:
> so I thought tcg_qemu_tb_exec "function" should do the work of executing the
> translated binary in the host.
> But then I found out it is just a define in tcg.h:
>
>> #define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void
>> *))code_gen_prologue)(tb_ptr)
>
> and again in exec.c
>
>> uint8_t code_gen_prologue[1024] code_gen_section;
>
> Maybe I have some problems with that C syntax, but I really don't understand
> what happens there.. how the execution happens!

Some hints:
 * go and look up the C syntax for function pointers and
casting things to function pointers
 * code_gen_prologue[] contains code which has been generated
once on startup -- go and find the function which is doing this,
which ought to tell you what the prologue code actually does...
 * try single stepping individual machine instructions in the
debugger as you go through tcg_qemu_tb_exec() and matching
this up with what is really happening here and with the bits of
qemu which generated that code.

-- PMM

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

* Re: [Qemu-devel] classic emulator Vs QEMU-TCG
  2010-12-16 15:20 [Qemu-devel] classic emulator Vs QEMU-TCG Stefano Bonifazi
  2010-12-16 15:41 ` Peter Maydell
@ 2010-12-16 15:57 ` Mulyadi Santosa
  2010-12-17  9:47   ` Stefano Bonifazi
  1 sibling, 1 reply; 7+ messages in thread
From: Mulyadi Santosa @ 2010-12-16 15:57 UTC (permalink / raw)
  To: Stefano Bonifazi; +Cc: qemu-devel

Hi Stefano....

I'll try to share what I know about TCG......

On Thu, Dec 16, 2010 at 22:20, Stefano Bonifazi
<stefboombastic@gmail.com> wrote:
> Actually as a student, I've never developed even a simple classic emulator
> myself,

you're not alone...trust me...... :)

>but in my idea it should follow this flow:
> 1) Fetch target instruction
>  i.e. PC(0x532652) : 0x104265 (I am just inventing)
> 2) Decode
>  Opcode 0x10 :  ADD,  R1: 0x42, R2: 0x65
> 3) Look up instruction function table:
>  switch(opcode)
>  case add :
>   add(R1, R2)
>  break;
> 4) Execution
>  void add(int R1, int R2)
>  { env->reg[R1] = env->reg[R1] + env[R2];}

You're right. Basically, we're taught that emulation is like big giant
"swith..case" with lots of condition. And that's exactly what Bochs
does AFAIK...

The pros of this approach is instruction could be simulated as precise
as possible and we could have more precise control about
timing...however the cons is... as we saw that big case
branching...cache miss could likely happen (in host machine I mean)
and pipeline stalls might happen more.

By doing what Qemu does, be it using the old dyngen or new TCG, we try
to maintain "execution fluidity" by interpreting instruction as less
as possible and strings together  the already translated blocks ...
And don't forget that Qemu sometimes does things like lazy flags
update, somewhat simple dead code elimination and so on. More like
tiny compiler...right?

> Now all of that would be compiled offline for the host machine and at
> runtime the host macine would just execute the binary host code for the
> instruction  "env->reg[R1] = env->reg[R1] + env[R2];" (its host binary
> translation)
>
> My big doubt is, how can I execute that new binary? .. Shall TCG put it in
> some memory location, and then make the process branch to that address (and
> then back) ?
> I really can't see how that happens in the code :(
>
> in cpu-exec.c : cpu_exec_nocache i find:
>
>> /* execute the generated code */
>>    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
>
> and in cpu-exec.c : cpu_exec
>
>> /* execute the generated code */
>>
>>                    next_tb = tcg_qemu_tb_exec(tc_ptr);
>
> so I thought tcg_qemu_tb_exec "function" should do the work of executing the
> translated binary in the host.
> But then I found out it is just a define in tcg.h:
>
>> #define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void
>> *))code_gen_prologue)(tb_ptr)
>
> and again in exec.c
>
>> uint8_t code_gen_prologue[1024] code_gen_section;
>
> Maybe I have some problems with that C syntax, but I really don't understand
> what happens there.. how the execution happens!

With my limited C knowledge, I saw that as a instruction jump (to
tb_ptr). The "code_gen_prologue" seems to me like a cast..... casting
each opcode in tb_ptr as uint8_t.... with maximum length=1024

I hope that's the right interpretation...I must admit Qemu is full of
gcc and C tricks here and there...


-- 
regards,

Mulyadi Santosa
Freelance Linux trainer and consultant

blog: the-hydra.blogspot.com
training: mulyaditraining.blogspot.com

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

* Re: [Qemu-devel] classic emulator Vs QEMU-TCG
  2010-12-16 15:57 ` Mulyadi Santosa
@ 2010-12-17  9:47   ` Stefano Bonifazi
  2010-12-17 10:18     ` Mulyadi Santosa
  2010-12-17 13:51     ` Andreas Färber
  0 siblings, 2 replies; 7+ messages in thread
From: Stefano Bonifazi @ 2010-12-17  9:47 UTC (permalink / raw)
  To: Mulyadi Santosa; +Cc: qemu-devel

On 12/16/2010 04:57 PM, Mulyadi Santosa wrote:
> With my limited C knowledge, I saw that as a instruction jump (to
> tb_ptr). The "code_gen_prologue" seems to me like a cast..... casting
> each opcode in tb_ptr as uint8_t.... with maximum length=1024
Hi! Thank you for your reply!

I've got an explanation from a C guru :)

>((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr)
>---------
>(long REGPARM (*)(void *)) is a type: a pointer pointing to a function, which takes one (void*) parameter. code_gen_prologue is an>array, array's name when used is considered to be a pointer to its first element, thus you are casting here pointer to the first byte of>array to pointer to function (...).
>Ellipsis with tb_ptr mean 'call function under this address and pass there whatever tb_ptr is'

Now everything is very clear for me :)
I do know pointer to functions, and if I had got:

>long REGPARM (*myfunc)(void *)

I would have recognized it.. but removing the function pointer name, 
leaving only the * was enough for me to be lost :[
also the definition of code_gen_prologue was tricky:
> uint8_t code_gen_prologue[1024] code_gen_section;
that code_gen_section at first confused my idea of a normal variable 
definition as "type identifier" .. until I found out it was a define for 
a compiler directive (alignment) :[

So inside code_gen_prologue array there is stored some function (in 
binary code) that takes a tb_ptr as argument and returns a long .. I 
have to check what it is inside there for understanding how the 
translated target code is run now ;)

> I hope that's the right interpretation...I must admit Qemu is full of
> gcc and C tricks here and there...
Yes! I've only had some experience in OO programming, really always 
avoided defines and odd compiler directives in my code before..

  Best Regards!
Stefano B.

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

* Re: [Qemu-devel] classic emulator Vs QEMU-TCG
  2010-12-17  9:47   ` Stefano Bonifazi
@ 2010-12-17 10:18     ` Mulyadi Santosa
  2010-12-17 13:51     ` Andreas Färber
  1 sibling, 0 replies; 7+ messages in thread
From: Mulyadi Santosa @ 2010-12-17 10:18 UTC (permalink / raw)
  To: Stefano Bonifazi; +Cc: qemu-devel

On Fri, Dec 17, 2010 at 16:47, Stefano Bonifazi
<stefboombastic@gmail.com> wrote:
> On 12/16/2010 04:57 PM, Mulyadi Santosa wrote:
>>
>> With my limited C knowledge, I saw that as a instruction jump (to
>> tb_ptr). The "code_gen_prologue" seems to me like a cast..... casting
>> each opcode in tb_ptr as uint8_t.... with maximum length=1024
>
> Hi! Thank you for your reply!
>
> I've got an explanation from a C guru :)

Thanks a lot for sharing it.....:) Hopefully your C skill is better now :)

-- 
regards,

Mulyadi Santosa
Freelance Linux trainer and consultant

blog: the-hydra.blogspot.com
training: mulyaditraining.blogspot.com

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

* Re: [Qemu-devel] classic emulator Vs QEMU-TCG
  2010-12-16 15:41 ` Peter Maydell
@ 2010-12-17 13:49   ` Stefano Bonifazi
  0 siblings, 0 replies; 7+ messages in thread
From: Stefano Bonifazi @ 2010-12-17 13:49 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

On 12/16/2010 04:41 PM, Peter Maydell wrote:
> Some hints:
>   * go and look up the C syntax for function pointers and
> casting things to function pointers
Yup! See the reply to Mr. Santosa, thank you!
>   * code_gen_prologue[] contains code which has been generated
> once on startup -- go and find the function which is doing this,
> which ought to tell you what the prologue code actually does...
Is that the following?
> /* init global prologue and epilogue */
>     s->code_buf = code_gen_prologue;
>     s->code_ptr = s->code_buf;
>     tcg_target_qemu_prologue(s);


Trying to understand the pseudo-assembly in tcg_target_qemu_prologue (in 
file tcg-target.c), I think it builds an assembly function scheleton 
storying it inside code_gen_prologue array..
Cosidering the implementation of that function for i386 I think the jmp 
*%eax is the actual code that jumps to the host binary produced by TCG 
from the target binary.. in fact, if I am not wrong,this binary function 
is what is actually called by tcg_qemu_tb_exec(tb_ptr) macro with tb_ptr 
passed to the function in %eax, thus "jmp *%eax" starts the execution of 
the binary code .. am I wrong?

>   * try single stepping individual machine instructions in the
> debugger as you go through tcg_qemu_tb_exec() and matching
> this up with what is really happening here and with the bits of
> qemu which generated that code.
>
> -- PMM
I would have already done that.. unluckily I have always used IDE with 
integrated debuggers, and I can't find an IDE for loading this project.. 
I guess I have no other choice than learning also gdb
Thank you for your tips! :)
Best Regards!
Stefano B.

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

* Re: [Qemu-devel] classic emulator Vs QEMU-TCG
  2010-12-17  9:47   ` Stefano Bonifazi
  2010-12-17 10:18     ` Mulyadi Santosa
@ 2010-12-17 13:51     ` Andreas Färber
  1 sibling, 0 replies; 7+ messages in thread
From: Andreas Färber @ 2010-12-17 13:51 UTC (permalink / raw)
  To: Stefano Bonifazi; +Cc: Mulyadi Santosa, qemu-devel

Hi,

Am 17.12.2010 um 10:47 schrieb Stefano Bonifazi:

> I've got an explanation from a C guru :)
>
>> ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr)
>> ---------
>> (long REGPARM (*)(void *)) is a type: a pointer pointing to a  
>> function, which takes one (void*) parameter. code_gen_prologue is  
>> an>array, array's name when used is considered to be a pointer to  
>> its first element, thus you are casting here pointer to the first  
>> byte of>array to pointer to function (...).
>> Ellipsis with tb_ptr mean 'call function under this address and  
>> pass there whatever tb_ptr is'
>
> Now everything is very clear for me :)
> I do know pointer to functions, and if I had got:
>
>> long REGPARM (*myfunc)(void *)
>
> I would have recognized it.. but removing the function pointer name,  
> leaving only the * was enough for me to be lost :[

Feel free to take the next step then and read CODING_GUIDELINES to  
create and submit your first Git patch to make the code more readable  
for others. Introducing a typedef for the cast might not be a bad idea.

> also the definition of code_gen_prologue was tricky:
>> uint8_t code_gen_prologue[1024] code_gen_section;
> that code_gen_section at first confused my idea of a normal variable  
> definition as "type identifier" .. until I found out it was a define  
> for a compiler directive (alignment) :[

Would capitalizing code_gen_section have helped to recognize it as a  
preprocessor define? Another patch idea. :)

Regards,
Andreas

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

end of thread, other threads:[~2010-12-17 13:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-16 15:20 [Qemu-devel] classic emulator Vs QEMU-TCG Stefano Bonifazi
2010-12-16 15:41 ` Peter Maydell
2010-12-17 13:49   ` Stefano Bonifazi
2010-12-16 15:57 ` Mulyadi Santosa
2010-12-17  9:47   ` Stefano Bonifazi
2010-12-17 10:18     ` Mulyadi Santosa
2010-12-17 13:51     ` Andreas Färber

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