|
|
|
@ -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) |
|
|
|
{ |
|
|
|
|