[hellogcc] Re: [投稿] QEMU Internal - Block Chaining 1/3

  • From: 陳韋任 <chenwj@xxxxxxxxxxxxxx>
  • To: hellogcc@xxxxxxxxxxxxx
  • Date: Mon, 3 Oct 2011 12:10:33 +0800

> > translation block 執行完後,它的跳躍目標確定且該跳躍目標也已經
> > 在 code cache 裡,那我們就把這兩個 translation block 串接起來。
> > 這個就叫做 block chaining/linking。
> > 
> 
> 这个在qemu是能控制的吗? block chaining/linking 可以打开或者关闭吗?

  是可以控制的。:-)

  QEMU 在生成 TCG IR 的時候,有考慮到 block chaining。所以在之後,一但
確定 tb1 下一個 block,tb2,在 code cache 的位址,QEMU 就會 patch 在
code cache 中的 tb1 其 jmp 指令的 address,這樣 tb1 一執行完就會直接跳
到 tb2 執行。

  struct TranslationBlock 裡的欄位 jmp_first 和 jmp_next 就是用來記錄整個
在 code cache 中 block chaining 的情況,這是用來以後做 block unchaining
之用,也就是你所說的關閉。

  我之後再來講 block unchaining。:-)
 
> > // 一般是這樣呼叫: tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
> > // 注意! 請留意其參數: (tcg_target_long)tb + tb_num。
> > static inline void tcg_gen_exit_tb(tcg_target_long val)
> > {
> >     // 將 INDEX_op_exit_tb 寫入 gen_opc_buf; val 寫入 gen_opparam_buf。
> >     tcg_gen_op1i(INDEX_op_exit_tb, val);
> > }
> > 
> 
> 不管是否支持block chaining/linking,这里应该都是这样吧。

  不太能這麼說。你看一下 cpu_exec 內層迴圈。

    if (next_tb != 0 && tb->page_addr[1] == -1) {
        // 這邊利用 TranlationBlock 指針的最低有效位後兩位指引 block
        // chaining 的方向。
        // next_tb -> tb
        tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
    }

    // 這邊要注意到,QEMU 利用 TranslatonBlock 指針後兩位必為零的結果
    // 做了一些手腳。QEMU 將其末兩位編碼成 0、1 或 2 來指引 block chaing
    // 的方向。這種技巧在 QEMU 用得非常嫻熟。
    next_tb = tcg_qemu_tb_exec(tc_ptr);

  tcg_gen_exit_tb 的參數 val,就是 tcg_qemu_tb_exec 的返回值 next_tb。這
val 是給 block chaining 用的,看一下 tb_add_jump。

  如果不做 block chaining,那直接返回 QEMU 就好,應該不需要返回什麼參數。
只需在返回之前,更新 env->eip。這樣從 code cache 回到 QEMU 之後,tb_find_fast
就會看 env->eip 是否已被翻譯過。
 
> >     case INDEX_op_exit_tb:
> >         // QEMU 把跳至 code cache 執行當作是函式呼叫,EAX 存放返回值。
> >         // 將 val 寫進 EAX,val 是 (tcg_target_long)tb + tb_num。 
> >         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
> > 
> 
> 这里相当于生成了这样一条指令 mov eax, #(tcg_target_long)tb + tb_num ?

  沒錯。
 
> >         // e9 是 jmp 指令,後面的 operand 為相對偏移量,將會加上 eip。
> >         // 底下兩條的總和效果是跳回 code_gen_prologue 中 prologue 以後的位置。
> >         tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
> 
> 这里可以多介绍一下jmp指令,可能跟好理解。jmp指令一共五个字节,第一个字节是opcode,
> 应该就是 e9,这里生成一个字节的opcode
> 
> >         // tb_ret_addr 在 tcg_target_qemu_prologue 初始成指向 code_gen_prologue
> >         // 中 prologue 以後的位置。
> >         // 生成 host binary 的同時,s->code_ptr 會移向下一個 code buffer 的位址。
> >         // 所以要減去 4。
> >         tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
> 
> 然后生成跳转地址偏移 tb_ret_addr - s->code_ptr - 4,所以就是这样一条指令
> 
>   jmp (tb_ret_addr - s->code_ptr - 4)
> 
> 这个 - 4 我不是和明白,是因为上边那条 mov eax, #((tcg_target_long)tb +
> tb_num),所以 - 4 吗?

  說實在話,我對 x86 ISA 不很熟,慚愧。我想是生成 host binary 的同時,s->code_ptr會
移向下一個 code buffer 的位址,所以要減去 4。
 
> 这里想到于生成了这样的两个指令
> 
> 
>    mov eax, #(tcg_target_long)tb + tb_num
>    jmp (tb_ret_addr - s->code_ptr - 4)
> 
> jmp过去以后,eax的值有什么用吗? 

  QEMU 將跳至 code cache 執行視為一個函式呼叫。code cache 是 function
body。那 function prologue/epilogue 在哪? 在 code_gen_prologue 裡面,
你可以回去參考一下 QEMU Internal - Tiny Code Generator (TCG) 1/2。
code cache -> code_gen_prologue -> QEMU (tcg_qemu_tb_exec)。我想那邊
就是把 eax 上的內容當作返回值。
 
> >         break;
> > }
> > 
> >   o tcg_out_movi 將 arg 移至 ret 代表的暫存器。
> >
> 
> 这个有什么用吗?

  這你得和上面一起看。:-) 這代表從 code cache 返回 QEMU 的時候,以哪一個
暫存器存放返回值。 
  
> > static inline void tcg_out_movi(TCGContext *s, TCGType type,
> >                                 int ret, int32_t arg)
> > {
> >     if (arg == 0) {
> >         /* xor r0,r0 */
> >         tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret);
> >     } else {
> >         // move arg 至 ret
> >         tcg_out8(s, 0xb8 + ret); // 0xb8 為 move,ret 代表目地暫存器。0xb8 + ret 合成一個 
> > opcode。
> 
> 这里是不是  0xb8 | ret 更好理解一些?

  我們來看一下 tcg_out8 的 prototype。

    static inline void tcg_out8(TCGContext *s, uint8_t v);

應該用 0xb8 + ret。當然以 binary 理解的話,確實是 0xb8 | ret。
 
> >         tcg_out32(s, arg);
> >     }
> > }
> > 
> 
> -- 
> Yao Qi <qiyaoltc AT gmail DOT com>
> 
> If two people love each other, there can be no happy end to it.
>               -- Ernest Hemingway

-- 
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667

Other related posts: