《一日二十四挨踢www.1024it.net》站文章在未特殊说明下默认为原创性文章。
在未有正式书面授权情况下,请勿转载。谢谢配合
学习qemu已经有半个月了,有了一点小想法,在这里做个小记录。
首先要说的是一个很经典的流程图,也许有很多人提到了这个,这里再次重复一下:
这里分两部分:
前端————>把guest code(这里也称作target code) 转换成TCG IR(这里也称作TCG-ops,这是一种独立于具体机器的中间代码);
后端————>利用TCG把TCG IR转换成host上能够运行的主机代码。
接着要说的就是QEMU中主要的代码了,先来一个截图吧(来自Qemu Detailed Study: 7 Chapter http://download.csdn.net/detail/ningxialieri/5323458)
vl.c ————>qemu的main函数就存在于此文件中,虚拟机是在这里建立,cpu的执行也是从此处开始的。也可以是说,这里包含了虚拟机的初始化过程。特别要说的一点是,main_loop()也存在于此文件中,虚拟机的转换是在这个循环中进行调用的。
target-xyz/translate.c————>此文件主要是用于提取guest的代码片段,进而转换成为与架构无关的 TCG IR。需要提出的一点是,转换过程中的单位元是一个TB,也就是说,一个TB转换执行结束后,才能轮到下一个TB。
tcg/tcg.c————>此文件包含了 TCG 的主要代码。TCG作为一个后端转换器,拥有自己的寄存器、操作指令、操作数等。
tcg/xyz/tcg-target.c————>此文件用来把TCG IR转换成为host 的code,它会调用tcg.c里面的函数。
cpu-exec.c————>在文件cpu-exec.c 里面的函数cpu-exec()会调用函数tb_find_fast()在code buffer中查找下一个TB(注意,这里的TB指的是已经翻译成host相关的TB,要与guest所对应的TB加以区分),如果找到了,就会调用tcg_qemu_tb_exec()来在host上执行。如果没有找到,就会调用tb_find_slow()来生成host对应的TB,这里的生成,就是指,由gues的TB经TCG转化生成能在host运行的TB,最后调用tcg_qemu_tb_exec()来在host上执行。
换个思路来说吧,我们可以把qemu分为两部分,一部分是转换(就是前面提到的,由guest的TB转换为host的TB,并且把host的TB放到code buffer中,注意:buffer中的TB会根据需要进行更新),第二部分就是执行,即,最终会用函数tcg_qemu_tb_exec()来执行,在此函数中,会在code buffer中查找host的tb,然后来执行。转换和执行的两个过程是使用中断进行切换的。
关于几个重要全局变量的定义和调用:
在 ./translate-all.c:141行,有TCGContext tcg_ctx;——————>在这里定义了全局变量tcg_ctx。
在 tcg/tcg.h:473行,有 extern TCGContext tcg_ctx;——————>在这里引入外部变量tcg_ctx。
在tcg/tcg-op.h中大量引用了变量tcg_ctx,并且,在文件开始包含了#include "tcg.h"。综上所述,tcg_ctx可以作为一个外部变量,在所有包含头文件#include "tcg.h的所有文件中调用。
这里加入一部分博主翻译内容,以便加深理解(原文来自:Qemu Detailed Study: 7 Chapter):
QEMU的作用就是,提取客户代码,然后转换成主机代码。整个转换过程由两部分组成:首先,Target Code的代码块(TB)被转换成TCG-ops(独立于机器的中间代码),第二步,就是用HOST 架构对应的TCG,把由TB生成的TCG-ops转换成Host Code。这个的优化过程在这两个步骤的中间完成。
当前,在QEMU中可以模拟的处理器架构有: Alpha, ARM, Cris,i386, M68K, PPC, Sparc, Mips, MicroBlaze, S390X and SH4。这些架构的处理器对应的/target -xyz/下的code,把TBs转换成TCG-ops,这里的xyz就是上面所说的架构名。因此,arm对应的code可以在/target-arm/下面找到。这部分可以被称为TCG前端。
主机端用/tcg/下的code把TCG-ops生成主机能运行的代码,这部分被称为TCG的后端。
在代码执行前,编译器要把源代码生成目标代码。为了将一个函数调用生成目标代码,编译器(如gcc)会产生一些特殊的代码,这些特殊代码应用在函数调用前和函数返回前。这些特殊代码被称为 Function Prologue 和 Epilogue。(本人认为,就是函数调用前的进栈和出栈处理)。
众所周知,TCG使用的是动态转换(Dynamic Translation)技术。所谓动态转换,就是在需要的时候才转换code。目的是,把大部分时间花费在执行生成的代码上。每次由TB块生成的code在被执行之前,都会被存在code cache中。大多数的时候,相同的TBs会被多次执行,因此从cache中调用是最好的方式,而不重新生成。一旦code cache被填满了,所有的code cache将被清空。
qemu中target意义的分析:
In qemu, there are two different meanings of target. The first meaning of ‘target’ means the emulated target machine architecture. For example, when emulating mips machine on x86, the target is mips and host is x86. However, in tcg(tiny code generator), target has a different meaning. It means the generated binary architecture. In the example of emulating mips on x86, in tcg the target means x86 because tcg will generate x86 binary.