diff --git a/cpu-exec.c b/cpu-exec.c index 08c35f72d4..fc185a4f04 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -288,6 +288,12 @@ int cpu_exec(CPUArchState *env) } #endif #if defined(TARGET_I386) +#if !defined(CONFIG_USER_ONLY) + if (interrupt_request & CPU_INTERRUPT_POLL) { + env->interrupt_request &= ~CPU_INTERRUPT_POLL; + apic_poll_irq(env->apic_state); + } +#endif if (interrupt_request & CPU_INTERRUPT_INIT) { cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0); diff --git a/hw/apic.c b/hw/apic.c index 5b8f3e8150..385555eb43 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -16,6 +16,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see */ +#include "qemu-thread.h" #include "apic_internal.h" #include "apic.h" #include "ioapic.h" @@ -361,7 +362,9 @@ static void apic_update_irq(APICCommonState *s) if (!(s->spurious_vec & APIC_SV_ENABLE)) { return; } - if (apic_irq_pending(s) > 0) { + if (!qemu_cpu_is_self(s->cpu_env)) { + cpu_interrupt(s->cpu_env, CPU_INTERRUPT_POLL); + } else if (apic_irq_pending(s) > 0) { cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); } } diff --git a/hw/apic.h b/hw/apic.h index 62179cebee..a89542b231 100644 --- a/hw/apic.h +++ b/hw/apic.h @@ -20,6 +20,7 @@ void apic_init_reset(DeviceState *s); void apic_sipi(DeviceState *s); void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, TPRAccess access); +void apic_poll_irq(DeviceState *d); /* pc.c */ int cpu_is_bsp(CPUX86State *env); diff --git a/hw/apic_internal.h b/hw/apic_internal.h index 60a6a8bdae..4d8ff490ce 100644 --- a/hw/apic_internal.h +++ b/hw/apic_internal.h @@ -141,7 +141,6 @@ void apic_report_irq_delivered(int delivered); bool apic_next_timer(APICCommonState *s, int64_t current_time); void apic_enable_tpr_access_reporting(DeviceState *d, bool enable); void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr); -void apic_poll_irq(DeviceState *d); void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip, TPRAccess access); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 33d221eae4..2a61c810bb 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -478,6 +478,7 @@ for syscall instruction */ /* i386-specific interrupt pending bits. */ +#define CPU_INTERRUPT_POLL CPU_INTERRUPT_TGT_EXT_1 #define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2 #define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3 #define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4 @@ -1048,7 +1049,8 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp) static inline bool cpu_has_work(CPUX86State *env) { - return ((env->interrupt_request & CPU_INTERRUPT_HARD) && + return ((env->interrupt_request & (CPU_INTERRUPT_HARD | + CPU_INTERRUPT_POLL)) && (env->eflags & IF_MASK)) || (env->interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_INIT | diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 52b577fe2b..e53c2f6bdf 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1732,6 +1732,10 @@ int kvm_arch_process_async_events(CPUX86State *env) return 0; } + if (env->interrupt_request & CPU_INTERRUPT_POLL) { + env->interrupt_request &= ~CPU_INTERRUPT_POLL; + apic_poll_irq(env->apic_state); + } if (((env->interrupt_request & CPU_INTERRUPT_HARD) && (env->eflags & IF_MASK)) || (env->interrupt_request & CPU_INTERRUPT_NMI)) {