QEMU翻译块(TB)分析

原创 2012年03月28日 13:32:05

1 翻译缓存

qemu中翻译缓存是一块连续的内存单元,使用全局变量code_gen_buffer保存其首地址,缓存大小由全局变量code_gen_buffer_size指示;全局变量code_gen_ptr指示当前未使用的缓存地址。
static uint8_t *code_gen_buffer;
static unsigned long code_gen_buffer_size;
static uint8_t *code_gen_ptr;

这片内存可以采用静态分配方式,也可以采用动态分配方式,前者将code_gen_buffer指向静态分配的空间,后者将code_gen_buffer指向动态分配的空间。编译时由宏USE_STATIC_CODE_GEN_BUFFER控制选用那种方式。
#ifdef USE_STATIC_CODE_GEN_BUFFER
code_gen_buffer = static_code_gen_buffer;
code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
map_exec(code_gen_buffer, code_gen_buffer_size);
#else
...
code_gen_buffer = qemu_malloc(code_gen_buffer_size);
map_exec(code_gen_buffer, code_gen_buffer_size);
#endif

2 翻译块存储

翻译块用一块连续的存储空间存放,采用动态申请的方式,用全局变量tbs保存返回值,一次申请全部的空间,空间大小由全局变量code_gen_max_blocks决定。
static TranslationBlock *tbs;
static int code_gen_max_blocks;

code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));

3 翻译块的结构

struct TranslationBlock {
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
target_ulong cs_base; /* CS base for this block */
uint64_t flags; /* flags defining in which context the code was generated */
uint16_t size; /* size of target code for this block (1 <=
size <= TARGET_PAGE_SIZE) */
uint16_t cflags; /* compile flags */
#define CF_COUNT_MASK 0x7fff
#define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */

uint8_t *tc_ptr; /* pointer to the translated code */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
/* first and second physical page containing code. The lower bit
of the pointer tells the index in page_next[] */
struct TranslationBlock *page_next[2];
tb_page_addr_t page_addr[2];

/* the following data are used to directly call another TB from
the code of this one. */
uint16_t tb_next_offset[2]; /* offset of original jump target */
#ifdef USE_DIRECT_JUMP
uint16_t tb_jmp_offset[2]; /* offset of jump instruction */
#else
unsigned long tb_next[2]; /* address of jump generated code */
#endif
/* list of TBs jumping to this one. This is a circular list using
the two least significant bits of the pointers to tell what is
the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
jmp_first */
struct TranslationBlock *jmp_next[2];
struct TranslationBlock *jmp_first;
uint32_t icount;
};

其中tc_ptr指向翻译块对应存放在翻译缓存中的翻译码;
jmp_first与jmp_next构成了循环链表,该链表既包含跳向当前TB的信息,也包含当前TB的跳转信息。这个循环链表是怎么构建的呢?设计者巧妙利用了jmp_next[n]与jmp_first的低两位,由于指针是4地址对齐,正常情况低两位为0,于是就用这两位指示那个是后继指针。
请看下面函数:
static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next)
{
/* NOTE: this test is only needed for thread safety */
if (!tb->jmp_next[n]) {
/* patch the native jump address */
tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);

/* add in TB jmp circular list */
tb->jmp_next[n] = tb_next->jmp_first;
tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
}
}
下面举例说明,假设tb1,tb2,tb3是未建立任何跳转关系的TB,注意此时
tb1->jmp_first为(TranslationBlock*)((long)(tb1) | 2);
tb2->jmp_first为(TranslationBlock*)((long)(tb2) | 2);
tb3->jmp_first为(TranslationBlock*)((long)(tb3) | 2);
在n=0情况下,如果tb2,tb3均跳转到tb1,执行语句
(1) tb_add_jump(tb2, 0, tb1);
(2) tb_add_jump(tb3, 0, tb1);
(3) tb_add_jump(tb2, 1, tb1);
语句(1)执行后,
tb2->jmp_next[0] = tb1->jmp_first;//即 (TranslationBlock*)((long)(tb1) | 2);
tb1->jmp_first = (TranslationBlock*)((long)(tb2) | 0);
语句(2)执行后,
tb3->jmp_next[0] = tb1->jmp_first;//即(TranslationBlock*)((long)(tb2) | 0);
tb1->jmp_first = (TranslationBlock*)((long)(tb3) | 0);
语句(3)执行后,
tb2->jmp_next[1] = tb1->jmp_first;//即(TranslationBlock*)((long)(tb3) | 0);
tb1->jmp_first = (TranslationBlock*)((long)(tb2) | 1);
这时构建的循环链表节点是:
tb1, tb1->jmp_first, tb2->jmp_next[1], tb3->jmp_next[0], tb2->jmp_next[0]
即tb1-->tb2(1)-->tb3(0)-->tb2(0)-->tb1(2)

从上述例子不难看出,循环链表包含了两方面的信息,一是跳向TB块的TB信息,如跳向tb1的TB块有tb3和tb2;二是TB块沿着一条链路跳向了那个节点,如tb3着链路0跳向了tb1,tb2沿着链路0、1均能跳到tb1.

4 TB的分配与释放

分配与释放函数分别是tb_alloc, tb_free函数,它们并不真正进行内存的申请与释放,只是对code_gen_ptr与nb_tbs进行增减操作。

5 TB相互间链接信息的删除

当一个TB无效时,需要清除与它有关的链接信息,一是要清除TB的跳转信息,二是要清除跳向该TB的信息。
清除TB的跳转信息用下面语句,先后清除两条链路上的信息:
tb_jmp_remove(tb, 0);
tb_jmp_remove(tb, 1);
函数tb_jmp_remove声明如下:
static inline void tb_jmp_remove(TranslationBlock *tb, int n);
实现过程是从tb的jmp_next[n]开始遍历n链路循环链表,当找到待清除节点且n值匹配时将其从链表中移出。如上例中执行语句tb_jmp_remove(tb2, 0);后链表变为:
tb1-->tb2(1)-->tb3(0)-->tb1(2)
执行语句tb_jmp_remove(tb2, 1);后链表变为:
tb1-->tb3(0)-->tb1(2)

清除跳向该TB的信息则比较容易,沿着jmp_first链表逐个移除,知道遇到低两位bit值为2的指针,这是循环链表遍历完的标志。

传输块(Transport Block)大小的计算

Transport Block Size and Code rate Since the size of transport block is not fixed, often a questi...
  • ycdhonker
  • ycdhonker
  • 2016年06月22日 20:38
  • 1606

qemu 学习(一)————qemu整体流程解读

本文由博主原创,转载请注明出处(保留此处和链接): IT人生 (http://blog.csdn.net/ningxialieri/article/details/8876599)       学习q...
  • ningxialieri
  • ningxialieri
  • 2013年05月02日 17:09
  • 5297

TB级别库迁移操作

一、场景 因一套RAC库的机器需要更换机房,必须在原先机房保留一套与之一样的数据库,以便应用不断的情形做机器的搬迁: 1)、应用暂停为零最好,这种情形用goldengate做,可以做到零停机,成本...
  • u013428681
  • u013428681
  • 2014年06月05日 09:04
  • 633

计算机硬盘大小转换(B,KB,MB,GB,TB,PB之间的大小转换)

程序员都很懒,你懂的!
  • xmt1139057136
  • xmt1139057136
  • 2014年05月27日 13:38
  • 5117

按键精灵一键从交易开拓者TB下载各个品种日线数据

Call xiazai("cu000")//下载铜 Call xiazai("al000")//下载铝 Call xiazai("zn000")//下载锌 Call xiazai("pb000")//...
  • qq_26948675
  • qq_26948675
  • 2017年04月24日 11:32
  • 637

每天TB级数据处理,携程大数据高并发应用架构涅槃

原文链接:http://www.open-open.com/lib/view/open1474600301132.html 互联网二次革命的移动互联网时代,如何吸引用户、留住用户并深入挖掘用户价...
  • xie_xiansheng
  • xie_xiansheng
  • 2017年07月05日 16:57
  • 438

TB-15A黑色栅栏接线端子TB接线端子TB端子排TB接线柱TB端子台

有乐-TB1-15A          20年无轨连接工艺的“佼佼者”   安全、环保、防滑丝 通过CE/CQC/Rosh体系认证 在连接技术创新的浪潮中尽情驰骋 TB接线端子是指从日本、台...
  • lianjie8888
  • lianjie8888
  • 2016年12月26日 14:07
  • 8

交易开拓者TB夜盘编程技术集

一、夜盘交易的基本情况 目前期货市场上,越来越多的品种都加入了夜盘交易大军。截止7月23日,目前已经确定在夜盘交易的有: 上海期货交易所:白银ag,铜cu,金au,锌zu 大连商品交...
  • duck_arrow
  • duck_arrow
  • 2014年09月03日 16:39
  • 2786

TB级SQL Server数据库表分区的实现

一般在千万级的数据压力下,分区是一种比较好的提升性能方法。本文将介绍SQL Server数据库表分区的实现。 回顾下经常使用的索引 一 .聚集索引 聚集索引的页级别包含了索引键,还包...
  • luoyanqing119
  • luoyanqing119
  • 2014年01月21日 09:47
  • 1363

用mybatis-generator的逆向工程生成bean和dao

1、在pom.xml里添加maven插件 org.mybatis.generator mybatis-generator-ma...
  • lJQueen
  • lJQueen
  • 2017年11月17日 12:11
  • 179
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:QEMU翻译块(TB)分析
举报原因:
原因补充:

(最多只允许输入30个字)