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