aboutsummaryrefslogtreecommitdiff
path: root/cpus.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2017-02-08 12:48:54 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2017-03-03 16:40:02 +0100
commit2ae41db262e02743b27719fe085e749d957613c0 (patch)
tree2f250d65d9a20985f56a574f7c5f4ee81e48437b /cpus.c
parent4d39892cca86a9162beaa3944057d118ef42edcd (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.c31
1 files changed, 13 insertions, 18 deletions
diff --git a/cpus.c b/cpus.c
index 399e2713b8..56b1338c87 100644
--- a/cpus.c
+++ b/cpus.c
@@ -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)