QEMU 用戶模式(User Mode)流程及源碼分析 (三)
??
TCG中間碼生成完畢后,由tcg_gen_code函數(shù)負責將 TCG 中間碼翻譯為 HOST 平臺代碼,這里以 GUEST 端為 x86_64, HOST 端為 ARM64 為例。
tcg_gen_code
tcg_gen_code的實現(xiàn)位于tcg/tcg.c文件內(nèi),總共有2個參數(shù),類型分別是TCGContext和TranslationBlock。其中TranslationBlock類型參數(shù)tb主要是用來表示翻譯的代碼存儲的位置,該位置是tb->tc.ptr,之后會將其值賦給TCGContext類型參數(shù)s的成員變量code_buf保存,參數(shù)tb在翻譯過程中的使命就結(jié)束了,TCGContext類型參數(shù)s貫穿整個翻譯流程。 TCGContext內(nèi)存儲TCG中間碼,參數(shù)s內(nèi)的ops即為存儲的每條TCG中間碼,通過遍歷每條中間碼,并根據(jù)HOST端類型翻譯成本機指令,并寫入到code_buf內(nèi)。
中間碼翻譯示例
GUEST端為x86_64時,存儲CPU狀態(tài)的結(jié)構(gòu)體類型為CPUX86State,在翻譯的HOST代碼中,存儲CPU狀態(tài)的結(jié)構(gòu)體指針地址值會存入指定寄存器。該寄存器由HOST端決定,例如,當HOST端為x86_64時,該寄存器為rbx;當HOST端為ARM64時,該寄存器為x19。以此來建立GUEST端和HOST端寄存器的映射。 例如,GUEST端為x86_64時,eip寄存器對應(yīng)的eip成員變量在CPUX86State結(jié)構(gòu)體的偏移為sizeof(target_ulong[CPU_NB_REGS])=108,那么當HOST端為ARM64時,eip被翻譯為[x19, #108];當HOST為x86_64時,eip被翻譯為108(%rbx)。
為了優(yōu)化翻譯的代碼,避免不必要的內(nèi)存讀取,每個代碼塊內(nèi),當且僅當GUEST寄存器在首次訪問和被同步時,才按照上述方式翻譯,并將值從內(nèi)存中加載進HOST端某個空閑寄存器,并建立該GUEST端寄存器與HOST端某個空閑寄存器的映射。例如,如下代碼中,rcx在CPUX86State的偏移為8,那么GUEST端代碼
被翻譯到ARM64的HOST端時,可能為
對于上一章提到的tcg中間碼
在HOST端為ARM64時,翻譯結(jié)果為