1 /* 2 * Generic intermediate code generation. 3 * 4 * Copyright (C) 2016-2017 Lluís Vilanova <vilanova@ac.upc.edu> 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 */ 9 10 #include "qemu/osdep.h" 11 #include "qemu/error-report.h" 12 #include "tcg/tcg.h" 13 #include "tcg/tcg-op.h" 14 #include "exec/exec-all.h" 15 #include "exec/log.h" 16 #include "exec/translator.h" 17 #include "exec/plugin-gen.h" 18 #include "exec/replay-core.h" 19 20 21 static void gen_io_start(void) 22 { 23 tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, 24 offsetof(ArchCPU, parent_obj.can_do_io) - 25 offsetof(ArchCPU, env)); 26 } 27 28 bool translator_io_start(DisasContextBase *db) 29 { 30 uint32_t cflags = tb_cflags(db->tb); 31 32 if (!(cflags & CF_USE_ICOUNT)) { 33 return false; 34 } 35 if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) { 36 /* Already started in translator_loop. */ 37 return true; 38 } 39 40 gen_io_start(); 41 42 /* 43 * Ensure that this instruction will be the last in the TB. 44 * The target may override this to something more forceful. 45 */ 46 if (db->is_jmp == DISAS_NEXT) { 47 db->is_jmp = DISAS_TOO_MANY; 48 } 49 return true; 50 } 51 52 static TCGOp *gen_tb_start(uint32_t cflags) 53 { 54 TCGv_i32 count = tcg_temp_new_i32(); 55 TCGOp *icount_start_insn = NULL; 56 57 tcg_gen_ld_i32(count, cpu_env, 58 offsetof(ArchCPU, neg.icount_decr.u32) - 59 offsetof(ArchCPU, env)); 60 61 if (cflags & CF_USE_ICOUNT) { 62 /* 63 * We emit a sub with a dummy immediate argument. Keep the insn index 64 * of the sub so that we later (when we know the actual insn count) 65 * can update the argument with the actual insn count. 66 */ 67 tcg_gen_sub_i32(count, count, tcg_constant_i32(0)); 68 icount_start_insn = tcg_last_op(); 69 } 70 71 /* 72 * Emit the check against icount_decr.u32 to see if we should exit 73 * unless we suppress the check with CF_NOIRQ. If we are using 74 * icount and have suppressed interruption the higher level code 75 * should have ensured we don't run more instructions than the 76 * budget. 77 */ 78 if (cflags & CF_NOIRQ) { 79 tcg_ctx->exitreq_label = NULL; 80 } else { 81 tcg_ctx->exitreq_label = gen_new_label(); 82 tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label); 83 } 84 85 if (cflags & CF_USE_ICOUNT) { 86 tcg_gen_st16_i32(count, cpu_env, 87 offsetof(ArchCPU, neg.icount_decr.u16.low) - 88 offsetof(ArchCPU, env)); 89 /* 90 * cpu->can_do_io is cleared automatically here at the beginning of 91 * each translation block. The cost is minimal and only paid for 92 * -icount, plus it would be very easy to forget doing it in the 93 * translator. Doing it here means we don't need a gen_io_end() to 94 * go with gen_io_start(). 95 */ 96 tcg_gen_st_i32(tcg_constant_i32(0), cpu_env, 97 offsetof(ArchCPU, parent_obj.can_do_io) - 98 offsetof(ArchCPU, env)); 99 } 100 101 return icount_start_insn; 102 } 103 104 static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags, 105 TCGOp *icount_start_insn, int num_insns) 106 { 107 if (cflags & CF_USE_ICOUNT) { 108 /* 109 * Update the num_insn immediate parameter now that we know 110 * the actual insn count. 111 */ 112 tcg_set_insn_param(icount_start_insn, 2, 113 tcgv_i32_arg(tcg_constant_i32(num_insns))); 114 } 115 116 if (tcg_ctx->exitreq_label) { 117 gen_set_label(tcg_ctx->exitreq_label); 118 tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED); 119 } 120 } 121 122 bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) 123 { 124 /* Suppress goto_tb if requested. */ 125 if (tb_cflags(db->tb) & CF_NO_GOTO_TB) { 126 return false; 127 } 128 129 /* Check for the dest on the same page as the start of the TB. */ 130 return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0; 131 } 132 133 void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, 134 target_ulong pc, void *host_pc, 135 const TranslatorOps *ops, DisasContextBase *db) 136 { 137 uint32_t cflags = tb_cflags(tb); 138 TCGOp *icount_start_insn; 139 bool plugin_enabled; 140 141 /* Initialize DisasContext */ 142 db->tb = tb; 143 db->pc_first = pc; 144 db->pc_next = pc; 145 db->is_jmp = DISAS_NEXT; 146 db->num_insns = 0; 147 db->max_insns = *max_insns; 148 db->singlestep_enabled = cflags & CF_SINGLE_STEP; 149 db->host_addr[0] = host_pc; 150 db->host_addr[1] = NULL; 151 152 #ifdef CONFIG_USER_ONLY 153 page_protect(pc); 154 #endif 155 156 ops->init_disas_context(db, cpu); 157 tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ 158 159 /* Start translating. */ 160 icount_start_insn = gen_tb_start(cflags); 161 ops->tb_start(db, cpu); 162 tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ 163 164 plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY); 165 166 while (true) { 167 *max_insns = ++db->num_insns; 168 ops->insn_start(db, cpu); 169 tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ 170 171 if (plugin_enabled) { 172 plugin_gen_insn_start(cpu, db); 173 } 174 175 /* Disassemble one instruction. The translate_insn hook should 176 update db->pc_next and db->is_jmp to indicate what should be 177 done next -- either exiting this loop or locate the start of 178 the next instruction. */ 179 if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) { 180 /* Accept I/O on the last instruction. */ 181 gen_io_start(); 182 ops->translate_insn(db, cpu); 183 } else { 184 /* we should only see CF_MEMI_ONLY for io_recompile */ 185 tcg_debug_assert(!(cflags & CF_MEMI_ONLY)); 186 ops->translate_insn(db, cpu); 187 } 188 189 /* 190 * We can't instrument after instructions that change control 191 * flow although this only really affects post-load operations. 192 * 193 * Calling plugin_gen_insn_end() before we possibly stop translation 194 * is important. Even if this ends up as dead code, plugin generation 195 * needs to see a matching plugin_gen_insn_{start,end}() pair in order 196 * to accurately track instrumented helpers that might access memory. 197 */ 198 if (plugin_enabled) { 199 plugin_gen_insn_end(); 200 } 201 202 /* Stop translation if translate_insn so indicated. */ 203 if (db->is_jmp != DISAS_NEXT) { 204 break; 205 } 206 207 /* Stop translation if the output buffer is full, 208 or we have executed all of the allowed instructions. */ 209 if (tcg_op_buf_full() || db->num_insns >= db->max_insns) { 210 db->is_jmp = DISAS_TOO_MANY; 211 break; 212 } 213 } 214 215 /* Emit code to exit the TB, as indicated by db->is_jmp. */ 216 ops->tb_stop(db, cpu); 217 gen_tb_end(tb, cflags, icount_start_insn, db->num_insns); 218 219 if (plugin_enabled) { 220 plugin_gen_tb_end(cpu); 221 } 222 223 /* The disas_log hook may use these values rather than recompute. */ 224 tb->size = db->pc_next - db->pc_first; 225 tb->icount = db->num_insns; 226 227 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) 228 && qemu_log_in_addr_range(db->pc_first)) { 229 FILE *logfile = qemu_log_trylock(); 230 if (logfile) { 231 fprintf(logfile, "----------------\n"); 232 ops->disas_log(db, cpu, logfile); 233 fprintf(logfile, "\n"); 234 qemu_log_unlock(logfile); 235 } 236 } 237 } 238 239 static void *translator_access(CPUArchState *env, DisasContextBase *db, 240 target_ulong pc, size_t len) 241 { 242 void *host; 243 target_ulong base, end; 244 TranslationBlock *tb; 245 246 tb = db->tb; 247 248 /* Use slow path if first page is MMIO. */ 249 if (unlikely(tb_page_addr0(tb) == -1)) { 250 return NULL; 251 } 252 253 end = pc + len - 1; 254 if (likely(is_same_page(db, end))) { 255 host = db->host_addr[0]; 256 base = db->pc_first; 257 } else { 258 host = db->host_addr[1]; 259 base = TARGET_PAGE_ALIGN(db->pc_first); 260 if (host == NULL) { 261 tb_page_addr_t phys_page = 262 get_page_addr_code_hostp(env, base, &db->host_addr[1]); 263 264 /* 265 * If the second page is MMIO, treat as if the first page 266 * was MMIO as well, so that we do not cache the TB. 267 */ 268 if (unlikely(phys_page == -1)) { 269 tb_set_page_addr0(tb, -1); 270 return NULL; 271 } 272 273 tb_set_page_addr1(tb, phys_page); 274 #ifdef CONFIG_USER_ONLY 275 page_protect(end); 276 #endif 277 host = db->host_addr[1]; 278 } 279 280 /* Use slow path when crossing pages. */ 281 if (is_same_page(db, pc)) { 282 return NULL; 283 } 284 } 285 286 tcg_debug_assert(pc >= base); 287 return host + (pc - base); 288 } 289 290 uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc) 291 { 292 uint8_t ret; 293 void *p = translator_access(env, db, pc, sizeof(ret)); 294 295 if (p) { 296 plugin_insn_append(pc, p, sizeof(ret)); 297 return ldub_p(p); 298 } 299 ret = cpu_ldub_code(env, pc); 300 plugin_insn_append(pc, &ret, sizeof(ret)); 301 return ret; 302 } 303 304 uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc) 305 { 306 uint16_t ret, plug; 307 void *p = translator_access(env, db, pc, sizeof(ret)); 308 309 if (p) { 310 plugin_insn_append(pc, p, sizeof(ret)); 311 return lduw_p(p); 312 } 313 ret = cpu_lduw_code(env, pc); 314 plug = tswap16(ret); 315 plugin_insn_append(pc, &plug, sizeof(ret)); 316 return ret; 317 } 318 319 uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc) 320 { 321 uint32_t ret, plug; 322 void *p = translator_access(env, db, pc, sizeof(ret)); 323 324 if (p) { 325 plugin_insn_append(pc, p, sizeof(ret)); 326 return ldl_p(p); 327 } 328 ret = cpu_ldl_code(env, pc); 329 plug = tswap32(ret); 330 plugin_insn_append(pc, &plug, sizeof(ret)); 331 return ret; 332 } 333 334 uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc) 335 { 336 uint64_t ret, plug; 337 void *p = translator_access(env, db, pc, sizeof(ret)); 338 339 if (p) { 340 plugin_insn_append(pc, p, sizeof(ret)); 341 return ldq_p(p); 342 } 343 ret = cpu_ldq_code(env, pc); 344 plug = tswap64(ret); 345 plugin_insn_append(pc, &plug, sizeof(ret)); 346 return ret; 347 } 348