1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "qemu/osdep.h"
20#include "cpu.h"
21#include "trace.h"
22#include "disas/disas.h"
23#include "tcg.h"
24#include "qemu/atomic.h"
25#include "sysemu/qtest.h"
26#include "qemu/timer.h"
27#include "exec/address-spaces.h"
28#include "qemu/rcu.h"
29#include "exec/tb-hash.h"
30#include "exec/log.h"
31#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
32#include "hw/i386/apic.h"
33#endif
34#include "sysemu/replay.h"
35
36
37
38typedef struct SyncClocks {
39 int64_t diff_clk;
40 int64_t last_cpu_icount;
41 int64_t realtime_clock;
42} SyncClocks;
43
44#if !defined(CONFIG_USER_ONLY)
45
46
47
48
49#define VM_CLOCK_ADVANCE 3000000
50#define THRESHOLD_REDUCE 1.5
51#define MAX_DELAY_PRINT_RATE 2000000000LL
52#define MAX_NB_PRINTS 100
53
54static void align_clocks(SyncClocks *sc, const CPUState *cpu)
55{
56 int64_t cpu_icount;
57
58 if (!icount_align_option) {
59 return;
60 }
61
62 cpu_icount = cpu->icount_extra + cpu->icount_decr.u16.low;
63 sc->diff_clk += cpu_icount_to_ns(sc->last_cpu_icount - cpu_icount);
64 sc->last_cpu_icount = cpu_icount;
65
66 if (sc->diff_clk > VM_CLOCK_ADVANCE) {
67#ifndef _WIN32
68 struct timespec sleep_delay, rem_delay;
69 sleep_delay.tv_sec = sc->diff_clk / 1000000000LL;
70 sleep_delay.tv_nsec = sc->diff_clk % 1000000000LL;
71 if (nanosleep(&sleep_delay, &rem_delay) < 0) {
72 sc->diff_clk = rem_delay.tv_sec * 1000000000LL + rem_delay.tv_nsec;
73 } else {
74 sc->diff_clk = 0;
75 }
76#else
77 Sleep(sc->diff_clk / SCALE_MS);
78 sc->diff_clk = 0;
79#endif
80 }
81}
82
83static void print_delay(const SyncClocks *sc)
84{
85 static float threshold_delay;
86 static int64_t last_realtime_clock;
87 static int nb_prints;
88
89 if (icount_align_option &&
90 sc->realtime_clock - last_realtime_clock >= MAX_DELAY_PRINT_RATE &&
91 nb_prints < MAX_NB_PRINTS) {
92 if ((-sc->diff_clk / (float)1000000000LL > threshold_delay) ||
93 (-sc->diff_clk / (float)1000000000LL <
94 (threshold_delay - THRESHOLD_REDUCE))) {
95 threshold_delay = (-sc->diff_clk / 1000000000LL) + 1;
96 printf("Warning: The guest is now late by %.1f to %.1f seconds\n",
97 threshold_delay - 1,
98 threshold_delay);
99 nb_prints++;
100 last_realtime_clock = sc->realtime_clock;
101 }
102 }
103}
104
105static void init_delay_params(SyncClocks *sc,
106 const CPUState *cpu)
107{
108 if (!icount_align_option) {
109 return;
110 }
111 sc->realtime_clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT);
112 sc->diff_clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - sc->realtime_clock;
113 sc->last_cpu_icount = cpu->icount_extra + cpu->icount_decr.u16.low;
114 if (sc->diff_clk < max_delay) {
115 max_delay = sc->diff_clk;
116 }
117 if (sc->diff_clk > max_advance) {
118 max_advance = sc->diff_clk;
119 }
120
121
122
123 print_delay(sc);
124}
125#else
126static void align_clocks(SyncClocks *sc, const CPUState *cpu)
127{
128}
129
130static void init_delay_params(SyncClocks *sc, const CPUState *cpu)
131{
132}
133#endif
134
135
136static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
137{
138 CPUArchState *env = cpu->env_ptr;
139 uintptr_t next_tb;
140 uint8_t *tb_ptr = itb->tc_ptr;
141
142 qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
143 "CPU%d Trace %p [" TARGET_FMT_lx "] %s\n",
144 cpu->cpu_index,
145 itb->tc_ptr, itb->pc, lookup_symbol(itb->pc));
146
147#if defined(DEBUG_DISAS)
148 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
149#if defined(TARGET_I386)
150 log_cpu_state(cpu, CPU_DUMP_CCOP);
151#elif defined(TARGET_M68K)
152
153 cpu_m68k_flush_flags(env, env->cc_op);
154 env->cc_op = CC_OP_FLAGS;
155 env->sr = (env->sr & 0xffe0) | env->cc_dest | (env->cc_x << 4);
156 log_cpu_state(cpu, 0);
157#else
158 log_cpu_state(cpu, 0);
159#endif
160 }
161#endif
162
163 cpu->can_do_io = !use_icount;
164 next_tb = tcg_qemu_tb_exec(env, tb_ptr);
165 cpu->can_do_io = 1;
166 trace_exec_tb_exit((void *) (next_tb & ~TB_EXIT_MASK),
167 next_tb & TB_EXIT_MASK);
168
169 if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
170
171
172
173
174 CPUClass *cc = CPU_GET_CLASS(cpu);
175 TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
176 qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
177 "Stopped execution of TB chain before %p ["
178 TARGET_FMT_lx "] %s\n",
179 itb->tc_ptr, itb->pc, lookup_symbol(itb->pc));
180 if (cc->synchronize_from_tb) {
181 cc->synchronize_from_tb(cpu, tb);
182 } else {
183 assert(cc->set_pc);
184 cc->set_pc(cpu, tb->pc);
185 }
186 }
187 if ((next_tb & TB_EXIT_MASK) == TB_EXIT_REQUESTED) {
188
189
190
191 cpu->tcg_exit_req = 0;
192 }
193 return next_tb;
194}
195
196
197
198static void cpu_exec_nocache(CPUState *cpu, int max_cycles,
199 TranslationBlock *orig_tb, bool ignore_icount)
200{
201 TranslationBlock *tb;
202
203
204
205 if (max_cycles > CF_COUNT_MASK)
206 max_cycles = CF_COUNT_MASK;
207
208 tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
209 max_cycles | CF_NOCACHE
210 | (ignore_icount ? CF_IGNORE_ICOUNT : 0));
211 tb->orig_tb = tcg_ctx.tb_ctx.tb_invalidated_flag ? NULL : orig_tb;
212 cpu->current_tb = tb;
213
214 trace_exec_tb_nocache(tb, tb->pc);
215 cpu_tb_exec(cpu, tb);
216 cpu->current_tb = NULL;
217 tb_phys_invalidate(tb, -1);
218 tb_free(tb);
219}
220
221static TranslationBlock *tb_find_physical(CPUState *cpu,
222 target_ulong pc,
223 target_ulong cs_base,
224 uint64_t flags)
225{
226 CPUArchState *env = (CPUArchState *)cpu->env_ptr;
227 TranslationBlock *tb, **ptb1;
228 unsigned int h;
229 tb_page_addr_t phys_pc, phys_page1;
230 target_ulong virt_page2;
231
232 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
233
234
235 phys_pc = get_page_addr_code(env, pc);
236 phys_page1 = phys_pc & TARGET_PAGE_MASK;
237 h = tb_phys_hash_func(phys_pc);
238 ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
239 for(;;) {
240 tb = *ptb1;
241 if (!tb) {
242 return NULL;
243 }
244 if (tb->pc == pc &&
245 tb->page_addr[0] == phys_page1 &&
246 tb->cs_base == cs_base &&
247 tb->flags == flags) {
248
249 if (tb->page_addr[1] != -1) {
250 tb_page_addr_t phys_page2;
251
252 virt_page2 = (pc & TARGET_PAGE_MASK) +
253 TARGET_PAGE_SIZE;
254 phys_page2 = get_page_addr_code(env, virt_page2);
255 if (tb->page_addr[1] == phys_page2) {
256 break;
257 }
258 } else {
259 break;
260 }
261 }
262 ptb1 = &tb->phys_hash_next;
263 }
264
265
266 *ptb1 = tb->phys_hash_next;
267 tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
268 tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
269 return tb;
270}
271
272static TranslationBlock *tb_find_slow(CPUState *cpu,
273 target_ulong pc,
274 target_ulong cs_base,
275 uint64_t flags)
276{
277 TranslationBlock *tb;
278
279 tb = tb_find_physical(cpu, pc, cs_base, flags);
280 if (tb) {
281 goto found;
282 }
283
284#ifdef CONFIG_USER_ONLY
285
286
287
288
289
290 tb_unlock();
291 mmap_lock();
292 tb_lock();
293 tb = tb_find_physical(cpu, pc, cs_base, flags);
294 if (tb) {
295 mmap_unlock();
296 goto found;
297 }
298#endif
299
300
301 tb = tb_gen_code(cpu, pc, cs_base, flags, 0);
302
303#ifdef CONFIG_USER_ONLY
304 mmap_unlock();
305#endif
306
307found:
308
309 cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
310 return tb;
311}
312
313static inline TranslationBlock *tb_find_fast(CPUState *cpu)
314{
315 CPUArchState *env = (CPUArchState *)cpu->env_ptr;
316 TranslationBlock *tb;
317 target_ulong cs_base, pc;
318 int flags;
319
320
321
322
323 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
324 tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
325 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
326 tb->flags != flags)) {
327 tb = tb_find_slow(cpu, pc, cs_base, flags);
328 }
329 return tb;
330}
331
332static void cpu_handle_debug_exception(CPUState *cpu)
333{
334 CPUClass *cc = CPU_GET_CLASS(cpu);
335 CPUWatchpoint *wp;
336
337 if (!cpu->watchpoint_hit) {
338 QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
339 wp->flags &= ~BP_WATCHPOINT_HIT;
340 }
341 }
342
343 cc->debug_excp_handler(cpu);
344}
345
346
347
348int cpu_exec(CPUState *cpu)
349{
350 CPUClass *cc = CPU_GET_CLASS(cpu);
351#ifdef TARGET_I386
352 X86CPU *x86_cpu = X86_CPU(cpu);
353 CPUArchState *env = &x86_cpu->env;
354#endif
355 int ret, interrupt_request;
356 TranslationBlock *tb;
357 uintptr_t next_tb;
358 SyncClocks sc;
359
360
361 current_cpu = cpu;
362
363 if (cpu->halted) {
364#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
365 if ((cpu->interrupt_request & CPU_INTERRUPT_POLL)
366 && replay_interrupt()) {
367 apic_poll_irq(x86_cpu->apic_state);
368 cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
369 }
370#endif
371 if (!cpu_has_work(cpu)) {
372 current_cpu = NULL;
373 return EXCP_HALTED;
374 }
375
376 cpu->halted = 0;
377 }
378
379 atomic_mb_set(&tcg_current_cpu, cpu);
380 rcu_read_lock();
381
382 if (unlikely(atomic_mb_read(&exit_request))) {
383 cpu->exit_request = 1;
384 }
385
386 cc->cpu_exec_enter(cpu);
387
388
389
390
391
392
393 init_delay_params(&sc, cpu);
394
395
396 for(;;) {
397 if (sigsetjmp(cpu->jmp_env, 0) == 0) {
398
399 if (cpu->exception_index >= 0) {
400 if (cpu->exception_index >= EXCP_INTERRUPT) {
401
402 ret = cpu->exception_index;
403 if (ret == EXCP_DEBUG) {
404 cpu_handle_debug_exception(cpu);
405 }
406 cpu->exception_index = -1;
407 break;
408 } else {
409#if defined(CONFIG_USER_ONLY)
410
411
412
413#if defined(TARGET_I386)
414 cc->do_interrupt(cpu);
415#endif
416 ret = cpu->exception_index;
417 cpu->exception_index = -1;
418 break;
419#else
420 if (replay_exception()) {
421 cc->do_interrupt(cpu);
422 cpu->exception_index = -1;
423 } else if (!replay_has_interrupt()) {
424
425 ret = EXCP_INTERRUPT;
426 break;
427 }
428#endif
429 }
430 } else if (replay_has_exception()
431 && cpu->icount_decr.u16.low + cpu->icount_extra == 0) {
432
433 cpu_exec_nocache(cpu, 1, tb_find_fast(cpu), true);
434 ret = -1;
435 break;
436 }
437
438 next_tb = 0;
439 for(;;) {
440 interrupt_request = cpu->interrupt_request;
441 if (unlikely(interrupt_request)) {
442 if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
443
444 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
445 }
446 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
447 cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
448 cpu->exception_index = EXCP_DEBUG;
449 cpu_loop_exit(cpu);
450 }
451 if (replay_mode == REPLAY_MODE_PLAY
452 && !replay_has_interrupt()) {
453
454 } else if (interrupt_request & CPU_INTERRUPT_HALT) {
455 replay_interrupt();
456 cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
457 cpu->halted = 1;
458 cpu->exception_index = EXCP_HLT;
459 cpu_loop_exit(cpu);
460 }
461#if defined(TARGET_I386)
462 else if (interrupt_request & CPU_INTERRUPT_INIT) {
463 replay_interrupt();
464 cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0);
465 do_cpu_init(x86_cpu);
466 cpu->exception_index = EXCP_HALTED;
467 cpu_loop_exit(cpu);
468 }
469#else
470 else if (interrupt_request & CPU_INTERRUPT_RESET) {
471 replay_interrupt();
472 cpu_reset(cpu);
473 cpu_loop_exit(cpu);
474 }
475#endif
476
477
478
479
480 else {
481 replay_interrupt();
482 if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
483 next_tb = 0;
484 }
485 }
486
487
488 if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {
489 cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
490
491
492 next_tb = 0;
493 }
494 }
495 if (unlikely(cpu->exit_request
496 || replay_has_interrupt())) {
497 cpu->exit_request = 0;
498 cpu->exception_index = EXCP_INTERRUPT;
499 cpu_loop_exit(cpu);
500 }
501 tb_lock();
502 tb = tb_find_fast(cpu);
503
504
505 if (tcg_ctx.tb_ctx.tb_invalidated_flag) {
506
507
508
509 next_tb = 0;
510 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
511 }
512
513
514
515 if (next_tb != 0 && tb->page_addr[1] == -1
516 && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
517 tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
518 next_tb & TB_EXIT_MASK, tb);
519 }
520 tb_unlock();
521 if (likely(!cpu->exit_request)) {
522 trace_exec_tb(tb, tb->pc);
523
524 cpu->current_tb = tb;
525 next_tb = cpu_tb_exec(cpu, tb);
526 cpu->current_tb = NULL;
527 switch (next_tb & TB_EXIT_MASK) {
528 case TB_EXIT_REQUESTED:
529
530
531
532
533
534
535
536
537
538
539 smp_rmb();
540 next_tb = 0;
541 break;
542 case TB_EXIT_ICOUNT_EXPIRED:
543 {
544
545 int insns_left = cpu->icount_decr.u32;
546 if (cpu->icount_extra && insns_left >= 0) {
547
548 cpu->icount_extra += insns_left;
549 insns_left = MIN(0xffff, cpu->icount_extra);
550 cpu->icount_extra -= insns_left;
551 cpu->icount_decr.u16.low = insns_left;
552 } else {
553 if (insns_left > 0) {
554
555 tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
556 cpu_exec_nocache(cpu, insns_left, tb, false);
557 align_clocks(&sc, cpu);
558 }
559 cpu->exception_index = EXCP_INTERRUPT;
560 next_tb = 0;
561 cpu_loop_exit(cpu);
562 }
563 break;
564 }
565 default:
566 break;
567 }
568 }
569
570
571 align_clocks(&sc, cpu);
572
573
574 }
575 } else {
576#if defined(__clang__) || !QEMU_GNUC_PREREQ(4, 6)
577
578
579
580
581 cpu = current_cpu;
582 cc = CPU_GET_CLASS(cpu);
583#ifdef TARGET_I386
584 x86_cpu = X86_CPU(cpu);
585 env = &x86_cpu->env;
586#endif
587#else
588
589 g_assert(cpu == current_cpu);
590 g_assert(cc == CPU_GET_CLASS(cpu));
591#ifdef TARGET_I386
592 g_assert(x86_cpu == X86_CPU(cpu));
593 g_assert(env == &x86_cpu->env);
594#endif
595#endif
596 cpu->can_do_io = 1;
597 tb_lock_reset();
598 }
599 }
600
601 cc->cpu_exec_exit(cpu);
602 rcu_read_unlock();
603
604
605 current_cpu = NULL;
606
607
608 atomic_set(&tcg_current_cpu, NULL);
609 return ret;
610}
611