From nobody Sun May 5 08:55:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1594130444; cv=none; d=zohomail.com; s=zohoarc; b=Q90TX3dK0Cix0IcCZtmw1mDFc33q4prnzO7lvv6ygAEg7rhoJXd41eCdd+w77zLOH2zRfinRJ6ElnZy8+R1Qx1yLZonPRHrf7/SVysofidLhkB/o3ybaFbMtbvqwjcze/b8Pa3u3X8vr5CHRCThnTrdkuZSM4Hb7JlOuFHQcqgA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594130444; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=YGqoRMUTcvgehe4eQWtdMamTV+78nqA/DFvzhIxwxMw=; b=e/N0jTkQPgBfHeUqjdx0it3fczTC/+9b0pa+OtyLNf8TmB0lXQ7xyX6jPvAoqBxR58jsJYO06ung8gdGhr4AWPDZ1OjcNbi7rQKNdiqjrLdcZqrnUm1GmsBHV/NUrwe/Aimq60SM2of29qV0LxU1imyTw77RT1eL1Jf/FHhjpX0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1594130444449335.6147617080168; Tue, 7 Jul 2020 07:00:44 -0700 (PDT) Received: from localhost ([::1]:48482 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jso9I-0007i9-Hw for importer@patchew.org; Tue, 07 Jul 2020 10:00:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54180) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso72-0003mt-ID for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:20 -0400 Received: from mx2.suse.de ([195.135.220.15]:45918) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso6w-0007FU-TT for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:20 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 05714AD7B; Tue, 7 Jul 2020 13:58:14 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , Thomas Huth , Laurent Vivier , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov , Markus Armbruster Subject: [RFC v2 1/6] cpus: extract out TCG-specific code to accel/tcg Date: Tue, 7 Jul 2020 15:58:03 +0200 Message-Id: <20200707135808.9241-2-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200707135808.9241-1-cfontana@suse.de> References: <20200707135808.9241-1-cfontana@suse.de> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=195.135.220.15; envelope-from=cfontana@suse.de; helo=mx2.suse.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 23:42:16 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x (no timestamps) [generic] X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Marcelo Tosatti , qemu-devel@nongnu.org, haxm-team@intel.com, Wenchao Wang , Sunil Muthuswamy , Richard Henderson , Claudio Fontana , Colin Xu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" TCG is the first accelerator to register a "CpusAccel" interface on initialization, providing functions for starting a vcpu, kicking a vcpu, and sychronizing state. Signed-off-by: Claudio Fontana --- accel/tcg/Makefile.objs | 1 + accel/tcg/tcg-all.c | 12 +- accel/tcg/tcg-cpus.c | 532 ++++++++++++++++++++++++++++++++++ accel/tcg/tcg-cpus.h | 17 ++ hw/core/cpu.c | 1 + include/sysemu/cpus.h | 33 +++ include/sysemu/hw_accel.h | 57 +--- softmmu/cpus.c | 643 ++++++++------------------------------= ---- stubs/Makefile.objs | 1 + stubs/cpu-synchronize-state.c | 15 + 10 files changed, 732 insertions(+), 580 deletions(-) create mode 100644 accel/tcg/tcg-cpus.c create mode 100644 accel/tcg/tcg-cpus.h create mode 100644 stubs/cpu-synchronize-state.c diff --git a/accel/tcg/Makefile.objs b/accel/tcg/Makefile.objs index a92f2c454b..ecf9aa582e 100644 --- a/accel/tcg/Makefile.objs +++ b/accel/tcg/Makefile.objs @@ -1,5 +1,6 @@ obj-$(CONFIG_SOFTMMU) +=3D tcg-all.o obj-$(CONFIG_SOFTMMU) +=3D cputlb.o +obj-$(CONFIG_SOFTMMU) +=3D tcg-cpus.o obj-y +=3D tcg-runtime.o tcg-runtime-gvec.o obj-y +=3D cpu-exec.o cpu-exec-common.o translate-all.o obj-y +=3D translator.o diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index e27385d051..3fd4bf2cab 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -24,19 +24,17 @@ */ =20 #include "qemu/osdep.h" -#include "sysemu/accel.h" +#include "qemu-common.h" #include "sysemu/tcg.h" -#include "qom/object.h" -#include "cpu.h" -#include "sysemu/cpus.h" #include "sysemu/cpu-timers.h" -#include "qemu/main-loop.h" #include "tcg/tcg.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/boards.h" #include "qapi/qapi-builtin-visit.h" =20 +#include "tcg-cpus.h" + typedef struct TCGState { AccelState parent_obj; =20 @@ -123,6 +121,8 @@ static void tcg_accel_instance_init(Object *obj) s->mttcg_enabled =3D default_mttcg_enabled(); } =20 +bool mttcg_enabled; + static int tcg_init(MachineState *ms) { TCGState *s =3D TCG_STATE(current_accel()); @@ -130,6 +130,8 @@ static int tcg_init(MachineState *ms) tcg_exec_init(s->tb_size * 1024 * 1024); cpu_interrupt_handler =3D tcg_handle_interrupt; mttcg_enabled =3D s->mttcg_enabled; + cpus_register_accel(&tcg_cpus); + return 0; } =20 diff --git a/accel/tcg/tcg-cpus.c b/accel/tcg/tcg-cpus.c new file mode 100644 index 0000000000..ff7a8b5e0b --- /dev/null +++ b/accel/tcg/tcg-cpus.c @@ -0,0 +1,532 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "sysemu/tcg.h" +#include "sysemu/replay.h" +#include "qemu/main-loop.h" +#include "qemu/guest-random.h" +#include "exec/exec-all.h" + +#include "tcg-cpus.h" + +/* Kick all RR vCPUs */ +static void qemu_cpu_kick_rr_cpus(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + cpu_exit(cpu); + }; +} + +static void tcg_kick_vcpu_thread(CPUState *cpu) +{ + if (qemu_tcg_mttcg_enabled()) { + cpu_exit(cpu); + } else { + qemu_cpu_kick_rr_cpus(); + } +} + +/* + * TCG vCPU kick timer + * + * The kick timer is responsible for moving single threaded vCPU + * emulation on to the next vCPU. If more than one vCPU is running a + * timer event with force a cpu->exit so the next vCPU can get + * scheduled. + * + * The timer is removed if all vCPUs are idle and restarted again once + * idleness is complete. + */ + +static QEMUTimer *tcg_kick_vcpu_timer; +static CPUState *tcg_current_rr_cpu; + +#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10) + +static inline int64_t qemu_tcg_next_kick(void) +{ + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD; +} + +/* Kick the currently round-robin scheduled vCPU to next */ +static void qemu_cpu_kick_rr_next_cpu(void) +{ + CPUState *cpu; + do { + cpu =3D atomic_mb_read(&tcg_current_rr_cpu); + if (cpu) { + cpu_exit(cpu); + } + } while (cpu !=3D atomic_mb_read(&tcg_current_rr_cpu)); +} + +static void kick_tcg_thread(void *opaque) +{ + timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); + qemu_cpu_kick_rr_next_cpu(); +} + +static void start_tcg_kick_timer(void) +{ + assert(!mttcg_enabled); + if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) { + tcg_kick_vcpu_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + kick_tcg_thread, NULL); + } + if (tcg_kick_vcpu_timer && !timer_pending(tcg_kick_vcpu_timer)) { + timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); + } +} + +static void stop_tcg_kick_timer(void) +{ + assert(!mttcg_enabled); + if (tcg_kick_vcpu_timer && timer_pending(tcg_kick_vcpu_timer)) { + timer_del(tcg_kick_vcpu_timer); + } +} + +static void qemu_tcg_destroy_vcpu(CPUState *cpu) +{ +} + +static void qemu_tcg_rr_wait_io_event(void) +{ + CPUState *cpu; + + while (all_cpu_threads_idle()) { + stop_tcg_kick_timer(); + qemu_cond_wait_iothread(first_cpu->halt_cond); + } + + start_tcg_kick_timer(); + + CPU_FOREACH(cpu) { + qemu_wait_io_event_common(cpu); + } +} + +static int64_t tcg_get_icount_limit(void) +{ + int64_t deadline; + + if (replay_mode !=3D REPLAY_MODE_PLAY) { + /* + * Include all the timers, because they may need an attention. + * Too long CPU execution may create unnecessary delay in UI. + */ + deadline =3D qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); + /* Check realtime timers, because they help with input processing = */ + deadline =3D qemu_soonest_timeout(deadline, + qemu_clock_deadline_ns_all(QEMU_CLOCK_REALTIME, + QEMU_TIMER_ATTR_ALL)); + + /* + * Maintain prior (possibly buggy) behaviour where if no deadline + * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more= than + * INT32_MAX nanoseconds ahead, we still use INT32_MAX + * nanoseconds. + */ + if ((deadline < 0) || (deadline > INT32_MAX)) { + deadline =3D INT32_MAX; + } + + return icount_round(deadline); + } else { + return replay_get_instructions(); + } +} + +static void notify_aio_contexts(void) +{ + /* Wake up other AioContexts. */ + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL); +} + +static void handle_icount_deadline(void) +{ + assert(qemu_in_vcpu_thread()); + if (icount_enabled()) { + int64_t deadline =3D qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); + + if (deadline =3D=3D 0) { + notify_aio_contexts(); + } + } +} + +static void prepare_icount_for_run(CPUState *cpu) +{ + if (icount_enabled()) { + int insns_left; + + /* + * These should always be cleared by process_icount_data after + * each vCPU execution. However u16.high can be raised + * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt + */ + g_assert(cpu_neg(cpu)->icount_decr.u16.low =3D=3D 0); + g_assert(cpu->icount_extra =3D=3D 0); + + cpu->icount_budget =3D tcg_get_icount_limit(); + insns_left =3D MIN(0xffff, cpu->icount_budget); + cpu_neg(cpu)->icount_decr.u16.low =3D insns_left; + cpu->icount_extra =3D cpu->icount_budget - insns_left; + + replay_mutex_lock(); + + if (cpu->icount_budget =3D=3D 0 && replay_has_checkpoint()) { + notify_aio_contexts(); + } + } +} + +static void process_icount_data(CPUState *cpu) +{ + if (icount_enabled()) { + /* Account for executed instructions */ + icount_update(cpu); + + /* Reset the counters */ + cpu_neg(cpu)->icount_decr.u16.low =3D 0; + cpu->icount_extra =3D 0; + cpu->icount_budget =3D 0; + + replay_account_executed_instructions(); + + replay_mutex_unlock(); + } +} + +static int tcg_cpu_exec(CPUState *cpu) +{ + int ret; +#ifdef CONFIG_PROFILER + int64_t ti; +#endif + + assert(tcg_enabled()); +#ifdef CONFIG_PROFILER + ti =3D profile_getclock(); +#endif + cpu_exec_start(cpu); + ret =3D cpu_exec(cpu); + cpu_exec_end(cpu); +#ifdef CONFIG_PROFILER + atomic_set(&tcg_ctx->prof.cpu_exec_time, + tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti); +#endif + return ret; +} + +/* + * Destroy any remaining vCPUs which have been unplugged and have + * finished running + */ +static void deal_with_unplugged_cpus(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + if (cpu->unplug && !cpu_can_run(cpu)) { + qemu_tcg_destroy_vcpu(cpu); + cpu_thread_signal_destroyed(cpu); + break; + } + } +} + +/* + * Single-threaded TCG + * + * In the single-threaded case each vCPU is simulated in turn. If + * there is more than a single vCPU we create a simple timer to kick + * the vCPU and ensure we don't get stuck in a tight loop in one vCPU. + * This is done explicitly rather than relying on side-effects + * elsewhere. + */ + +static void *tcg_rr_cpu_thread_fn(void *arg) +{ + CPUState *cpu =3D arg; + + assert(tcg_enabled()); + rcu_register_thread(); + tcg_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + + cpu->thread_id =3D qemu_get_thread_id(); + cpu->can_do_io =3D 1; + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + /* wait for initial kick-off after machine start */ + while (first_cpu->stopped) { + qemu_cond_wait_iothread(first_cpu->halt_cond); + + /* process any pending work */ + CPU_FOREACH(cpu) { + current_cpu =3D cpu; + qemu_wait_io_event_common(cpu); + } + } + + start_tcg_kick_timer(); + + cpu =3D first_cpu; + + /* process any pending work */ + cpu->exit_request =3D 1; + + while (1) { + qemu_mutex_unlock_iothread(); + replay_mutex_lock(); + qemu_mutex_lock_iothread(); + /* Account partial waits to QEMU_CLOCK_VIRTUAL. */ + icount_account_warp_timer(); + + /* + * Run the timers here. This is much more efficient than + * waking up the I/O thread and waiting for completion. + */ + handle_icount_deadline(); + + replay_mutex_unlock(); + + if (!cpu) { + cpu =3D first_cpu; + } + + while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) { + + atomic_mb_set(&tcg_current_rr_cpu, cpu); + current_cpu =3D cpu; + + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, + (cpu->singlestep_enabled & SSTEP_NOTIMER) = =3D=3D 0); + + if (cpu_can_run(cpu)) { + int r; + + qemu_mutex_unlock_iothread(); + prepare_icount_for_run(cpu); + + r =3D tcg_cpu_exec(cpu); + + process_icount_data(cpu); + qemu_mutex_lock_iothread(); + + if (r =3D=3D EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + break; + } else if (r =3D=3D EXCP_ATOMIC) { + qemu_mutex_unlock_iothread(); + cpu_exec_step_atomic(cpu); + qemu_mutex_lock_iothread(); + break; + } + } else if (cpu->stop) { + if (cpu->unplug) { + cpu =3D CPU_NEXT(cpu); + } + break; + } + + cpu =3D CPU_NEXT(cpu); + } /* while (cpu && !cpu->exit_request).. */ + + /* Does not need atomic_mb_set because a spurious wakeup is okay. = */ + atomic_set(&tcg_current_rr_cpu, NULL); + + if (cpu && cpu->exit_request) { + atomic_mb_set(&cpu->exit_request, 0); + } + + if (icount_enabled() && all_cpu_threads_idle()) { + /* + * When all cpus are sleeping (e.g in WFI), to avoid a deadlock + * in the main_loop, wake it up in order to start the warp tim= er. + */ + qemu_notify_event(); + } + + qemu_tcg_rr_wait_io_event(); + deal_with_unplugged_cpus(); + } + + rcu_unregister_thread(); + return NULL; +} + +/* + * Multi-threaded TCG + * + * In the multi-threaded case each vCPU has its own thread. The TLS + * variable current_cpu can be used deep in the code to find the + * current CPUState for a given thread. + */ + +static void *tcg_cpu_thread_fn(void *arg) +{ + CPUState *cpu =3D arg; + + assert(tcg_enabled()); + g_assert(!icount_enabled()); + + rcu_register_thread(); + tcg_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + + cpu->thread_id =3D qemu_get_thread_id(); + cpu->can_do_io =3D 1; + current_cpu =3D cpu; + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + /* process any pending work */ + cpu->exit_request =3D 1; + + do { + if (cpu_can_run(cpu)) { + int r; + qemu_mutex_unlock_iothread(); + r =3D tcg_cpu_exec(cpu); + qemu_mutex_lock_iothread(); + switch (r) { + case EXCP_DEBUG: + cpu_handle_guest_debug(cpu); + break; + case EXCP_HALTED: + /* + * during start-up the vCPU is reset and the thread is + * kicked several times. If we don't ensure we go back + * to sleep in the halted state we won't cleanly + * start-up when the vCPU is enabled. + * + * cpu->halted should ensure we sleep in wait_io_event + */ + g_assert(cpu->halted); + break; + case EXCP_ATOMIC: + qemu_mutex_unlock_iothread(); + cpu_exec_step_atomic(cpu); + qemu_mutex_lock_iothread(); + default: + /* Ignore everything else? */ + break; + } + } + + atomic_mb_set(&cpu->exit_request, 0); + qemu_wait_io_event(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + qemu_tcg_destroy_vcpu(cpu); + cpu_thread_signal_destroyed(cpu); + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + +static void tcg_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + static QemuCond *single_tcg_halt_cond; + static QemuThread *single_tcg_cpu_thread; + static int tcg_region_inited; + + assert(tcg_enabled()); + /* + * Initialize TCG regions--once. Now is a good time, because: + * (1) TCG's init context, prologue and target globals have been set u= p. + * (2) qemu_tcg_mttcg_enabled() works now (TCG init code runs before t= he + * -accel flag is processed, so the check doesn't work then). + */ + if (!tcg_region_inited) { + tcg_region_inited =3D 1; + tcg_region_init(); + } + + if (qemu_tcg_mttcg_enabled() || !single_tcg_cpu_thread) { + cpu->thread =3D g_malloc0(sizeof(QemuThread)); + cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + + if (qemu_tcg_mttcg_enabled()) { + /* create a thread per vCPU with TCG (MTTCG) */ + parallel_cpus =3D true; + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG", + cpu->cpu_index); + + qemu_thread_create(cpu->thread, thread_name, tcg_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); + + } else { + /* share a single thread for all cpus with TCG */ + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG"); + qemu_thread_create(cpu->thread, thread_name, + tcg_rr_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); + + single_tcg_halt_cond =3D cpu->halt_cond; + single_tcg_cpu_thread =3D cpu->thread; + } +#ifdef _WIN32 + cpu->hThread =3D qemu_thread_get_handle(cpu->thread); +#endif + } else { + /* For non-MTTCG cases we share the thread */ + cpu->thread =3D single_tcg_cpu_thread; + cpu->halt_cond =3D single_tcg_halt_cond; + cpu->thread_id =3D first_cpu->thread_id; + cpu->can_do_io =3D 1; + cpu->created =3D true; + } +} + +static void tcg_cpu_synchronize_noop(CPUState *cpu) +{ +} + +CpusAccel tcg_cpus =3D { + .create_vcpu_thread =3D tcg_start_vcpu_thread, + .kick_vcpu_thread =3D tcg_kick_vcpu_thread, + + .synchronize_post_reset =3D tcg_cpu_synchronize_noop, + .synchronize_post_init =3D tcg_cpu_synchronize_noop, + .synchronize_state =3D tcg_cpu_synchronize_noop, + .synchronize_pre_loadvm =3D tcg_cpu_synchronize_noop, +}; diff --git a/accel/tcg/tcg-cpus.h b/accel/tcg/tcg-cpus.h new file mode 100644 index 0000000000..af4be6a151 --- /dev/null +++ b/accel/tcg/tcg-cpus.h @@ -0,0 +1,17 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef TCG_CPUS_H +#define TCG_CPUS_H + +#include "sysemu/cpus.h" + +extern CpusAccel tcg_cpus; + +#endif /* TCG_CPUS_H */ diff --git a/hw/core/cpu.c b/hw/core/cpu.c index 0f23409f1d..2e6bb3b4d3 100644 --- a/hw/core/cpu.c +++ b/hw/core/cpu.c @@ -33,6 +33,7 @@ #include "hw/qdev-properties.h" #include "trace-root.h" #include "qemu/plugin.h" +#include "sysemu/hw_accel.h" =20 CPUInterruptHandler cpu_interrupt_handler; =20 diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index 149de000a0..10cc5a2d22 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -4,7 +4,40 @@ #include "qemu/timer.h" =20 /* cpus.c */ + +/* CPU execution threads */ + +typedef struct CpusAccel { + void (*create_vcpu_thread)(CPUState *cpu); + void (*kick_vcpu_thread)(CPUState *cpu); + + void (*synchronize_post_reset)(CPUState *cpu); + void (*synchronize_post_init)(CPUState *cpu); + void (*synchronize_state)(CPUState *cpu); + void (*synchronize_pre_loadvm)(CPUState *cpu); +} CpusAccel; + +/* register accel-specific cpus interface implementation */ +void cpus_register_accel(CpusAccel *i); + +/* interface available for cpus accelerator threads */ + +/* For temporary buffers for forming a name */ +#define VCPU_THREAD_NAME_SIZE 16 + +void cpus_kick_thread(CPUState *cpu); +bool cpu_work_list_empty(CPUState *cpu); +bool cpu_thread_is_idle(CPUState *cpu); bool all_cpu_threads_idle(void); +bool cpu_can_run(CPUState *cpu); +void qemu_wait_io_event_common(CPUState *cpu); +void qemu_wait_io_event(CPUState *cpu); +void cpu_thread_signal_created(CPUState *cpu); +void cpu_thread_signal_destroyed(CPUState *cpu); +void cpu_handle_guest_debug(CPUState *cpu); + +/* end interface for cpus accelerator threads */ + bool qemu_in_vcpu_thread(void); void qemu_init_cpu_loop(void); void resume_all_vcpus(void); diff --git a/include/sysemu/hw_accel.h b/include/sysemu/hw_accel.h index 0ec2372477..336740e10a 100644 --- a/include/sysemu/hw_accel.h +++ b/include/sysemu/hw_accel.h @@ -1,5 +1,5 @@ /* - * QEMU Hardware accelertors support + * QEMU Hardware accelerators support * * Copyright 2016 Google, Inc. * @@ -16,56 +16,9 @@ #include "sysemu/kvm.h" #include "sysemu/whpx.h" =20 -static inline void cpu_synchronize_state(CPUState *cpu) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_state(cpu); - } - if (hax_enabled()) { - hax_cpu_synchronize_state(cpu); - } - if (whpx_enabled()) { - whpx_cpu_synchronize_state(cpu); - } -} - -static inline void cpu_synchronize_post_reset(CPUState *cpu) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_post_reset(cpu); - } - if (hax_enabled()) { - hax_cpu_synchronize_post_reset(cpu); - } - if (whpx_enabled()) { - whpx_cpu_synchronize_post_reset(cpu); - } -} - -static inline void cpu_synchronize_post_init(CPUState *cpu) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_post_init(cpu); - } - if (hax_enabled()) { - hax_cpu_synchronize_post_init(cpu); - } - if (whpx_enabled()) { - whpx_cpu_synchronize_post_init(cpu); - } -} - -static inline void cpu_synchronize_pre_loadvm(CPUState *cpu) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_pre_loadvm(cpu); - } - if (hax_enabled()) { - hax_cpu_synchronize_pre_loadvm(cpu); - } - if (whpx_enabled()) { - whpx_cpu_synchronize_pre_loadvm(cpu); - } -} +void cpu_synchronize_state(CPUState *cpu); +void cpu_synchronize_post_reset(CPUState *cpu); +void cpu_synchronize_post_init(CPUState *cpu); +void cpu_synchronize_pre_loadvm(CPUState *cpu); =20 #endif /* QEMU_HW_ACCEL_H */ diff --git a/softmmu/cpus.c b/softmmu/cpus.c index a44960cd70..5fadc8f34c 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -24,27 +24,19 @@ =20 #include "qemu/osdep.h" #include "qemu-common.h" -#include "qemu/config-file.h" -#include "qemu/cutils.h" -#include "migration/vmstate.h" #include "monitor/monitor.h" #include "qapi/error.h" #include "qapi/qapi-commands-misc.h" #include "qapi/qapi-events-run-state.h" #include "qapi/qmp/qerror.h" -#include "qemu/error-report.h" -#include "qemu/qemu-print.h" #include "sysemu/tcg.h" -#include "sysemu/block-backend.h" #include "exec/gdbstub.h" -#include "sysemu/dma.h" #include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "sysemu/hax.h" #include "sysemu/hvf.h" #include "sysemu/whpx.h" #include "exec/exec-all.h" - #include "qemu/thread.h" #include "qemu/plugin.h" #include "sysemu/cpus.h" @@ -87,7 +79,7 @@ bool cpu_is_stopped(CPUState *cpu) return cpu->stopped || !runstate_is_running(); } =20 -static inline bool cpu_work_list_empty(CPUState *cpu) +bool cpu_work_list_empty(CPUState *cpu) { bool ret; =20 @@ -97,7 +89,7 @@ static inline bool cpu_work_list_empty(CPUState *cpu) return ret; } =20 -static bool cpu_thread_is_idle(CPUState *cpu) +bool cpu_thread_is_idle(CPUState *cpu) { if (cpu->stop || !cpu_work_list_empty(cpu)) { return false; @@ -124,79 +116,6 @@ bool all_cpu_threads_idle(void) return true; } =20 -bool mttcg_enabled; - - -/***********************************************************/ -/* TCG vCPU kick timer - * - * The kick timer is responsible for moving single threaded vCPU - * emulation on to the next vCPU. If more than one vCPU is running a - * timer event with force a cpu->exit so the next vCPU can get - * scheduled. - * - * The timer is removed if all vCPUs are idle and restarted again once - * idleness is complete. - */ - -static QEMUTimer *tcg_kick_vcpu_timer; -static CPUState *tcg_current_rr_cpu; - -#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10) - -static inline int64_t qemu_tcg_next_kick(void) -{ - return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD; -} - -/* Kick the currently round-robin scheduled vCPU to next */ -static void qemu_cpu_kick_rr_next_cpu(void) -{ - CPUState *cpu; - do { - cpu =3D atomic_mb_read(&tcg_current_rr_cpu); - if (cpu) { - cpu_exit(cpu); - } - } while (cpu !=3D atomic_mb_read(&tcg_current_rr_cpu)); -} - -/* Kick all RR vCPUs */ -static void qemu_cpu_kick_rr_cpus(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - cpu_exit(cpu); - }; -} - -static void kick_tcg_thread(void *opaque) -{ - timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); - qemu_cpu_kick_rr_next_cpu(); -} - -static void start_tcg_kick_timer(void) -{ - assert(!mttcg_enabled); - if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) { - tcg_kick_vcpu_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, - kick_tcg_thread, NULL); - } - if (tcg_kick_vcpu_timer && !timer_pending(tcg_kick_vcpu_timer)) { - timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); - } -} - -static void stop_tcg_kick_timer(void) -{ - assert(!mttcg_enabled); - if (tcg_kick_vcpu_timer && timer_pending(tcg_kick_vcpu_timer)) { - timer_del(tcg_kick_vcpu_timer); - } -} - /***********************************************************/ void hw_error(const char *fmt, ...) { @@ -215,6 +134,11 @@ void hw_error(const char *fmt, ...) abort(); } =20 +/* + * The chosen accelerator is supposed to register this. + */ +static CpusAccel *cpus_accel; + void cpu_synchronize_all_states(void) { CPUState *cpu; @@ -263,6 +187,74 @@ void cpu_synchronize_all_pre_loadvm(void) } } =20 +void cpu_synchronize_state(CPUState *cpu) +{ + if (cpus_accel) { + /* accelerator already implements the CpusAccel interface */ + cpus_accel->synchronize_state(cpu); + } + if (kvm_enabled()) { + kvm_cpu_synchronize_state(cpu); + } + if (hax_enabled()) { + hax_cpu_synchronize_state(cpu); + } + if (whpx_enabled()) { + whpx_cpu_synchronize_state(cpu); + } +} + +void cpu_synchronize_post_reset(CPUState *cpu) +{ + if (cpus_accel) { + /* accelerator already implements the CpusAccel interface */ + cpus_accel->synchronize_post_reset(cpu); + } + if (kvm_enabled()) { + kvm_cpu_synchronize_post_reset(cpu); + } + if (hax_enabled()) { + hax_cpu_synchronize_post_reset(cpu); + } + if (whpx_enabled()) { + whpx_cpu_synchronize_post_reset(cpu); + } +} + +void cpu_synchronize_post_init(CPUState *cpu) +{ + if (cpus_accel) { + /* accelerator already implements the CpusAccel interface */ + cpus_accel->synchronize_post_init(cpu); + } + if (kvm_enabled()) { + kvm_cpu_synchronize_post_init(cpu); + } + if (hax_enabled()) { + hax_cpu_synchronize_post_init(cpu); + } + if (whpx_enabled()) { + whpx_cpu_synchronize_post_init(cpu); + } +} + +void cpu_synchronize_pre_loadvm(CPUState *cpu) +{ + if (cpus_accel) { + /* accelerator already implements the CpusAccel interface */ + cpus_accel->synchronize_pre_loadvm(cpu); + } + if (kvm_enabled()) { + kvm_cpu_synchronize_pre_loadvm(cpu); + } + if (hax_enabled()) { + hax_cpu_synchronize_pre_loadvm(cpu); + } + if (whpx_enabled()) { + whpx_cpu_synchronize_pre_loadvm(cpu); + } +} + static int do_vm_stop(RunState state, bool send_stop) { int ret =3D 0; @@ -291,7 +283,7 @@ int vm_shutdown(void) return do_vm_stop(RUN_STATE_SHUTDOWN, false); } =20 -static bool cpu_can_run(CPUState *cpu) +bool cpu_can_run(CPUState *cpu) { if (cpu->stop) { return false; @@ -302,7 +294,7 @@ static bool cpu_can_run(CPUState *cpu) return true; } =20 -static void cpu_handle_guest_debug(CPUState *cpu) +void cpu_handle_guest_debug(CPUState *cpu) { gdb_set_stop_cpu(cpu); qemu_system_debug_request(); @@ -393,10 +385,6 @@ static void qemu_kvm_destroy_vcpu(CPUState *cpu) } } =20 -static void qemu_tcg_destroy_vcpu(CPUState *cpu) -{ -} - static void qemu_cpu_stop(CPUState *cpu, bool exit) { g_assert(qemu_cpu_is_self(cpu)); @@ -408,7 +396,7 @@ static void qemu_cpu_stop(CPUState *cpu, bool exit) qemu_cond_broadcast(&qemu_pause_cond); } =20 -static void qemu_wait_io_event_common(CPUState *cpu) +void qemu_wait_io_event_common(CPUState *cpu) { atomic_mb_set(&cpu->thread_kicked, false); if (cpu->stop) { @@ -417,23 +405,7 @@ static void qemu_wait_io_event_common(CPUState *cpu) process_queued_cpu_work(cpu); } =20 -static void qemu_tcg_rr_wait_io_event(void) -{ - CPUState *cpu; - - while (all_cpu_threads_idle()) { - stop_tcg_kick_timer(); - qemu_cond_wait(first_cpu->halt_cond, &qemu_global_mutex); - } - - start_tcg_kick_timer(); - - CPU_FOREACH(cpu) { - qemu_wait_io_event_common(cpu); - } -} - -static void qemu_wait_io_event(CPUState *cpu) +void qemu_wait_io_event(CPUState *cpu) { bool slept =3D false; =20 @@ -449,7 +421,8 @@ static void qemu_wait_io_event(CPUState *cpu) } =20 #ifdef _WIN32 - /* Eat dummy APC queued by qemu_cpu_kick_thread. */ + /* Eat dummy APC queued by hax_kick_vcpu_thread */ + /* NB!!! Should not this be if (hax_enabled)? Is this wrong for whpx? = */ if (!tcg_enabled()) { SleepEx(0, TRUE); } @@ -479,8 +452,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) kvm_init_cpu_signals(cpu); =20 /* signal CPU creation */ - cpu->created =3D true; - qemu_cond_signal(&qemu_cpu_cond); + cpu_thread_signal_created(cpu); qemu_guest_random_seed_thread_part2(cpu->random_seed); =20 do { @@ -494,8 +466,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) } while (!cpu->unplug || cpu_can_run(cpu)); =20 qemu_kvm_destroy_vcpu(cpu); - cpu->created =3D false; - qemu_cond_signal(&qemu_cpu_cond); + cpu_thread_signal_destroyed(cpu); qemu_mutex_unlock_iothread(); rcu_unregister_thread(); return NULL; @@ -523,8 +494,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) sigaddset(&waitset, SIG_IPI); =20 /* signal CPU creation */ - cpu->created =3D true; - qemu_cond_signal(&qemu_cpu_cond); + cpu_thread_signal_created(cpu); qemu_guest_random_seed_thread_part2(cpu->random_seed); =20 do { @@ -547,261 +517,6 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) #endif } =20 -static int64_t tcg_get_icount_limit(void) -{ - int64_t deadline; - - if (replay_mode !=3D REPLAY_MODE_PLAY) { - /* - * Include all the timers, because they may need an attention. - * Too long CPU execution may create unnecessary delay in UI. - */ - deadline =3D qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, - QEMU_TIMER_ATTR_ALL); - /* Check realtime timers, because they help with input processing = */ - deadline =3D qemu_soonest_timeout(deadline, - qemu_clock_deadline_ns_all(QEMU_CLOCK_REALTIME, - QEMU_TIMER_ATTR_ALL)); - - /* Maintain prior (possibly buggy) behaviour where if no deadline - * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more= than - * INT32_MAX nanoseconds ahead, we still use INT32_MAX - * nanoseconds. - */ - if ((deadline < 0) || (deadline > INT32_MAX)) { - deadline =3D INT32_MAX; - } - - return icount_round(deadline); - } else { - return replay_get_instructions(); - } -} - -static void notify_aio_contexts(void) -{ - /* Wake up other AioContexts. */ - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL); -} - -static void handle_icount_deadline(void) -{ - assert(qemu_in_vcpu_thread()); - if (icount_enabled()) { - int64_t deadline =3D qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, - QEMU_TIMER_ATTR_ALL); - - if (deadline =3D=3D 0) { - notify_aio_contexts(); - } - } -} - -static void prepare_icount_for_run(CPUState *cpu) -{ - if (icount_enabled()) { - int insns_left; - - /* These should always be cleared by process_icount_data after - * each vCPU execution. However u16.high can be raised - * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt - */ - g_assert(cpu_neg(cpu)->icount_decr.u16.low =3D=3D 0); - g_assert(cpu->icount_extra =3D=3D 0); - - cpu->icount_budget =3D tcg_get_icount_limit(); - insns_left =3D MIN(0xffff, cpu->icount_budget); - cpu_neg(cpu)->icount_decr.u16.low =3D insns_left; - cpu->icount_extra =3D cpu->icount_budget - insns_left; - - replay_mutex_lock(); - - if (cpu->icount_budget =3D=3D 0 && replay_has_checkpoint()) { - notify_aio_contexts(); - } - } -} - -static void process_icount_data(CPUState *cpu) -{ - if (icount_enabled()) { - /* Account for executed instructions */ - icount_update(cpu); - - /* Reset the counters */ - cpu_neg(cpu)->icount_decr.u16.low =3D 0; - cpu->icount_extra =3D 0; - cpu->icount_budget =3D 0; - - replay_account_executed_instructions(); - - replay_mutex_unlock(); - } -} - - -static int tcg_cpu_exec(CPUState *cpu) -{ - int ret; -#ifdef CONFIG_PROFILER - int64_t ti; -#endif - - assert(tcg_enabled()); -#ifdef CONFIG_PROFILER - ti =3D profile_getclock(); -#endif - cpu_exec_start(cpu); - ret =3D cpu_exec(cpu); - cpu_exec_end(cpu); -#ifdef CONFIG_PROFILER - atomic_set(&tcg_ctx->prof.cpu_exec_time, - tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti); -#endif - return ret; -} - -/* Destroy any remaining vCPUs which have been unplugged and have - * finished running - */ -static void deal_with_unplugged_cpus(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - if (cpu->unplug && !cpu_can_run(cpu)) { - qemu_tcg_destroy_vcpu(cpu); - cpu->created =3D false; - qemu_cond_signal(&qemu_cpu_cond); - break; - } - } -} - -/* Single-threaded TCG - * - * In the single-threaded case each vCPU is simulated in turn. If - * there is more than a single vCPU we create a simple timer to kick - * the vCPU and ensure we don't get stuck in a tight loop in one vCPU. - * This is done explicitly rather than relying on side-effects - * elsewhere. - */ - -static void *qemu_tcg_rr_cpu_thread_fn(void *arg) -{ - CPUState *cpu =3D arg; - - assert(tcg_enabled()); - rcu_register_thread(); - tcg_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - - cpu->thread_id =3D qemu_get_thread_id(); - cpu->created =3D true; - cpu->can_do_io =3D 1; - qemu_cond_signal(&qemu_cpu_cond); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - /* wait for initial kick-off after machine start */ - while (first_cpu->stopped) { - qemu_cond_wait(first_cpu->halt_cond, &qemu_global_mutex); - - /* process any pending work */ - CPU_FOREACH(cpu) { - current_cpu =3D cpu; - qemu_wait_io_event_common(cpu); - } - } - - start_tcg_kick_timer(); - - cpu =3D first_cpu; - - /* process any pending work */ - cpu->exit_request =3D 1; - - while (1) { - qemu_mutex_unlock_iothread(); - replay_mutex_lock(); - qemu_mutex_lock_iothread(); - /* Account partial waits to QEMU_CLOCK_VIRTUAL. */ - icount_account_warp_timer(); - - /* Run the timers here. This is much more efficient than - * waking up the I/O thread and waiting for completion. - */ - handle_icount_deadline(); - - replay_mutex_unlock(); - - if (!cpu) { - cpu =3D first_cpu; - } - - while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) { - - atomic_mb_set(&tcg_current_rr_cpu, cpu); - current_cpu =3D cpu; - - qemu_clock_enable(QEMU_CLOCK_VIRTUAL, - (cpu->singlestep_enabled & SSTEP_NOTIMER) = =3D=3D 0); - - if (cpu_can_run(cpu)) { - int r; - - qemu_mutex_unlock_iothread(); - prepare_icount_for_run(cpu); - - r =3D tcg_cpu_exec(cpu); - - process_icount_data(cpu); - qemu_mutex_lock_iothread(); - - if (r =3D=3D EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - break; - } else if (r =3D=3D EXCP_ATOMIC) { - qemu_mutex_unlock_iothread(); - cpu_exec_step_atomic(cpu); - qemu_mutex_lock_iothread(); - break; - } - } else if (cpu->stop) { - if (cpu->unplug) { - cpu =3D CPU_NEXT(cpu); - } - break; - } - - cpu =3D CPU_NEXT(cpu); - } /* while (cpu && !cpu->exit_request).. */ - - /* Does not need atomic_mb_set because a spurious wakeup is okay. = */ - atomic_set(&tcg_current_rr_cpu, NULL); - - if (cpu && cpu->exit_request) { - atomic_mb_set(&cpu->exit_request, 0); - } - - if (icount_enabled() && all_cpu_threads_idle()) { - /* - * When all cpus are sleeping (e.g in WFI), to avoid a deadlock - * in the main_loop, wake it up in order to start the warp tim= er. - */ - qemu_notify_event(); - } - - qemu_tcg_rr_wait_io_event(); - deal_with_unplugged_cpus(); - } - - rcu_unregister_thread(); - return NULL; -} - static void *qemu_hax_cpu_thread_fn(void *arg) { CPUState *cpu =3D arg; @@ -812,11 +527,9 @@ static void *qemu_hax_cpu_thread_fn(void *arg) qemu_thread_get_self(cpu->thread); =20 cpu->thread_id =3D qemu_get_thread_id(); - cpu->created =3D true; current_cpu =3D cpu; - hax_init_vcpu(cpu); - qemu_cond_signal(&qemu_cpu_cond); + cpu_thread_signal_created(cpu); qemu_guest_random_seed_thread_part2(cpu->random_seed); =20 do { @@ -855,8 +568,7 @@ static void *qemu_hvf_cpu_thread_fn(void *arg) hvf_init_vcpu(cpu); =20 /* signal CPU creation */ - cpu->created =3D true; - qemu_cond_signal(&qemu_cpu_cond); + cpu_thread_signal_created(cpu); qemu_guest_random_seed_thread_part2(cpu->random_seed); =20 do { @@ -870,8 +582,7 @@ static void *qemu_hvf_cpu_thread_fn(void *arg) } while (!cpu->unplug || cpu_can_run(cpu)); =20 hvf_vcpu_destroy(cpu); - cpu->created =3D false; - qemu_cond_signal(&qemu_cpu_cond); + cpu_thread_signal_destroyed(cpu); qemu_mutex_unlock_iothread(); rcu_unregister_thread(); return NULL; @@ -896,8 +607,7 @@ static void *qemu_whpx_cpu_thread_fn(void *arg) } =20 /* signal CPU creation */ - cpu->created =3D true; - qemu_cond_signal(&qemu_cpu_cond); + cpu_thread_signal_created(cpu); qemu_guest_random_seed_thread_part2(cpu->random_seed); =20 do { @@ -914,8 +624,7 @@ static void *qemu_whpx_cpu_thread_fn(void *arg) } while (!cpu->unplug || cpu_can_run(cpu)); =20 whpx_destroy_vcpu(cpu); - cpu->created =3D false; - qemu_cond_signal(&qemu_cpu_cond); + cpu_thread_signal_destroyed(cpu); qemu_mutex_unlock_iothread(); rcu_unregister_thread(); return NULL; @@ -927,79 +636,7 @@ static void CALLBACK dummy_apc_func(ULONG_PTR unused) } #endif =20 -/* Multi-threaded TCG - * - * In the multi-threaded case each vCPU has its own thread. The TLS - * variable current_cpu can be used deep in the code to find the - * current CPUState for a given thread. - */ - -static void *qemu_tcg_cpu_thread_fn(void *arg) -{ - CPUState *cpu =3D arg; - - assert(tcg_enabled()); - g_assert(!icount_enabled()); - - rcu_register_thread(); - tcg_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - - cpu->thread_id =3D qemu_get_thread_id(); - cpu->created =3D true; - cpu->can_do_io =3D 1; - current_cpu =3D cpu; - qemu_cond_signal(&qemu_cpu_cond); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - /* process any pending work */ - cpu->exit_request =3D 1; - - do { - if (cpu_can_run(cpu)) { - int r; - qemu_mutex_unlock_iothread(); - r =3D tcg_cpu_exec(cpu); - qemu_mutex_lock_iothread(); - switch (r) { - case EXCP_DEBUG: - cpu_handle_guest_debug(cpu); - break; - case EXCP_HALTED: - /* during start-up the vCPU is reset and the thread is - * kicked several times. If we don't ensure we go back - * to sleep in the halted state we won't cleanly - * start-up when the vCPU is enabled. - * - * cpu->halted should ensure we sleep in wait_io_event - */ - g_assert(cpu->halted); - break; - case EXCP_ATOMIC: - qemu_mutex_unlock_iothread(); - cpu_exec_step_atomic(cpu); - qemu_mutex_lock_iothread(); - default: - /* Ignore everything else? */ - break; - } - } - - atomic_mb_set(&cpu->exit_request, 0); - qemu_wait_io_event(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - - qemu_tcg_destroy_vcpu(cpu); - cpu->created =3D false; - qemu_cond_signal(&qemu_cpu_cond); - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -} - -static void qemu_cpu_kick_thread(CPUState *cpu) +void cpus_kick_thread(CPUState *cpu) { #ifndef _WIN32 int err; @@ -1029,12 +666,9 @@ static void qemu_cpu_kick_thread(CPUState *cpu) void qemu_cpu_kick(CPUState *cpu) { qemu_cond_broadcast(cpu->halt_cond); - if (tcg_enabled()) { - if (qemu_tcg_mttcg_enabled()) { - cpu_exit(cpu); - } else { - qemu_cpu_kick_rr_cpus(); - } + if (cpus_accel) { + /* accelerator already implements the CpusAccel interface */ + cpus_accel->kick_vcpu_thread(cpu); } else { if (hax_enabled()) { /* @@ -1043,14 +677,14 @@ void qemu_cpu_kick(CPUState *cpu) */ cpu->exit_request =3D 1; } - qemu_cpu_kick_thread(cpu); + cpus_kick_thread(cpu); } } =20 void qemu_cpu_kick_self(void) { assert(current_cpu); - qemu_cpu_kick_thread(current_cpu); + cpus_kick_thread(current_cpu); } =20 bool qemu_cpu_is_self(CPUState *cpu) @@ -1100,6 +734,21 @@ void qemu_cond_timedwait_iothread(QemuCond *cond, int= ms) qemu_cond_timedwait(cond, &qemu_global_mutex, ms); } =20 +/* signal CPU creation */ +void cpu_thread_signal_created(CPUState *cpu) +{ + cpu->created =3D true; + qemu_cond_signal(&qemu_cpu_cond); +} + +/* signal CPU destruction */ +void cpu_thread_signal_destroyed(CPUState *cpu) +{ + cpu->created =3D false; + qemu_cond_signal(&qemu_cpu_cond); +} + + static bool all_vcpus_paused(void) { CPUState *cpu; @@ -1175,65 +824,6 @@ void cpu_remove_sync(CPUState *cpu) qemu_mutex_lock_iothread(); } =20 -/* For temporary buffers for forming a name */ -#define VCPU_THREAD_NAME_SIZE 16 - -static void qemu_tcg_init_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - static QemuCond *single_tcg_halt_cond; - static QemuThread *single_tcg_cpu_thread; - static int tcg_region_inited; - - assert(tcg_enabled()); - /* - * Initialize TCG regions--once. Now is a good time, because: - * (1) TCG's init context, prologue and target globals have been set u= p. - * (2) qemu_tcg_mttcg_enabled() works now (TCG init code runs before t= he - * -accel flag is processed, so the check doesn't work then). - */ - if (!tcg_region_inited) { - tcg_region_inited =3D 1; - tcg_region_init(); - } - - if (qemu_tcg_mttcg_enabled() || !single_tcg_cpu_thread) { - cpu->thread =3D g_malloc0(sizeof(QemuThread)); - cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - - if (qemu_tcg_mttcg_enabled()) { - /* create a thread per vCPU with TCG (MTTCG) */ - parallel_cpus =3D true; - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG", - cpu->cpu_index); - - qemu_thread_create(cpu->thread, thread_name, qemu_tcg_cpu_thre= ad_fn, - cpu, QEMU_THREAD_JOINABLE); - - } else { - /* share a single thread for all cpus with TCG */ - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG"); - qemu_thread_create(cpu->thread, thread_name, - qemu_tcg_rr_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); - - single_tcg_halt_cond =3D cpu->halt_cond; - single_tcg_cpu_thread =3D cpu->thread; - } -#ifdef _WIN32 - cpu->hThread =3D qemu_thread_get_handle(cpu->thread); -#endif - } else { - /* For non-MTTCG cases we share the thread */ - cpu->thread =3D single_tcg_cpu_thread; - cpu->halt_cond =3D single_tcg_halt_cond; - cpu->thread_id =3D first_cpu->thread_id; - cpu->can_do_io =3D 1; - cpu->created =3D true; - } -} - static void qemu_hax_start_vcpu(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; @@ -1298,6 +888,12 @@ static void qemu_whpx_start_vcpu(CPUState *cpu) #endif } =20 +void cpus_register_accel(CpusAccel *ca) +{ + assert(ca !=3D NULL); + cpus_accel =3D ca; +} + static void qemu_dummy_start_vcpu(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; @@ -1328,14 +924,15 @@ void qemu_init_vcpu(CPUState *cpu) cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory); } =20 - if (kvm_enabled()) { + if (cpus_accel) { + /* accelerator already implements the CpusAccel interface */ + cpus_accel->create_vcpu_thread(cpu); + } else if (kvm_enabled()) { qemu_kvm_start_vcpu(cpu); } else if (hax_enabled()) { qemu_hax_start_vcpu(cpu); } else if (hvf_enabled()) { qemu_hvf_start_vcpu(cpu); - } else if (tcg_enabled()) { - qemu_tcg_init_vcpu(cpu); } else if (whpx_enabled()) { qemu_whpx_start_vcpu(cpu); } else { diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 42d4f459e6..276123e245 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -26,6 +26,7 @@ stub-obj-y +=3D tpm.o stub-obj-y +=3D trace-control.o stub-obj-y +=3D vmstate.o stub-obj-$(CONFIG_SOFTMMU) +=3D win32-kbd-hook.o +stub-obj-y +=3D cpu-synchronize-state.o =20 ####################################################################### # code used by both qemu system emulation and qemu-img diff --git a/stubs/cpu-synchronize-state.c b/stubs/cpu-synchronize-state.c new file mode 100644 index 0000000000..3112fe439d --- /dev/null +++ b/stubs/cpu-synchronize-state.c @@ -0,0 +1,15 @@ +#include "qemu/osdep.h" +#include "sysemu/hw_accel.h" + +void cpu_synchronize_state(CPUState *cpu) +{ +} +void cpu_synchronize_post_reset(CPUState *cpu) +{ +} +void cpu_synchronize_post_init(CPUState *cpu) +{ +} +void cpu_synchronize_pre_loadvm(CPUState *cpu) +{ +} --=20 2.16.4 From nobody Sun May 5 08:55:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1594130467; cv=none; d=zohomail.com; s=zohoarc; b=RLvPYvKZa6Czi/1+h4jK+ALnQXkl9nESAl2IlTN0P/UMy9uRoYZgAl/7Ho8F9uIRdMFQjVyT6fxwRNHDASlUBeaNVSR6o7DYmhY5rnuSdMX/Y/Xn8JI4Nu+W6XvG0o8MQqWRrl4nz9KHDGpFY9FXHqeUUO690sbDDiIrLMU4bbg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594130467; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=TjD8OkFEk5LoeGVoxnxiHU7b1iC+11jUbWuZ4EoFcXE=; b=RPwVMx6YYrLRJ9cDFb2yUo+10bUDpXB+j2v0p0gix7ZWizV2uCJ0GoCeREJi5ZzQpVZQg2lR165k1OJY0MZ2LU8pyCzk7XOGWWi/RqI31Ruzo4ND6Yw41ffYVxjpOw1k/de/Q5Iz+5REaph9+nmw/ADjejcvLMEVTUvTq0D+nmI= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1594130467204553.265552200972; Tue, 7 Jul 2020 07:01:07 -0700 (PDT) Received: from localhost ([::1]:47988 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jso9A-0007Ua-8v for importer@patchew.org; Tue, 07 Jul 2020 10:00:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54126) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso6z-0003iI-FH for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:17 -0400 Received: from mx2.suse.de ([195.135.220.15]:45940) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso6x-0007Fg-Al for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:17 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 86BCEAE2C; Tue, 7 Jul 2020 13:58:14 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , Thomas Huth , Laurent Vivier , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov , Markus Armbruster Subject: [RFC v2 2/6] cpus: extract out qtest-specific code to accel/qtest Date: Tue, 7 Jul 2020 15:58:04 +0200 Message-Id: <20200707135808.9241-3-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200707135808.9241-1-cfontana@suse.de> References: <20200707135808.9241-1-cfontana@suse.de> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=195.135.220.15; envelope-from=cfontana@suse.de; helo=mx2.suse.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 23:42:16 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x (no timestamps) [generic] X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Marcelo Tosatti , qemu-devel@nongnu.org, haxm-team@intel.com, Wenchao Wang , Sunil Muthuswamy , Richard Henderson , Claudio Fontana , Colin Xu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" register a "CpusAccel" interface for qtest as well. Signed-off-by: Claudio Fontana --- MAINTAINERS | 2 +- accel/Makefile.objs | 2 +- accel/qtest/Makefile.objs | 2 + accel/qtest/qtest-cpus.c | 104 ++++++++++++++++++++++++++++++++++++++++++= ++++ accel/qtest/qtest-cpus.h | 17 ++++++++ accel/{ =3D> qtest}/qtest.c | 7 ++++ softmmu/cpus.c | 61 +-------------------------- 7 files changed, 133 insertions(+), 62 deletions(-) create mode 100644 accel/qtest/Makefile.objs create mode 100644 accel/qtest/qtest-cpus.c create mode 100644 accel/qtest/qtest-cpus.h rename accel/{ =3D> qtest}/qtest.c (86%) diff --git a/MAINTAINERS b/MAINTAINERS index 8d3e5dedbc..100b7489ea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2380,7 +2380,7 @@ M: Laurent Vivier R: Paolo Bonzini S: Maintained F: softmmu/qtest.c -F: accel/qtest.c +F: accel/qtest/ F: tests/qtest/ X: tests/qtest/bios-tables-test-allowed-diff.h =20 diff --git a/accel/Makefile.objs b/accel/Makefile.objs index ff72f0d030..c5e58eb53d 100644 --- a/accel/Makefile.objs +++ b/accel/Makefile.objs @@ -1,5 +1,5 @@ common-obj-$(CONFIG_SOFTMMU) +=3D accel.o -obj-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_POSIX)) +=3D qtest.o +obj-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_POSIX)) +=3D qtest/ obj-$(CONFIG_KVM) +=3D kvm/ obj-$(CONFIG_TCG) +=3D tcg/ obj-$(CONFIG_XEN) +=3D xen/ diff --git a/accel/qtest/Makefile.objs b/accel/qtest/Makefile.objs new file mode 100644 index 0000000000..627014200e --- /dev/null +++ b/accel/qtest/Makefile.objs @@ -0,0 +1,2 @@ +obj-y +=3D qtest.o +obj-y +=3D qtest-cpus.o diff --git a/accel/qtest/qtest-cpus.c b/accel/qtest/qtest-cpus.c new file mode 100644 index 0000000000..525bb22f16 --- /dev/null +++ b/accel/qtest/qtest-cpus.c @@ -0,0 +1,104 @@ +/* + * QTest accelerator code + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/rcu.h" +#include "qapi/error.h" +#include "qemu/module.h" +#include "qemu/option.h" +#include "qemu/config-file.h" +#include "sysemu/accel.h" +#include "sysemu/qtest.h" +#include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" +#include "qemu/guest-random.h" +#include "qemu/main-loop.h" +#include "hw/core/cpu.h" + +#include "qtest-cpus.h" +static void qtest_cpu_synchronize_noop(CPUState *cpu) +{ +} + +static void qtest_kick_vcpu_thread(CPUState *cpu) +{ + cpus_kick_thread(cpu); +} + +static void *qtest_cpu_thread_fn(void *arg) +{ +#ifdef _WIN32 + error_report("qtest is not supported under Windows"); + exit(1); +#else + CPUState *cpu =3D arg; + sigset_t waitset; + int r; + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + cpu->thread_id =3D qemu_get_thread_id(); + cpu->can_do_io =3D 1; + current_cpu =3D cpu; + + sigemptyset(&waitset); + sigaddset(&waitset, SIG_IPI); + + /* signal CPU creation */ + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + qemu_mutex_unlock_iothread(); + do { + int sig; + r =3D sigwait(&waitset, &sig); + } while (r =3D=3D -1 && (errno =3D=3D EAGAIN || errno =3D=3D EINTR= )); + if (r =3D=3D -1) { + perror("sigwait"); + exit(1); + } + qemu_mutex_lock_iothread(); + qemu_wait_io_event(cpu); + } while (!cpu->unplug); + + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +#endif +} + +static void qtest_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread =3D g_malloc0(sizeof(QemuThread)); + cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, qtest_cpu_thread_fn, cpu, + QEMU_THREAD_JOINABLE); +} + +CpusAccel qtest_cpus =3D { + .create_vcpu_thread =3D qtest_start_vcpu_thread, + .kick_vcpu_thread =3D qtest_kick_vcpu_thread, + + .synchronize_post_reset =3D qtest_cpu_synchronize_noop, + .synchronize_post_init =3D qtest_cpu_synchronize_noop, + .synchronize_state =3D qtest_cpu_synchronize_noop, + .synchronize_pre_loadvm =3D qtest_cpu_synchronize_noop, +}; diff --git a/accel/qtest/qtest-cpus.h b/accel/qtest/qtest-cpus.h new file mode 100644 index 0000000000..c1fab96b9e --- /dev/null +++ b/accel/qtest/qtest-cpus.h @@ -0,0 +1,17 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef QTEST_CPUS_H +#define QTEST_CPUS_H + +#include "sysemu/cpus.h" + +extern CpusAccel qtest_cpus; + +#endif /* QTEST_CPUS_H */ diff --git a/accel/qtest.c b/accel/qtest/qtest.c similarity index 86% rename from accel/qtest.c rename to accel/qtest/qtest.c index 119d0f16a4..537e8b449c 100644 --- a/accel/qtest.c +++ b/accel/qtest/qtest.c @@ -12,6 +12,7 @@ */ =20 #include "qemu/osdep.h" +#include "qemu/rcu.h" #include "qapi/error.h" #include "qemu/module.h" #include "qemu/option.h" @@ -20,9 +21,15 @@ #include "sysemu/qtest.h" #include "sysemu/cpus.h" #include "sysemu/cpu-timers.h" +#include "qemu/guest-random.h" +#include "qemu/main-loop.h" +#include "hw/core/cpu.h" + +#include "qtest-cpus.h" =20 static int qtest_init_accel(MachineState *ms) { + cpus_register_accel(&qtest_cpus); return 0; } =20 diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 5fadc8f34c..bb1e534601 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -40,7 +40,6 @@ #include "qemu/thread.h" #include "qemu/plugin.h" #include "sysemu/cpus.h" -#include "sysemu/qtest.h" #include "qemu/main-loop.h" #include "qemu/option.h" #include "qemu/bitmap.h" @@ -472,51 +471,6 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) return NULL; } =20 -static void *qemu_dummy_cpu_thread_fn(void *arg) -{ -#ifdef _WIN32 - error_report("qtest is not supported under Windows"); - exit(1); -#else - CPUState *cpu =3D arg; - sigset_t waitset; - int r; - - rcu_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - cpu->thread_id =3D qemu_get_thread_id(); - cpu->can_do_io =3D 1; - current_cpu =3D cpu; - - sigemptyset(&waitset); - sigaddset(&waitset, SIG_IPI); - - /* signal CPU creation */ - cpu_thread_signal_created(cpu); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - qemu_mutex_unlock_iothread(); - do { - int sig; - r =3D sigwait(&waitset, &sig); - } while (r =3D=3D -1 && (errno =3D=3D EAGAIN || errno =3D=3D EINTR= )); - if (r =3D=3D -1) { - perror("sigwait"); - exit(1); - } - qemu_mutex_lock_iothread(); - qemu_wait_io_event(cpu); - } while (!cpu->unplug); - - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -#endif -} - static void *qemu_hax_cpu_thread_fn(void *arg) { CPUState *cpu =3D arg; @@ -894,19 +848,6 @@ void cpus_register_accel(CpusAccel *ca) cpus_accel =3D ca; } =20 -static void qemu_dummy_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - cpu->thread =3D g_malloc0(sizeof(QemuThread)); - cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_dummy_cpu_thread_fn,= cpu, - QEMU_THREAD_JOINABLE); -} - void qemu_init_vcpu(CPUState *cpu) { MachineState *ms =3D MACHINE(qdev_get_machine()); @@ -936,7 +877,7 @@ void qemu_init_vcpu(CPUState *cpu) } else if (whpx_enabled()) { qemu_whpx_start_vcpu(cpu); } else { - qemu_dummy_start_vcpu(cpu); + assert(0); } =20 while (!cpu->created) { --=20 2.16.4 From nobody Sun May 5 08:55:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1594130351; cv=none; d=zohomail.com; s=zohoarc; b=kYgbpy9Vgp79QAWEI4c+tnBrYFu0rCboxxxUVKqfTyPRmdutbzayGhWXQ81QhsmcKADbZP1skfJxKro1d82ezunvgIbbJUetO/gQ88F+cLKUysCLBfTGl6eNdIXhCZqTHd8y4EDz8md9pMKVCnE2UWVONDi1/9ez3+7hxvxWwFE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594130351; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=7fmDDweCtN6tNEugDHNQ5hOdCZB9VF+Yu4UFNPMgnF0=; b=HU+qSbahP8qnnJn8Djh0yjbnuMs17HQDNM+GLLSF8U0RiZl/JTTjznrRxteYO9MjfZIreKUFlPoZ//73ArCUrY5Y+qBy3VX9HOjd5u44Js77wWGqwavWPX5YgM4EAi9B+5kvK+El7r9LcSUrr8B7qPcfN51/MTTq20pKss4wSes= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1594130351562105.8337407849807; Tue, 7 Jul 2020 06:59:11 -0700 (PDT) Received: from localhost ([::1]:41938 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jso7p-00051B-Vo for importer@patchew.org; Tue, 07 Jul 2020 09:59:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54144) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso70-0003iU-0P for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:18 -0400 Received: from mx2.suse.de ([195.135.220.15]:45964) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso6x-0007Fr-RR for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:17 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 157B4AEE7; Tue, 7 Jul 2020 13:58:15 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , Thomas Huth , Laurent Vivier , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov , Markus Armbruster Subject: [RFC v2 3/6] cpus: extract out kvm-specific code to accel/kvm Date: Tue, 7 Jul 2020 15:58:05 +0200 Message-Id: <20200707135808.9241-4-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200707135808.9241-1-cfontana@suse.de> References: <20200707135808.9241-1-cfontana@suse.de> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=195.135.220.15; envelope-from=cfontana@suse.de; helo=mx2.suse.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 23:42:16 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x (no timestamps) [generic] X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Marcelo Tosatti , qemu-devel@nongnu.org, haxm-team@intel.com, Wenchao Wang , Sunil Muthuswamy , Richard Henderson , Claudio Fontana , Colin Xu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" register a "CpusAccel" interface for KVM as well. Signed-off-by: Claudio Fontana --- accel/kvm/Makefile.objs | 2 ++ accel/kvm/kvm-all.c | 14 +++++++- accel/kvm/kvm-cpus.c | 94 +++++++++++++++++++++++++++++++++++++++++++++= ++++ accel/kvm/kvm-cpus.h | 17 +++++++++ accel/stubs/kvm-stub.c | 3 +- include/sysemu/kvm.h | 2 +- softmmu/cpus.c | 77 ---------------------------------------- 7 files changed, 128 insertions(+), 81 deletions(-) create mode 100644 accel/kvm/kvm-cpus.c create mode 100644 accel/kvm/kvm-cpus.h diff --git a/accel/kvm/Makefile.objs b/accel/kvm/Makefile.objs index fdfa481578..ce0f492b8d 100644 --- a/accel/kvm/Makefile.objs +++ b/accel/kvm/Makefile.objs @@ -1,2 +1,4 @@ obj-y +=3D kvm-all.o +obj-y +=3D kvm-cpus.o + obj-$(call lnot,$(CONFIG_SEV)) +=3D sev-stub.o diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index d54a8701d8..0932f7cb94 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -45,6 +45,9 @@ #include "qapi/qapi-types-common.h" #include "qapi/qapi-visit-common.h" #include "sysemu/reset.h" +#include "qemu/guest-random.h" +#include "sysemu/hw_accel.h" +#include "kvm-cpus.h" =20 #include "hw/boards.h" =20 @@ -379,7 +382,7 @@ err: return ret; } =20 -int kvm_destroy_vcpu(CPUState *cpu) +static int do_kvm_destroy_vcpu(CPUState *cpu) { KVMState *s =3D kvm_state; long mmap_size; @@ -413,6 +416,14 @@ err: return ret; } =20 +void kvm_destroy_vcpu(CPUState *cpu) +{ + if (do_kvm_destroy_vcpu(cpu) < 0) { + error_report("kvm_destroy_vcpu failed"); + exit(EXIT_FAILURE); + } +} + static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) { struct KVMParkedVcpu *cpu; @@ -2232,6 +2243,7 @@ static int kvm_init(MachineState *ms) qemu_balloon_inhibit(true); } =20 + cpus_register_accel(&kvm_cpus); return 0; =20 err: diff --git a/accel/kvm/kvm-cpus.c b/accel/kvm/kvm-cpus.c new file mode 100644 index 0000000000..ac6945a9e6 --- /dev/null +++ b/accel/kvm/kvm-cpus.c @@ -0,0 +1,94 @@ +/* + * QEMU KVM support + * + * Copyright IBM, Corp. 2008 + * Red Hat, Inc. 2008 + * + * Authors: + * Anthony Liguori + * Glauber Costa + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "sysemu/kvm_int.h" +#include "sysemu/runstate.h" +#include "sysemu/cpus.h" +#include "qemu/guest-random.h" + +#include "kvm-cpus.h" + +static void kvm_kick_vcpu_thread(CPUState *cpu) +{ + cpus_kick_thread(cpu); +} + +static void *kvm_vcpu_thread_fn(void *arg) +{ + CPUState *cpu =3D arg; + int r; + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + cpu->thread_id =3D qemu_get_thread_id(); + cpu->can_do_io =3D 1; + current_cpu =3D cpu; + + r =3D kvm_init_vcpu(cpu); + if (r < 0) { + error_report("kvm_init_vcpu failed: %s", strerror(-r)); + exit(1); + } + + kvm_init_cpu_signals(cpu); + + /* signal CPU creation */ + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + if (cpu_can_run(cpu)) { + r =3D kvm_cpu_exec(cpu); + if (r =3D=3D EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + qemu_wait_io_event(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + kvm_destroy_vcpu(cpu); + cpu_thread_signal_destroyed(cpu); + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + +static void kvm_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread =3D g_malloc0(sizeof(QemuThread)); + cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, kvm_vcpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); +} + +CpusAccel kvm_cpus =3D { + .create_vcpu_thread =3D kvm_start_vcpu_thread, + .kick_vcpu_thread =3D kvm_kick_vcpu_thread, + + .synchronize_post_reset =3D kvm_cpu_synchronize_post_reset, + .synchronize_post_init =3D kvm_cpu_synchronize_post_init, + .synchronize_state =3D kvm_cpu_synchronize_state, + .synchronize_pre_loadvm =3D kvm_cpu_synchronize_pre_loadvm, +}; diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h new file mode 100644 index 0000000000..62fbc911d9 --- /dev/null +++ b/accel/kvm/kvm-cpus.h @@ -0,0 +1,17 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef KVM_CPUS_H +#define KVM_CPUS_H + +#include "sysemu/cpus.h" + +extern CpusAccel kvm_cpus; + +#endif /* KVM_CPUS_H */ diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index 82f118d2df..69f8a842da 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -32,9 +32,8 @@ bool kvm_readonly_mem_allowed; bool kvm_ioeventfd_any_length_allowed; bool kvm_msi_use_devid; =20 -int kvm_destroy_vcpu(CPUState *cpu) +void kvm_destroy_vcpu(CPUState *cpu) { - return -ENOSYS; } =20 int kvm_init_vcpu(CPUState *cpu) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index b4174d941c..7a5f973b6f 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -218,7 +218,7 @@ int kvm_has_intx_set_mask(void); =20 int kvm_init_vcpu(CPUState *cpu); int kvm_cpu_exec(CPUState *cpu); -int kvm_destroy_vcpu(CPUState *cpu); +void kvm_destroy_vcpu(CPUState *cpu); =20 /** * kvm_arm_supports_user_irq diff --git a/softmmu/cpus.c b/softmmu/cpus.c index bb1e534601..9a55bd2c4e 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -192,9 +192,6 @@ void cpu_synchronize_state(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_state(cpu); } - if (kvm_enabled()) { - kvm_cpu_synchronize_state(cpu); - } if (hax_enabled()) { hax_cpu_synchronize_state(cpu); } @@ -209,9 +206,6 @@ void cpu_synchronize_post_reset(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_post_reset(cpu); } - if (kvm_enabled()) { - kvm_cpu_synchronize_post_reset(cpu); - } if (hax_enabled()) { hax_cpu_synchronize_post_reset(cpu); } @@ -226,9 +220,6 @@ void cpu_synchronize_post_init(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_post_init(cpu); } - if (kvm_enabled()) { - kvm_cpu_synchronize_post_init(cpu); - } if (hax_enabled()) { hax_cpu_synchronize_post_init(cpu); } @@ -243,9 +234,6 @@ void cpu_synchronize_pre_loadvm(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_pre_loadvm(cpu); } - if (kvm_enabled()) { - kvm_cpu_synchronize_pre_loadvm(cpu); - } if (hax_enabled()) { hax_cpu_synchronize_pre_loadvm(cpu); } @@ -376,14 +364,6 @@ void run_on_cpu(CPUState *cpu, run_on_cpu_func func, r= un_on_cpu_data data) do_run_on_cpu(cpu, func, data, &qemu_global_mutex); } =20 -static void qemu_kvm_destroy_vcpu(CPUState *cpu) -{ - if (kvm_destroy_vcpu(cpu) < 0) { - error_report("kvm_destroy_vcpu failed"); - exit(EXIT_FAILURE); - } -} - static void qemu_cpu_stop(CPUState *cpu, bool exit) { g_assert(qemu_cpu_is_self(cpu)); @@ -429,48 +409,6 @@ void qemu_wait_io_event(CPUState *cpu) qemu_wait_io_event_common(cpu); } =20 -static void *qemu_kvm_cpu_thread_fn(void *arg) -{ - CPUState *cpu =3D arg; - int r; - - rcu_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - cpu->thread_id =3D qemu_get_thread_id(); - cpu->can_do_io =3D 1; - current_cpu =3D cpu; - - r =3D kvm_init_vcpu(cpu); - if (r < 0) { - error_report("kvm_init_vcpu failed: %s", strerror(-r)); - exit(1); - } - - kvm_init_cpu_signals(cpu); - - /* signal CPU creation */ - cpu_thread_signal_created(cpu); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - if (cpu_can_run(cpu)) { - r =3D kvm_cpu_exec(cpu); - if (r =3D=3D EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - } - } - qemu_wait_io_event(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - - qemu_kvm_destroy_vcpu(cpu); - cpu_thread_signal_destroyed(cpu); - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -} - static void *qemu_hax_cpu_thread_fn(void *arg) { CPUState *cpu =3D arg; @@ -795,19 +733,6 @@ static void qemu_hax_start_vcpu(CPUState *cpu) #endif } =20 -static void qemu_kvm_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - cpu->thread =3D g_malloc0(sizeof(QemuThread)); - cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); -} - static void qemu_hvf_start_vcpu(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; @@ -868,8 +793,6 @@ void qemu_init_vcpu(CPUState *cpu) if (cpus_accel) { /* accelerator already implements the CpusAccel interface */ cpus_accel->create_vcpu_thread(cpu); - } else if (kvm_enabled()) { - qemu_kvm_start_vcpu(cpu); } else if (hax_enabled()) { qemu_hax_start_vcpu(cpu); } else if (hvf_enabled()) { --=20 2.16.4 From nobody Sun May 5 08:55:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1594130351; cv=none; d=zohomail.com; s=zohoarc; b=NWrMZu7fCQ6zAg/W+jTwawWP1iod2muD3Ma1KeOJj8c7D72GHPt8NTd4ap0CglrR9p6zozHQzfqI654c+5TPa4Gn/IjQQJ8gSU9zRthpris+wnHefF1SyVp5C5MhJqCmoKvz6MbiQ+Qjv2ZRi4xys9rZH/R7wleCyqvDhzhX4j8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594130351; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=26QpRMZptvFl7A55NSz8rPnRkqt0H2nQkRnphjKuGVA=; b=IwiF8i9CETYHqLl8IijLrvjhGFAnpLUcDhR6MYpDRipyYXyKmpZVTfMMIpxrZa5n39Dqq7fHl9V1n6bDewMKg7fAkT/WgZ5bQ1y06JTEuCoAbhHRKArAbT0l2/kY8oSObObtCB7slZeEI9O4V138vKhEdYK6zrGDoiruSonW3wc= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1594130351041360.4939537526334; Tue, 7 Jul 2020 06:59:11 -0700 (PDT) Received: from localhost ([::1]:41802 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jso7p-0004xx-Ly for importer@patchew.org; Tue, 07 Jul 2020 09:59:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54152) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso70-0003jN-Os for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:18 -0400 Received: from mx2.suse.de ([195.135.220.15]:45990) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso6y-0007G6-CQ for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:18 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 9027EAF0E; Tue, 7 Jul 2020 13:58:15 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , Thomas Huth , Laurent Vivier , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov , Markus Armbruster Subject: [RFC v2 4/6] cpus: extract out hax-specific code to target/i386/ Date: Tue, 7 Jul 2020 15:58:06 +0200 Message-Id: <20200707135808.9241-5-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200707135808.9241-1-cfontana@suse.de> References: <20200707135808.9241-1-cfontana@suse.de> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=195.135.220.15; envelope-from=cfontana@suse.de; helo=mx2.suse.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 23:42:16 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x (no timestamps) [generic] X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Marcelo Tosatti , qemu-devel@nongnu.org, haxm-team@intel.com, Wenchao Wang , Sunil Muthuswamy , Richard Henderson , Claudio Fontana , Colin Xu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" register a "CpusAccel" interface for HAX as well. Signed-off-by: Claudio Fontana --- softmmu/cpus.c | 78 ------------------------------------------- target/i386/Makefile.objs | 5 +-- target/i386/hax-all.c | 6 +++- target/i386/hax-cpus.c | 85 +++++++++++++++++++++++++++++++++++++++++++= ++++ target/i386/hax-cpus.h | 17 ++++++++++ target/i386/hax-i386.h | 2 ++ target/i386/hax-posix.c | 12 +++++++ target/i386/hax-windows.c | 20 +++++++++++ 8 files changed, 144 insertions(+), 81 deletions(-) create mode 100644 target/i386/hax-cpus.c create mode 100644 target/i386/hax-cpus.h diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 9a55bd2c4e..091641bf18 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -33,7 +33,6 @@ #include "exec/gdbstub.h" #include "sysemu/hw_accel.h" #include "sysemu/kvm.h" -#include "sysemu/hax.h" #include "sysemu/hvf.h" #include "sysemu/whpx.h" #include "exec/exec-all.h" @@ -192,9 +191,6 @@ void cpu_synchronize_state(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_state(cpu); } - if (hax_enabled()) { - hax_cpu_synchronize_state(cpu); - } if (whpx_enabled()) { whpx_cpu_synchronize_state(cpu); } @@ -206,9 +202,6 @@ void cpu_synchronize_post_reset(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_post_reset(cpu); } - if (hax_enabled()) { - hax_cpu_synchronize_post_reset(cpu); - } if (whpx_enabled()) { whpx_cpu_synchronize_post_reset(cpu); } @@ -220,9 +213,6 @@ void cpu_synchronize_post_init(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_post_init(cpu); } - if (hax_enabled()) { - hax_cpu_synchronize_post_init(cpu); - } if (whpx_enabled()) { whpx_cpu_synchronize_post_init(cpu); } @@ -234,9 +224,6 @@ void cpu_synchronize_pre_loadvm(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_pre_loadvm(cpu); } - if (hax_enabled()) { - hax_cpu_synchronize_pre_loadvm(cpu); - } if (whpx_enabled()) { whpx_cpu_synchronize_pre_loadvm(cpu); } @@ -409,35 +396,6 @@ void qemu_wait_io_event(CPUState *cpu) qemu_wait_io_event_common(cpu); } =20 -static void *qemu_hax_cpu_thread_fn(void *arg) -{ - CPUState *cpu =3D arg; - int r; - - rcu_register_thread(); - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - - cpu->thread_id =3D qemu_get_thread_id(); - current_cpu =3D cpu; - hax_init_vcpu(cpu); - cpu_thread_signal_created(cpu); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - if (cpu_can_run(cpu)) { - r =3D hax_smp_cpu_exec(cpu); - if (r =3D=3D EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - } - } - - qemu_wait_io_event(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - rcu_unregister_thread(); - return NULL; -} - /* The HVF-specific vCPU thread function. This one should only run when th= e host * CPU supports the VMX "unrestricted guest" feature. */ static void *qemu_hvf_cpu_thread_fn(void *arg) @@ -522,12 +480,6 @@ static void *qemu_whpx_cpu_thread_fn(void *arg) return NULL; } =20 -#ifdef _WIN32 -static void CALLBACK dummy_apc_func(ULONG_PTR unused) -{ -} -#endif - void cpus_kick_thread(CPUState *cpu) { #ifndef _WIN32 @@ -546,10 +498,6 @@ void cpus_kick_thread(CPUState *cpu) if (!qemu_cpu_is_self(cpu)) { if (whpx_enabled()) { whpx_vcpu_kick(cpu); - } else if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) { - fprintf(stderr, "%s: QueueUserAPC failed with error %lu\n", - __func__, GetLastError()); - exit(1); } } #endif @@ -562,13 +510,6 @@ void qemu_cpu_kick(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->kick_vcpu_thread(cpu); } else { - if (hax_enabled()) { - /* - * FIXME: race condition with the exit_request check in - * hax_vcpu_hax_exec - */ - cpu->exit_request =3D 1; - } cpus_kick_thread(cpu); } } @@ -716,23 +657,6 @@ void cpu_remove_sync(CPUState *cpu) qemu_mutex_lock_iothread(); } =20 -static void qemu_hax_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - cpu->thread =3D g_malloc0(sizeof(QemuThread)); - cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HAX", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_hax_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); -#ifdef _WIN32 - cpu->hThread =3D qemu_thread_get_handle(cpu->thread); -#endif -} - static void qemu_hvf_start_vcpu(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; @@ -793,8 +717,6 @@ void qemu_init_vcpu(CPUState *cpu) if (cpus_accel) { /* accelerator already implements the CpusAccel interface */ cpus_accel->create_vcpu_thread(cpu); - } else if (hax_enabled()) { - qemu_hax_start_vcpu(cpu); } else if (hvf_enabled()) { qemu_hvf_start_vcpu(cpu); } else if (whpx_enabled()) { diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs index 48e0c28434..3cd3e89298 100644 --- a/target/i386/Makefile.objs +++ b/target/i386/Makefile.objs @@ -9,11 +9,12 @@ obj-y +=3D machine.o arch_memory_mapping.o arch_dump.o mo= nitor.o obj-$(CONFIG_KVM) +=3D kvm.o obj-$(CONFIG_HYPERV) +=3D hyperv.o obj-$(call lnot,$(CONFIG_HYPERV)) +=3D hyperv-stub.o +obj-$(CONFIG_HAX) +=3D hax-all.o hax-mem.o hax-cpus.o ifeq ($(CONFIG_WIN32),y) -obj-$(CONFIG_HAX) +=3D hax-all.o hax-mem.o hax-windows.o +obj-$(CONFIG_HAX) +=3D hax-windows.o endif ifeq ($(CONFIG_POSIX),y) -obj-$(CONFIG_HAX) +=3D hax-all.o hax-mem.o hax-posix.o +obj-$(CONFIG_HAX) +=3D hax-posix.o endif obj-$(CONFIG_HVF) +=3D hvf/ obj-$(CONFIG_WHPX) +=3D whpx-all.o diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c index c93bb23a44..b66ddeb8bf 100644 --- a/target/i386/hax-all.c +++ b/target/i386/hax-all.c @@ -32,9 +32,10 @@ #include "sysemu/accel.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" -#include "qemu/main-loop.h" #include "hw/boards.h" =20 +#include "hax-cpus.h" + #define DEBUG_HAX 0 =20 #define DPRINTF(fmt, ...) \ @@ -374,6 +375,9 @@ static int hax_accel_init(MachineState *ms) !ret ? "working" : "not working", !ret ? "fast virt" : "emulation"); } + if (ret =3D=3D 0) { + cpus_register_accel(&hax_cpus); + } return ret; } =20 diff --git a/target/i386/hax-cpus.c b/target/i386/hax-cpus.c new file mode 100644 index 0000000000..69a4162939 --- /dev/null +++ b/target/i386/hax-cpus.c @@ -0,0 +1,85 @@ +/* + * QEMU HAX support + * + * Copyright IBM, Corp. 2008 + * Red Hat, Inc. 2008 + * + * Authors: + * Anthony Liguori + * Glauber Costa + * + * Copyright (c) 2011 Intel Corporation + * Written by: + * Jiang Yunhong + * Xin Xiaohui + * Zhang Xiantao + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "hax-i386.h" +#include "sysemu/runstate.h" +#include "sysemu/cpus.h" +#include "qemu/guest-random.h" + +#include "hax-cpus.h" + +static void *hax_cpu_thread_fn(void *arg) +{ + CPUState *cpu =3D arg; + int r; + + rcu_register_thread(); + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + + cpu->thread_id =3D qemu_get_thread_id(); + hax_init_vcpu(cpu); + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + if (cpu_can_run(cpu)) { + r =3D hax_smp_cpu_exec(cpu); + if (r =3D=3D EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + + qemu_wait_io_event(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + rcu_unregister_thread(); + return NULL; +} + +static void hax_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread =3D g_malloc0(sizeof(QemuThread)); + cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HAX", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, hax_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); +#ifdef _WIN32 + cpu->hThread =3D qemu_thread_get_handle(cpu->thread); +#endif +} + +CpusAccel hax_cpus =3D { + .create_vcpu_thread =3D hax_start_vcpu_thread, + .kick_vcpu_thread =3D hax_kick_vcpu_thread, + + .synchronize_post_reset =3D hax_cpu_synchronize_post_reset, + .synchronize_post_init =3D hax_cpu_synchronize_post_init, + .synchronize_state =3D hax_cpu_synchronize_state, + .synchronize_pre_loadvm =3D hax_cpu_synchronize_pre_loadvm, +}; diff --git a/target/i386/hax-cpus.h b/target/i386/hax-cpus.h new file mode 100644 index 0000000000..ac3cf1f8ae --- /dev/null +++ b/target/i386/hax-cpus.h @@ -0,0 +1,17 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef HAX_CPUS_H +#define HAX_CPUS_H + +#include "sysemu/cpus.h" + +extern CpusAccel hax_cpus; + +#endif /* HAX_CPUS_H */ diff --git a/target/i386/hax-i386.h b/target/i386/hax-i386.h index ec28708185..48c4abe14e 100644 --- a/target/i386/hax-i386.h +++ b/target/i386/hax-i386.h @@ -60,6 +60,8 @@ int hax_inject_interrupt(CPUArchState *env, int vector); struct hax_vm *hax_vm_create(struct hax_state *hax, int max_cpus); int hax_vcpu_run(struct hax_vcpu_state *vcpu); int hax_vcpu_create(int id); +void hax_kick_vcpu_thread(CPUState *cpu); + int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set); int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set); diff --git a/target/i386/hax-posix.c b/target/i386/hax-posix.c index 3bad89f133..ea956ddfc1 100644 --- a/target/i386/hax-posix.c +++ b/target/i386/hax-posix.c @@ -16,6 +16,8 @@ =20 #include "target/i386/hax-i386.h" =20 +#include "sysemu/cpus.h" + hax_fd hax_mod_open(void) { int fd =3D open("/dev/HAX", O_RDWR); @@ -292,3 +294,13 @@ int hax_inject_interrupt(CPUArchState *env, int vector) =20 return ioctl(fd, HAX_VCPU_IOCTL_INTERRUPT, &vector); } + +void hax_kick_vcpu_thread(CPUState *cpu) +{ + /* + * FIXME: race condition with the exit_request check in + * hax_vcpu_hax_exec + */ + cpu->exit_request =3D 1; + cpus_kick_thread(cpu); +} diff --git a/target/i386/hax-windows.c b/target/i386/hax-windows.c index 863c2bcc19..469b48e608 100644 --- a/target/i386/hax-windows.c +++ b/target/i386/hax-windows.c @@ -463,3 +463,23 @@ int hax_inject_interrupt(CPUArchState *env, int vector) return 0; } } + +static void CALLBACK dummy_apc_func(ULONG_PTR unused) +{ +} + +void hax_kick_vcpu_thread(CPUState *cpu) +{ + /* + * FIXME: race condition with the exit_request check in + * hax_vcpu_hax_exec + */ + cpu->exit_request =3D 1; + if (!qemu_cpu_is_self(cpu)) { + if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) { + fprintf(stderr, "%s: QueueUserAPC failed with error %lu\n", + __func__, GetLastError()); + exit(1); + } + } +} --=20 2.16.4 From nobody Sun May 5 08:55:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1594130537; cv=none; d=zohomail.com; s=zohoarc; b=mS3yQzb0vg7pmWlKDJEVcmcBlpT0Fn1gl6KwmGNO1oLbQjCEu2+dSj0pvQ6wiUXjPGCV+YSO9ZHHLkT2lb7H7AI49Oysv4D7HBoc3LlTYdhdk3JpYtJQVL/ybRuqu1LUrxKn5mSRNJjjrHCKpyFyNx3PbHw8wQMAjYT0R0SWUmU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594130537; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=Gmg1ICroO8nOSKAqo3vnvx1EqIO9rb+nOWthgNRKGUE=; b=h6LSF+oQ/VwySPc+DtxpIvrbyVeWpnIlEuU0RISOfTvyYJPwiU9vyE6QqB0suWvad58pNKto3Hf/TlHgOv11GwvkZOUMB3mvYtva0qutVYdlqEPCbw+YVZwrZgZ1FgZolv+aUfKhxhGfw+GKGImk1eUe8GWNjmTojQU6tJR6CJg= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 159413053749783.21205650994102; Tue, 7 Jul 2020 07:02:17 -0700 (PDT) Received: from localhost ([::1]:53386 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jsoAq-00025r-Ih for importer@patchew.org; Tue, 07 Jul 2020 10:02:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54184) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso73-0003pH-Na for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:21 -0400 Received: from mx2.suse.de ([195.135.220.15]:46030) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso6z-0007GR-VV for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:21 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 20ED4AF0F; Tue, 7 Jul 2020 13:58:16 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , Thomas Huth , Laurent Vivier , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov , Markus Armbruster Subject: [RFC v2 5/6] cpus: extract out whpx-specific code to target/i386/ Date: Tue, 7 Jul 2020 15:58:07 +0200 Message-Id: <20200707135808.9241-6-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200707135808.9241-1-cfontana@suse.de> References: <20200707135808.9241-1-cfontana@suse.de> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=195.135.220.15; envelope-from=cfontana@suse.de; helo=mx2.suse.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 23:42:16 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x (no timestamps) [generic] X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Marcelo Tosatti , qemu-devel@nongnu.org, haxm-team@intel.com, Wenchao Wang , Sunil Muthuswamy , Richard Henderson , Claudio Fontana , Colin Xu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" register a "CpusAccel" interface for WHPX as well. Signed-off-by: Claudio Fontana --- MAINTAINERS | 1 + softmmu/cpus.c | 81 --------------------------------------- target/i386/Makefile.objs | 2 +- target/i386/whpx-all.c | 3 ++ target/i386/whpx-cpus.c | 96 +++++++++++++++++++++++++++++++++++++++++++= ++++ target/i386/whpx-cpus.h | 17 +++++++++ 6 files changed, 118 insertions(+), 82 deletions(-) create mode 100644 target/i386/whpx-cpus.c create mode 100644 target/i386/whpx-cpus.h diff --git a/MAINTAINERS b/MAINTAINERS index 100b7489ea..a737eb70ce 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -427,6 +427,7 @@ WHPX CPUs M: Sunil Muthuswamy S: Supported F: target/i386/whpx-all.c +F: target/i386/whpx-cpus.c F: target/i386/whp-dispatch.h F: accel/stubs/whpx-stub.c F: include/sysemu/whpx.h diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 091641bf18..ed9cd8ec72 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -34,7 +34,6 @@ #include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "sysemu/hvf.h" -#include "sysemu/whpx.h" #include "exec/exec-all.h" #include "qemu/thread.h" #include "qemu/plugin.h" @@ -191,9 +190,6 @@ void cpu_synchronize_state(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_state(cpu); } - if (whpx_enabled()) { - whpx_cpu_synchronize_state(cpu); - } } =20 void cpu_synchronize_post_reset(CPUState *cpu) @@ -202,9 +198,6 @@ void cpu_synchronize_post_reset(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_post_reset(cpu); } - if (whpx_enabled()) { - whpx_cpu_synchronize_post_reset(cpu); - } } =20 void cpu_synchronize_post_init(CPUState *cpu) @@ -213,9 +206,6 @@ void cpu_synchronize_post_init(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_post_init(cpu); } - if (whpx_enabled()) { - whpx_cpu_synchronize_post_init(cpu); - } } =20 void cpu_synchronize_pre_loadvm(CPUState *cpu) @@ -224,9 +214,6 @@ void cpu_synchronize_pre_loadvm(CPUState *cpu) /* accelerator already implements the CpusAccel interface */ cpus_accel->synchronize_pre_loadvm(cpu); } - if (whpx_enabled()) { - whpx_cpu_synchronize_pre_loadvm(cpu); - } } =20 static int do_vm_stop(RunState state, bool send_stop) @@ -438,48 +425,6 @@ static void *qemu_hvf_cpu_thread_fn(void *arg) return NULL; } =20 -static void *qemu_whpx_cpu_thread_fn(void *arg) -{ - CPUState *cpu =3D arg; - int r; - - rcu_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - cpu->thread_id =3D qemu_get_thread_id(); - current_cpu =3D cpu; - - r =3D whpx_init_vcpu(cpu); - if (r < 0) { - fprintf(stderr, "whpx_init_vcpu failed: %s\n", strerror(-r)); - exit(1); - } - - /* signal CPU creation */ - cpu_thread_signal_created(cpu); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - if (cpu_can_run(cpu)) { - r =3D whpx_vcpu_exec(cpu); - if (r =3D=3D EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - } - } - while (cpu_thread_is_idle(cpu)) { - qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); - } - qemu_wait_io_event_common(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - - whpx_destroy_vcpu(cpu); - cpu_thread_signal_destroyed(cpu); - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -} - void cpus_kick_thread(CPUState *cpu) { #ifndef _WIN32 @@ -494,12 +439,6 @@ void cpus_kick_thread(CPUState *cpu) fprintf(stderr, "qemu:%s: %s", __func__, strerror(err)); exit(1); } -#else /* _WIN32 */ - if (!qemu_cpu_is_self(cpu)) { - if (whpx_enabled()) { - whpx_vcpu_kick(cpu); - } - } #endif } =20 @@ -509,8 +448,6 @@ void qemu_cpu_kick(CPUState *cpu) if (cpus_accel) { /* accelerator already implements the CpusAccel interface */ cpus_accel->kick_vcpu_thread(cpu); - } else { - cpus_kick_thread(cpu); } } =20 @@ -675,22 +612,6 @@ static void qemu_hvf_start_vcpu(CPUState *cpu) cpu, QEMU_THREAD_JOINABLE); } =20 -static void qemu_whpx_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - cpu->thread =3D g_malloc0(sizeof(QemuThread)); - cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/WHPX", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_whpx_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); -#ifdef _WIN32 - cpu->hThread =3D qemu_thread_get_handle(cpu->thread); -#endif -} - void cpus_register_accel(CpusAccel *ca) { assert(ca !=3D NULL); @@ -719,8 +640,6 @@ void qemu_init_vcpu(CPUState *cpu) cpus_accel->create_vcpu_thread(cpu); } else if (hvf_enabled()) { qemu_hvf_start_vcpu(cpu); - } else if (whpx_enabled()) { - qemu_whpx_start_vcpu(cpu); } else { assert(0); } diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs index 3cd3e89298..8a086933bc 100644 --- a/target/i386/Makefile.objs +++ b/target/i386/Makefile.objs @@ -17,7 +17,7 @@ ifeq ($(CONFIG_POSIX),y) obj-$(CONFIG_HAX) +=3D hax-posix.o endif obj-$(CONFIG_HVF) +=3D hvf/ -obj-$(CONFIG_WHPX) +=3D whpx-all.o +obj-$(CONFIG_WHPX) +=3D whpx-all.o whpx-cpus.o endif obj-$(CONFIG_SEV) +=3D sev.o obj-$(call lnot,$(CONFIG_SEV)) +=3D sev-stub.o diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index c78baac6df..8b6986c864 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -24,6 +24,8 @@ #include "migration/blocker.h" #include "whp-dispatch.h" =20 +#include "whpx-cpus.h" + #include #include =20 @@ -1575,6 +1577,7 @@ static int whpx_accel_init(MachineState *ms) whpx_memory_init(); =20 cpu_interrupt_handler =3D whpx_handle_interrupt; + cpus_register_accel(&whpx_cpus); =20 printf("Windows Hypervisor Platform accelerator is operational\n"); return 0; diff --git a/target/i386/whpx-cpus.c b/target/i386/whpx-cpus.c new file mode 100644 index 0000000000..3a0b69f771 --- /dev/null +++ b/target/i386/whpx-cpus.c @@ -0,0 +1,96 @@ +/* + * QEMU Windows Hypervisor Platform accelerator (WHPX) + * + * Copyright Microsoft Corp. 2017 + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "sysemu/kvm_int.h" +#include "qemu/main-loop.h" +#include "sysemu/cpus.h" +#include "qemu/guest-random.h" + +#include "sysemu/whpx.h" +#include "whpx-cpus.h" + +#include +#include + +static void *whpx_cpu_thread_fn(void *arg) +{ + CPUState *cpu =3D arg; + int r; + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + cpu->thread_id =3D qemu_get_thread_id(); + current_cpu =3D cpu; + + r =3D whpx_init_vcpu(cpu); + if (r < 0) { + fprintf(stderr, "whpx_init_vcpu failed: %s\n", strerror(-r)); + exit(1); + } + + /* signal CPU creation */ + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + if (cpu_can_run(cpu)) { + r =3D whpx_vcpu_exec(cpu); + if (r =3D=3D EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + while (cpu_thread_is_idle(cpu)) { + qemu_cond_wait_iothread(cpu->halt_cond); + } + qemu_wait_io_event_common(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + whpx_destroy_vcpu(cpu); + cpu_thread_signal_destroyed(cpu); + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + +static void whpx_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread =3D g_malloc0(sizeof(QemuThread)); + cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/WHPX", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, whpx_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); +#ifdef _WIN32 + cpu->hThread =3D qemu_thread_get_handle(cpu->thread); +#endif +} + +static void whpx_kick_vcpu_thread(CPUState *cpu) +{ + if (!qemu_cpu_is_self(cpu)) { + whpx_vcpu_kick(cpu); + } +} + +CpusAccel whpx_cpus =3D { + .create_vcpu_thread =3D whpx_start_vcpu_thread, + .kick_vcpu_thread =3D whpx_kick_vcpu_thread, + + .synchronize_post_reset =3D whpx_cpu_synchronize_post_reset, + .synchronize_post_init =3D whpx_cpu_synchronize_post_init, + .synchronize_state =3D whpx_cpu_synchronize_state, + .synchronize_pre_loadvm =3D whpx_cpu_synchronize_pre_loadvm, +}; diff --git a/target/i386/whpx-cpus.h b/target/i386/whpx-cpus.h new file mode 100644 index 0000000000..60b7be3735 --- /dev/null +++ b/target/i386/whpx-cpus.h @@ -0,0 +1,17 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef WHPX_CPUS_H +#define WHPX_CPUS_H + +#include "sysemu/cpus.h" + +extern CpusAccel whpx_cpus; + +#endif /* WHPX_CPUS_H */ --=20 2.16.4 From nobody Sun May 5 08:55:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1594130522; cv=none; d=zohomail.com; s=zohoarc; b=CCdJk19Nh0nv/26bI3g2J33Rk6s0CX0tM5QScWCfR1OF2r/9N2ea0P0QoBb8mBZMKEVjUk1SQT1JpdtfgL3HU+enyCN6lG6WwoZRdv6dtVhfTlAtl9uG6neDF2XPeb239JWPA4Ul5mPN6BPja6gX9w2My5/XWTt9X/5GNGhGonc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594130522; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=dsP3HX28RrQefFfMnHZJ9phF48nxFwBko0+8RNp7hOw=; b=XNmqKvRJfavxDSC9O+fjGHRj3NO2MOMY42ZJvn27fQG0UXdcUYWgb55VcvFMvuzXCc1SWoTqFR7wYrBfIX0JMuqCGPDD6rc2XpsBjujQIf2jKH2aL1iz6kLMCaf9jyfFmgr+vIEJxYBF+3fhNowDLIm0yhzy3kufnsrW7m6b3To= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1594130522574177.75667505376498; Tue, 7 Jul 2020 07:02:02 -0700 (PDT) Received: from localhost ([::1]:48372 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jso9G-0007fU-DQ for importer@patchew.org; Tue, 07 Jul 2020 10:00:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54182) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso73-0003oe-9R for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:21 -0400 Received: from mx2.suse.de ([195.135.220.15]:46028) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jso6z-0007GQ-Ub for qemu-devel@nongnu.org; Tue, 07 Jul 2020 09:58:20 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 9EA78AF13; Tue, 7 Jul 2020 13:58:16 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , Thomas Huth , Laurent Vivier , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov , Markus Armbruster Subject: [RFC v2 6/6] cpus: extract out hvf-specific code to target/i386/hvf/ Date: Tue, 7 Jul 2020 15:58:08 +0200 Message-Id: <20200707135808.9241-7-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200707135808.9241-1-cfontana@suse.de> References: <20200707135808.9241-1-cfontana@suse.de> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=195.135.220.15; envelope-from=cfontana@suse.de; helo=mx2.suse.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/06 23:42:16 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x (no timestamps) [generic] X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Marcelo Tosatti , qemu-devel@nongnu.org, haxm-team@intel.com, Wenchao Wang , Sunil Muthuswamy , Richard Henderson , Claudio Fontana , Colin Xu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" register a "CpusAccel" interface for HVF as well. Signed-off-by: Claudio Fontana --- softmmu/cpus.c | 75 ---------------------- target/i386/hvf/Makefile.objs | 2 +- target/i386/hvf/hvf-cpus.c | 141 ++++++++++++++++++++++++++++++++++++++= ++++ target/i386/hvf/hvf-cpus.h | 17 +++++ target/i386/hvf/hvf.c | 3 + 5 files changed, 162 insertions(+), 76 deletions(-) create mode 100644 target/i386/hvf/hvf-cpus.c create mode 100644 target/i386/hvf/hvf-cpus.h diff --git a/softmmu/cpus.c b/softmmu/cpus.c index ed9cd8ec72..2b27373c3e 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -33,7 +33,6 @@ #include "exec/gdbstub.h" #include "sysemu/hw_accel.h" #include "sysemu/kvm.h" -#include "sysemu/hvf.h" #include "exec/exec-all.h" #include "qemu/thread.h" #include "qemu/plugin.h" @@ -142,10 +141,6 @@ void cpu_synchronize_all_states(void) =20 CPU_FOREACH(cpu) { cpu_synchronize_state(cpu); - /* TODO: move to cpu_synchronize_state() */ - if (hvf_enabled()) { - hvf_cpu_synchronize_state(cpu); - } } } =20 @@ -155,10 +150,6 @@ void cpu_synchronize_all_post_reset(void) =20 CPU_FOREACH(cpu) { cpu_synchronize_post_reset(cpu); - /* TODO: move to cpu_synchronize_post_reset() */ - if (hvf_enabled()) { - hvf_cpu_synchronize_post_reset(cpu); - } } } =20 @@ -168,10 +159,6 @@ void cpu_synchronize_all_post_init(void) =20 CPU_FOREACH(cpu) { cpu_synchronize_post_init(cpu); - /* TODO: move to cpu_synchronize_post_init() */ - if (hvf_enabled()) { - hvf_cpu_synchronize_post_init(cpu); - } } } =20 @@ -383,48 +370,6 @@ void qemu_wait_io_event(CPUState *cpu) qemu_wait_io_event_common(cpu); } =20 -/* The HVF-specific vCPU thread function. This one should only run when th= e host - * CPU supports the VMX "unrestricted guest" feature. */ -static void *qemu_hvf_cpu_thread_fn(void *arg) -{ - CPUState *cpu =3D arg; - - int r; - - assert(hvf_enabled()); - - rcu_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - - cpu->thread_id =3D qemu_get_thread_id(); - cpu->can_do_io =3D 1; - current_cpu =3D cpu; - - hvf_init_vcpu(cpu); - - /* signal CPU creation */ - cpu_thread_signal_created(cpu); - qemu_guest_random_seed_thread_part2(cpu->random_seed); - - do { - if (cpu_can_run(cpu)) { - r =3D hvf_vcpu_exec(cpu); - if (r =3D=3D EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - } - } - qemu_wait_io_event(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - - hvf_vcpu_destroy(cpu); - cpu_thread_signal_destroyed(cpu); - qemu_mutex_unlock_iothread(); - rcu_unregister_thread(); - return NULL; -} - void cpus_kick_thread(CPUState *cpu) { #ifndef _WIN32 @@ -594,24 +539,6 @@ void cpu_remove_sync(CPUState *cpu) qemu_mutex_lock_iothread(); } =20 -static void qemu_hvf_start_vcpu(CPUState *cpu) -{ - char thread_name[VCPU_THREAD_NAME_SIZE]; - - /* HVF currently does not support TCG, and only runs in - * unrestricted-guest mode. */ - assert(hvf_enabled()); - - cpu->thread =3D g_malloc0(sizeof(QemuThread)); - cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); - qemu_cond_init(cpu->halt_cond); - - snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF", - cpu->cpu_index); - qemu_thread_create(cpu->thread, thread_name, qemu_hvf_cpu_thread_fn, - cpu, QEMU_THREAD_JOINABLE); -} - void cpus_register_accel(CpusAccel *ca) { assert(ca !=3D NULL); @@ -638,8 +565,6 @@ void qemu_init_vcpu(CPUState *cpu) if (cpus_accel) { /* accelerator already implements the CpusAccel interface */ cpus_accel->create_vcpu_thread(cpu); - } else if (hvf_enabled()) { - qemu_hvf_start_vcpu(cpu); } else { assert(0); } diff --git a/target/i386/hvf/Makefile.objs b/target/i386/hvf/Makefile.objs index 927b86bc67..af9f7dcfc1 100644 --- a/target/i386/hvf/Makefile.objs +++ b/target/i386/hvf/Makefile.objs @@ -1,2 +1,2 @@ -obj-y +=3D hvf.o +obj-y +=3D hvf.o hvf-cpus.o obj-y +=3D x86.o x86_cpuid.o x86_decode.o x86_descr.o x86_emu.o x86_flags.= o x86_mmu.o x86hvf.o x86_task.o diff --git a/target/i386/hvf/hvf-cpus.c b/target/i386/hvf/hvf-cpus.c new file mode 100644 index 0000000000..a6970701c3 --- /dev/null +++ b/target/i386/hvf/hvf-cpus.c @@ -0,0 +1,141 @@ +/* + * Copyright 2008 IBM Corporation + * 2008 Red Hat, Inc. + * Copyright 2011 Intel Corporation + * Copyright 2016 Veertu, Inc. + * Copyright 2017 The Android Open Source Project + * + * QEMU Hypervisor.framework support + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * This file contain code under public domain from the hvdos project: + * https://github.com/mist64/hvdos + * + * Parts Copyright (c) 2011 NetApp, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP= OSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENT= IAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STR= ICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY W= AY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "sysemu/hvf.h" +#include "sysemu/runstate.h" +#include "target/i386/cpu.h" +#include "qemu/guest-random.h" + +#include "hvf-cpus.h" + +/* + * The HVF-specific vCPU thread function. This one should only run when th= e host + * CPU supports the VMX "unrestricted guest" feature. + */ +static void *hvf_cpu_thread_fn(void *arg) +{ + CPUState *cpu =3D arg; + + int r; + + assert(hvf_enabled()); + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + + cpu->thread_id =3D qemu_get_thread_id(); + cpu->can_do_io =3D 1; + current_cpu =3D cpu; + + hvf_init_vcpu(cpu); + + /* signal CPU creation */ + cpu_thread_signal_created(cpu); + qemu_guest_random_seed_thread_part2(cpu->random_seed); + + do { + if (cpu_can_run(cpu)) { + r =3D hvf_vcpu_exec(cpu); + if (r =3D=3D EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + qemu_wait_io_event(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + hvf_vcpu_destroy(cpu); + cpu_thread_signal_destroyed(cpu); + qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); + return NULL; +} + +static void hvf_kick_vcpu_thread(CPUState *cpu) +{ + cpus_kick_thread(cpu); +} + +static void hvf_cpu_synchronize_noop(CPUState *cpu) +{ +} + +static void hvf_start_vcpu_thread(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + /* + * HVF currently does not support TCG, and only runs in + * unrestricted-guest mode. + */ + assert(hvf_enabled()); + + cpu->thread =3D g_malloc0(sizeof(QemuThread)); + cpu->halt_cond =3D g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, hvf_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); +} + +CpusAccel hvf_cpus =3D { + .create_vcpu_thread =3D hvf_start_vcpu_thread, + .kick_vcpu_thread =3D hvf_kick_vcpu_thread, + + .synchronize_post_reset =3D hvf_cpu_synchronize_post_reset, + .synchronize_post_init =3D hvf_cpu_synchronize_post_init, + .synchronize_state =3D hvf_cpu_synchronize_state, + .synchronize_pre_loadvm =3D hvf_cpu_synchronize_noop, +}; diff --git a/target/i386/hvf/hvf-cpus.h b/target/i386/hvf/hvf-cpus.h new file mode 100644 index 0000000000..b66f4889b0 --- /dev/null +++ b/target/i386/hvf/hvf-cpus.h @@ -0,0 +1,17 @@ +/* + * Accelerator CPUS Interface + * + * Copyright 2020 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef HVF_CPUS_H +#define HVF_CPUS_H + +#include "sysemu/cpus.h" + +extern CpusAccel hvf_cpus; + +#endif /* HVF_CPUS_H */ diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index be016b951a..23e5ee6048 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -72,6 +72,8 @@ #include "sysemu/accel.h" #include "target/i386/cpu.h" =20 +#include "hvf-cpus.h" + HVFState *hvf_state; =20 static void assert_hvf_ok(hv_return_t ret) @@ -977,6 +979,7 @@ static int hvf_accel_init(MachineState *ms) hvf_state =3D s; cpu_interrupt_handler =3D hvf_handle_interrupt; memory_listener_register(&hvf_memory_listener, &address_space_memory); + cpus_register_accel(&hvf_cpus); return 0; } =20 --=20 2.16.4