diff --git a/cpus.c b/cpus.c index 56b1338c87..c857ad2957 100644 --- a/cpus.c +++ b/cpus.c @@ -950,69 +950,10 @@ static void qemu_init_sigbus(void) prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0); } - -static void dummy_signal(int sig) -{ -} - -static void qemu_kvm_init_cpu_signals(CPUState *cpu) -{ - int r; - sigset_t set; - struct sigaction sigact; - - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = dummy_signal; - sigaction(SIG_IPI, &sigact, NULL); - - pthread_sigmask(SIG_BLOCK, NULL, &set); - sigdelset(&set, SIGBUS); - pthread_sigmask(SIG_SETMASK, &set, NULL); - sigdelset(&set, SIG_IPI); - r = kvm_set_signal_mask(cpu, &set); - if (r) { - fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r)); - exit(1); - } -} - -static void qemu_kvm_eat_signals(CPUState *cpu) -{ - struct timespec ts = { 0, 0 }; - siginfo_t siginfo; - sigset_t waitset; - sigset_t chkset; - int r; - - sigemptyset(&waitset); - sigaddset(&waitset, SIG_IPI); - - do { - r = sigtimedwait(&waitset, &siginfo, &ts); - if (r == -1 && !(errno == EAGAIN || errno == EINTR)) { - perror("sigtimedwait"); - exit(1); - } - - r = sigpending(&chkset); - if (r == -1) { - perror("sigpending"); - exit(1); - } - } while (sigismember(&chkset, SIG_IPI)); -} #else /* !CONFIG_LINUX */ static void qemu_init_sigbus(void) { } - -static void qemu_kvm_eat_signals(CPUState *cpu) -{ -} - -static void qemu_kvm_init_cpu_signals(CPUState *cpu) -{ -} #endif /* !CONFIG_LINUX */ static QemuMutex qemu_global_mutex; @@ -1089,7 +1030,6 @@ static void qemu_kvm_wait_io_event(CPUState *cpu) qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); } - qemu_kvm_eat_signals(cpu); qemu_wait_io_event_common(cpu); } @@ -1112,7 +1052,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) exit(1); } - qemu_kvm_init_cpu_signals(cpu); + kvm_init_cpu_signals(cpu); /* signal CPU creation */ cpu->created = true; diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index a1b019da6f..24281fc7f8 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -238,9 +238,6 @@ int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr, target_ulong len, int type); void kvm_remove_all_breakpoints(CPUState *cpu); int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap); -#ifndef _WIN32 -int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset); -#endif int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr); int kvm_on_sigbus(int code, void *addr); @@ -463,6 +460,8 @@ void kvm_cpu_synchronize_state(CPUState *cpu); void kvm_cpu_synchronize_post_reset(CPUState *cpu); void kvm_cpu_synchronize_post_init(CPUState *cpu); +void kvm_init_cpu_signals(CPUState *cpu); + /** * kvm_irqchip_add_msi_route - Add MSI route for specific vector * @s: KVM state diff --git a/kvm-all.c b/kvm-all.c index 0baa193763..1d7fc6c1e8 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1899,6 +1899,32 @@ static __thread int pending_sigbus_code; static __thread bool have_sigbus_pending; #endif +static void kvm_eat_signals(CPUState *cpu) +{ + struct timespec ts = { 0, 0 }; + siginfo_t siginfo; + sigset_t waitset; + sigset_t chkset; + int r; + + sigemptyset(&waitset); + sigaddset(&waitset, SIG_IPI); + + do { + r = sigtimedwait(&waitset, &siginfo, &ts); + if (r == -1 && !(errno == EAGAIN || errno == EINTR)) { + perror("sigtimedwait"); + exit(1); + } + + r = sigpending(&chkset); + if (r == -1) { + perror("sigpending"); + exit(1); + } + } while (sigismember(&chkset, SIG_IPI)); +} + int kvm_cpu_exec(CPUState *cpu) { struct kvm_run *run = cpu->kvm_run; @@ -1949,6 +1975,7 @@ int kvm_cpu_exec(CPUState *cpu) if (run_ret < 0) { if (run_ret == -EINTR || run_ret == -EAGAIN) { DPRINTF("io window exit\n"); + kvm_eat_signals(cpu); ret = EXCP_INTERRUPT; break; } @@ -2388,16 +2415,12 @@ void kvm_remove_all_breakpoints(CPUState *cpu) } #endif /* !KVM_CAP_SET_GUEST_DEBUG */ -int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) +static int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) { KVMState *s = kvm_state; struct kvm_signal_mask *sigmask; int r; - if (!sigset) { - return kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, NULL); - } - sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset)); sigmask->len = s->sigmask_len; @@ -2408,6 +2431,33 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) return r; } +static void dummy_signal(int sig) +{ +} + +void kvm_init_cpu_signals(CPUState *cpu) +{ + int r; + sigset_t set; + struct sigaction sigact; + + memset(&sigact, 0, sizeof(sigact)); + sigact.sa_handler = dummy_signal; + sigaction(SIG_IPI, &sigact, NULL); + + pthread_sigmask(SIG_BLOCK, NULL, &set); +#if defined KVM_HAVE_MCE_INJECTION + sigdelset(&set, SIGBUS); + pthread_sigmask(SIG_SETMASK, &set, NULL); +#endif + sigdelset(&set, SIG_IPI); + r = kvm_set_signal_mask(cpu, &set); + if (r) { + fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r)); + exit(1); + } +} + /* Called asynchronously in VCPU thread. */ int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) { diff --git a/kvm-stub.c b/kvm-stub.c index b1b6b96c96..ef0c7346af 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -95,13 +95,6 @@ void kvm_remove_all_breakpoints(CPUState *cpu) { } -#ifndef _WIN32 -int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) -{ - abort(); -} -#endif - int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) { return 1; @@ -157,4 +150,9 @@ bool kvm_has_free_slot(MachineState *ms) { return false; } + +void kvm_init_cpu_signals(CPUState *cpu) +{ + abort(); +} #endif