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: 96756 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 o44D4MTU004056 for ; Tue, 4 May 2010 13:04:24 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932179Ab0EDND4 (ORCPT ); Tue, 4 May 2010 09:03:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:6715 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932170Ab0EDNDt (ORCPT ); Tue, 4 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 Cc: Marcelo Tosatti Subject: [patch uq/master 4/9] port qemu-kvm's on_vcpu code References: <20100504124518.979470863@redhat.com> Content-Disposition: inline; filename=on-vcpu X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 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]); Tue, 04 May 2010 13:04:25 +0000 (UTC) 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