1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "config.h"
20#include "cpu.h"
21#include "disas/disas.h"
22#include "tcg.h"
23#include "qemu/atomic.h"
24#include "sysemu/qtest.h"
25
26int tb_invalidated_flag;
27
28
29
30bool qemu_cpu_has_work(CPUState *cpu)
31{
32 return cpu_has_work(cpu);
33}
34
35void cpu_loop_exit(CPUArchState *env)
36{
37 env->current_tb = NULL;
38 longjmp(env->jmp_env, 1);
39}
40
41
42
43
44#if defined(CONFIG_SOFTMMU)
45void cpu_resume_from_signal(CPUArchState *env, void *puc)
46{
47
48
49 env->exception_index = -1;
50 longjmp(env->jmp_env, 1);
51}
52#endif
53
54
55
56static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
57 TranslationBlock *orig_tb)
58{
59 tcg_target_ulong next_tb;
60 TranslationBlock *tb;
61
62
63
64 if (max_cycles > CF_COUNT_MASK)
65 max_cycles = CF_COUNT_MASK;
66
67 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
68 max_cycles);
69 env->current_tb = tb;
70
71 next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
72 env->current_tb = NULL;
73
74 if ((next_tb & 3) == 2) {
75
76
77 cpu_pc_from_tb(env, tb);
78 }
79 tb_phys_invalidate(tb, -1);
80 tb_free(tb);
81}
82
83static TranslationBlock *tb_find_slow(CPUArchState *env,
84 target_ulong pc,
85 target_ulong cs_base,
86 uint64_t flags)
87{
88 TranslationBlock *tb, **ptb1;
89 unsigned int h;
90 tb_page_addr_t phys_pc, phys_page1;
91 target_ulong virt_page2;
92
93 tb_invalidated_flag = 0;
94
95
96 phys_pc = get_page_addr_code(env, pc);
97 phys_page1 = phys_pc & TARGET_PAGE_MASK;
98 h = tb_phys_hash_func(phys_pc);
99 ptb1 = &tb_phys_hash[h];
100 for(;;) {
101 tb = *ptb1;
102 if (!tb)
103 goto not_found;
104 if (tb->pc == pc &&
105 tb->page_addr[0] == phys_page1 &&
106 tb->cs_base == cs_base &&
107 tb->flags == flags) {
108
109 if (tb->page_addr[1] != -1) {
110 tb_page_addr_t phys_page2;
111
112 virt_page2 = (pc & TARGET_PAGE_MASK) +
113 TARGET_PAGE_SIZE;
114 phys_page2 = get_page_addr_code(env, virt_page2);
115 if (tb->page_addr[1] == phys_page2)
116 goto found;
117 } else {
118 goto found;
119 }
120 }
121 ptb1 = &tb->phys_hash_next;
122 }
123 not_found:
124
125 tb = tb_gen_code(env, pc, cs_base, flags, 0);
126
127 found:
128
129 if (likely(*ptb1)) {
130 *ptb1 = tb->phys_hash_next;
131 tb->phys_hash_next = tb_phys_hash[h];
132 tb_phys_hash[h] = tb;
133 }
134
135 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
136 return tb;
137}
138
139static inline TranslationBlock *tb_find_fast(CPUArchState *env)
140{
141 TranslationBlock *tb;
142 target_ulong cs_base, pc;
143 int flags;
144
145
146
147
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}
156
157static CPUDebugExcpHandler *debug_excp_handler;
158
159void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
160{
161 debug_excp_handler = handler;
162}
163
164static void cpu_handle_debug_exception(CPUArchState *env)
165{
166 CPUWatchpoint *wp;
167
168 if (!env->watchpoint_hit) {
169 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
170 wp->flags &= ~BP_WATCHPOINT_HIT;
171 }
172 }
173 if (debug_excp_handler) {
174 debug_excp_handler(env);
175 }
176}
177
178
179
180volatile sig_atomic_t exit_request;
181
182int cpu_exec(CPUArchState *env)
183{
184 CPUState *cpu = ENV_GET_CPU(env);
185 int ret, interrupt_request;
186 TranslationBlock *tb;
187 uint8_t *tc_ptr;
188 tcg_target_ulong next_tb;
189
190 if (env->halted) {
191 if (!cpu_has_work(cpu)) {
192 return EXCP_HALTED;
193 }
194
195 env->halted = 0;
196 }
197
198 cpu_single_env = env;
199
200 if (unlikely(exit_request)) {
201 env->exit_request = 1;
202 }
203
204#if defined(TARGET_I386)
205
206 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
207 DF = 1 - (2 * ((env->eflags >> 10) & 1));
208 CC_OP = CC_OP_EFLAGS;
209 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
210#elif defined(TARGET_SPARC)
211#elif defined(TARGET_M68K)
212 env->cc_op = CC_OP_FLAGS;
213 env->cc_dest = env->sr & 0xf;
214 env->cc_x = (env->sr >> 4) & 1;
215#elif defined(TARGET_ALPHA)
216#elif defined(TARGET_ARM)
217#elif defined(TARGET_UNICORE32)
218#elif defined(TARGET_PPC)
219 env->reserve_addr = -1;
220#elif defined(TARGET_LM32)
221#elif defined(TARGET_MICROBLAZE)
222#elif defined(TARGET_MIPS)
223#elif defined(TARGET_OPENRISC)
224#elif defined(TARGET_SH4)
225#elif defined(TARGET_CRIS)
226#elif defined(TARGET_S390X)
227#elif defined(TARGET_XTENSA)
228
229#else
230#error unsupported target CPU
231#endif
232 env->exception_index = -1;
233
234
235 for(;;) {
236 if (setjmp(env->jmp_env) == 0) {
237
238 if (env->exception_index >= 0) {
239 if (env->exception_index >= EXCP_INTERRUPT) {
240
241 ret = env->exception_index;
242 if (ret == EXCP_DEBUG) {
243 cpu_handle_debug_exception(env);
244 }
245 break;
246 } else {
247#if defined(CONFIG_USER_ONLY)
248
249
250
251#if defined(TARGET_I386)
252 do_interrupt(env);
253#endif
254 ret = env->exception_index;
255 break;
256#else
257 do_interrupt(env);
258 env->exception_index = -1;
259#endif
260 }
261 }
262
263 next_tb = 0;
264 for(;;) {
265 interrupt_request = env->interrupt_request;
266 if (unlikely(interrupt_request)) {
267 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
268
269 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
270 }
271 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
272 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
273 env->exception_index = EXCP_DEBUG;
274 cpu_loop_exit(env);
275 }
276#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
277 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
278 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
279 if (interrupt_request & CPU_INTERRUPT_HALT) {
280 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
281 env->halted = 1;
282 env->exception_index = EXCP_HLT;
283 cpu_loop_exit(env);
284 }
285#endif
286#if defined(TARGET_I386)
287#if !defined(CONFIG_USER_ONLY)
288 if (interrupt_request & CPU_INTERRUPT_POLL) {
289 env->interrupt_request &= ~CPU_INTERRUPT_POLL;
290 apic_poll_irq(env->apic_state);
291 }
292#endif
293 if (interrupt_request & CPU_INTERRUPT_INIT) {
294 cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
295 0);
296 do_cpu_init(x86_env_get_cpu(env));
297 env->exception_index = EXCP_HALTED;
298 cpu_loop_exit(env);
299 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
300 do_cpu_sipi(x86_env_get_cpu(env));
301 } else if (env->hflags2 & HF2_GIF_MASK) {
302 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
303 !(env->hflags & HF_SMM_MASK)) {
304 cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
305 0);
306 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
307 do_smm_enter(env);
308 next_tb = 0;
309 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
310 !(env->hflags2 & HF2_NMI_MASK)) {
311 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
312 env->hflags2 |= HF2_NMI_MASK;
313 do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
314 next_tb = 0;
315 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
316 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
317 do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
318 next_tb = 0;
319 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
320 (((env->hflags2 & HF2_VINTR_MASK) &&
321 (env->hflags2 & HF2_HIF_MASK)) ||
322 (!(env->hflags2 & HF2_VINTR_MASK) &&
323 (env->eflags & IF_MASK &&
324 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
325 int intno;
326 cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
327 0);
328 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
329 intno = cpu_get_pic_interrupt(env);
330 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
331 do_interrupt_x86_hardirq(env, intno, 1);
332
333
334 next_tb = 0;
335#if !defined(CONFIG_USER_ONLY)
336 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
337 (env->eflags & IF_MASK) &&
338 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
339 int intno;
340
341 cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
342 0);
343 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
344 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
345 do_interrupt_x86_hardirq(env, intno, 1);
346 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
347 next_tb = 0;
348#endif
349 }
350 }
351#elif defined(TARGET_PPC)
352 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
353 cpu_reset(cpu);
354 }
355 if (interrupt_request & CPU_INTERRUPT_HARD) {
356 ppc_hw_interrupt(env);
357 if (env->pending_interrupts == 0)
358 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
359 next_tb = 0;
360 }
361#elif defined(TARGET_LM32)
362 if ((interrupt_request & CPU_INTERRUPT_HARD)
363 && (env->ie & IE_IE)) {
364 env->exception_index = EXCP_IRQ;
365 do_interrupt(env);
366 next_tb = 0;
367 }
368#elif defined(TARGET_MICROBLAZE)
369 if ((interrupt_request & CPU_INTERRUPT_HARD)
370 && (env->sregs[SR_MSR] & MSR_IE)
371 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
372 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
373 env->exception_index = EXCP_IRQ;
374 do_interrupt(env);
375 next_tb = 0;
376 }
377#elif defined(TARGET_MIPS)
378 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
379 cpu_mips_hw_interrupts_pending(env)) {
380
381 env->exception_index = EXCP_EXT_INTERRUPT;
382 env->error_code = 0;
383 do_interrupt(env);
384 next_tb = 0;
385 }
386#elif defined(TARGET_OPENRISC)
387 {
388 int idx = -1;
389 if ((interrupt_request & CPU_INTERRUPT_HARD)
390 && (env->sr & SR_IEE)) {
391 idx = EXCP_INT;
392 }
393 if ((interrupt_request & CPU_INTERRUPT_TIMER)
394 && (env->sr & SR_TEE)) {
395 idx = EXCP_TICK;
396 }
397 if (idx >= 0) {
398 env->exception_index = idx;
399 do_interrupt(env);
400 next_tb = 0;
401 }
402 }
403#elif defined(TARGET_SPARC)
404 if (interrupt_request & CPU_INTERRUPT_HARD) {
405 if (cpu_interrupts_enabled(env) &&
406 env->interrupt_index > 0) {
407 int pil = env->interrupt_index & 0xf;
408 int type = env->interrupt_index & 0xf0;
409
410 if (((type == TT_EXTINT) &&
411 cpu_pil_allowed(env, pil)) ||
412 type != TT_EXTINT) {
413 env->exception_index = env->interrupt_index;
414 do_interrupt(env);
415 next_tb = 0;
416 }
417 }
418 }
419#elif defined(TARGET_ARM)
420 if (interrupt_request & CPU_INTERRUPT_FIQ
421 && !(env->uncached_cpsr & CPSR_F)) {
422 env->exception_index = EXCP_FIQ;
423 do_interrupt(env);
424 next_tb = 0;
425 }
426
427
428
429
430
431
432
433
434
435 if (interrupt_request & CPU_INTERRUPT_HARD
436 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
437 || !(env->uncached_cpsr & CPSR_I))) {
438 env->exception_index = EXCP_IRQ;
439 do_interrupt(env);
440 next_tb = 0;
441 }
442#elif defined(TARGET_UNICORE32)
443 if (interrupt_request & CPU_INTERRUPT_HARD
444 && !(env->uncached_asr & ASR_I)) {
445 env->exception_index = UC32_EXCP_INTR;
446 do_interrupt(env);
447 next_tb = 0;
448 }
449#elif defined(TARGET_SH4)
450 if (interrupt_request & CPU_INTERRUPT_HARD) {
451 do_interrupt(env);
452 next_tb = 0;
453 }
454#elif defined(TARGET_ALPHA)
455 {
456 int idx = -1;
457
458 switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
459 case 0 ... 3:
460 if (interrupt_request & CPU_INTERRUPT_HARD) {
461 idx = EXCP_DEV_INTERRUPT;
462 }
463
464 case 4:
465 if (interrupt_request & CPU_INTERRUPT_TIMER) {
466 idx = EXCP_CLK_INTERRUPT;
467 }
468
469 case 5:
470 if (interrupt_request & CPU_INTERRUPT_SMP) {
471 idx = EXCP_SMP_INTERRUPT;
472 }
473
474 case 6:
475 if (interrupt_request & CPU_INTERRUPT_MCHK) {
476 idx = EXCP_MCHK;
477 }
478 }
479 if (idx >= 0) {
480 env->exception_index = idx;
481 env->error_code = 0;
482 do_interrupt(env);
483 next_tb = 0;
484 }
485 }
486#elif defined(TARGET_CRIS)
487 if (interrupt_request & CPU_INTERRUPT_HARD
488 && (env->pregs[PR_CCS] & I_FLAG)
489 && !env->locked_irq) {
490 env->exception_index = EXCP_IRQ;
491 do_interrupt(env);
492 next_tb = 0;
493 }
494 if (interrupt_request & CPU_INTERRUPT_NMI) {
495 unsigned int m_flag_archval;
496 if (env->pregs[PR_VR] < 32) {
497 m_flag_archval = M_FLAG_V10;
498 } else {
499 m_flag_archval = M_FLAG_V32;
500 }
501 if ((env->pregs[PR_CCS] & m_flag_archval)) {
502 env->exception_index = EXCP_NMI;
503 do_interrupt(env);
504 next_tb = 0;
505 }
506 }
507#elif defined(TARGET_M68K)
508 if (interrupt_request & CPU_INTERRUPT_HARD
509 && ((env->sr & SR_I) >> SR_I_SHIFT)
510 < env->pending_level) {
511
512
513
514
515
516 env->exception_index = env->pending_vector;
517 do_interrupt_m68k_hardirq(env);
518 next_tb = 0;
519 }
520#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
521 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
522 (env->psw.mask & PSW_MASK_EXT)) {
523 do_interrupt(env);
524 next_tb = 0;
525 }
526#elif defined(TARGET_XTENSA)
527 if (interrupt_request & CPU_INTERRUPT_HARD) {
528 env->exception_index = EXC_IRQ;
529 do_interrupt(env);
530 next_tb = 0;
531 }
532#endif
533
534
535 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
536 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
537
538
539 next_tb = 0;
540 }
541 }
542 if (unlikely(env->exit_request)) {
543 env->exit_request = 0;
544 env->exception_index = EXCP_INTERRUPT;
545 cpu_loop_exit(env);
546 }
547#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
548 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
549
550#if defined(TARGET_I386)
551 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
552 | (DF & DF_MASK);
553 log_cpu_state(env, CPU_DUMP_CCOP);
554 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
555#elif defined(TARGET_M68K)
556 cpu_m68k_flush_flags(env, env->cc_op);
557 env->cc_op = CC_OP_FLAGS;
558 env->sr = (env->sr & 0xffe0)
559 | env->cc_dest | (env->cc_x << 4);
560 log_cpu_state(env, 0);
561#else
562 log_cpu_state(env, 0);
563#endif
564 }
565#endif
566 spin_lock(&tb_lock);
567 tb = tb_find_fast(env);
568
569
570 if (tb_invalidated_flag) {
571
572
573
574 next_tb = 0;
575 tb_invalidated_flag = 0;
576 }
577#ifdef CONFIG_DEBUG_EXEC
578 qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
579 tb->tc_ptr, tb->pc,
580 lookup_symbol(tb->pc));
581#endif
582
583
584
585 if (next_tb != 0 && tb->page_addr[1] == -1) {
586 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
587 }
588 spin_unlock(&tb_lock);
589
590
591
592
593
594 env->current_tb = tb;
595 barrier();
596 if (likely(!env->exit_request)) {
597 tc_ptr = tb->tc_ptr;
598
599 next_tb = tcg_qemu_tb_exec(env, tc_ptr);
600 if ((next_tb & 3) == 2) {
601
602 int insns_left;
603 tb = (TranslationBlock *)(next_tb & ~3);
604
605 cpu_pc_from_tb(env, tb);
606 insns_left = env->icount_decr.u32;
607 if (env->icount_extra && insns_left >= 0) {
608
609 env->icount_extra += insns_left;
610 if (env->icount_extra > 0xffff) {
611 insns_left = 0xffff;
612 } else {
613 insns_left = env->icount_extra;
614 }
615 env->icount_extra -= insns_left;
616 env->icount_decr.u16.low = insns_left;
617 } else {
618 if (insns_left > 0) {
619
620 cpu_exec_nocache(env, insns_left, tb);
621 }
622 env->exception_index = EXCP_INTERRUPT;
623 next_tb = 0;
624 cpu_loop_exit(env);
625 }
626 }
627 }
628 env->current_tb = NULL;
629
630
631 }
632 } else {
633
634
635 env = cpu_single_env;
636 }
637 }
638
639
640#if defined(TARGET_I386)
641
642 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
643 | (DF & DF_MASK);
644#elif defined(TARGET_ARM)
645
646#elif defined(TARGET_UNICORE32)
647#elif defined(TARGET_SPARC)
648#elif defined(TARGET_PPC)
649#elif defined(TARGET_LM32)
650#elif defined(TARGET_M68K)
651 cpu_m68k_flush_flags(env, env->cc_op);
652 env->cc_op = CC_OP_FLAGS;
653 env->sr = (env->sr & 0xffe0)
654 | env->cc_dest | (env->cc_x << 4);
655#elif defined(TARGET_MICROBLAZE)
656#elif defined(TARGET_MIPS)
657#elif defined(TARGET_OPENRISC)
658#elif defined(TARGET_SH4)
659#elif defined(TARGET_ALPHA)
660#elif defined(TARGET_CRIS)
661#elif defined(TARGET_S390X)
662#elif defined(TARGET_XTENSA)
663
664#else
665#error unsupported target CPU
666#endif
667
668
669 cpu_single_env = NULL;
670 return ret;
671}
672