【QEMU源码】cpu_exec_loop实现

cpu_exec_loop函数流程概述

cpu_exec_loop是TCG执行的主要循环函数,负责处理异常、中断和TB(Translation Block)的查找执行循环

1. 异常处理外层循环

函数首先进入异常处理循环,通过cpu_handle_exception检查是否有待处理的异常

cpu-exec.c:921 

    /* if an exception is pending, we execute it here */
    while (!cpu_handle_exception(cpu, &ret))

如果有异常需要处理,函数会退出并返回相应的异常码

cpu-exec.c:686-749 

    static inline bool cpu_handle_exception(CPUState *cpu, int *ret) {}

2. 中断处理内层循环

在异常处理循环内部,函数进入中断处理循环,通过cpu_handle_interrupt检查中断请求

cpu-exec.c:925 

while (!cpu_handle_interrupt(cpu, &last_tb)){

}

中断处理函数会检查各种中断标志,包括调试中断、复位中断等

cpu-exec.c:764-865 


static inline bool cpu_handle_interrupt(CPUState *cpu,
    TranslationBlock **last_tb) {
}

3. TB预处理

在中断处理循环内部,函数执行核心的TB查找和执行逻辑:

获取CPU状态:通过get_tb_cpu_state获取当前CPU状态,包括PC、CS基址、标志位等

cpu-exec.c:927-928 

    TranslationBlock *tb;
    TCGTBCPUState s = cpu->cc->tcg_ops->get_tb_cpu_state(cpu);
    s.cflags = cpu->cflags_next_tb;

处理编译标志:检查是否有特定的编译标志需要应用,如单步调试、指令计数等

cpu-exec.c:937-941 


/*
* When requested, use an exact setting for cflags for the next
* execution.  This is used for icount, precise smc, and stop-
* after-access watchpoints.  Since this request should never
* have CF_INVALID set, -1 is a convenient invalid value that
* does not require tcg headers for cpu_common_reset.
*/
if (s.cflags == -1) {
    s.cflags = curr_cflags(cpu);
} else {
    cpu->cflags_next_tb = -1;
}

断点检查:调用check_for_breakpoints检查是否命中断点

cpu-exec.c:943-945 


if (check_for_breakpoints(cpu, s.pc, &s.cflags)) {
    break;
}

4. TB查找或生成

TB查找:使用tb_lookup函数在缓存中查找现有的TB

cpu-exec.c:947 


tb = tb_lookup(cpu, s);

TB生成:如果TB不存在,调用tb_gen_code生成新的TB

cpu-exec.c:948-954 

if (tb == NULL) {
    CPUJumpCache *jc;
    uint32_t h;

    mmap_lock();
    tb = tb_gen_code(cpu, s);
    mmap_unlock();
    ...
}

缓存更新:将新生成的TB添加到跳转缓存中

cpu-exec.c:960-964 

if (tb == NULL) {
    ...
    /*
        * We add the TB in the virtual pc hash table
        * for the fast lookup
        */
    h = tb_jmp_cache_hash_func(s.pc);
    jc = cpu->tb_jmp_cache;
    jc->array[h].pc = s.pc;
    qatomic_set(&jc->array[h].tb, tb);
}

5. TB链接优化

跨页检查:在系统模式下,检查TB是否跨越页面边界,如果是则不能建立直接链接

cpu-exec.c:973-976 


if (tb_page_addr1(tb) != -1) {
    last_tb = NULL;
}

TB链接:如果存在上一个TB且满足条件,调用tb_add_jump建立直接跳转链接

cpu-exec.c:978-980 

/* See if we can patch the calling TB. */
if (last_tb) {
    tb_add_jump(last_tb, tb_exit, tb);
}

6. TB执行

执行TB

调用cpu_loop_exec_tb执行当前TB cpu-exec.c:982 。

该函数内部会调用cpu_tb_exec执行实际的机器码 cpu-exec.c:871-872 。

时钟同步:执行完TB后,调用align_clocks进行时钟同步

cpu-exec.c:986 


            /* Try to align the host and virtual clocks
               if the guest is in advance */
            align_clocks(sc, cpu);

7. 指令计数处理

cpu_loop_exec_tb函数中,还会处理指令计数相关的逻辑:

指令计数检查:如果启用了指令计数,会检查是否达到指令限制 cpu-exec.c:891 。

计数器更新:更新指令计数器并重新填充 cpu-exec.c:894-899 。

动态标志调整:根据剩余指令数动态调整编译标志 cpu-exec.c:905-909 。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务