qemu tcg程式碼執行流程
一.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 staticinline
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 staticinlineint
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 staticvoid
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
}