@@ -220,6 +220,7 @@ struct KVMCPUState {
const char *cpu_model_str; \
struct KVMState *kvm_state; \
struct kvm_run *kvm_run; \
+ int sigusr1_fd; \
int kvm_fd; \
int kvm_vcpu_dirty; \
struct KVMCPUState kvm_cpu_state;
@@ -1351,6 +1351,29 @@ static void pause_all_threads(void)
}
}
+static void vcpu_stop(CPUState *env)
+{
+ if (env != cpu_single_env) {
+ env->stop = 1;
+ pthread_kill(env->kvm_cpu_state.thread, SIG_IPI);
+ } else {
+ env->stop = 0;
+ env->stopped = 1;
+ cpu_exit(env);
+ }
+
+ while (!env->stopped) {
+ qemu_cond_wait(&qemu_pause_cond);
+ }
+}
+
+static void vcpu_start(CPUState *env)
+{
+ env->stop = 0;
+ env->stopped = 0;
+ pthread_kill(env->kvm_cpu_state.thread, SIG_IPI);
+}
+
static void resume_all_threads(void)
{
CPUState *penv = first_cpu;
@@ -1426,6 +1449,37 @@ static int kvm_main_loop_cpu(CPUState *env)
return 0;
}
+static __thread int sigusr1_wfd;
+
+static void on_sigusr1(int signo)
+{
+ char ch = 0;
+ if (write(sigusr1_wfd, &ch, 1) < 0) {
+ /* who cares */
+ }
+}
+
+static void sigusr1_read(void *opaque)
+{
+ CPUState *env = opaque;
+ ssize_t len;
+ int caught_signal = 0;
+
+ do {
+ char buffer[256];
+ len = read(env->sigusr1_fd, buffer, sizeof(buffer));
+ caught_signal = 1;
+ } while (len > 0);
+
+ if (caught_signal) {
+ if (env->stopped) {
+ vcpu_start(env);
+ } else {
+ vcpu_stop(env);
+ }
+ }
+}
+
static void *ap_main_loop(void *_env)
{
CPUState *env = _env;
@@ -1433,10 +1487,12 @@ static void *ap_main_loop(void *_env)
#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
struct ioperm_data *data = NULL;
#endif
+ int fds[2];
current_env = env;
env->thread_id = kvm_get_thread_id();
sigfillset(&signals);
+ sigdelset(&signals, SIGUSR1);
sigprocmask(SIG_BLOCK, &signals, NULL);
#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
@@ -1451,6 +1507,18 @@ static void *ap_main_loop(void *_env)
kvm_create_vcpu(env, env->cpu_index);
setup_kernel_sigmask(env);
+ if (pipe(fds) == -1) {
+ /* do nothing */
+ }
+
+ fcntl(fds[0], F_SETFL, O_NONBLOCK);
+ fcntl(fds[1], F_SETFL, O_NONBLOCK);
+
+ env->sigusr1_fd = fds[0];
+ sigusr1_wfd = fds[1];
+
+ qemu_set_fd_handler2(fds[0], NULL, sigusr1_read, NULL, env);
+
/* signal VCPU creation */
current_env->created = 1;
pthread_cond_signal(&qemu_vcpu_cond);
@@ -1463,6 +1531,8 @@ static void *ap_main_loop(void *_env)
/* re-initialize cpu_single_env after re-acquiring qemu_mutex */
cpu_single_env = env;
+ signal(SIGUSR1, on_sigusr1);
+
kvm_main_loop_cpu(env);
return NULL;
}
@@ -783,6 +783,7 @@ struct KVMState {
int irqchip_in_kernel;
int pit_in_kernel;
int xsave, xcrs;
+ int sigusr2_fd;
struct kvm_context kvm_context;
};