diff mbox

[01/20] qemu-kvm: Move thread-related code to cpus.c

Message ID c5f8ecf38f30eb8d5924e0cf00bea0353d9eedf9.1306498737.git.jan.kiszka@siemens.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Kiszka May 27, 2011, 12:19 p.m. UTC
As a first step towards unified threading support, move all the related
qemu-kvm-specific bits from qemu-kvm.c to cpus.c. This already allows to
drop 3 identical functions (sigbus_reraise, sigbus_handler,
sigfd_handler) and should provide the environment for consolidating the
rest.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 cpus.c     |  425 +++++++++++++++++++++++++++++++++++++++++++++++++++
 cpus.h     |    1 +
 kvm-all.c  |    2 +-
 qemu-kvm.c |  494 +-----------------------------------------------------------
 qemu-kvm.h |    1 +
 5 files changed, 430 insertions(+), 493 deletions(-)
diff mbox

Patch

diff --git a/cpus.c b/cpus.c
index b64c29f..d209535 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1179,3 +1179,428 @@  void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
     cpu_list(f, cpu_fprintf); /* deprecated */
 #endif
 }
+
+
+
+/*
+ * qemu-kvm threading code, integration zone
+ */
+#ifdef CONFIG_KVM
+
+#include <sys/syscall.h>
+
+#include "qemu-thread.h"
+
+pthread_mutex_t qemu_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t qemu_vcpu_cond = PTHREAD_COND_INITIALIZER;
+pthread_cond_t qemu_system_cond = PTHREAD_COND_INITIALIZER;
+pthread_cond_t qemu_pause_cond = PTHREAD_COND_INITIALIZER;
+pthread_cond_t qemu_work_cond = PTHREAD_COND_INITIALIZER;
+__thread CPUState *current_env;
+
+static int qemu_system_ready;
+
+static CPUState *kvm_debug_cpu_requested;
+
+unsigned long kvm_get_thread_id(void)
+{
+    return syscall(SYS_gettid);
+}
+
+static void kvm_cond_wait(pthread_cond_t *cond)
+{
+    CPUState *env = cpu_single_env;
+
+    pthread_cond_wait(cond, &qemu_mutex);
+    cpu_single_env = env;
+}
+
+static void sig_ipi_handler(int n)
+{
+}
+
+void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
+{
+    struct qemu_work_item wi;
+
+    if (env == current_env) {
+        func(data);
+        return;
+    }
+
+    wi.func = func;
+    wi.data = data;
+    if (!env->kvm_cpu_state.queued_work_first) {
+        env->kvm_cpu_state.queued_work_first = &wi;
+    } else {
+        env->kvm_cpu_state.queued_work_last->next = &wi;
+    }
+    env->kvm_cpu_state.queued_work_last = &wi;
+    wi.next = NULL;
+    wi.done = false;
+
+    pthread_kill(env->thread->thread, SIG_IPI);
+    while (!wi.done) {
+        kvm_cond_wait(&qemu_work_cond);
+    }
+}
+
+void kvm_update_interrupt_request(CPUState *env)
+{
+    int signal = 0;
+
+    if (env) {
+        if (!current_env || !current_env->created) {
+            signal = 1;
+        }
+        /*
+         * Testing for created here is really redundant
+         */
+        if (current_env && current_env->created &&
+            env != current_env && !env->thread_kicked) {
+            signal = 1;
+        }
+
+        if (signal) {
+            env->thread_kicked = true;
+            if (env->thread) {
+                pthread_kill(env->thread->thread, SIG_IPI);
+            }
+        }
+    }
+}
+
+static int kvm_cpu_is_stopped(CPUState *env)
+{
+    return !vm_running || env->stopped;
+}
+
+static void flush_queued_work(CPUState *env)
+{
+    struct qemu_work_item *wi;
+
+    if (!env->kvm_cpu_state.queued_work_first) {
+        return;
+    }
+
+    while ((wi = env->kvm_cpu_state.queued_work_first)) {
+        env->kvm_cpu_state.queued_work_first = wi->next;
+        wi->func(wi->data);
+        wi->done = true;
+    }
+    env->kvm_cpu_state.queued_work_last = NULL;
+    pthread_cond_broadcast(&qemu_work_cond);
+}
+
+static void kvm_main_loop_wait(CPUState *env, int timeout)
+{
+    struct timespec ts;
+    int r, e;
+    siginfo_t siginfo;
+    sigset_t waitset;
+    sigset_t chkset;
+
+    ts.tv_sec = timeout / 1000;
+    ts.tv_nsec = (timeout % 1000) * 1000000;
+    sigemptyset(&waitset);
+    sigaddset(&waitset, SIG_IPI);
+    sigaddset(&waitset, SIGBUS);
+
+    do {
+        pthread_mutex_unlock(&qemu_mutex);
+
+        r = sigtimedwait(&waitset, &siginfo, &ts);
+        e = errno;
+
+        pthread_mutex_lock(&qemu_mutex);
+
+        if (r == -1 && !(e == EAGAIN || e == EINTR)) {
+            printf("sigtimedwait: %s\n", strerror(e));
+            exit(1);
+        }
+
+        switch (r) {
+        case SIGBUS:
+            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr))
+                sigbus_reraise();
+            break;
+        default:
+            break;
+        }
+
+        r = sigpending(&chkset);
+        if (r == -1) {
+            printf("sigpending: %s\n", strerror(e));
+            exit(1);
+        }
+    } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
+
+    cpu_single_env = env;
+    flush_queued_work(env);
+
+    if (env->stop) {
+        env->stop = 0;
+        env->stopped = 1;
+        pthread_cond_signal(&qemu_pause_cond);
+    }
+
+    env->thread_kicked = false;
+}
+
+static int all_threads_paused(void)
+{
+    CPUState *penv = first_cpu;
+
+    while (penv) {
+        if (penv->stop) {
+            return 0;
+        }
+        penv = (CPUState *) penv->next_cpu;
+    }
+
+    return 1;
+}
+
+static void pause_all_threads(void)
+{
+    CPUState *penv = first_cpu;
+
+    while (penv) {
+        if (penv != cpu_single_env) {
+            penv->stop = 1;
+            pthread_kill(penv->thread->thread, SIG_IPI);
+        } else {
+            penv->stop = 0;
+            penv->stopped = 1;
+            cpu_exit(penv);
+        }
+        penv = (CPUState *) penv->next_cpu;
+    }
+
+    while (!all_threads_paused()) {
+        kvm_cond_wait(&qemu_pause_cond);
+    }
+}
+
+static void resume_all_threads(void)
+{
+    CPUState *penv = first_cpu;
+
+    assert(!cpu_single_env);
+
+    while (penv) {
+        penv->stop = 0;
+        penv->stopped = 0;
+        pthread_kill(penv->thread->thread, SIG_IPI);
+        penv = (CPUState *) penv->next_cpu;
+    }
+}
+
+static void kvm_vm_state_change_handler(void *context, int running, int reason)
+{
+    if (running) {
+        resume_all_threads();
+    } else {
+        pause_all_threads();
+    }
+}
+
+static void setup_kernel_sigmask(CPUState *env)
+{
+    sigset_t set;
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGUSR2);
+    sigaddset(&set, SIGIO);
+    sigaddset(&set, SIGALRM);
+    sigprocmask(SIG_BLOCK, &set, NULL);
+
+    sigprocmask(SIG_BLOCK, NULL, &set);
+    sigdelset(&set, SIG_IPI);
+    sigdelset(&set, SIGBUS);
+
+    kvm_set_signal_mask(env, &set);
+}
+
+static void qemu_kvm_system_reset(void)
+{
+    pause_all_threads();
+
+    cpu_synchronize_all_states();
+    qemu_system_reset();
+
+    resume_all_threads();
+}
+
+static int kvm_main_loop_cpu(CPUState *env)
+{
+    while (1) {
+        int timeout = 1000;
+        if (!kvm_cpu_is_stopped(env)) {
+            switch (kvm_cpu_exec(env)) {
+            case EXCP_HLT:
+                break;
+            case EXCP_DEBUG:
+                kvm_debug_cpu_requested = env;
+                env->stopped = 1;
+                break;
+            default:
+                timeout = 0;
+                break;
+            }
+        }
+        kvm_main_loop_wait(env, timeout);
+    }
+    pthread_mutex_unlock(&qemu_mutex);
+    return 0;
+}
+
+static void *ap_main_loop(void *_env)
+{
+    CPUState *env = _env;
+
+    current_env = env;
+    env->thread_id = kvm_get_thread_id();
+
+    pthread_mutex_lock(&qemu_mutex);
+    cpu_single_env = env;
+
+    if (kvm_create_vcpu(env) < 0) {
+        abort();
+    }
+    setup_kernel_sigmask(env);
+
+    /* signal VCPU creation */
+    current_env->created = 1;
+    pthread_cond_signal(&qemu_vcpu_cond);
+
+    /* and wait for machine initialization */
+    while (!qemu_system_ready) {
+        kvm_cond_wait(&qemu_system_cond);
+    }
+
+    /* re-initialize cpu_single_env after re-acquiring qemu_mutex */
+    cpu_single_env = env;
+
+    kvm_main_loop_cpu(env);
+    return NULL;
+}
+
+int kvm_init_vcpu(CPUState *env)
+{
+    env->thread = qemu_mallocz(sizeof(QemuThread));
+    qemu_thread_create(env->thread, ap_main_loop, env);
+
+    while (env->created == 0) {
+        kvm_cond_wait(&qemu_vcpu_cond);
+    }
+
+    return 0;
+}
+
+int kvm_init_ap(void)
+{
+    struct sigaction action;
+
+    pthread_mutex_lock(&qemu_mutex);
+
+    qemu_add_vm_change_state_handler(kvm_vm_state_change_handler, NULL);
+
+    signal(SIG_IPI, sig_ipi_handler);
+
+    memset(&action, 0, sizeof(action));
+    action.sa_flags = SA_SIGINFO;
+    action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
+    sigaction(SIGBUS, &action, NULL);
+    prctl(PR_MCE_KILL, 1, 1, 0, 0);
+    return 0;
+}
+
+bool qemu_system_is_ready(void)
+{
+    return qemu_system_ready;
+}
+
+int kvm_main_loop(void)
+{
+    sigset_t mask;
+    int sigfd;
+
+    qemu_system_ready = 1;
+
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGIO);
+    sigaddset(&mask, SIGALRM);
+    sigaddset(&mask, SIGBUS);
+    sigprocmask(SIG_BLOCK, &mask, NULL);
+
+    sigfd = qemu_signalfd(&mask);
+    if (sigfd == -1) {
+        fprintf(stderr, "failed to create signalfd\n");
+        return -errno;
+    }
+
+    fcntl(sigfd, F_SETFL, O_NONBLOCK);
+
+    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
+                         (void *)(unsigned long) sigfd);
+
+    pthread_cond_broadcast(&qemu_system_cond);
+
+    cpu_single_env = NULL;
+
+    while (1) {
+        main_loop_wait(0);
+        if (qemu_shutdown_requested()) {
+            monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
+            if (qemu_no_shutdown()) {
+                vm_stop(VMSTOP_SHUTDOWN);
+            } else {
+                break;
+            }
+        } else if (qemu_powerdown_requested()) {
+            monitor_protocol_event(QEVENT_POWERDOWN, NULL);
+            qemu_irq_raise(qemu_system_powerdown);
+        } else if (qemu_reset_requested()) {
+            qemu_kvm_system_reset();
+        } else if (kvm_debug_cpu_requested) {
+            gdb_set_stop_cpu(kvm_debug_cpu_requested);
+            vm_stop(VMSTOP_DEBUG);
+            kvm_debug_cpu_requested = NULL;
+        }
+    }
+
+    bdrv_close_all();
+    pause_all_threads();
+    pthread_mutex_unlock(&qemu_mutex);
+
+    return 0;
+}
+
+static void kvm_mutex_unlock(void)
+{
+    assert(!cpu_single_env);
+    pthread_mutex_unlock(&qemu_mutex);
+}
+
+static void kvm_mutex_lock(void)
+{
+    pthread_mutex_lock(&qemu_mutex);
+    cpu_single_env = NULL;
+}
+
+void qemu_mutex_unlock_iothread(void)
+{
+    if (kvm_enabled()) {
+        kvm_mutex_unlock();
+    }
+}
+
+void qemu_mutex_lock_iothread(void)
+{
+    if (kvm_enabled()) {
+        kvm_mutex_lock();
+    }
+}
+
+#endif /* CONFIG_KVM */
diff --git a/cpus.h b/cpus.h
index 6fdeb0d..4838b16 100644
--- a/cpus.h
+++ b/cpus.h
@@ -7,6 +7,7 @@  void qemu_main_loop_start(void);
 void resume_all_vcpus(void);
 void pause_all_vcpus(void);
 void cpu_stop_current(void);
+bool qemu_system_is_ready(void);
 
 void cpu_synchronize_all_states(void);
 void cpu_synchronize_all_post_reset(void);
diff --git a/kvm-all.c b/kvm-all.c
index 88d0785..bd53422 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -208,7 +208,7 @@  int kvm_pit_in_kernel(void)
     return kvm_state->pit_in_kernel;
 }
 
-static int kvm_create_vcpu(CPUState *env)
+int kvm_create_vcpu(CPUState *env)
 {
     KVMState *s = kvm_state;
     long mmap_size;
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 94e12f3..dfbf045 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -19,29 +19,9 @@ 
 #include "gdbstub.h"
 #include "monitor.h"
 #include "cpus.h"
-#include "qemu-thread.h"
 
 #include "qemu-kvm.h"
 
-#include <pthread.h>
-#include <sys/utsname.h>
-#include <sys/syscall.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include "compatfd.h"
-#include <sys/prctl.h>
-
-#ifndef PR_MCE_KILL
-#define PR_MCE_KILL 33
-#endif
-
-#ifndef BUS_MCEERR_AR
-#define BUS_MCEERR_AR 4
-#endif
-#ifndef BUS_MCEERR_AO
-#define BUS_MCEERR_AO 5
-#endif
-
 #define EXPECTED_KVM_API_VERSION 12
 
 #if EXPECTED_KVM_API_VERSION != KVM_API_VERSION
@@ -53,19 +33,6 @@  int kvm_pit = 1;
 int kvm_pit_reinject = 1;
 int kvm_nested = 0;
 
-pthread_mutex_t qemu_mutex = PTHREAD_MUTEX_INITIALIZER;
-pthread_cond_t qemu_vcpu_cond = PTHREAD_COND_INITIALIZER;
-pthread_cond_t qemu_system_cond = PTHREAD_COND_INITIALIZER;
-pthread_cond_t qemu_pause_cond = PTHREAD_COND_INITIALIZER;
-pthread_cond_t qemu_work_cond = PTHREAD_COND_INITIALIZER;
-__thread CPUState *current_env;
-
-static int qemu_system_ready;
-
-#define SIG_IPI (SIGRTMIN+4)
-
-CPUState *kvm_debug_cpu_requested;
-
 #define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
 
 static inline void set_gsi(KVMState *s, unsigned int gsi)
@@ -571,326 +538,6 @@  int kvm_assign_set_msix_entry(KVMState *s,
 }
 #endif
 
-unsigned long kvm_get_thread_id(void)
-{
-    return syscall(SYS_gettid);
-}
-
-static void kvm_cond_wait(pthread_cond_t *cond)
-{
-    CPUState *env = cpu_single_env;
-
-    pthread_cond_wait(cond, &qemu_mutex);
-    cpu_single_env = env;
-}
-
-static void sig_ipi_handler(int n)
-{
-}
-
-static void sigbus_reraise(void)
-{
-    sigset_t set;
-    struct sigaction action;
-
-    memset(&action, 0, sizeof(action));
-    action.sa_handler = SIG_DFL;
-    if (!sigaction(SIGBUS, &action, NULL)) {
-        raise(SIGBUS);
-        sigemptyset(&set);
-        sigaddset(&set, SIGBUS);
-        sigprocmask(SIG_UNBLOCK, &set, NULL);
-    }
-    perror("Failed to re-raise SIGBUS!\n");
-    abort();
-}
-
-static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
-                           void *ctx)
-{
-    if (kvm_on_sigbus(siginfo->ssi_code, (void *)(intptr_t)siginfo->ssi_addr))
-        sigbus_reraise();
-}
-
-void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
-{
-    struct qemu_work_item wi;
-
-    if (env == current_env) {
-        func(data);
-        return;
-    }
-
-    wi.func = func;
-    wi.data = data;
-    if (!env->kvm_cpu_state.queued_work_first) {
-        env->kvm_cpu_state.queued_work_first = &wi;
-    } else {
-        env->kvm_cpu_state.queued_work_last->next = &wi;
-    }
-    env->kvm_cpu_state.queued_work_last = &wi;
-    wi.next = NULL;
-    wi.done = false;
-
-    pthread_kill(env->thread->thread, SIG_IPI);
-    while (!wi.done) {
-        kvm_cond_wait(&qemu_work_cond);
-    }
-}
-
-void kvm_update_interrupt_request(CPUState *env)
-{
-    int signal = 0;
-
-    if (env) {
-        if (!current_env || !current_env->created) {
-            signal = 1;
-        }
-        /*
-         * Testing for created here is really redundant
-         */
-        if (current_env && current_env->created &&
-            env != current_env && !env->thread_kicked) {
-            signal = 1;
-        }
-
-        if (signal) {
-            env->thread_kicked = true;
-            if (env->thread) {
-                pthread_kill(env->thread->thread, SIG_IPI);
-            }
-        }
-    }
-}
-
-static int kvm_cpu_is_stopped(CPUState *env)
-{
-    return !vm_running || env->stopped;
-}
-
-static void flush_queued_work(CPUState *env)
-{
-    struct qemu_work_item *wi;
-
-    if (!env->kvm_cpu_state.queued_work_first) {
-        return;
-    }
-
-    while ((wi = env->kvm_cpu_state.queued_work_first)) {
-        env->kvm_cpu_state.queued_work_first = wi->next;
-        wi->func(wi->data);
-        wi->done = true;
-    }
-    env->kvm_cpu_state.queued_work_last = NULL;
-    pthread_cond_broadcast(&qemu_work_cond);
-}
-
-static void kvm_main_loop_wait(CPUState *env, int timeout)
-{
-    struct timespec ts;
-    int r, e;
-    siginfo_t siginfo;
-    sigset_t waitset;
-    sigset_t chkset;
-
-    ts.tv_sec = timeout / 1000;
-    ts.tv_nsec = (timeout % 1000) * 1000000;
-    sigemptyset(&waitset);
-    sigaddset(&waitset, SIG_IPI);
-    sigaddset(&waitset, SIGBUS);
-
-    do {
-        pthread_mutex_unlock(&qemu_mutex);
-
-        r = sigtimedwait(&waitset, &siginfo, &ts);
-        e = errno;
-
-        pthread_mutex_lock(&qemu_mutex);
-
-        if (r == -1 && !(e == EAGAIN || e == EINTR)) {
-            printf("sigtimedwait: %s\n", strerror(e));
-            exit(1);
-        }
-
-        switch (r) {
-        case SIGBUS:
-            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr))
-                sigbus_reraise();
-            break;
-        default:
-            break;
-        }
-
-        r = sigpending(&chkset);
-        if (r == -1) {
-            printf("sigpending: %s\n", strerror(e));
-            exit(1);
-        }
-    } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
-
-    cpu_single_env = env;
-    flush_queued_work(env);
-
-    if (env->stop) {
-        env->stop = 0;
-        env->stopped = 1;
-        pthread_cond_signal(&qemu_pause_cond);
-    }
-
-    env->thread_kicked = false;
-}
-
-static int all_threads_paused(void)
-{
-    CPUState *penv = first_cpu;
-
-    while (penv) {
-        if (penv->stop) {
-            return 0;
-        }
-        penv = (CPUState *) penv->next_cpu;
-    }
-
-    return 1;
-}
-
-static void pause_all_threads(void)
-{
-    CPUState *penv = first_cpu;
-
-    while (penv) {
-        if (penv != cpu_single_env) {
-            penv->stop = 1;
-            pthread_kill(penv->thread->thread, SIG_IPI);
-        } else {
-            penv->stop = 0;
-            penv->stopped = 1;
-            cpu_exit(penv);
-        }
-        penv = (CPUState *) penv->next_cpu;
-    }
-
-    while (!all_threads_paused()) {
-        kvm_cond_wait(&qemu_pause_cond);
-    }
-}
-
-static void resume_all_threads(void)
-{
-    CPUState *penv = first_cpu;
-
-    assert(!cpu_single_env);
-
-    while (penv) {
-        penv->stop = 0;
-        penv->stopped = 0;
-        pthread_kill(penv->thread->thread, SIG_IPI);
-        penv = (CPUState *) penv->next_cpu;
-    }
-}
-
-static void kvm_vm_state_change_handler(void *context, int running, int reason)
-{
-    if (running) {
-        resume_all_threads();
-    } else {
-        pause_all_threads();
-    }
-}
-
-static void setup_kernel_sigmask(CPUState *env)
-{
-    sigset_t set;
-
-    sigemptyset(&set);
-    sigaddset(&set, SIGUSR2);
-    sigaddset(&set, SIGIO);
-    sigaddset(&set, SIGALRM);
-    sigprocmask(SIG_BLOCK, &set, NULL);
-
-    sigprocmask(SIG_BLOCK, NULL, &set);
-    sigdelset(&set, SIG_IPI);
-    sigdelset(&set, SIGBUS);
-
-    kvm_set_signal_mask(env, &set);
-}
-
-static void qemu_kvm_system_reset(void)
-{
-    pause_all_threads();
-
-    cpu_synchronize_all_states();
-    qemu_system_reset();
-
-    resume_all_threads();
-}
-
-static int kvm_main_loop_cpu(CPUState *env)
-{
-    while (1) {
-        int timeout = 1000;
-        if (!kvm_cpu_is_stopped(env)) {
-            switch (kvm_cpu_exec(env)) {
-            case EXCP_HLT:
-                break;
-            case EXCP_DEBUG:
-                kvm_debug_cpu_requested = env;
-                env->stopped = 1;
-                break;
-            default:
-                timeout = 0;
-                break;
-            }
-        }
-        kvm_main_loop_wait(env, timeout);
-    }
-    pthread_mutex_unlock(&qemu_mutex);
-    return 0;
-}
-
-static void *ap_main_loop(void *_env)
-{
-    CPUState *env = _env;
-
-    current_env = env;
-    env->thread_id = kvm_get_thread_id();
-
-    pthread_mutex_lock(&qemu_mutex);
-    cpu_single_env = env;
-
-    if (kvm_create_vcpu(env) < 0) {
-        abort();
-    }
-    setup_kernel_sigmask(env);
-
-    /* signal VCPU creation */
-    current_env->created = 1;
-    pthread_cond_signal(&qemu_vcpu_cond);
-
-    /* and wait for machine initialization */
-    while (!qemu_system_ready) {
-        kvm_cond_wait(&qemu_system_cond);
-    }
-
-    /* re-initialize cpu_single_env after re-acquiring qemu_mutex */
-    cpu_single_env = env;
-
-    kvm_main_loop_cpu(env);
-    return NULL;
-}
-
-int kvm_init_vcpu(CPUState *env)
-{
-    env->thread = qemu_mallocz(sizeof(QemuThread));
-    qemu_thread_create(env->thread, ap_main_loop, env);
-
-    while (env->created == 0) {
-        kvm_cond_wait(&qemu_vcpu_cond);
-    }
-
-    return 0;
-}
-
 #ifdef TARGET_I386
 void kvm_hpet_disable_kpit(void)
 {
@@ -911,116 +558,6 @@  void kvm_hpet_enable_kpit(void)
 }
 #endif
 
-int kvm_init_ap(void)
-{
-    struct sigaction action;
-
-    pthread_mutex_lock(&qemu_mutex);
-
-    qemu_add_vm_change_state_handler(kvm_vm_state_change_handler, NULL);
-
-    signal(SIG_IPI, sig_ipi_handler);
-
-    memset(&action, 0, sizeof(action));
-    action.sa_flags = SA_SIGINFO;
-    action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
-    sigaction(SIGBUS, &action, NULL);
-    prctl(PR_MCE_KILL, 1, 1, 0, 0);
-    return 0;
-}
-
-/* If we have signalfd, we mask out the signals we want to handle and then
- * use signalfd to listen for them.  We rely on whatever the current signal
- * handler is to dispatch the signals when we receive them.
- */
-
-static void sigfd_handler(void *opaque)
-{
-    int fd = (unsigned long) opaque;
-    struct qemu_signalfd_siginfo info;
-    struct sigaction action;
-    ssize_t len;
-
-    while (1) {
-        do {
-            len = read(fd, &info, sizeof(info));
-        } while (len == -1 && errno == EINTR);
-
-        if (len == -1 && errno == EAGAIN) {
-            break;
-        }
-
-        if (len != sizeof(info)) {
-            printf("read from sigfd returned %zd: %m\n", len);
-            return;
-        }
-
-        sigaction(info.ssi_signo, NULL, &action);
-        if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
-            action.sa_sigaction(info.ssi_signo,
-                                (siginfo_t *)&info, NULL);
-        } else if (action.sa_handler) {
-            action.sa_handler(info.ssi_signo);
-        }
-    }
-}
-
-int kvm_main_loop(void)
-{
-    sigset_t mask;
-    int sigfd;
-
-    qemu_system_ready = 1;
-
-    sigemptyset(&mask);
-    sigaddset(&mask, SIGIO);
-    sigaddset(&mask, SIGALRM);
-    sigaddset(&mask, SIGBUS);
-    sigprocmask(SIG_BLOCK, &mask, NULL);
-
-    sigfd = qemu_signalfd(&mask);
-    if (sigfd == -1) {
-        fprintf(stderr, "failed to create signalfd\n");
-        return -errno;
-    }
-
-    fcntl(sigfd, F_SETFL, O_NONBLOCK);
-
-    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
-                         (void *)(unsigned long) sigfd);
-
-    pthread_cond_broadcast(&qemu_system_cond);
-
-    cpu_single_env = NULL;
-
-    while (1) {
-        main_loop_wait(0);
-        if (qemu_shutdown_requested()) {
-            monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
-            if (qemu_no_shutdown()) {
-                vm_stop(VMSTOP_SHUTDOWN);
-            } else {
-                break;
-            }
-        } else if (qemu_powerdown_requested()) {
-            monitor_protocol_event(QEVENT_POWERDOWN, NULL);
-            qemu_irq_raise(qemu_system_powerdown);
-        } else if (qemu_reset_requested()) {
-            qemu_kvm_system_reset();
-        } else if (kvm_debug_cpu_requested) {
-            gdb_set_stop_cpu(kvm_debug_cpu_requested);
-            vm_stop(VMSTOP_DEBUG);
-            kvm_debug_cpu_requested = NULL;
-        }
-    }
-
-    bdrv_close_all();
-    pause_all_threads();
-    pthread_mutex_unlock(&qemu_mutex);
-
-    return 0;
-}
-
 #if !defined(TARGET_I386)
 int kvm_arch_init_irq_routing(void)
 {
@@ -1028,32 +565,6 @@  int kvm_arch_init_irq_routing(void)
 }
 #endif
 
-static void kvm_mutex_unlock(void)
-{
-    assert(!cpu_single_env);
-    pthread_mutex_unlock(&qemu_mutex);
-}
-
-static void kvm_mutex_lock(void)
-{
-    pthread_mutex_lock(&qemu_mutex);
-    cpu_single_env = NULL;
-}
-
-void qemu_mutex_unlock_iothread(void)
-{
-    if (kvm_enabled()) {
-        kvm_mutex_unlock();
-    }
-}
-
-void qemu_mutex_lock_iothread(void)
-{
-    if (kvm_enabled()) {
-        kvm_mutex_lock();
-    }
-}
-
 #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 typedef struct KVMIOPortRegion {
     unsigned long start;
@@ -1089,7 +600,7 @@  int kvm_add_ioport_region(unsigned long start, unsigned long size)
     region->status = 1;
     QLIST_INSERT_HEAD(&ioport_regions, region, entry);
 
-    if (qemu_system_ready) {
+    if (qemu_system_is_ready()) {
         for (env = first_cpu; env != NULL; env = env->next_cpu) {
             on_vcpu(env, do_set_ioport_access, region);
             if (region->status < 0) {
@@ -1112,7 +623,7 @@  int kvm_remove_ioport_region(unsigned long start, unsigned long size)
         if (region->start == start && region->size == size) {
             region->status = 0;
         }
-        if (qemu_system_ready) {
+        if (qemu_system_is_ready()) {
             for (env = first_cpu; env != NULL; env = env->next_cpu) {
                 on_vcpu(env, do_set_ioport_access, region);
             }
@@ -1155,4 +666,3 @@  int kvm_set_boot_cpu_id(KVMState *s, uint32_t id)
 #endif
     return -ENOSYS;
 }
-
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 094aef2..0ebd3eb 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -265,6 +265,7 @@  struct kvm_pit_state {
 
 #endif                          /* !CONFIG_KVM */
 
+int kvm_create_vcpu(CPUState *env);
 int kvm_main_loop(void);
 int kvm_init_ap(void);
 void kvm_save_lapic(CPUState *env);