diff --git a/configure b/configure index 598e8e1ebb0fb1634b565fdcaf8199b3a67f5bf6..a3f53456f4e0cfbd05e3bd99d781491f591b872e 100755 --- a/configure +++ b/configure @@ -2057,6 +2057,12 @@ EOF if compile_prog "" "" ; then signalfd=yes +elif test "$kvm" = "yes" -a "$io_thread" != "yes"; then + echo + echo "ERROR: Host kernel lacks signalfd() support," + echo "but KVM depends on it when the IO thread is disabled." + echo + exit 1 fi # check if eventfd is supported diff --git a/cpus.c b/cpus.c index 84792f0a0e91f57ae9226441a72a7c267b64a98f..38dd506b9248a4e7ae54489d4e1513d67219229f 100644 --- a/cpus.c +++ b/cpus.c @@ -319,6 +319,12 @@ static void qemu_kvm_eat_signals(CPUState *env) exit(1); } } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS)); + +#ifndef CONFIG_IOTHREAD + if (sigismember(&chkset, SIGIO) || sigismember(&chkset, SIGALRM)) { + qemu_notify_event(); + } +#endif } #else /* _WIN32 */ @@ -368,11 +374,15 @@ static void qemu_kvm_init_cpu_signals(CPUState *env) sigemptyset(&set); sigaddset(&set, SIG_IPI); + sigaddset(&set, SIGIO); + sigaddset(&set, SIGALRM); pthread_sigmask(SIG_BLOCK, &set, NULL); pthread_sigmask(SIG_BLOCK, NULL, &set); sigdelset(&set, SIG_IPI); sigdelset(&set, SIGBUS); + sigdelset(&set, SIGIO); + sigdelset(&set, SIGALRM); r = kvm_set_signal_mask(env, &set); if (r) { fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r)); @@ -381,13 +391,32 @@ static void qemu_kvm_init_cpu_signals(CPUState *env) #endif } +#ifndef _WIN32 +static sigset_t block_synchronous_signals(void) +{ + sigset_t set; + + sigemptyset(&set); + if (kvm_enabled()) { + /* + * We need to process timer signals synchronously to avoid a race + * between exit_request check and KVM vcpu entry. + */ + sigaddset(&set, SIGIO); + sigaddset(&set, SIGALRM); + } + + return set; +} +#endif + int qemu_init_main_loop(void) { #ifndef _WIN32 sigset_t blocked_signals; int ret; - sigemptyset(&blocked_signals); + blocked_signals = block_synchronous_signals(); ret = qemu_signalfd_init(blocked_signals); if (ret) {