Lines Matching full:cpu
24 #include "hw/core/cpu.h"
25 #include "accel/tcg/cpu-ops.h"
29 #include "exec/cpu-common.h"
30 #include "exec/cpu-interrupt.h"
70 static void align_clocks(SyncClocks *sc, CPUState *cpu) in align_clocks() argument
78 cpu_icount = cpu->icount_extra + cpu->neg.icount_decr.u16.low; in align_clocks()
121 static void init_delay_params(SyncClocks *sc, CPUState *cpu) in init_delay_params() argument
129 = cpu->icount_extra + cpu->neg.icount_decr.u16.low; in init_delay_params()
142 static void align_clocks(SyncClocks *sc, const CPUState *cpu) in align_clocks() argument
146 static void init_delay_params(SyncClocks *sc, const CPUState *cpu) in init_delay_params() argument
194 static TranslationBlock *tb_htable_lookup(CPUState *cpu, TCGTBCPUState s) in tb_htable_lookup() argument
201 desc.env = cpu_env(cpu); in tb_htable_lookup()
214 * @cpu: CPU that will execute the returned translation block
221 * @cflags. Uses @cpu's tb_jmp_cache. Might cause an exception, so have a
226 static inline TranslationBlock *tb_lookup(CPUState *cpu, TCGTBCPUState s) in tb_lookup() argument
236 jc = cpu->tb_jmp_cache; in tb_lookup()
247 tb = tb_htable_lookup(cpu, s); in tb_lookup()
264 static void log_cpu_exec(vaddr pc, CPUState *cpu, in log_cpu_exec() argument
271 cpu->cpu_index, tb->tc.ptr, tb->cs_base, pc, in log_cpu_exec()
285 cpu_dump_state(cpu, logfile, flags); in log_cpu_exec()
292 static bool check_for_breakpoints_slow(CPUState *cpu, vaddr pc, in check_for_breakpoints_slow() argument
307 if (cpu->singlestep_enabled) { in check_for_breakpoints_slow()
311 QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { in check_for_breakpoints_slow()
325 const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; in check_for_breakpoints_slow()
327 match_bp = tcg_ops->debug_check_breakpoint(cpu); in check_for_breakpoints_slow()
332 cpu->exception_index = EXCP_DEBUG; in check_for_breakpoints_slow()
358 static inline bool check_for_breakpoints(CPUState *cpu, vaddr pc, in check_for_breakpoints() argument
361 return unlikely(!QTAILQ_EMPTY(&cpu->breakpoints)) && in check_for_breakpoints()
362 check_for_breakpoints_slow(cpu, pc, cflags); in check_for_breakpoints()
367 * @env: current cpu state
369 * Look for an existing TB matching the current cpu state.
375 CPUState *cpu = env_cpu(env); in HELPER() local
385 cpu->neg.can_do_io = true; in HELPER()
387 TCGTBCPUState s = cpu->cc->tcg_ops->get_tb_cpu_state(cpu); in HELPER()
388 s.cflags = curr_cflags(cpu); in HELPER()
390 if (check_for_breakpoints(cpu, s.pc, &s.cflags)) { in HELPER()
391 cpu_loop_exit(cpu); in HELPER()
394 tb = tb_lookup(cpu, s); in HELPER()
400 log_cpu_exec(s.pc, cpu, tb); in HELPER()
406 /* Return the current PC from CPU, which may be cached in TB. */
407 static vaddr log_pc(CPUState *cpu, const TranslationBlock *tb) in log_pc() argument
410 return cpu->cc->get_pc(cpu); in log_pc()
416 /* Execute a TB, and fix up the CPU state afterwards if necessary */
427 cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) in cpu_tb_exec() argument
434 log_cpu_exec(log_pc(cpu, itb), cpu, itb); in cpu_tb_exec()
438 ret = tcg_qemu_tb_exec(cpu_env(cpu), tb_ptr); in cpu_tb_exec()
439 cpu->neg.can_do_io = true; in cpu_tb_exec()
440 qemu_plugin_disable_mem_helpers(cpu); in cpu_tb_exec()
459 CPUClass *cc = cpu->cc; in cpu_tb_exec()
463 tcg_ops->synchronize_from_tb(cpu, last_tb); in cpu_tb_exec()
467 cc->set_pc(cpu, last_tb->pc); in cpu_tb_exec()
470 vaddr pc = log_pc(cpu, last_tb); in cpu_tb_exec()
484 if (unlikely(cpu->singlestep_enabled) && cpu->exception_index == -1) { in cpu_tb_exec()
485 cpu->exception_index = EXCP_DEBUG; in cpu_tb_exec()
486 cpu_loop_exit(cpu); in cpu_tb_exec()
493 static void cpu_exec_enter(CPUState *cpu) in cpu_exec_enter() argument
495 const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; in cpu_exec_enter()
498 tcg_ops->cpu_exec_enter(cpu); in cpu_exec_enter()
502 static void cpu_exec_exit(CPUState *cpu) in cpu_exec_exit() argument
504 const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; in cpu_exec_exit()
507 tcg_ops->cpu_exec_exit(cpu); in cpu_exec_exit()
511 static void cpu_exec_longjmp_cleanup(CPUState *cpu) in cpu_exec_longjmp_cleanup() argument
514 g_assert(cpu == current_cpu); in cpu_exec_longjmp_cleanup()
525 * have one tcg_ctx per thread, so we know it was this cpu doing in cpu_exec_longjmp_cleanup()
533 * Alternative 2: Set and restore cpu->jmp_env in tb_gen_code to in cpu_exec_longjmp_cleanup()
548 void cpu_exec_step_atomic(CPUState *cpu) in cpu_exec_step_atomic() argument
553 if (sigsetjmp(cpu->jmp_env, 0) == 0) { in cpu_exec_step_atomic()
555 g_assert(cpu == current_cpu); in cpu_exec_step_atomic()
556 g_assert(!cpu->running); in cpu_exec_step_atomic()
557 cpu->running = true; in cpu_exec_step_atomic()
559 TCGTBCPUState s = cpu->cc->tcg_ops->get_tb_cpu_state(cpu); in cpu_exec_step_atomic()
560 s.cflags = curr_cflags(cpu); in cpu_exec_step_atomic()
573 tb = tb_lookup(cpu, s); in cpu_exec_step_atomic()
576 tb = tb_gen_code(cpu, s); in cpu_exec_step_atomic()
580 cpu_exec_enter(cpu); in cpu_exec_step_atomic()
583 cpu_tb_exec(cpu, tb, &tb_exit); in cpu_exec_step_atomic()
584 cpu_exec_exit(cpu); in cpu_exec_step_atomic()
586 cpu_exec_longjmp_cleanup(cpu); in cpu_exec_step_atomic()
594 g_assert(cpu_in_exclusive_context(cpu)); in cpu_exec_step_atomic()
595 cpu->running = false; in cpu_exec_step_atomic()
652 static inline bool cpu_handle_halt(CPUState *cpu) in cpu_handle_halt() argument
655 if (cpu->halted) { in cpu_handle_halt()
656 const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; in cpu_handle_halt()
657 bool leave_halt = tcg_ops->cpu_exec_halt(cpu); in cpu_handle_halt()
663 cpu->halted = 0; in cpu_handle_halt()
670 static inline void cpu_handle_debug_exception(CPUState *cpu) in cpu_handle_debug_exception() argument
672 const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; in cpu_handle_debug_exception()
675 if (!cpu->watchpoint_hit) { in cpu_handle_debug_exception()
676 QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { in cpu_handle_debug_exception()
682 tcg_ops->debug_excp_handler(cpu); in cpu_handle_debug_exception()
686 static inline bool cpu_handle_exception(CPUState *cpu, int *ret) in cpu_handle_exception() argument
688 if (cpu->exception_index < 0) { in cpu_handle_exception()
691 && cpu->neg.icount_decr.u16.low + cpu->icount_extra == 0) { in cpu_handle_exception()
693 cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT) in cpu_handle_exception()
700 if (cpu->exception_index >= EXCP_INTERRUPT) { in cpu_handle_exception()
701 /* exit request from the cpu execution loop */ in cpu_handle_exception()
702 *ret = cpu->exception_index; in cpu_handle_exception()
704 cpu_handle_debug_exception(cpu); in cpu_handle_exception()
706 cpu->exception_index = -1; in cpu_handle_exception()
713 * handled outside the cpu execution loop. in cpu_handle_exception()
715 const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; in cpu_handle_exception()
717 tcg_ops->fake_user_interrupt(cpu); in cpu_handle_exception()
719 *ret = cpu->exception_index; in cpu_handle_exception()
720 cpu->exception_index = -1; in cpu_handle_exception()
724 const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; in cpu_handle_exception()
727 tcg_ops->do_interrupt(cpu); in cpu_handle_exception()
729 cpu->exception_index = -1; in cpu_handle_exception()
731 if (unlikely(cpu->singlestep_enabled)) { in cpu_handle_exception()
738 cpu_handle_debug_exception(cpu); in cpu_handle_exception()
751 static inline bool icount_exit_request(CPUState *cpu) in icount_exit_request() argument
756 if (cpu->cflags_next_tb != -1 && !(cpu->cflags_next_tb & CF_USE_ICOUNT)) { in icount_exit_request()
759 return cpu->neg.icount_decr.u16.low + cpu->icount_extra == 0; in icount_exit_request()
762 static inline bool cpu_handle_interrupt(CPUState *cpu, in cpu_handle_interrupt() argument
770 if (cpu->cflags_next_tb != -1 && cpu->cflags_next_tb & CF_NOIRQ) { in cpu_handle_interrupt()
775 * cpu->interrupt_request and cpu->exit_request. in cpu_handle_interrupt()
776 * Ensure zeroing happens before reading cpu->exit_request or in cpu_handle_interrupt()
777 * cpu->interrupt_request (see also smp_wmb in cpu_exit()) in cpu_handle_interrupt()
779 qatomic_set_mb(&cpu->neg.icount_decr.u16.high, 0); in cpu_handle_interrupt()
781 if (unlikely(qatomic_read(&cpu->interrupt_request))) { in cpu_handle_interrupt()
784 interrupt_request = cpu->interrupt_request; in cpu_handle_interrupt()
785 if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) { in cpu_handle_interrupt()
790 cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG; in cpu_handle_interrupt()
791 cpu->exception_index = EXCP_DEBUG; in cpu_handle_interrupt()
800 cpu->interrupt_request &= ~CPU_INTERRUPT_HALT; in cpu_handle_interrupt()
801 cpu->halted = 1; in cpu_handle_interrupt()
802 cpu->exception_index = EXCP_HLT; in cpu_handle_interrupt()
806 const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; in cpu_handle_interrupt()
810 tcg_ops->cpu_exec_reset(cpu); in cpu_handle_interrupt()
821 if (tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) { in cpu_handle_interrupt()
831 if (unlikely(cpu->singlestep_enabled)) { in cpu_handle_interrupt()
832 cpu->exception_index = EXCP_DEBUG; in cpu_handle_interrupt()
836 cpu->exception_index = -1; in cpu_handle_interrupt()
839 /* The target hook may have updated the 'cpu->interrupt_request'; in cpu_handle_interrupt()
841 interrupt_request = cpu->interrupt_request; in cpu_handle_interrupt()
845 cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB; in cpu_handle_interrupt()
856 if (unlikely(qatomic_read(&cpu->exit_request)) || icount_exit_request(cpu)) { in cpu_handle_interrupt()
857 qatomic_set(&cpu->exit_request, 0); in cpu_handle_interrupt()
858 if (cpu->exception_index == -1) { in cpu_handle_interrupt()
859 cpu->exception_index = EXCP_INTERRUPT; in cpu_handle_interrupt()
867 static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, in cpu_loop_exec_tb() argument
872 tb = cpu_tb_exec(cpu, tb, tb_exit); in cpu_loop_exec_tb()
879 if (cpu_loop_exit_requested(cpu)) { in cpu_loop_exec_tb()
885 * clear cpu->icount_decr.u16.high. in cpu_loop_exec_tb()
894 icount_update(cpu); in cpu_loop_exec_tb()
896 int32_t insns_left = MIN(0xffff, cpu->icount_budget); in cpu_loop_exec_tb()
897 cpu->neg.icount_decr.u16.low = insns_left; in cpu_loop_exec_tb()
898 cpu->icount_extra = cpu->icount_budget - insns_left; in cpu_loop_exec_tb()
907 assert(cpu->icount_extra == 0); in cpu_loop_exec_tb()
908 cpu->cflags_next_tb = (tb->cflags & ~CF_COUNT_MASK) | insns_left; in cpu_loop_exec_tb()
916 cpu_exec_loop(CPUState *cpu, SyncClocks *sc) in cpu_exec_loop() argument
921 while (!cpu_handle_exception(cpu, &ret)) { in cpu_exec_loop()
925 while (!cpu_handle_interrupt(cpu, &last_tb)) { in cpu_exec_loop()
927 TCGTBCPUState s = cpu->cc->tcg_ops->get_tb_cpu_state(cpu); in cpu_exec_loop()
928 s.cflags = cpu->cflags_next_tb; in cpu_exec_loop()
938 s.cflags = curr_cflags(cpu); in cpu_exec_loop()
940 cpu->cflags_next_tb = -1; in cpu_exec_loop()
943 if (check_for_breakpoints(cpu, s.pc, &s.cflags)) { in cpu_exec_loop()
947 tb = tb_lookup(cpu, s); in cpu_exec_loop()
953 tb = tb_gen_code(cpu, s); in cpu_exec_loop()
961 jc = cpu->tb_jmp_cache; in cpu_exec_loop()
982 cpu_loop_exec_tb(cpu, tb, s.pc, &last_tb, &tb_exit); in cpu_exec_loop()
986 align_clocks(sc, cpu); in cpu_exec_loop()
992 static int cpu_exec_setjmp(CPUState *cpu, SyncClocks *sc) in cpu_exec_setjmp() argument
995 if (unlikely(sigsetjmp(cpu->jmp_env, 0) != 0)) { in cpu_exec_setjmp()
996 cpu_exec_longjmp_cleanup(cpu); in cpu_exec_setjmp()
999 return cpu_exec_loop(cpu, sc); in cpu_exec_setjmp()
1002 int cpu_exec(CPUState *cpu) in cpu_exec() argument
1008 current_cpu = cpu; in cpu_exec()
1010 if (cpu_handle_halt(cpu)) { in cpu_exec()
1015 cpu_exec_enter(cpu); in cpu_exec()
1023 init_delay_params(&sc, cpu); in cpu_exec()
1025 ret = cpu_exec_setjmp(cpu, &sc); in cpu_exec()
1027 cpu_exec_exit(cpu); in cpu_exec()
1031 bool tcg_exec_realizefn(CPUState *cpu, Error **errp) in tcg_exec_realizefn() argument
1037 const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; in tcg_exec_realizefn()
1051 cpu->tb_jmp_cache = g_new0(CPUJumpCache, 1); in tcg_exec_realizefn()
1052 tlb_init(cpu); in tcg_exec_realizefn()
1054 tcg_iommu_init_notifier_list(cpu); in tcg_exec_realizefn()
1062 void tcg_exec_unrealizefn(CPUState *cpu) in tcg_exec_unrealizefn() argument
1065 tcg_iommu_free_notifier_list(cpu); in tcg_exec_unrealizefn()
1068 tlb_destroy(cpu); in tcg_exec_unrealizefn()
1069 g_free_rcu(cpu->tb_jmp_cache, rcu); in tcg_exec_unrealizefn()