1. qemu运用动态翻译的技术将guest binary instructions动态翻译成host binary instructions,之后由host运行翻译后的指令。在qemu-0.9之前的版本都采用dyngen的动态翻译技术,而从qemu-0.10开始的版本开始采用TCG(Tiny  Code Generator)的翻译技术。

  2. TBs ( Translated Blocks )

    Qemu将TB定义为碰到下一个jump指令或修改CPU state的指令之前的所有代码称为一个TB。

  3. 动态翻译的基本思想就是把每一条Target指令切分成为若干条微指令,每条微指令由一段简单的C代码来实现,运行时通过一个动态代码生成器把这些微指令组合成一个函数,最后执行这个函数,就相当于执行了一条Target指令

  4. 从QEMU-0.10.0开始,TCG成为QEMU新的翻译引擎.

    TCG的全称为“Tiny Code Generator”, 主要负责分析、优化Target代码以及生成Host代码

    Target指令 ----> TCG ----> Host指令

  5. 多数CPU指令不外乎以下几大类:数据传送、算术运算、逻辑运算、程序控制;

    例如,数据传送包括:传送指令(如MOV)、堆栈操作(PUSH、POP)等

                程序控制包括:函数调用(CALL)、转移指令(JMP)等;

    基于此,TCG就把微指令按以上几大类定义(见tcg/i386/tcg-target.c)

  6. TCG在生成目标指令的过程中是采用硬编码的,因此,要让TCG运行在不同的Host平台上,就必须为不同的平台编写微操作函数.

  7. QEMU维护着一个称为 CPUState 的数据结构,这个结构包括了Target机CPU的所有寄存器,像EAX,EBP,ESP,CS,EIP,EFLAGS等。它总是代表着Target机的当前状态

    用变量env来表示 CPUState 结构,则QEMU每次解析Target指令时,总是以 env.cs+env.eip 为开始地址的。 

    eg: typedef struct CPUX86State {...} in target-i386/cpu.h

  8. TCG翻译流程

    guest binary instructions -> TCG IR(intermediate representation) -> host binary instructions 

    TCG IR大致可以分为以下几类:

    - Mov类操作: mov, movi, ...

    - 逻辑操作: and, or, xor, shl, shr, ...

    - 算术操作: add, sub, mul, div, ...

    - 分支跳转操作: jmp, br, brcond

    - 函数调用: call - 内存操作: ld, st

    - QEMU的特殊操作: tb_exit, goto_tb, qemu_ld/qemu_st

    每条TCG指令的具体用法,参见qemu源码tcg/readme。

    在qemu源码中,target-ARCH/* 定义了如何将guest binary instructions 反汇编成 TCG IR,tcg/ARCH 定义了如何將 TCG IR 翻译成 host binary instructions。

  9. Starting from QEMU 1.0, all emulated CPUs run in a single thread.

  10. QEMU的main函数定义在/vl.c中,它也是执行的起点,这个函数的功能主要是建立一个虚拟的硬件环境.

  11. 所有的硬件设备都在/hw/ 目录下面,所有的设备都有独自的文件,包括总线,串口,网卡,鼠标等等。它们通过设备模块串在一起,在vl.c中的machine _init中初始化。

  12. /target-arch/目录就对应了相应架构(Guest)的代码,如/target-i386/就对应了x86系列的代码部分。虽然不同架构做法不同,但是都是为了实现将对应客户机CPU架构的TBs转化成TCG的中间代码。这个就是TCG的前半部分.

  13. 使用TCG代码生成主机的代码在/tcg/里面,在这个目录里面也对应了不同的架构(Host),分别在不同的子目录里面,如i386就在/tcg/i386中。整个生成主机代码的过程也可以称为TCG的后半部分。

  14. /vl.c                                   最主要的模拟循环,虚拟机机器环境初始化,和CPU的执行。

    /target-arch/translate.c   将客户机代码转化成不同架构的TCG操作码。

    /tcg/tcg.c                           主要的TCG代码。

    /tcg/arch/tcg-target.c       将TCG代码转化生成主机代码

    /cpu-exec.c                      其中的cpu-exec()函数主要寻找下一个TB(翻译代码块),如果没找到就请求得到下一个TB,并且操作生成的代码块。

  15. 在QEMU中,从代码cache到静态代码再回到代码cache,这个过程比较耗时,所以在QEMU中涉及了一个TB链将所有TB连在一起,可以让一个TB执行完以后直接跳到下一个TB,而不用每次都返回到静态代码部分。

    cpu_exex() --> prologue --> TB1 --> ... --> TBn --> Epilogue --> cpu_exex()