diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2017-02-08 12:48:54 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-03-03 16:40:02 +0100 |
commit | 2ae41db262e02743b27719fe085e749d957613c0 (patch) | |
tree | 2f250d65d9a20985f56a574f7c5f4ee81e48437b /cpus.c | |
parent | 4d39892cca86a9162beaa3944057d118ef42edcd (diff) |
KVM: do not use sigtimedwait to catch SIGBUS
Call kvm_on_sigbus_vcpu asynchronously from the VCPU thread.
Information for the SIGBUS can be stored in thread-local variables
and processed later in kvm_cpu_exec.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'cpus.c')
-rw-r--r-- | cpus.c | 31 |
1 files changed, 13 insertions, 18 deletions
@@ -926,8 +926,16 @@ static void sigbus_handler(int n, siginfo_t *siginfo, void *ctx) sigbus_reraise(); } - if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) { - sigbus_reraise(); + if (current_cpu) { + /* Called asynchronously in VCPU thread. */ + if (kvm_on_sigbus_vcpu(current_cpu, siginfo->si_code, siginfo->si_addr)) { + sigbus_reraise(); + } + } else { + /* Called synchronously (via signalfd) in main thread. */ + if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) { + sigbus_reraise(); + } } } @@ -958,8 +966,9 @@ static void qemu_kvm_init_cpu_signals(CPUState *cpu) sigaction(SIG_IPI, &sigact, NULL); pthread_sigmask(SIG_BLOCK, NULL, &set); - sigdelset(&set, SIG_IPI); 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)); @@ -977,7 +986,6 @@ static void qemu_kvm_eat_signals(CPUState *cpu) sigemptyset(&waitset); sigaddset(&waitset, SIG_IPI); - sigaddset(&waitset, SIGBUS); do { r = sigtimedwait(&waitset, &siginfo, &ts); @@ -986,25 +994,12 @@ static void qemu_kvm_eat_signals(CPUState *cpu) exit(1); } - switch (r) { - case SIGBUS: - if (siginfo.si_code != BUS_MCEERR_AO && siginfo.si_code != BUS_MCEERR_AR) { - sigbus_reraise(); - } - if (kvm_on_sigbus_vcpu(cpu, siginfo.si_code, siginfo.si_addr)) { - sigbus_reraise(); - } - break; - default: - break; - } - r = sigpending(&chkset); if (r == -1) { perror("sigpending"); exit(1); } - } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS)); + } while (sigismember(&chkset, SIG_IPI)); } #else /* !CONFIG_LINUX */ static void qemu_init_sigbus(void) |