From patchwork Wed May 12 21:24:59 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Tosatti X-Patchwork-Id: 99112 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o4CLRLHH029210 for ; Wed, 12 May 2010 21:27:22 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757941Ab0ELV1S (ORCPT ); Wed, 12 May 2010 17:27:18 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51105 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757896Ab0ELV1L (ORCPT ); Wed, 12 May 2010 17:27:11 -0400 Received: from int-mx05.intmail.prod.int.phx2.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.18]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o4CLR6XY015258 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 12 May 2010 17:27:07 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx05.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o4CLR6dP019622; Wed, 12 May 2010 17:27:06 -0400 Received: from amt.cnet (vpn2-10-158.ams2.redhat.com [10.36.10.158]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id o4CLR3cu021866; Wed, 12 May 2010 17:27:04 -0400 Received: from amt.cnet (amt.cnet [127.0.0.1]) by amt.cnet (Postfix) with ESMTP id 4F7EA65607A; Wed, 12 May 2010 18:25:58 -0300 (BRT) Received: (from marcelo@localhost) by amt.cnet (8.14.3/8.14.3/Submit) id o4CLPrcB028647; Wed, 12 May 2010 18:25:53 -0300 From: Marcelo Tosatti To: Anthony Liguori Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org, Marcelo Tosatti , Avi Kivity Subject: [PATCH 05/12] port qemu-kvm's on_vcpu code Date: Wed, 12 May 2010 18:24:59 -0300 Message-Id: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.67 on 10.5.11.18 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 12 May 2010 21:27:22 +0000 (UTC) diff --git a/cpu-all.h b/cpu-all.h index 52a1817..9efb8a9 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -821,6 +821,7 @@ void cpu_watchpoint_remove_all(CPUState *env, int mask); 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) diff --git a/cpu-defs.h b/cpu-defs.h index 0140596..c764d67 100644 --- a/cpu-defs.h +++ b/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; \ diff --git a/cpus.c b/cpus.c index 5afdb4a..af87007 100644 --- a/cpus.c +++ b/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(CPUState *env) env->stopped = 1; qemu_cond_signal(&qemu_pause_cond); } + flush_queued_work(env); } static void qemu_wait_io_event(CPUState *env) diff --git a/qemu-common.h b/qemu-common.h index 4ba0cda..a4888e5 100644 --- a/qemu-common.h +++ b/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