From patchwork Tue May 4 12:45:22 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Tosatti X-Patchwork-Id: 51603 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D0CC5B7D18 for ; Tue, 4 May 2010 23:07:00 +1000 (EST) Received: from localhost ([127.0.0.1]:59153 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O9Hpy-0007ju-6U for incoming@patchwork.ozlabs.org; Tue, 04 May 2010 09:06:58 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O9Hn1-0006kx-KJ for qemu-devel@nongnu.org; Tue, 04 May 2010 09:03:55 -0400 Received: from [140.186.70.92] (port=52684 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O9Hmz-0006jy-BB for qemu-devel@nongnu.org; Tue, 04 May 2010 09:03:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O9Hmv-0003C2-QC for qemu-devel@nongnu.org; Tue, 04 May 2010 09:03:53 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55227) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O9Hmv-0003BJ-GD for qemu-devel@nongnu.org; Tue, 04 May 2010 09:03:49 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o44D3mVm014095 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 4 May 2010 09:03:48 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o44D3lIR006939; Tue, 4 May 2010 09:03:47 -0400 Received: from amt.cnet (vpn2-10-150.ams2.redhat.com [10.36.10.150]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id o44D20QW023682; Tue, 4 May 2010 09:03:38 -0400 Received: from amt.cnet (amt.cnet [127.0.0.1]) by amt.cnet (Postfix) with ESMTP id 5B85568A9C4; Tue, 4 May 2010 09:54:56 -0300 (BRT) Received: (from marcelo@localhost) by amt.cnet (8.14.3/8.14.3/Submit) id o44CssFJ016564; Tue, 4 May 2010 09:54:54 -0300 Message-Id: <20100504124634.342442182@redhat.com> User-Agent: quilt/0.47-1 Date: Tue, 04 May 2010 09:45:22 -0300 From: Marcelo Tosatti To: kvm@vger.kernel.org, qemu-devel@nongnu.org References: <20100504124518.979470863@redhat.com> Content-Disposition: inline; filename=on-vcpu X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: Marcelo Tosatti Subject: [Qemu-devel] [patch uq/master 4/9] port qemu-kvm's on_vcpu code X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org run_on_cpu allows to execute work on a given CPUState context. Signed-off-by: Marcelo Tosatti Index: qemu/cpu-all.h =================================================================== --- qemu.orig/cpu-all.h +++ qemu/cpu-all.h @@ -818,6 +818,7 @@ void cpu_watchpoint_remove_all(CPUState void cpu_single_step(CPUState *env, int enabled); void cpu_reset(CPUState *s); +void run_on_cpu(CPUState *env, void (*func)(void *data), void *data); #define CPU_LOG_TB_OUT_ASM (1 << 0) #define CPU_LOG_TB_IN_ASM (1 << 1) Index: qemu/cpu-defs.h =================================================================== --- qemu.orig/cpu-defs.h +++ qemu/cpu-defs.h @@ -132,6 +132,7 @@ typedef struct icount_decr_u16 { struct kvm_run; struct KVMState; +struct qemu_work_item; typedef struct CPUBreakpoint { target_ulong pc; @@ -204,6 +205,7 @@ typedef struct CPUWatchpoint { uint32_t created; \ struct QemuThread *thread; \ struct QemuCond *halt_cond; \ + struct qemu_work_item *queued_work_first, *queued_work_last; \ const char *cpu_model_str; \ struct KVMState *kvm_state; \ struct kvm_run *kvm_run; \ Index: qemu/cpus.c =================================================================== --- qemu.orig/cpus.c +++ qemu/cpus.c @@ -115,6 +115,8 @@ static int cpu_has_work(CPUState *env) { if (env->stop) return 1; + if (env->queued_work_first) + return 1; if (env->stopped || !vm_running) return 0; if (!env->halted) @@ -252,6 +254,11 @@ int qemu_cpu_self(void *env) return 1; } +void run_on_cpu(CPUState *env, void (*func)(void *data), void *data) +{ + func(data); +} + void resume_all_vcpus(void) { } @@ -304,6 +311,7 @@ static QemuCond qemu_cpu_cond; /* system init */ static QemuCond qemu_system_cond; static QemuCond qemu_pause_cond; +static QemuCond qemu_work_cond; static void tcg_block_io_signals(void); static void kvm_block_io_signals(CPUState *env); @@ -334,6 +342,50 @@ void qemu_main_loop_start(void) qemu_cond_broadcast(&qemu_system_cond); } +void run_on_cpu(CPUState *env, void (*func)(void *data), void *data) +{ + struct qemu_work_item wi; + + if (qemu_cpu_self(env)) { + func(data); + return; + } + + wi.func = func; + wi.data = data; + if (!env->queued_work_first) + env->queued_work_first = &wi; + else + env->queued_work_last->next = &wi; + env->queued_work_last = &wi; + wi.next = NULL; + wi.done = false; + + qemu_cpu_kick(env); + while (!wi.done) { + CPUState *self_env = cpu_single_env; + + qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex); + cpu_single_env = self_env; + } +} + +static void flush_queued_work(CPUState *env) +{ + struct qemu_work_item *wi; + + if (!env->queued_work_first) + return; + + while ((wi = env->queued_work_first)) { + env->queued_work_first = wi->next; + wi->func(wi->data); + wi->done = true; + } + env->queued_work_last = NULL; + qemu_cond_broadcast(&qemu_work_cond); +} + static void qemu_wait_io_event_common(CPUState *env) { if (env->stop) { @@ -341,6 +393,7 @@ static void qemu_wait_io_event_common(CP env->stopped = 1; qemu_cond_signal(&qemu_pause_cond); } + flush_queued_work(env); } static void qemu_wait_io_event(CPUState *env) Index: qemu/qemu-common.h =================================================================== --- qemu.orig/qemu-common.h +++ qemu/qemu-common.h @@ -249,6 +249,14 @@ void qemu_notify_event(void); void qemu_cpu_kick(void *env); int qemu_cpu_self(void *env); +/* work queue */ +struct qemu_work_item { + struct qemu_work_item *next; + void (*func)(void *data); + void *data; + int done; +}; + #ifdef CONFIG_USER_ONLY #define qemu_init_vcpu(env) do { } while (0) #else