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

只有偏执狂才能生存

文章分类

全部博文(489)

文章存档

2016年(10)

2015年(112)

2014年(66)

2013年(273)

2012年(28)

分类: LINUX

2013-08-26 10:59:20

使用全局变量use_icount标记qemu如何进行指令计数。

use_icout=0:表示不统计执行的指令数;

use_icout=1:表示精确同时执行的指令数;

use_icout=2:表示对执行的指令数进行适应性估计。


在configure_icount函数中对use_icount进行设置

void configure_icount(const char *option);

输入参数optionNULL时,use_icount=0;为"auto"时,use_icount=1;否则use_icount=1.

use_icount1时,option中还包含着icount_time_shift的信息:     icount_time_shift = strtol(option, NULL, 0);

use_icount2时,icount_time_shift = 3;


qemu中使用全局变量qemu_icount记录执行的指令数,但这个计数值会大于实际执行的指令数,因为其中包含了尚未执行的一些指令。利用这个全局变量计数的功能在qemu_cpu_exec函数中实现。

    if (use_icount) {

        int64_t count;

        int decr;

        qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);

        env->icount_decr.u16.low = 0;

        env->icount_extra = 0;

        count = qemu_icount_round (qemu_next_deadline());

//count是距离下次事件发生还需执行的指令数,这些指令尚未执行

        qemu_icount += count;

//所以,加上countqemu_icount表示的就不仅仅是已经执行的指令数

        decr = (count > 0xffff) ? 0xffff : count;

        count -= decr;

//count分成了两部分,一部分存放在icount_decr.u16.low中,这用来控制TB的执行,防止连续执行的指令过多,以至于超出限制。

        env->icount_decr.u16.low = decr;

        env->icount_extra = count;

    }

ret = cpu_exec(env);

//cpu_exec会连续执行,但执行指令数不会超过env->icount_extraenv->icount_decr.u16.low之和。

    if (use_icount) {

        qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);

//这时的qemu_icount是实际执行的指令数

        env->icount_decr.u32 = 0;

        env->icount_extra = 0;

    }

TB执行时是如何进行指令计数呢?

在生成中间码函数gen_intermediate_code_internal中,调用了两个函数来生成指令计数代码,它们可记录下来所翻译TB中包含的目标指令数目。这两个函数就是gen_icount_startgen_icount_end。但在use_icount0时,它们不起任何作用。下面我们来看看这两个函数的内容,并分析它们所起的作用是什么。

static inline void gen_icount_start(void)

{

    TCGv_i32 count;

    if (!use_icount)

        return;

    icount_label = gen_new_label();

    count = tcg_temp_local_new_i32();

    tcg_gen_ld_i32(count, cpu_env, offsetof(CPUState, icount_decr.u32));

    /* This is a horrid hack to allow fixing up the value later.  */

    icount_arg = gen_opparam_ptr + 1;

    tcg_gen_subi_i32(count, count, 0xdeadbeef);

    tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label);

    tcg_gen_st16_i32(count, cpu_env, offsetof(CPUState, icount_decr.u16.low));

    tcg_temp_free_i32(count);

}

use_icount不为0时,gen_icount_start函数执行后产生一系列的中间码,根据这些中间码,TCG引擎将会生成关于指令计数的代码。

函数中的常量0xdeadbeef并无实际意义,它只是起辅助作用,因为用它生成的中间码在TCG之前还会被修改。icount_arg指向存放0xdeadbeef的中间码参数指针,在gen_icount_end函数中会对其修改。

static void gen_icount_end(TranslationBlock *tb, int num_insns)

{

    if (use_icount) {

        *icount_arg = num_insns;

        gen_set_label(icount_label);

        tcg_gen_exit_tb((long)tb + 2);

    }

}

可以看到,gen_icount_end中语句:

*icount_arg = num_insns;

作用是修改gen_icount_start中的临时参数0xdeadbeefnum_insns,即所翻译TB中的目标指令数。

综合gen_icount_startgen_icount_end函数,它们的作用就是让TCG引擎生成完成下面操作的代码:

比较env->icount_decr.u32num_insns,如果小于0,跳过TB代码,并返回(long)tb+2;否则,env->icount_decr.u32 -= num_insns

返回(long)tb+2后,在cpu_exec函数中执行下面语句:

  1. next_tb = tcg_qemu_tb_exec(tc_ptr);  
  2. if ((next_tb & 3) == 2) {  
  3.     /* Instruction counter expired.  */  
  4.     int insns_left;  
  5.     tb = (TranslationBlock *)(long)(next_tb & ~3);  
  6.     /* Restore PC.  */  
  7.     cpu_pc_from_tb(env, tb);  
  8.     insns_left = env->icount_decr.u32;  
  9.     if (env->icount_extra && insns_left >= 0) {  
  10.         /* Refill decrementer and continue execution.  */  
  11.         env->icount_extra += insns_left;  
  12.         if (env->icount_extra > 0xffff) {  
  13.             insns_left = 0xffff;  
  14.         } else {  
  15.             insns_left = env->icount_extra;  
  16.         }  
  17.         env->icount_extra -= insns_left;  
  18.         env->icount_decr.u16.low = insns_left;  
  19.     } else {  
  20.         if (insns_left > 0) {  
  21.             /* Execute remaining instructions.  */  
  22.             cpu_exec_nocache(insns_left, tb);  
  23.         }  
  24.         env->exception_index = EXCP_INTERRUPT;  
  25.         next_tb = 0;  
  26.         cpu_loop_exit();  
  27.     }  
  28. }  
阅读(1256) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册