From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=60017 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PKfN9-0000AQ-Nq for qemu-devel@nongnu.org; Mon, 22 Nov 2010 18:00:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PKfN8-0001Ff-G2 for qemu-devel@nongnu.org; Mon, 22 Nov 2010 18:00:31 -0500 Received: from e9.ny.us.ibm.com ([32.97.182.139]:47350) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PKfN8-0001FT-DY for qemu-devel@nongnu.org; Mon, 22 Nov 2010 18:00:30 -0500 Received: from d01relay03.pok.ibm.com (d01relay03.pok.ibm.com [9.56.227.235]) by e9.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id oAMMcVQF025828 for ; Mon, 22 Nov 2010 17:38:31 -0500 Received: from d01av02.pok.ibm.com (d01av02.pok.ibm.com [9.56.224.216]) by d01relay03.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id oAMN0PmG339282 for ; Mon, 22 Nov 2010 18:00:25 -0500 Received: from d01av02.pok.ibm.com (loopback [127.0.0.1]) by d01av02.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id oAMN0PqS023640 for ; Mon, 22 Nov 2010 21:00:25 -0200 From: Anthony Liguori Date: Mon, 22 Nov 2010 17:00:18 -0600 Message-Id: <1290466818-5230-1-git-send-email-aliguori@us.ibm.com> Subject: [Qemu-devel] [PATCH] qemu-kvm: introduce cpu_start/cpu_stop commands List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Chris Wright , Anthony Liguori , kvm@vger.kernel.org qemu-kvm vcpu threads don't response to SIGSTOP/SIGCONT. Instead of teaching them to respond to these signals, introduce monitor commands that stop and start individual vcpus. The purpose of these commands are to implement CPU hard limits using an external tool that watches the CPU consumption and stops the CPU as appropriate. The monitor commands provide a more elegant solution that signals because it ensures that a stopped vcpu isn't holding the qemu_mutex. I'll reply to this note with an example tool. Signed-off-by: Anthony Liguori diff --git a/hmp-commands.hx b/hmp-commands.hx index ba6de28..827bd67 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -279,6 +279,24 @@ Resume emulation. ETEXI { + .name = "cpu_start", + .args_type = "cpu:i", + .params = "[cpu]", + .help = "start cpu emulation", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_vcpu_start, + }, + + { + .name = "cpu_stop", + .args_type = "cpu:i", + .params = "[cpu]", + .help = "stop cpu emulation", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_vcpu_stop, + }, + + { .name = "gdbserver", .args_type = "device:s?", .params = "[device]", diff --git a/qemu-kvm.c b/qemu-kvm.c index 471306b..35121ed 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -1351,6 +1351,65 @@ static void pause_all_threads(void) } } +static void vcpu_stop(int cpu) +{ + CPUState *env = first_cpu; + + for (env = first_cpu; env; env = env->next_cpu) { + if (env->cpu_index == cpu) { + break; + } + } + + if (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(int cpu) +{ + CPUState *env = first_cpu; + + assert(!cpu_single_env); + + for (env = first_cpu; env; env = env->next_cpu) { + if (env->cpu_index == cpu) { + break; + } + } + + if (env) { + env->stop = 0; + env->stopped = 0; + pthread_kill(env->kvm_cpu_state.thread, SIG_IPI); + } +} + +int do_vcpu_stop(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + int vcpu = qdict_get_int(qdict, "cpu"); + vcpu_stop(vcpu); + return 0; +} + +int do_vcpu_start(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + int vcpu = qdict_get_int(qdict, "cpu"); + vcpu_start(vcpu); + return 0; +} + static void resume_all_threads(void) { CPUState *penv = first_cpu; diff --git a/sysemu.h b/sysemu.h index 849dc8c..3ef68dd 100644 --- a/sysemu.h +++ b/sysemu.h @@ -61,6 +61,9 @@ void qemu_system_reset(void); void qemu_add_exit_notifier(Notifier *notify); void qemu_remove_exit_notifier(Notifier *notify); +int do_vcpu_stop(Monitor *mon, const QDict *qdict, QObject **ret_data); +int do_vcpu_start(Monitor *mon, const QDict *qdict, QObject **ret_data); + void do_savevm(Monitor *mon, const QDict *qdict); int load_vmstate(const char *name); void do_delvm(Monitor *mon, const QDict *qdict); -- 1.7.0.4