diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2010-02-24 16:01:21 -0300 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-02-24 16:01:21 -0300 |
commit | 9e49066b3dd6b659fc04eb4375e016dcb9492dce (patch) | |
tree | 279e4179ea95e1bfd3765c370699fe2120c1985a | |
parent | 6249f61a891b6b003531ca4e459c3a553faa82bc (diff) | |
parent | cc84de9570ffe01a9c3c169bd62ab9586a9a080c (diff) |
Merge commit 'cc84de9570ffe01a9c3c169bd62ab9586a9a080c' into upstream-merge
* commit 'cc84de9570ffe01a9c3c169bd62ab9586a9a080c':
kvm: consume internal signal with sigtimedwait
kvm specific wait_io_event
block SIGCHLD in vcpu thread(s)
kvm: Kill CR3_CACHE feature references
kvm: Fix eflags corruption in kvm mode
Conflicts:
kvm-all.c
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | cpu-exec.c | 12 | ||||
-rw-r--r-- | kvm-all.c | 20 | ||||
-rw-r--r-- | kvm.h | 1 | ||||
-rw-r--r-- | qemu-kvm.c | 17 | ||||
-rw-r--r-- | qemu-kvm.h | 15 | ||||
-rw-r--r-- | vl.c | 114 |
6 files changed, 125 insertions, 54 deletions
diff --git a/cpu-exec.c b/cpu-exec.c index 3da7730b3..fe1176ddb 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -234,11 +234,13 @@ int cpu_exec(CPUState *env1) env = env1; #if defined(TARGET_I386) - /* put eflags in CPU temporary format */ - CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); - DF = 1 - (2 * ((env->eflags >> 10) & 1)); - CC_OP = CC_OP_EFLAGS; - env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); + if (!kvm_enabled()) { + /* put eflags in CPU temporary format */ + CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); + DF = 1 - (2 * ((env->eflags >> 10) & 1)); + CC_OP = CC_OP_EFLAGS; + env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); + } #elif defined(TARGET_SPARC) #elif defined(TARGET_M68K) env->cc_op = CC_OP_FLAGS; @@ -789,6 +789,7 @@ int kvm_cpu_exec(CPUState *env) kvm_arch_post_run(env, run); if (ret == -EINTR || ret == -EAGAIN) { + cpu_exit(env); dprintf("io window exit\n"); ret = 0; break; @@ -1137,5 +1138,24 @@ void kvm_remove_all_breakpoints(CPUState *current_env) } #endif /* !KVM_CAP_SET_GUEST_DEBUG */ +int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset) +{ + struct kvm_signal_mask *sigmask; + int r; + + if (!sigset) + return kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, NULL); + + sigmask = qemu_malloc(sizeof(*sigmask) + sizeof(*sigset)); + + sigmask->len = 8; + memcpy(sigmask->sigset, sigset, sizeof(*sigset)); + r = kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, sigmask); + free(sigmask); + + return r; +} + #undef PAGE_SIZE #include "qemu-kvm.c" + @@ -60,6 +60,7 @@ int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr, target_ulong len, int type); void kvm_remove_all_breakpoints(CPUState *current_env); int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap); +int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset); int kvm_pit_in_kernel(void); int kvm_irqchip_in_kernel(void); diff --git a/qemu-kvm.c b/qemu-kvm.c index 979038925..29365a9cf 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -1026,23 +1026,6 @@ int kvm_inject_irq(CPUState *env, unsigned irq) return kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr); } -int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset) -{ - struct kvm_signal_mask *sigmask; - int r; - - if (!sigset) { - return kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, NULL); - } - sigmask = qemu_malloc(sizeof(*sigmask) + sizeof(*sigset)); - - sigmask->len = 8; - memcpy(sigmask->sigset, sigset, sizeof(*sigset)); - r = kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, sigmask); - free(sigmask); - return r; -} - int kvm_inject_nmi(CPUState *env) { #ifdef KVM_CAP_USER_NMI diff --git a/qemu-kvm.h b/qemu-kvm.h index 93b144ff7..ecb52c1f6 100644 --- a/qemu-kvm.h +++ b/qemu-kvm.h @@ -373,21 +373,6 @@ int kvm_get_shadow_pages(kvm_context_t kvm, unsigned int *nrshadow_pages); #endif /*! - * \brief Set a vcpu's signal mask for guest mode - * - * A vcpu can have different signals blocked in guest mode and user mode. - * This allows guest execution to be interrupted on a signal, without requiring - * that the signal be delivered to a signal handler (the signal can be - * dequeued using sigwait(2). - * - * \param kvm Pointer to the current kvm_context - * \param vcpu Which virtual CPU should be initialized - * \param sigset signal mask for guest mode - * \return 0 on success, or -errno on error - */ -int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset); - -/*! * \brief Dump VCPU registers * * This dumps some of the information that KVM has about a virtual CPU, namely: @@ -283,6 +283,12 @@ uint8_t qemu_uuid[16]; static QEMUBootSetHandler *boot_set_handler; static void *boot_set_opaque; +#ifdef SIGRTMIN +#define SIG_IPI (SIGRTMIN+4) +#else +#define SIG_IPI SIGUSR1 +#endif + static int default_serial = 1; static int default_parallel = 1; static int default_virtcon = 1; @@ -3388,9 +3394,11 @@ static QemuCond qemu_cpu_cond; static QemuCond qemu_system_cond; static QemuCond qemu_pause_cond; -static void block_io_signals(void); +static void tcg_block_io_signals(void); +static void kvm_block_io_signals(CPUState *env); static void unblock_io_signals(void); static int tcg_has_work(void); +static int cpu_has_work(CPUState *env); static int qemu_init_main_loop(void) { @@ -3411,6 +3419,15 @@ static int qemu_init_main_loop(void) return 0; } +static void qemu_wait_io_event_common(CPUState *env) +{ + if (env->stop) { + env->stop = 0; + env->stopped = 1; + qemu_cond_signal(&qemu_pause_cond); + } +} + static void qemu_wait_io_event(CPUState *env) { while (!tcg_has_work()) @@ -3427,24 +3444,54 @@ static void qemu_wait_io_event(CPUState *env) qemu_mutex_unlock(&qemu_fair_mutex); qemu_mutex_lock(&qemu_global_mutex); - if (env->stop) { - env->stop = 0; - env->stopped = 1; - qemu_cond_signal(&qemu_pause_cond); + qemu_wait_io_event_common(env); +} + +static void qemu_kvm_eat_signal(CPUState *env, int timeout) +{ + struct timespec ts; + int r, e; + siginfo_t siginfo; + sigset_t waitset; + + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + + sigemptyset(&waitset); + sigaddset(&waitset, SIG_IPI); + + qemu_mutex_unlock(&qemu_global_mutex); + r = sigtimedwait(&waitset, &siginfo, &ts); + e = errno; + qemu_mutex_lock(&qemu_global_mutex); + + if (r == -1 && !(e == EAGAIN || e == EINTR)) { + fprintf(stderr, "sigtimedwait: %s\n", strerror(e)); + exit(1); } } +static void qemu_kvm_wait_io_event(CPUState *env) +{ + while (!cpu_has_work(env)) + qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000); + + qemu_kvm_eat_signal(env, 0); + qemu_wait_io_event_common(env); +} + static int qemu_cpu_exec(CPUState *env); static void *kvm_cpu_thread_fn(void *arg) { CPUState *env = arg; - block_io_signals(); qemu_thread_self(env->thread); if (kvm_enabled()) kvm_init_vcpu(env); + kvm_block_io_signals(env); + /* signal CPU creation */ qemu_mutex_lock(&qemu_global_mutex); env->created = 1; @@ -3457,7 +3504,7 @@ static void *kvm_cpu_thread_fn(void *arg) while (1) { if (cpu_can_run(env)) qemu_cpu_exec(env); - qemu_wait_io_event(env); + qemu_kvm_wait_io_event(env); } return NULL; @@ -3469,7 +3516,7 @@ static void *tcg_cpu_thread_fn(void *arg) { CPUState *env = arg; - block_io_signals(); + tcg_block_io_signals(); qemu_thread_self(env->thread); /* signal CPU creation */ @@ -3495,7 +3542,7 @@ void qemu_cpu_kick(void *_env) CPUState *env = _env; qemu_cond_broadcast(env->halt_cond); if (kvm_enabled()) - qemu_thread_signal(env->thread, SIGUSR1); + qemu_thread_signal(env->thread, SIG_IPI); } int qemu_cpu_self(void *_env) @@ -3514,7 +3561,7 @@ static void cpu_signal(int sig) cpu_exit(cpu_single_env); } -static void block_io_signals(void) +static void tcg_block_io_signals(void) { sigset_t set; struct sigaction sigact; @@ -3523,15 +3570,48 @@ static void block_io_signals(void) sigaddset(&set, SIGUSR2); sigaddset(&set, SIGIO); sigaddset(&set, SIGALRM); + sigaddset(&set, SIGCHLD); pthread_sigmask(SIG_BLOCK, &set, NULL); sigemptyset(&set); - sigaddset(&set, SIGUSR1); + sigaddset(&set, SIG_IPI); pthread_sigmask(SIG_UNBLOCK, &set, NULL); memset(&sigact, 0, sizeof(sigact)); sigact.sa_handler = cpu_signal; - sigaction(SIGUSR1, &sigact, NULL); + sigaction(SIG_IPI, &sigact, NULL); +} + +static void dummy_signal(int sig) +{ +} + +static void kvm_block_io_signals(CPUState *env) +{ + int r; + sigset_t set; + struct sigaction sigact; + + sigemptyset(&set); + sigaddset(&set, SIGUSR2); + sigaddset(&set, SIGIO); + sigaddset(&set, SIGALRM); + sigaddset(&set, SIGCHLD); + sigaddset(&set, SIG_IPI); + pthread_sigmask(SIG_BLOCK, &set, NULL); + + pthread_sigmask(SIG_BLOCK, NULL, &set); + sigdelset(&set, SIG_IPI); + + memset(&sigact, 0, sizeof(sigact)); + sigact.sa_handler = dummy_signal; + sigaction(SIG_IPI, &sigact, NULL); + + r = kvm_set_signal_mask(env, &set); + if (r) { + fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(r)); + exit(1); + } } static void unblock_io_signals(void) @@ -3545,7 +3625,7 @@ static void unblock_io_signals(void) pthread_sigmask(SIG_UNBLOCK, &set, NULL); sigemptyset(&set); - sigaddset(&set, SIGUSR1); + sigaddset(&set, SIG_IPI); pthread_sigmask(SIG_BLOCK, &set, NULL); } @@ -3554,7 +3634,7 @@ static void qemu_signal_lock(unsigned int msecs) qemu_mutex_lock(&qemu_fair_mutex); while (qemu_mutex_trylock(&qemu_global_mutex)) { - qemu_thread_signal(tcg_cpu_thread, SIGUSR1); + qemu_thread_signal(tcg_cpu_thread, SIG_IPI); if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs)) break; } @@ -3595,7 +3675,7 @@ static void pause_all_vcpus(void) while (penv) { penv->stop = 1; - qemu_thread_signal(penv->thread, SIGUSR1); + qemu_thread_signal(penv->thread, SIG_IPI); qemu_cpu_kick(penv); penv = (CPUState *)penv->next_cpu; } @@ -3604,7 +3684,7 @@ static void pause_all_vcpus(void) qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100); penv = first_cpu; while (penv) { - qemu_thread_signal(penv->thread, SIGUSR1); + qemu_thread_signal(penv->thread, SIG_IPI); penv = (CPUState *)penv->next_cpu; } } @@ -3617,7 +3697,7 @@ static void resume_all_vcpus(void) while (penv) { penv->stop = 0; penv->stopped = 0; - qemu_thread_signal(penv->thread, SIGUSR1); + qemu_thread_signal(penv->thread, SIG_IPI); qemu_cpu_kick(penv); penv = (CPUState *)penv->next_cpu; } |