(转)qemu执行流程分析
(2014-04-24 12:56:35)分类: 云计算与虚拟化 |
一.qemu简介
Qemu代码翻译流程:target instruction
->micro-op->tcg->host instruction
2.qemu代码执行流程:
cpu_init
qemu_init_vcpu
qemu_tcg_init_vcpu
qemu_tcg_cpu_thread_fn
-
for(;;)
{ -
process
interruptrequest; -
-
tb_find_fast();
-
-
tcg_qemu_tb_exec(tc_ptr);
-
}
-
139
static inline TranslationBlock *tb_find_fast(CPUArchState *env) -
140
{ -
141
TranslationBlock *tb; -
142
target_ulong cs_base, pc; -
143
int flags; -
144
-
145
-
148
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); -
149
tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; -
150
if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base || -
151
tb->flags != flags)) { -
152
tb = tb_find_slow(env, pc, cs_base, flags); -
153
} -
154
return tb; -
155
}
-
1029
TranslationBlock *tb_gen_code(CPUArchState *env, -
1030
target_ulong pc, target_ulong cs_base, -
1031
int flags, intcflags) -
1032
{ -
1033
TranslationBlock *tb; -
1034
uint8_t *tc_ptr; -
1035
tb_page_addr_t phys_pc, phys_page2; -
1036
target_ulong virt_page2; -
1037
int code_gen_size; -
1038
-
1039
phys_pc = get_page_addr_code(env, pc); -
1040
tb = tb_alloc(pc); -
1041
if (!tb) { -
1042
-
1043
tb_flush(env); -
1044
-
1045
tb = tb_alloc(pc); -
1046
-
1047
tb_invalidated_flag = 1; -
1048
} -
1049
tc_ptr = code_gen_ptr; -
1050
tb->tc_ptr = tc_ptr; -
1051
tb->cs_base = cs_base; -
1052
tb->flags = flags; -
1053
tb->cflags = cflags; -
1054
cpu_gen_code(env, tb, &code_gen_size); -
1055
code_gen_ptr = (void *)((( uintptr_t)code_gen_ptr+ code_gen_size + -
1056
CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); -
1057
-
1058
-
1059
virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; -
1060
phys_page2 = -1; -
1061
if ((pc & TARGET_PAGE_MASK) != virt_page2) { -
1062
phys_page2 = get_page_addr_code(env, virt_page2); -
1063
} -
1064
tb_link_page(tb, phys_pc, phys_page2); -
1065
return tb; -
1066
}
-
54
int cpu_gen_code(CPUArchState int*env, TranslationBlock *tb, *gen_code_size_ptr) -
55 { -
56 TCGContext *s = &tcg_ctx; -
57 uint8_t *gen_code_buf; -
58 int gen_code_size; -
59 #ifdef CONFIG_PROFILER -
60 int64_t ti; -
61 #endif -
62 -
63 #ifdef CONFIG_PROFILER -
64 s->tb_count1++; -
66 ti = profile_getclock(); -
67 #endif -
68 tcg_func_start(s); -
69 -
70 gen_intermediate_code(env, tb); -
71 -
72 -
73 gen_code_buf = tb->tc_ptr; -
74 tb->tb_next_offset[0] = 0xffff; -
75 tb->tb_next_offset[1] = 0xffff; -
76 s->tb_next_offset = tb->tb_next_offset; -
77 #ifdef USE_DIRECT_JUMP -
78 s->tb_jmp_offset = tb->tb_jmp_offset; -
79 s->tb_next = NULL; -
80 #else -
81 s->tb_jmp_offset = NULL; -
82 s->tb_next = tb->tb_next; -
83 #endif -
84 -
85 #ifdef CONFIG_PROFILER -
86 s->tb_count++; -
87 s->interm_time += profile_getclock() - ti; -
88 s->code_time -= profile_getclock(); -
89 #endif -
90 gen_code_size = tcg_gen_code(s, gen_code_buf); -
91 *gen_code_size_ptr = gen_code_size; -
92 #ifdef CONFIG_PROFILER -
93 s->code_time += profile_getclock(); -
94 s->code_in_len += tb->size; -
95 s->code_out_len += gen_code_size; -
96 #endif -
97 -
98 #ifdef DEBUG_DISAS -
99 if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) { -
100
qemu_log("OUT: [size=%d]\n" ,*gen_code_size_ptr); -
101
log_disas(tb->tc_ptr, *gen_code_size_ptr); -
102
qemu_log("\n"); -
103
qemu_log_flush(); -
104
} -
105
#endif -
106
return 0; -
107
}
-
2175
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf) -
2176
{ -
2177
#ifdef CONFIG_PROFILER -
2178
{ -
2179
int n; -
2180
n = (gen_opc_ptr - gen_opc_buf); -
2181
s->op_count += n; -
2182
if (n > s->op_count_max) -
2183
s->op_count_max = n; -
2184
-
2185
s->temp_count += s->nb_temps; -
2186
if (s->nb_temps > s->temp_count_max) -
2187
s->temp_count_max = s->nb_temps; -
2188
} -
2189
#endif -
2190
-
2191
tcg_gen_code_common(s, gen_code_buf, -1); -
2192
-
2193
-
2194
flush_icache_range((tcg_target_ulong)gen_code_buf, -
2195
(tcg_target_ulong)s->code_ptr); -
2196
-
2197
return s->code_ptr - gen_code_buf; -
2198
}
-
2045
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, -
2046
long search_pc) -
2047
{ -
2048
TCGOpcode opc; -
2049
int op_index; -
2050
const TCGOpDef *def; -
2051
unsigned int dead_args; -
2052
const TCGArg *args; -
2053
-
2054
#ifdef DEBUG_DISAS -
2055
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { -
2056
qemu_log("OP:\n"); -
2057
tcg_dump_ops(s); -
2058
qemu_log("\n"); -
2059
} -
2060
#endif -
2061
-
2062
#ifdef USE_TCG_OPTIMIZATIONS -
2063
gen_opparam_ptr = -
2064
tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs); -
2065
#endif -
2066
-
2067
#ifdef CONFIG_PROFILER -
2068
s->la_time -= profile_getclock(); -
2069
#endif -
2070
tcg_liveness_analysis(s); -
2071
#ifdef CONFIG_PROFILER -
2072
s->la_time += profile_getclock(); -
2073
#endif -
2074
-
2075
#ifdef DEBUG_DISAS -
2076
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) { -
2077
qemu_log("OP after );liveness analysis:\n" -
2078
tcg_dump_ops(s); -
2079
qemu_log("\n"); -
2080
} -
2081
#endif -
2082
-
2083
tcg_reg_alloc_start(s); -
2084
-
2085
s->code_buf = gen_code_buf; -
2086
s->code_ptr = gen_code_buf; -
2087
-
2088
args = gen_opparam_buf; -
2089 op_index = 0; -
2090
-
2091
for(;;) { -
2092
opc = gen_opc_buf[op_index]; -
2093
#ifdef CONFIG_PROFILER -
2094
tcg_table_op_count[opc]++; -
2095
#endif -
2096
def = &tcg_op_defs[opc]; -
2097
#if 0 -
2098
printf("%s: %d ,%d %d\n" def->name, -
2099
def->nb_oargs, def->nb_iargs, def->nb_cargs); -
2100
// dump_regs(s); -
2101
#endif -
2102
switch(opc) { -
2103
case INDEX_op_mov_i32: -
2104
#if TCG_TARGET_REG_BITS == 64 -
2105
case INDEX_op_mov_i64: -
2106
#endif -
2107
dead_args = s->op_dead_args[op_index]; -
2108
tcg_reg_alloc_mov(s, def, args, dead_args); -
2109
break; -
2110
case INDEX_op_movi_i32: -
2111
#if TCG_TARGET_REG_BITS == 64 -
2112
case INDEX_op_movi_i64: -
2113
#endif -
2114
tcg_reg_alloc_movi(s, args); -
2115
break; -
2116
case INDEX_op_debug_insn_start: -
2117
-
2118
break; -
2119
case INDEX_op_nop: -
2120
case INDEX_op_nop1: -
2121
case INDEX_op_nop2: -
2122
case INDEX_op_nop3: -
2123
break; -
2124
case INDEX_op_nopn: -
2125
args += args[0]; -
2126
goto next; -
2127
case INDEX_op_discard: -
2128
{ -
2129 TCGTemp *ts; -
2130
ts = &s->temps[args[0]]; -
2131
-
2132
if (!ts->fixed_reg) { -
2133
if (ts->val_type == TEMP_VAL_REG) -
2134
s->reg_to_temp[ts->reg] = -1; -
2135
ts->val_type = TEMP_VAL_DEAD; -
2136
} -
2137
} -
2138
break; -
2139
case INDEX_op_set_label: -
2140
tcg_reg_alloc_bb_end(s, s->reserved_regs); -
2141
tcg_out_label(s, args[0], s->code_ptr); -
2142
break; -
2143
case INDEX_op_call: -
2144
dead_args = s->op_dead_args[op_index]; -
2145
args += tcg_reg_alloc_call(s, def, opc, args, dead_args); -
2146
goto next; -
2147
case INDEX_op_end: -
2148
goto the_end; -
2149
default: -
2150
-
2151
if (def->flags & TCG_OPF_NOT_PRESENT) { -
2152
tcg_abort(); -
2153
} -
2154
-
2157
dead_args = s->op_dead_args[op_index]; -
2158
tcg_reg_alloc_op(s, def, opc, args, dead_args); -
2159
break; -
2160
} -
2161
args += def->nb_args; -
2162
next: -
2163
if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) { -
2164
return op_index; -
2165
} -
2166
op_index++; -
2167
#ifndef NDEBUG -
2168
check_regs(s); -
2169
#endif -
2170
} -
2171 the_end: -
2172
return -1; -
2173
}
3.翻译代码块的执行
以host是arm为例,入口函数主要是保存寄存器的状态,然后将tcg_qemu_tb_exec传进来的第一的参数(env)给TCG_AREG0,然后跳转至tb_ptr,开始执行代码。同时代码执行的返回地址也确定了,返回后恢复之前保存的状态。
以host是arm为例,入口函数主要是保存寄存器的状态,然后将tcg_qemu_tb_exec传进来的第一的参数(env)给TCG_AREG0,然后跳转至tb_ptr,开始执行代码。同时代码执行的返回地址也确定了,返回后恢复之前保存的状态。-
100
#define tcg_qemu_tb_exec(env, tb_ptr) \ -
101
((long __attribute__ ((longcall)) \ -
102
(*)(void *, void*))code_gen_prologue)(env, tb_ptr)
-
1881
static void tcg_target_qemu_prologue(TCGContext *s) -
1882
{ -
1883
-
1886
-
1887
-
1888
tcg_out32(s, (COND_AL << 28) | 0x092d5ff0); -
1889
-
1890
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); -
1891
-
1892
tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]); -
1893
tb_ret_addr = s->code_ptr; -
1894
-
1895
-
1896
tcg_out32(s, (COND_AL << 28) | 0x08bd9ff0); -
1897
}