Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1426116
  • 博文数量: 487
  • 博客积分: 161
  • 博客等级: 入伍新兵
  • 技术积分: 5064
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-01 07:37
个人简介

只有偏执狂才能生存

文章分类

全部博文(487)

文章存档

2016年(10)

2015年(111)

2014年(66)

2013年(272)

2012年(28)

分类: LINUX

2013-10-29 23:54:22


OCT 1ST, 2010
QEMU 作为开源界最热门的 Emulator,被广泛的应用在诸如内核调试,跨平台开发等领域。例如现在很火的 Android 上的手机应用开发,就需要用到的基于 QEMU 的 Android Emulator

QEMU Internals

首先介绍一下 QEMU 中访存相关的几个设计,由于接触 QEMU 源代码时间还不长,如有什么疏漏还请各位大牛指正。

TB

TB (Translation Block) 是 QEMU 中指令翻译的基本单位,一般为 Guest Code 中的 Basic Block。如下图所示,Guest Code 通过 QEMU 以 TB 为基本单位动态的翻译并被放入 Translation Cache 中

image

TCG

自 0.9.1 版本之后的 QEMU (0.12.5) 采用了名为 TCG (Tiny Code Genertor) 的机制以实现独立于编译器的动态指令翻译,依照 Guest Code –> TCG Code –> Host Code 的顺序执行翻译流程,如下图所示。

Step 1. 以  TB 为单位读入当前 PC 位置的 Guest Code

image

Step 2. 生成 TCG Code。其中与访存相关的 TCG 指令只有两条:ld 和 st。

image

Step 3. 翻译 TCG Code 为 Host Code。到此就实现了由 Guest 到 Host 的翻译过程,需要注意的是,由 TCG 带来的抽象可以帮助开发人员将 Guest 与 Host 的对应关系分离出来,以提高开发效率。

image

Chain

以 TB 为单位的指令动态翻译和 TB Cache 的应用,为 Translated Code 的重用提供了机会。为了进一步提高性能,需要尽可能的减少 Guest Code 与 QEMU Translation Code 之间的切换。对于 TB Cache 中的 TB,在确定了各 TB 之间的跳转顺序后,可以将各个 TB 链接起来,即形成 TB Chain,让 TB 间直接跳转,而不需要切换回 QEMU。

一个典型的 Chain 如下图所示,每次由 TB 返回到 QEMU 时将下一个 TB 链接到上一个 TB,以帮助各 TB 可以直接跳转到下一个 TB 的 PC:

Chain Step 1 Chain Step 2
Chain Step 3 Chain Step 4
Chain Step 5 Unchain for interupt

 

需要注意的是,为了能够正确响应并处理 Guest 的中断与异常,必须在检测到中断时,将 TB Unchain,并切换回 QEMU 进行处理。

Soft MMU

对于全系统模拟,QEMU 提供了 Soft MMU 机制实现了软件模拟的 MMU 与 TLB,以提高由 Guest 虚拟地址到 Host 虚拟地址的转换效率。由于 Soft MMU 本身较为复杂,当前版本中的 QEMU 使用 helper function 来实现其功能,具体的实现可以 参见此文

Watch Point

QEMU 本身提供了一套 Debug 接口,通过定义各种 handle function,并为特定地址的访存行为插入相应的 watchpoint,以实现在运行时侦测到指定的行为并做出一定的行为(如生产 Trace 或者提供额外的 Assert)。

Memory Tracing Hack

对于 QEMU 的 Memory Tracing Hack,在 Qemu-devel 的邮件列表中被提到过多次,但至今还没有人能提供好用的 Patch。本文大致上总结了以下几种可能的实现方案:

TCG Hack

位于 target-$arch 目录下的 translate.c 文件实现了 Guest 到 TCG 的翻译,通过添加形如以下代码的宏,在 TCG 的 ld/st 指令之前加入 trace 相关的 TCG Code 或者调用 Helper function。


#define tcg_gen_qemu_ld32u(arg, addr, mem_index) \ { \ GEN_TRACE(TRACE_MEM_LOAD, TRACE_MEM_SIZE_LONG, addr); \ (tcg_gen_qemu_ld32u)(arg, addr, mem_index); \ }






Host Assembly Hack



位于 tcg/$arch/ 目录下的 tcg-target.c 文件实现了 TCG 到 Host 的翻译,通过往 tcg_out_qemu_ld() 与 tcg_out_qemu_st() 函数中插入 Trace 相关的 Assembly Code 可以非常方便的记录下 Guest 的访存行为。需要注意的是,这儿一定要注意寄存器与 CPU 状态的保护。对于 i386/x86_64 体系来说,通过构建并输出 opc 为 0x89/0x8b 的 mov 指令将 Trace 记录到 Trace Buffer 中。



SoftMMU Hack



对于全系统模拟,直接 Hack SoftMMU 模块显得更为简单有效,通过往 softmmu-template.c 文件中 的 glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mem_index) /glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, mem_index) 函数直接添加 C 代码可以方便的记录所需要的 Trace,其中 SUFFIX 表示 ld/st 的长度, addr 为 Guest 访存地址,mem_index 为相应的偏移量。



总结



QEMU 的早期版本非常 Tricky,比如 0.9.1 之前的 QEMU 依赖于特定版本的 GCC。之后由于 TCG 的引入,QEMU 在抽象层面变得更加清晰。但 TCG 带来的复杂性的提高却为各种 Hack 增加了难度,在过去的一个月,我几乎天天都在和 segfault 打交道。但是通过阅读和修改 QEMU 的代码,对于体系结构的理解更加深入和清晰了。




阅读(2840) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~