diff options
Diffstat (limited to 'accel/tcg/tcg-all.c')
-rw-r--r-- | accel/tcg/tcg-all.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index e327d90afd..c1ccad34f1 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -27,13 +27,45 @@ #include "sysemu/accel.h" #include "sysemu/sysemu.h" #include "qom/object.h" +#include "qemu-common.h" +#include "qom/cpu.h" +#include "sysemu/cpus.h" +#include "qemu/main-loop.h" unsigned long tcg_tb_size; static bool tcg_allowed = true; +#ifndef CONFIG_USER_ONLY +/* mask must never be zero, except for A20 change call */ +static void tcg_handle_interrupt(CPUState *cpu, int mask) +{ + int old_mask; + g_assert(qemu_mutex_iothread_locked()); + + old_mask = cpu->interrupt_request; + cpu->interrupt_request |= mask; + + /* + * If called from iothread context, wake the target cpu in + * case its halted. + */ + if (!qemu_cpu_is_self(cpu)) { + qemu_cpu_kick(cpu); + } else { + cpu->icount_decr.u16.high = -1; + if (use_icount && + !cpu->can_do_io + && (mask & ~old_mask) != 0) { + cpu_abort(cpu, "Raised interrupt while not in I/O function"); + } + } +} +#endif + static int tcg_init(MachineState *ms) { tcg_exec_init(tcg_tb_size * 1024 * 1024); + cpu_interrupt_handler = tcg_handle_interrupt; return 0; } |