摘要:
分析下Qemu的内部结构,qemu大概是一个使用原始便携动态翻译器的快速机器仿真工具,。它能在很多机器上(x86, ARM PowerPC, Sparc….) 仿真CPU (x86, ARM,PowerPC, Sparc),QEMU支持完整的系统仿真,可以在虚拟机和Linux用户模式下仿真完整的操作系统,同时编译完成后的仿真操作系统可以运行在不同cpu上。
QEMU是一个机器仿真器:仿真器可以运行在一个正常的操作系统下(比如Windows或者Linux),也可以运行在一个虚拟机里。QEMU本身肯定也可以跑在不同的操作系统上,比如Linux, Windows和Mac OS X。以及不同的物理硬件,比如主机型号和CPU可以不同。
QEMU的主要用法是在一个操作系统里运行另一个操作系统,比如Windows上跑Linux,或者Linux上跑Windows。另一种用法是调试,因为虚拟机很容易就突然停止,所以需要检查,保存和恢复其状态。另外,也可以模拟新的设备,通过这些模拟的设备来测试程序。
QEMU还集成了Linux专用的用户模式仿真器。 它是机器仿真器的一个子集,这个进程可以跑在模拟的CPU上也可以跑在物理CPU上。它主要用于测试交叉编译器的结果或测试CPU仿真器,而无需启动完整的虚拟机。
QEMU由以下子系统组成:
本文将探讨QEMU的动态翻译器的实现。 动态转换器执行VCPU指令到Host指令集的运行时转换。 所得到的二进制代码存储在翻译缓存中,以便可以重用它。 与解释器相比的优点是目标指令仅被取出和解码一次。
通常,动态翻译器难以从一个主机端口传输到另一个主机,因为整个代码生成器必须被重写。它代表与向C编译器添加更多相同的代码。 QEMU简单得多,因为它只是连接了由GNU C编译器在线生成的机器代码
CPU模拟器也面临其他更经典但是困难的问题:
第一步是将每个目标CPU指令分成更简单的简单指令,称为微操作。每个微操作都由一小段C代码实现。这个小C代码由GCC编译为一个对象文件。微操作的选择会使得它们的数量比VCPU的指令和操作数的所有组合小得多(通常是几百个)。从VCPU指令到微操作的转换完全是用代码来完成的(软件的方式)。源代码针对可读性和紧凑性进行了优化,因为此阶段的速度与解释器相比不太重要。
编译时工具dyngen使用包含微操作的对象文件作为输入来生成动态代码生成器。这个动态代码生成器在运行时被调用以产生一个连接几个微操作的完整主机功能。
在编译时要做更多的工作来获得更好的性能。特别地,一个关键思想是在QEMU中可以给定常数参数进行微操作。为此,为每个常量参数使用GCC生成虚拟代码重定位。这使得dyngen工具能够定位重定位,并在生成动态代码时生成适当的C代码来解决这些错误。还支持重定位,以便在微操作中引用静态数据和其他功能。
假设我们要仿真PowerPC,宿主机host为x86,下面说明整个翻译过程:
在x86上 T0匹配ebx寄存器,cpu状态的上下文信息保存在ebp寄存器上
dyngen是QEMU翻译的关键。在包含微操作的对象文件上运行时执行以下任务:
当编译微操作代码时,使用一组GCC标志来将功能序言和结尾码的生成操作为易于解析的形式。 虚拟组装宏强制GCC通过单个返回指令总是终止与每个微操作相对应的功能。 如果在单个微操作中产生几个返回指令,则代码级联将不起作用。
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删