From nobody Mon Jul 1 19:59:17 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=1597257266; cv=none; d=zohomail.com; s=zohoarc; b=D6van2gGTqOhRu1SXCdEfOIvgPXEVm5GTPpZ+39LJQAmbDccaOst5JDi+zXdoiqWMvM/23FepTxhGuXPae3LIf9+C+uW/R9VsNaRZBr3r7Bko8iSlZ8U71JtjkufVtVn9H6Zv4+j69EIyuiV5Fp/aB8NCBGZ56izb9XUSwkYDr0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257266; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=kPQYPFaeaxVOO0z/5/BbOHQ3FPf7SBI64+I8zyTBzqs=; b=m0zjX6B6JTMM0yNSvI73m3H/AycKGlWHC847kWFxzT/ZQHYYLjXBAMo3UvhovvSi3WYb69ojB34zbn4hAJY0lyic5eRb4cWEHBD+uzwRl/uA2W//pEdpxXd12NdBE/Tk5Ic5pK+EjxFTurweENo/3awF6eqNTnLsTRIFvN5lQRg= 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 1597257266497867.4900931911933; Wed, 12 Aug 2020 11:34:26 -0700 (PDT) Received: from localhost ([::1]:43452 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vZw-00027T-Vs for importer@patchew.org; Wed, 12 Aug 2020 14:34:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46280) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYZ-0000Fi-F3 for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:32:59 -0400 Received: from mx2.suse.de ([195.135.220.15]:40548) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYV-0002Cz-3P for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:32:59 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 563DBAE08; Wed, 12 Aug 2020 18:33:15 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 01/14] cpu-timers, icount: new modules Date: Wed, 12 Aug 2020 20:32:37 +0200 Message-Id: <20200812183250.9221-2-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-1-cfontana@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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/08/11 23:47:43 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, URIBL_BLOCKED=0.001 autolearn=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" refactoring of cpus.c continues with cpu timer state extraction. cpu-timers: responsible for the softmmu cpu timers state, including cpu clocks and ticks. icount: counts the TCG instructions executed. As such it is specific to the TCG accelerator. Therefore, it is built only under CONFIG_TCG. One complication is due to qtest, which uses an icount field to warp time as part of qtest (qtest_clock_warp). In order to solve this problem, provide a separate counter for qtest. This requires fixing assumptions scattered in the code that qtest_enabled() implies icount_enabled(), checking each specific case. Signed-off-by: Claudio Fontana Reviewed-by: Alex Benn=C3=A9e --- MAINTAINERS | 2 + accel/qtest.c | 6 +- accel/tcg/cpu-exec.c | 43 ++- accel/tcg/tcg-all.c | 7 +- accel/tcg/translate-all.c | 3 +- dma-helpers.c | 4 +- docs/replay.txt | 6 +- exec.c | 4 - hw/core/ptimer.c | 8 +- hw/i386/x86.c | 1 + include/exec/cpu-all.h | 4 + include/exec/exec-all.h | 4 +- include/qemu/timer.h | 24 +- include/sysemu/cpu-timers.h | 81 +++++ include/sysemu/cpus.h | 12 +- include/sysemu/qtest.h | 2 + include/sysemu/replay.h | 4 +- replay/replay.c | 6 +- softmmu/Makefile.objs | 2 + softmmu/cpu-timers.c | 284 ++++++++++++++++ softmmu/cpus.c | 750 +--------------------------------------= ---- softmmu/icount.c | 497 ++++++++++++++++++++++++++++ softmmu/qtest.c | 34 +- softmmu/timers-state.h | 69 ++++ softmmu/vl.c | 11 +- stubs/Makefile.objs | 4 +- stubs/clock-warp.c | 7 - stubs/cpu-get-clock.c | 3 +- stubs/cpu-get-icount.c | 21 -- stubs/icount.c | 52 +++ stubs/qemu-timer-notify-cb.c | 8 + stubs/qtest.c | 5 + target/alpha/translate.c | 3 +- target/arm/helper.c | 7 +- target/riscv/csr.c | 8 +- tests/ptimer-test-stubs.c | 7 +- tests/test-timed-average.c | 2 +- util/main-loop.c | 12 +- util/qemu-timer.c | 14 +- 39 files changed, 1158 insertions(+), 863 deletions(-) create mode 100644 include/sysemu/cpu-timers.h create mode 100644 softmmu/cpu-timers.c create mode 100644 softmmu/icount.c create mode 100644 softmmu/timers-state.h delete mode 100644 stubs/clock-warp.c delete mode 100644 stubs/cpu-get-icount.c create mode 100644 stubs/icount.c create mode 100644 stubs/qemu-timer-notify-cb.c diff --git a/MAINTAINERS b/MAINTAINERS index 0886eb3d2b..7dcc3ef4c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2285,6 +2285,8 @@ F: softmmu/vl.c F: softmmu/main.c F: softmmu/cpus.c F: softmmu/cpu-throttle.c +F: softmmu/cpu-timers.c +F: softmmu/icount.c F: qapi/run-state.json =20 Human Monitor (HMP) diff --git a/accel/qtest.c b/accel/qtest.c index 5b88f55921..119d0f16a4 100644 --- a/accel/qtest.c +++ b/accel/qtest.c @@ -19,14 +19,10 @@ #include "sysemu/accel.h" #include "sysemu/qtest.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" =20 static int qtest_init_accel(MachineState *ms) { - QemuOpts *opts =3D qemu_opts_create(qemu_find_opts("icount"), NULL, 0, - &error_abort); - qemu_opt_set(opts, "shift", "0", &error_abort); - configure_icount(opts, &error_abort); - qemu_opts_del(opts); return 0; } =20 diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 66d38f9d85..b44e92b753 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -19,6 +19,7 @@ =20 #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/qemu-print.h" #include "cpu.h" #include "trace.h" #include "disas/disas.h" @@ -36,6 +37,8 @@ #include "hw/i386/apic.h" #endif #include "sysemu/cpus.h" +#include "exec/cpu-all.h" +#include "sysemu/cpu-timers.h" #include "sysemu/replay.h" =20 /* -icount align implementation. */ @@ -56,6 +59,9 @@ typedef struct SyncClocks { #define MAX_DELAY_PRINT_RATE 2000000000LL #define MAX_NB_PRINTS 100 =20 +static int64_t max_delay; +static int64_t max_advance; + static void align_clocks(SyncClocks *sc, CPUState *cpu) { int64_t cpu_icount; @@ -65,7 +71,7 @@ static void align_clocks(SyncClocks *sc, CPUState *cpu) } =20 cpu_icount =3D cpu->icount_extra + cpu_neg(cpu)->icount_decr.u16.low; - sc->diff_clk +=3D cpu_icount_to_ns(sc->last_cpu_icount - cpu_icount); + sc->diff_clk +=3D icount_to_ns(sc->last_cpu_icount - cpu_icount); sc->last_cpu_icount =3D cpu_icount; =20 if (sc->diff_clk > VM_CLOCK_ADVANCE) { @@ -98,9 +104,9 @@ static void print_delay(const SyncClocks *sc) (-sc->diff_clk / (float)1000000000LL < (threshold_delay - THRESHOLD_REDUCE))) { threshold_delay =3D (-sc->diff_clk / 1000000000LL) + 1; - printf("Warning: The guest is now late by %.1f to %.1f seconds= \n", - threshold_delay - 1, - threshold_delay); + qemu_printf("Warning: The guest is now late by %.1f to %.1f se= conds\n", + threshold_delay - 1, + threshold_delay); nb_prints++; last_realtime_clock =3D sc->realtime_clock; } @@ -614,7 +620,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, =20 /* Finally, check if we need to exit to the main loop. */ if (unlikely(atomic_read(&cpu->exit_request)) - || (use_icount + || (icount_enabled() && cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra =3D= =3D 0)) { atomic_set(&cpu->exit_request, 0); if (cpu->exception_index =3D=3D -1) { @@ -655,10 +661,10 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, Tr= anslationBlock *tb, } =20 /* Instruction counter expired. */ - assert(use_icount); + assert(icount_enabled()); #ifndef CONFIG_USER_ONLY /* Ensure global icount has gone forward */ - cpu_update_icount(cpu); + icount_update(cpu); /* Refill decrementer and continue execution. */ insns_left =3D MIN(0xffff, cpu->icount_budget); cpu_neg(cpu)->icount_decr.u16.low =3D insns_left; @@ -758,3 +764,26 @@ int cpu_exec(CPUState *cpu) =20 return ret; } + +#ifndef CONFIG_USER_ONLY + +void dump_drift_info(void) +{ + if (!icount_enabled()) { + return; + } + + qemu_printf("Host - Guest clock %"PRIi64" ms\n", + (cpu_get_clock() - icount_get()) / SCALE_MS); + if (icount_align_option) { + qemu_printf("Max guest delay %"PRIi64" ms\n", + -max_delay / SCALE_MS); + qemu_printf("Max guest advance %"PRIi64" ms\n", + max_advance / SCALE_MS); + } else { + qemu_printf("Max guest delay NA\n"); + qemu_printf("Max guest advance NA\n"); + } +} + +#endif /* !CONFIG_USER_ONLY */ diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index eace2c113b..f1feea20c8 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -29,6 +29,7 @@ #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" @@ -65,7 +66,7 @@ static void tcg_handle_interrupt(CPUState *cpu, int mask) qemu_cpu_kick(cpu); } else { atomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1); - if (use_icount && + if (icount_enabled() && !cpu->can_do_io && (mask & ~old_mask) !=3D 0) { cpu_abort(cpu, "Raised interrupt while not in I/O function"); @@ -104,7 +105,7 @@ static bool check_tcg_memory_orders_compatible(void) =20 static bool default_mttcg_enabled(void) { - if (use_icount || TCG_OVERSIZED_GUEST) { + if (icount_enabled() || TCG_OVERSIZED_GUEST) { return false; } else { #ifdef TARGET_SUPPORTS_MTTCG @@ -146,7 +147,7 @@ static void tcg_set_thread(Object *obj, const char *val= ue, Error **errp) if (strcmp(value, "multi") =3D=3D 0) { if (TCG_OVERSIZED_GUEST) { error_setg(errp, "No MTTCG when guest word size > hosts"); - } else if (use_icount) { + } else if (icount_enabled()) { error_setg(errp, "No MTTCG when icount is enabled"); } else { #ifndef TARGET_SUPPORTS_MTTCG diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 2d83013633..c39ff7b047 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -57,6 +57,7 @@ #include "qemu/main-loop.h" #include "exec/log.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "sysemu/tcg.h" =20 /* #define DEBUG_TB_INVALIDATE */ @@ -369,7 +370,7 @@ static int cpu_restore_state_from_tb(CPUState *cpu, Tra= nslationBlock *tb, =20 found: if (reset_icount && (tb_cflags(tb) & CF_USE_ICOUNT)) { - assert(use_icount); + assert(icount_enabled()); /* Reset the cycle counter to the start of the block and shift if to the number of actually executed instructions */ cpu_neg(cpu)->icount_decr.u16.low +=3D num_insns - i; diff --git a/dma-helpers.c b/dma-helpers.c index 2a77b5a9cb..240ef4d5b8 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -13,7 +13,7 @@ #include "trace-root.h" #include "qemu/thread.h" #include "qemu/main-loop.h" -#include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "qemu/range.h" =20 /* #define DEBUG_IOMMU */ @@ -151,7 +151,7 @@ static void dma_blk_cb(void *opaque, int ret) * from several sectors. This code splits all SGs into several * groups. SGs in every group do not overlap. */ - if (mem && use_icount && dbs->dir =3D=3D DMA_DIRECTION_FROM_DEVICE= ) { + if (mem && icount_enabled() && dbs->dir =3D=3D DMA_DIRECTION_FROM_= DEVICE) { int i; for (i =3D 0 ; i < dbs->iov.niov ; ++i) { if (ranges_overlap((intptr_t)dbs->iov.iov[i].iov_base, diff --git a/docs/replay.txt b/docs/replay.txt index 70c27edb36..8952e6d852 100644 --- a/docs/replay.txt +++ b/docs/replay.txt @@ -184,11 +184,11 @@ is then incremented (which is called "warping" the vi= rtual clock) as soon as the timer fires or the CPUs need to go out of the idle state. Two functions are used for this purpose; because these actions change virtual machine state and must be deterministic, each of them creates a -checkpoint. qemu_start_warp_timer checks if the CPUs are idle and if so -starts accounting real time to virtual clock. qemu_account_warp_timer +checkpoint. icount_start_warp_timer checks if the CPUs are idle and if so +starts accounting real time to virtual clock. icount_account_warp_timer is called when the CPUs get an interrupt or when the warp timer fires, and it warps the virtual clock by the amount of real time that has passed -since qemu_start_warp_timer. +since icount_start_warp_timer. =20 Bottom halves ------------- diff --git a/exec.c b/exec.c index 6f381f98e2..a89ffa93c1 100644 --- a/exec.c +++ b/exec.c @@ -102,10 +102,6 @@ uintptr_t qemu_host_page_size; intptr_t qemu_host_page_mask; =20 #if !defined(CONFIG_USER_ONLY) -/* 0 =3D Do not count executed instructions. - 1 =3D Precise instruction counting. - 2 =3D Adaptive rate instruction counting. */ -int use_icount; =20 typedef struct PhysPageEntry PhysPageEntry; =20 diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c index b5a54e2536..c6d2beb1da 100644 --- a/hw/core/ptimer.c +++ b/hw/core/ptimer.c @@ -7,11 +7,11 @@ */ =20 #include "qemu/osdep.h" -#include "qemu/timer.h" #include "hw/ptimer.h" #include "migration/vmstate.h" #include "qemu/host-utils.h" #include "sysemu/replay.h" +#include "sysemu/cpu-timers.h" #include "sysemu/qtest.h" #include "block/aio.h" #include "sysemu/cpus.h" @@ -134,7 +134,8 @@ static void ptimer_reload(ptimer_state *s, int delta_ad= just) * on the current generation of host machines. */ =20 - if (s->enabled =3D=3D 1 && (delta * period < 10000) && !use_icount) { + if (s->enabled =3D=3D 1 && (delta * period < 10000) && + !icount_enabled() && !qtest_enabled()) { period =3D 10000 / delta; period_frac =3D 0; } @@ -217,7 +218,8 @@ uint64_t ptimer_get_count(ptimer_state *s) uint32_t period_frac =3D s->period_frac; uint64_t period =3D s->period; =20 - if (!oneshot && (s->delta * period < 10000) && !use_icount) { + if (!oneshot && (s->delta * period < 10000) && + !icount_enabled() && !qtest_enabled()) { period =3D 10000 / s->delta; period_frac =3D 0; } diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 67bee1bcb8..58cf2229d5 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -34,6 +34,7 @@ #include "sysemu/numa.h" #include "sysemu/replay.h" #include "sysemu/sysemu.h" +#include "sysemu/cpu-timers.h" #include "trace.h" =20 #include "hw/i386/x86.h" diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index fc403d456b..25b6005a91 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -407,8 +407,12 @@ static inline bool tlb_hit(target_ulong tlb_addr, targ= et_ulong addr) return tlb_hit_page(tlb_addr, addr & TARGET_PAGE_MASK); } =20 +#ifdef CONFIG_TCG +void dump_drift_info(void); void dump_exec_info(void); void dump_opcount_info(void); +#endif /* CONFIG_TCG */ + #endif /* !CONFIG_USER_ONLY */ =20 /* Returns: 0 on success, -1 on error */ diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 3cf88272df..e019b505a5 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -25,7 +25,7 @@ #ifdef CONFIG_TCG #include "exec/cpu_ldst.h" #endif -#include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" =20 /* allow to see translation results - the slowdown should be negligible, s= o we leave it */ #define DEBUG_DISAS @@ -497,7 +497,7 @@ static inline uint32_t tb_cflags(const TranslationBlock= *tb) static inline uint32_t curr_cflags(void) { return (parallel_cpus ? CF_PARALLEL : 0) - | (use_icount ? CF_USE_ICOUNT : 0); + | (icount_enabled() ? CF_USE_ICOUNT : 0); } =20 /* TranslationBlock invalidate API */ diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 6a8b48b5a9..2f7afc1f68 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -166,8 +166,8 @@ bool qemu_clock_expired(QEMUClockType type); * * Determine whether a clock should be used for deadline * calculations. Some clocks, for instance vm_clock with - * use_icount set, do not count in nanoseconds. Such clocks - * are not used for deadline calculations, and are presumed + * icount_enabled() set, do not count in nanoseconds. + * Such clocks are not used for deadline calculations, and are presumed * to interrupt any poll using qemu_notify/aio_notify * etc. * @@ -224,13 +224,6 @@ void qemu_clock_notify(QEMUClockType type); */ void qemu_clock_enable(QEMUClockType type, bool enabled); =20 -/** - * qemu_start_warp_timer: - * - * Starts a timer for virtual clock update - */ -void qemu_start_warp_timer(void); - /** * qemu_clock_run_timers: * @type: clock on which to operate @@ -791,12 +784,6 @@ static inline int64_t qemu_soonest_timeout(int64_t tim= eout1, int64_t timeout2) */ void init_clocks(QEMUTimerListNotifyCB *notify_cb); =20 -int64_t cpu_get_ticks(void); -/* Caller must hold BQL */ -void cpu_enable_ticks(void); -/* Caller must hold BQL */ -void cpu_disable_ticks(void); - static inline int64_t get_max_clock_jump(void) { /* This should be small enough to prevent excessive interrupts from be= ing @@ -850,13 +837,6 @@ static inline int64_t get_clock(void) } #endif =20 -/* icount */ -int64_t cpu_get_icount_raw(void); -int64_t cpu_get_icount(void); -int64_t cpu_get_clock(void); -int64_t cpu_icount_to_ns(int64_t icount); -void cpu_update_icount(CPUState *cpu); - /*******************************************/ /* host CPU ticks (if available) */ =20 diff --git a/include/sysemu/cpu-timers.h b/include/sysemu/cpu-timers.h new file mode 100644 index 0000000000..07d724672f --- /dev/null +++ b/include/sysemu/cpu-timers.h @@ -0,0 +1,81 @@ +/* + * CPU timers state API + * + * 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 SYSEMU_CPU_TIMERS_H +#define SYSEMU_CPU_TIMERS_H + +#include "qemu/timer.h" + +/* init the whole cpu timers API, including icount, ticks, and cpu_throttl= e */ +void cpu_timers_init(void); + +/* icount - Instruction Counter API */ + +/* + * Return the icount enablement state: + * + * 0 =3D Disabled - Do not count executed instructions. + * 1 =3D Enabled - Fixed conversion of insn to ns via "shift" option + * 2 =3D Enabled - Runtime adaptive algorithm to compute shift + */ +int icount_enabled(void); +/* + * Update the icount with the executed instructions. Called by + * cpus-tcg vCPU thread so the main-loop can see time has moved forward. + */ +void icount_update(CPUState *cpu); + +/* get raw icount value */ +int64_t icount_get_raw(void); + +/* return the virtual CPU time in ns, based on the instruction counter. */ +int64_t icount_get(void); +/* + * convert an instruction counter value to ns, based on the icount shift. + * This shift is set as a fixed value with the icount "shift" option + * (precise mode), or it is constantly approximated and corrected at + * runtime in adaptive mode. + */ +int64_t icount_to_ns(int64_t icount); + +/* configure the icount options, including "shift" */ +void icount_configure(QemuOpts *opts, Error **errp); + +/* used by tcg vcpu thread to calc icount budget */ +int64_t icount_round(int64_t count); + +/* if the CPUs are idle, start accounting real time to virtual clock. */ +void icount_start_warp_timer(void); +void icount_account_warp_timer(void); + +/* + * CPU Ticks and Clock + */ + +/* Caller must hold BQL */ +void cpu_enable_ticks(void); +/* Caller must hold BQL */ +void cpu_disable_ticks(void); + +/* + * return the time elapsed in VM between vm_start and vm_stop. Unless + * icount is active, cpu_get_ticks() uses units of the host CPU cycle + * counter. + */ +int64_t cpu_get_ticks(void); + +/* + * Returns the monotonic time elapsed in VM, i.e., + * the time between vm_start and vm_stop + */ +int64_t cpu_get_clock(void); + +void qemu_timer_notify_cb(void *opaque, QEMUClockType type); + +#endif /* SYSEMU_CPU_TIMERS_H */ diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index 3c1da6a018..149de000a0 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -4,33 +4,23 @@ #include "qemu/timer.h" =20 /* cpus.c */ +bool all_cpu_threads_idle(void); bool qemu_in_vcpu_thread(void); void qemu_init_cpu_loop(void); void resume_all_vcpus(void); void pause_all_vcpus(void); void cpu_stop_current(void); -void cpu_ticks_init(void); =20 -void configure_icount(QemuOpts *opts, Error **errp); -extern int use_icount; extern int icount_align_option; =20 -/* drift information for info jit command */ -extern int64_t max_delay; -extern int64_t max_advance; -void dump_drift_info(void); - /* Unblock cpu */ void qemu_cpu_kick_self(void); -void qemu_timer_notify_cb(void *opaque, QEMUClockType type); =20 void cpu_synchronize_all_states(void); void cpu_synchronize_all_post_reset(void); void cpu_synchronize_all_post_init(void); void cpu_synchronize_all_pre_loadvm(void); =20 -void qtest_clock_warp(int64_t dest); - #ifndef CONFIG_USER_ONLY /* vl.c */ /* *-user doesn't have configurable SMP topology */ diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h index eedd3664f0..4c53537ef3 100644 --- a/include/sysemu/qtest.h +++ b/include/sysemu/qtest.h @@ -30,4 +30,6 @@ void qtest_server_set_send_handler(void (*send)(void *, c= onst char *), void *opaque); void qtest_server_inproc_recv(void *opaque, const char *buf); =20 +int64_t qtest_get_virtual_clock(void); + #endif diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h index 5471bb514d..a140d69a73 100644 --- a/include/sysemu/replay.h +++ b/include/sysemu/replay.h @@ -109,12 +109,12 @@ int64_t replay_read_clock(ReplayClockKind kind); #define REPLAY_CLOCK(clock, value) \ (replay_mode =3D=3D REPLAY_MODE_PLAY ? replay_read_clock((clock)) = \ : replay_mode =3D=3D REPLAY_MODE_RECORD = \ - ? replay_save_clock((clock), (value), cpu_get_icount_raw()) \ + ? replay_save_clock((clock), (value), icount_get_raw()) \ : (value)) #define REPLAY_CLOCK_LOCKED(clock, value) \ (replay_mode =3D=3D REPLAY_MODE_PLAY ? replay_read_clock((clock)) = \ : replay_mode =3D=3D REPLAY_MODE_RECORD = \ - ? replay_save_clock((clock), (value), cpu_get_icount_raw_locke= d()) \ + ? replay_save_clock((clock), (value), icount_get_raw_locked())= \ : (value)) =20 /* Processing data from random generators */ diff --git a/replay/replay.c b/replay/replay.c index 83ed9e0e24..4c1457b07e 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -11,10 +11,10 @@ =20 #include "qemu/osdep.h" #include "qapi/error.h" +#include "sysemu/cpu-timers.h" #include "sysemu/replay.h" #include "sysemu/runstate.h" #include "replay-internal.h" -#include "qemu/timer.h" #include "qemu/main-loop.h" #include "qemu/option.h" #include "sysemu/cpus.h" @@ -64,7 +64,7 @@ bool replay_next_event_is(int event) =20 uint64_t replay_get_current_icount(void) { - return cpu_get_icount_raw(); + return icount_get_raw(); } =20 int replay_get_instructions(void) @@ -345,7 +345,7 @@ void replay_start(void) error_reportf_err(replay_blockers->data, "Record/replay: "); exit(1); } - if (!use_icount) { + if (!icount_enabled()) { error_report("Please enable icount to use record/replay"); exit(1); } diff --git a/softmmu/Makefile.objs b/softmmu/Makefile.objs index a414a74c50..9c0125f37b 100644 --- a/softmmu/Makefile.objs +++ b/softmmu/Makefile.objs @@ -7,6 +7,8 @@ obj-y +=3D balloon.o obj-y +=3D ioport.o obj-y +=3D memory.o obj-y +=3D memory_mapping.o +obj-y +=3D cpu-timers.o +obj-$(CONFIG_TCG) +=3D icount.o =20 obj-y +=3D qtest.o =20 diff --git a/softmmu/cpu-timers.c b/softmmu/cpu-timers.c new file mode 100644 index 0000000000..64addb315d --- /dev/null +++ b/softmmu/cpu-timers.c @@ -0,0 +1,284 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * 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 "qemu/cutils.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "exec/exec-all.h" +#include "sysemu/cpus.h" +#include "sysemu/qtest.h" +#include "qemu/main-loop.h" +#include "qemu/option.h" +#include "qemu/seqlock.h" +#include "sysemu/replay.h" +#include "sysemu/runstate.h" +#include "hw/core/cpu.h" +#include "sysemu/cpu-timers.h" +#include "sysemu/cpu-throttle.h" +#include "timers-state.h" + +/* clock and ticks */ + +static int64_t cpu_get_ticks_locked(void) +{ + int64_t ticks =3D timers_state.cpu_ticks_offset; + if (timers_state.cpu_ticks_enabled) { + ticks +=3D cpu_get_host_ticks(); + } + + if (timers_state.cpu_ticks_prev > ticks) { + /* Non increasing ticks may happen if the host uses software suspe= nd. */ + timers_state.cpu_ticks_offset +=3D timers_state.cpu_ticks_prev - t= icks; + ticks =3D timers_state.cpu_ticks_prev; + } + + timers_state.cpu_ticks_prev =3D ticks; + return ticks; +} + +/* + * return the time elapsed in VM between vm_start and vm_stop. Unless + * icount is active, cpu_get_ticks() uses units of the host CPU cycle + * counter. + */ +int64_t cpu_get_ticks(void) +{ + int64_t ticks; + + if (icount_enabled()) { + return icount_get(); + } + + qemu_spin_lock(&timers_state.vm_clock_lock); + ticks =3D cpu_get_ticks_locked(); + qemu_spin_unlock(&timers_state.vm_clock_lock); + return ticks; +} + +int64_t cpu_get_clock_locked(void) +{ + int64_t time; + + time =3D timers_state.cpu_clock_offset; + if (timers_state.cpu_ticks_enabled) { + time +=3D get_clock(); + } + + return time; +} + +/* + * Return the monotonic time elapsed in VM, i.e., + * the time between vm_start and vm_stop + */ +int64_t cpu_get_clock(void) +{ + int64_t ti; + unsigned start; + + do { + start =3D seqlock_read_begin(&timers_state.vm_clock_seqlock); + ti =3D cpu_get_clock_locked(); + } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); + + return ti; +} + +/* + * enable cpu_get_ticks() + * Caller must hold BQL which serves as mutex for vm_clock_seqlock. + */ +void cpu_enable_ticks(void) +{ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + if (!timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset -=3D cpu_get_host_ticks(); + timers_state.cpu_clock_offset -=3D get_clock(); + timers_state.cpu_ticks_enabled =3D 1; + } + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); +} + +/* + * disable cpu_get_ticks() : the clock is stopped. You must not call + * cpu_get_ticks() after that. + * Caller must hold BQL which serves as mutex for vm_clock_seqlock. + */ +void cpu_disable_ticks(void) +{ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + if (timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset +=3D cpu_get_host_ticks(); + timers_state.cpu_clock_offset =3D cpu_get_clock_locked(); + timers_state.cpu_ticks_enabled =3D 0; + } + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); +} + +static bool icount_state_needed(void *opaque) +{ + return icount_enabled(); +} + +static bool icount_shift_state_needed(void *opaque) +{ + return icount_enabled() =3D=3D 2; +} + +static bool warp_timer_state_needed(void *opaque) +{ + TimersState *s =3D opaque; + return s->icount_warp_timer !=3D NULL; +} + +static bool adjust_timers_state_needed(void *opaque) +{ + TimersState *s =3D opaque; + return s->icount_rt_timer !=3D NULL; +} + +/* + * Subsection for warp timer migration is optional, because may not be cre= ated + */ +static const VMStateDescription icount_vmstate_warp_timer =3D { + .name =3D "timer/icount/warp_timer", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D warp_timer_state_needed, + .fields =3D (VMStateField[]) { + VMSTATE_INT64(vm_clock_warp_start, TimersState), + VMSTATE_TIMER_PTR(icount_warp_timer, TimersState), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription icount_vmstate_adjust_timers =3D { + .name =3D "timer/icount/timers", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D adjust_timers_state_needed, + .fields =3D (VMStateField[]) { + VMSTATE_TIMER_PTR(icount_rt_timer, TimersState), + VMSTATE_TIMER_PTR(icount_vm_timer, TimersState), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription icount_vmstate_shift =3D { + .name =3D "timer/icount/shift", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D icount_shift_state_needed, + .fields =3D (VMStateField[]) { + VMSTATE_INT16(icount_time_shift, TimersState), + VMSTATE_END_OF_LIST() + } +}; + +/* + * This is a subsection for icount migration. + */ +static const VMStateDescription icount_vmstate_timers =3D { + .name =3D "timer/icount", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D icount_state_needed, + .fields =3D (VMStateField[]) { + VMSTATE_INT64(qemu_icount_bias, TimersState), + VMSTATE_INT64(qemu_icount, TimersState), + VMSTATE_END_OF_LIST() + }, + .subsections =3D (const VMStateDescription * []) { + &icount_vmstate_warp_timer, + &icount_vmstate_adjust_timers, + &icount_vmstate_shift, + NULL + } +}; + +static const VMStateDescription vmstate_timers =3D { + .name =3D "timer", + .version_id =3D 2, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_INT64(cpu_ticks_offset, TimersState), + VMSTATE_UNUSED(8), + VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2), + VMSTATE_END_OF_LIST() + }, + .subsections =3D (const VMStateDescription * []) { + &icount_vmstate_timers, + NULL + } +}; + +static void do_nothing(CPUState *cpu, run_on_cpu_data unused) +{ +} + +void qemu_timer_notify_cb(void *opaque, QEMUClockType type) +{ + if (!icount_enabled() || type !=3D QEMU_CLOCK_VIRTUAL) { + qemu_notify_event(); + return; + } + + if (qemu_in_vcpu_thread()) { + /* + * A CPU is currently running; kick it back out to the + * tcg_cpu_exec() loop so it will recalculate its + * icount deadline immediately. + */ + qemu_cpu_kick(current_cpu); + } else if (first_cpu) { + /* + * qemu_cpu_kick is not enough to kick a halted CPU out of + * qemu_tcg_wait_io_event. async_run_on_cpu, instead, + * causes cpu_thread_is_idle to return false. This way, + * handle_icount_deadline can run. + * If we have no CPUs at all for some reason, we don't + * need to do anything. + */ + async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL); + } +} + +TimersState timers_state; + +/* initialize timers state and the cpu throttle for convenience */ +void cpu_timers_init(void) +{ + seqlock_init(&timers_state.vm_clock_seqlock); + qemu_spin_init(&timers_state.vm_clock_lock); + vmstate_register(NULL, 0, &vmstate_timers, &timers_state); + + cpu_throttle_init(); +} diff --git a/softmmu/cpus.c b/softmmu/cpus.c index a802e899ab..54fdb2761c 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -58,11 +58,10 @@ #include "hw/nmi.h" #include "sysemu/replay.h" #include "sysemu/runstate.h" +#include "sysemu/cpu-timers.h" #include "hw/boards.h" #include "hw/hw.h" =20 -#include "sysemu/cpu-throttle.h" - #ifdef CONFIG_LINUX =20 #include @@ -83,9 +82,6 @@ =20 static QemuMutex qemu_global_mutex; =20 -int64_t max_delay; -int64_t max_advance; - bool cpu_is_stopped(CPUState *cpu) { return cpu->stopped || !runstate_is_running(); @@ -116,7 +112,7 @@ static bool cpu_thread_is_idle(CPUState *cpu) return true; } =20 -static bool all_cpu_threads_idle(void) +bool all_cpu_threads_idle(void) { CPUState *cpu; =20 @@ -128,688 +124,9 @@ static bool all_cpu_threads_idle(void) return true; } =20 -/***********************************************************/ -/* guest cycle counter */ - -/* Protected by TimersState seqlock */ - -static bool icount_sleep =3D true; -/* Arbitrarily pick 1MIPS as the minimum allowable speed. */ -#define MAX_ICOUNT_SHIFT 10 - -typedef struct TimersState { - /* Protected by BQL. */ - int64_t cpu_ticks_prev; - int64_t cpu_ticks_offset; - - /* Protect fields that can be respectively read outside the - * BQL, and written from multiple threads. - */ - QemuSeqLock vm_clock_seqlock; - QemuSpin vm_clock_lock; - - int16_t cpu_ticks_enabled; - - /* Conversion factor from emulated instructions to virtual clock ticks= . */ - int16_t icount_time_shift; - - /* Compensate for varying guest execution speed. */ - int64_t qemu_icount_bias; - - int64_t vm_clock_warp_start; - int64_t cpu_clock_offset; - - /* Only written by TCG thread */ - int64_t qemu_icount; - - /* for adjusting icount */ - QEMUTimer *icount_rt_timer; - QEMUTimer *icount_vm_timer; - QEMUTimer *icount_warp_timer; -} TimersState; - -static TimersState timers_state; bool mttcg_enabled; =20 =20 -/* The current number of executed instructions is based on what we - * originally budgeted minus the current state of the decrementing - * icount counters in extra/u16.low. - */ -static int64_t cpu_get_icount_executed(CPUState *cpu) -{ - return (cpu->icount_budget - - (cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra)); -} - -/* - * Update the global shared timer_state.qemu_icount to take into - * account executed instructions. This is done by the TCG vCPU - * thread so the main-loop can see time has moved forward. - */ -static void cpu_update_icount_locked(CPUState *cpu) -{ - int64_t executed =3D cpu_get_icount_executed(cpu); - cpu->icount_budget -=3D executed; - - atomic_set_i64(&timers_state.qemu_icount, - timers_state.qemu_icount + executed); -} - -/* - * Update the global shared timer_state.qemu_icount to take into - * account executed instructions. This is done by the TCG vCPU - * thread so the main-loop can see time has moved forward. - */ -void cpu_update_icount(CPUState *cpu) -{ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - cpu_update_icount_locked(cpu); - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); -} - -static int64_t cpu_get_icount_raw_locked(void) -{ - CPUState *cpu =3D current_cpu; - - if (cpu && cpu->running) { - if (!cpu->can_do_io) { - error_report("Bad icount read"); - exit(1); - } - /* Take into account what has run */ - cpu_update_icount_locked(cpu); - } - /* The read is protected by the seqlock, but needs atomic64 to avoid U= B */ - return atomic_read_i64(&timers_state.qemu_icount); -} - -static int64_t cpu_get_icount_locked(void) -{ - int64_t icount =3D cpu_get_icount_raw_locked(); - return atomic_read_i64(&timers_state.qemu_icount_bias) + - cpu_icount_to_ns(icount); -} - -int64_t cpu_get_icount_raw(void) -{ - int64_t icount; - unsigned start; - - do { - start =3D seqlock_read_begin(&timers_state.vm_clock_seqlock); - icount =3D cpu_get_icount_raw_locked(); - } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); - - return icount; -} - -/* Return the virtual CPU time, based on the instruction counter. */ -int64_t cpu_get_icount(void) -{ - int64_t icount; - unsigned start; - - do { - start =3D seqlock_read_begin(&timers_state.vm_clock_seqlock); - icount =3D cpu_get_icount_locked(); - } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); - - return icount; -} - -int64_t cpu_icount_to_ns(int64_t icount) -{ - return icount << atomic_read(&timers_state.icount_time_shift); -} - -static int64_t cpu_get_ticks_locked(void) -{ - int64_t ticks =3D timers_state.cpu_ticks_offset; - if (timers_state.cpu_ticks_enabled) { - ticks +=3D cpu_get_host_ticks(); - } - - if (timers_state.cpu_ticks_prev > ticks) { - /* Non increasing ticks may happen if the host uses software suspe= nd. */ - timers_state.cpu_ticks_offset +=3D timers_state.cpu_ticks_prev - t= icks; - ticks =3D timers_state.cpu_ticks_prev; - } - - timers_state.cpu_ticks_prev =3D ticks; - return ticks; -} - -/* return the time elapsed in VM between vm_start and vm_stop. Unless - * icount is active, cpu_get_ticks() uses units of the host CPU cycle - * counter. - */ -int64_t cpu_get_ticks(void) -{ - int64_t ticks; - - if (use_icount) { - return cpu_get_icount(); - } - - qemu_spin_lock(&timers_state.vm_clock_lock); - ticks =3D cpu_get_ticks_locked(); - qemu_spin_unlock(&timers_state.vm_clock_lock); - return ticks; -} - -static int64_t cpu_get_clock_locked(void) -{ - int64_t time; - - time =3D timers_state.cpu_clock_offset; - if (timers_state.cpu_ticks_enabled) { - time +=3D get_clock(); - } - - return time; -} - -/* Return the monotonic time elapsed in VM, i.e., - * the time between vm_start and vm_stop - */ -int64_t cpu_get_clock(void) -{ - int64_t ti; - unsigned start; - - do { - start =3D seqlock_read_begin(&timers_state.vm_clock_seqlock); - ti =3D cpu_get_clock_locked(); - } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); - - return ti; -} - -/* enable cpu_get_ticks() - * Caller must hold BQL which serves as mutex for vm_clock_seqlock. - */ -void cpu_enable_ticks(void) -{ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - if (!timers_state.cpu_ticks_enabled) { - timers_state.cpu_ticks_offset -=3D cpu_get_host_ticks(); - timers_state.cpu_clock_offset -=3D get_clock(); - timers_state.cpu_ticks_enabled =3D 1; - } - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); -} - -/* disable cpu_get_ticks() : the clock is stopped. You must not call - * cpu_get_ticks() after that. - * Caller must hold BQL which serves as mutex for vm_clock_seqlock. - */ -void cpu_disable_ticks(void) -{ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - if (timers_state.cpu_ticks_enabled) { - timers_state.cpu_ticks_offset +=3D cpu_get_host_ticks(); - timers_state.cpu_clock_offset =3D cpu_get_clock_locked(); - timers_state.cpu_ticks_enabled =3D 0; - } - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); -} - -/* Correlation between real and virtual time is always going to be - fairly approximate, so ignore small variation. - When the guest is idle real and virtual time will be aligned in - the IO wait loop. */ -#define ICOUNT_WOBBLE (NANOSECONDS_PER_SECOND / 10) - -static void icount_adjust(void) -{ - int64_t cur_time; - int64_t cur_icount; - int64_t delta; - - /* Protected by TimersState mutex. */ - static int64_t last_delta; - - /* If the VM is not running, then do nothing. */ - if (!runstate_is_running()) { - return; - } - - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - cur_time =3D REPLAY_CLOCK_LOCKED(REPLAY_CLOCK_VIRTUAL_RT, - cpu_get_clock_locked()); - cur_icount =3D cpu_get_icount_locked(); - - delta =3D cur_icount - cur_time; - /* FIXME: This is a very crude algorithm, somewhat prone to oscillatio= n. */ - if (delta > 0 - && last_delta + ICOUNT_WOBBLE < delta * 2 - && timers_state.icount_time_shift > 0) { - /* The guest is getting too far ahead. Slow time down. */ - atomic_set(&timers_state.icount_time_shift, - timers_state.icount_time_shift - 1); - } - if (delta < 0 - && last_delta - ICOUNT_WOBBLE > delta * 2 - && timers_state.icount_time_shift < MAX_ICOUNT_SHIFT) { - /* The guest is getting too far behind. Speed time up. */ - atomic_set(&timers_state.icount_time_shift, - timers_state.icount_time_shift + 1); - } - last_delta =3D delta; - atomic_set_i64(&timers_state.qemu_icount_bias, - cur_icount - (timers_state.qemu_icount - << timers_state.icount_time_shift)); - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); -} - -static void icount_adjust_rt(void *opaque) -{ - timer_mod(timers_state.icount_rt_timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000); - icount_adjust(); -} - -static void icount_adjust_vm(void *opaque) -{ - timer_mod(timers_state.icount_vm_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - NANOSECONDS_PER_SECOND / 10); - icount_adjust(); -} - -static int64_t qemu_icount_round(int64_t count) -{ - int shift =3D atomic_read(&timers_state.icount_time_shift); - return (count + (1 << shift) - 1) >> shift; -} - -static void icount_warp_rt(void) -{ - unsigned seq; - int64_t warp_start; - - /* The icount_warp_timer is rescheduled soon after vm_clock_warp_start - * changes from -1 to another value, so the race here is okay. - */ - do { - seq =3D seqlock_read_begin(&timers_state.vm_clock_seqlock); - warp_start =3D timers_state.vm_clock_warp_start; - } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, seq)); - - if (warp_start =3D=3D -1) { - return; - } - - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - if (runstate_is_running()) { - int64_t clock =3D REPLAY_CLOCK_LOCKED(REPLAY_CLOCK_VIRTUAL_RT, - cpu_get_clock_locked()); - int64_t warp_delta; - - warp_delta =3D clock - timers_state.vm_clock_warp_start; - if (use_icount =3D=3D 2) { - /* - * In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too - * far ahead of real time. - */ - int64_t cur_icount =3D cpu_get_icount_locked(); - int64_t delta =3D clock - cur_icount; - warp_delta =3D MIN(warp_delta, delta); - } - atomic_set_i64(&timers_state.qemu_icount_bias, - timers_state.qemu_icount_bias + warp_delta); - } - timers_state.vm_clock_warp_start =3D -1; - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - - if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) { - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - } -} - -static void icount_timer_cb(void *opaque) -{ - /* No need for a checkpoint because the timer already synchronizes - * with CHECKPOINT_CLOCK_VIRTUAL_RT. - */ - icount_warp_rt(); -} - -void qtest_clock_warp(int64_t dest) -{ - int64_t clock =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - AioContext *aio_context; - assert(qtest_enabled()); - aio_context =3D qemu_get_aio_context(); - while (clock < dest) { - int64_t deadline =3D qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, - QEMU_TIMER_ATTR_ALL); - int64_t warp =3D qemu_soonest_timeout(dest - clock, deadline); - - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - atomic_set_i64(&timers_state.qemu_icount_bias, - timers_state.qemu_icount_bias + warp); - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - - qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL); - timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]); - clock =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - } - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); -} - -void qemu_start_warp_timer(void) -{ - int64_t clock; - int64_t deadline; - - if (!use_icount) { - return; - } - - /* Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers - * do not fire, so computing the deadline does not make sense. - */ - if (!runstate_is_running()) { - return; - } - - if (replay_mode !=3D REPLAY_MODE_PLAY) { - if (!all_cpu_threads_idle()) { - return; - } - - if (qtest_enabled()) { - /* When testing, qtest commands advance icount. */ - return; - } - - replay_checkpoint(CHECKPOINT_CLOCK_WARP_START); - } else { - /* warp clock deterministically in record/replay mode */ - if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_START)) { - /* vCPU is sleeping and warp can't be started. - It is probably a race condition: notification sent - to vCPU was processed in advance and vCPU went to sleep. - Therefore we have to wake it up for doing someting. */ - if (replay_has_checkpoint()) { - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - } - return; - } - } - - /* We want to use the earliest deadline from ALL vm_clocks */ - clock =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); - deadline =3D qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, - ~QEMU_TIMER_ATTR_EXTERNAL); - if (deadline < 0) { - static bool notified; - if (!icount_sleep && !notified) { - warn_report("icount sleep disabled and no active timers"); - notified =3D true; - } - return; - } - - if (deadline > 0) { - /* - * Ensure QEMU_CLOCK_VIRTUAL proceeds even when the virtual CPU go= es to - * sleep. Otherwise, the CPU might be waiting for a future timer - * interrupt to wake it up, but the interrupt never comes because - * the vCPU isn't running any insns and thus doesn't advance the - * QEMU_CLOCK_VIRTUAL. - */ - if (!icount_sleep) { - /* - * We never let VCPUs sleep in no sleep icount mode. - * If there is a pending QEMU_CLOCK_VIRTUAL timer we just adva= nce - * to the next QEMU_CLOCK_VIRTUAL event and notify it. - * It is useful when we want a deterministic execution time, - * isolated from host latencies. - */ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - atomic_set_i64(&timers_state.qemu_icount_bias, - timers_state.qemu_icount_bias + deadline); - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - } else { - /* - * We do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL after = some - * "real" time, (related to the time left until the next event= ) has - * passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this. - * This avoids that the warps are visible externally; for exam= ple, - * you will not be sending network packets continuously instea= d of - * every 100ms. - */ - seqlock_write_lock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - if (timers_state.vm_clock_warp_start =3D=3D -1 - || timers_state.vm_clock_warp_start > clock) { - timers_state.vm_clock_warp_start =3D clock; - } - seqlock_write_unlock(&timers_state.vm_clock_seqlock, - &timers_state.vm_clock_lock); - timer_mod_anticipate(timers_state.icount_warp_timer, - clock + deadline); - } - } else if (deadline =3D=3D 0) { - qemu_clock_notify(QEMU_CLOCK_VIRTUAL); - } -} - -static void qemu_account_warp_timer(void) -{ - if (!use_icount || !icount_sleep) { - return; - } - - /* Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers - * do not fire, so computing the deadline does not make sense. - */ - if (!runstate_is_running()) { - return; - } - - /* warp clock deterministically in record/replay mode */ - if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_ACCOUNT)) { - return; - } - - timer_del(timers_state.icount_warp_timer); - icount_warp_rt(); -} - -static bool icount_state_needed(void *opaque) -{ - return use_icount; -} - -static bool warp_timer_state_needed(void *opaque) -{ - TimersState *s =3D opaque; - return s->icount_warp_timer !=3D NULL; -} - -static bool adjust_timers_state_needed(void *opaque) -{ - TimersState *s =3D opaque; - return s->icount_rt_timer !=3D NULL; -} - -static bool shift_state_needed(void *opaque) -{ - return use_icount =3D=3D 2; -} - -/* - * Subsection for warp timer migration is optional, because may not be cre= ated - */ -static const VMStateDescription icount_vmstate_warp_timer =3D { - .name =3D "timer/icount/warp_timer", - .version_id =3D 1, - .minimum_version_id =3D 1, - .needed =3D warp_timer_state_needed, - .fields =3D (VMStateField[]) { - VMSTATE_INT64(vm_clock_warp_start, TimersState), - VMSTATE_TIMER_PTR(icount_warp_timer, TimersState), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription icount_vmstate_adjust_timers =3D { - .name =3D "timer/icount/timers", - .version_id =3D 1, - .minimum_version_id =3D 1, - .needed =3D adjust_timers_state_needed, - .fields =3D (VMStateField[]) { - VMSTATE_TIMER_PTR(icount_rt_timer, TimersState), - VMSTATE_TIMER_PTR(icount_vm_timer, TimersState), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription icount_vmstate_shift =3D { - .name =3D "timer/icount/shift", - .version_id =3D 1, - .minimum_version_id =3D 1, - .needed =3D shift_state_needed, - .fields =3D (VMStateField[]) { - VMSTATE_INT16(icount_time_shift, TimersState), - VMSTATE_END_OF_LIST() - } -}; - -/* - * This is a subsection for icount migration. - */ -static const VMStateDescription icount_vmstate_timers =3D { - .name =3D "timer/icount", - .version_id =3D 1, - .minimum_version_id =3D 1, - .needed =3D icount_state_needed, - .fields =3D (VMStateField[]) { - VMSTATE_INT64(qemu_icount_bias, TimersState), - VMSTATE_INT64(qemu_icount, TimersState), - VMSTATE_END_OF_LIST() - }, - .subsections =3D (const VMStateDescription*[]) { - &icount_vmstate_warp_timer, - &icount_vmstate_adjust_timers, - &icount_vmstate_shift, - NULL - } -}; - -static const VMStateDescription vmstate_timers =3D { - .name =3D "timer", - .version_id =3D 2, - .minimum_version_id =3D 1, - .fields =3D (VMStateField[]) { - VMSTATE_INT64(cpu_ticks_offset, TimersState), - VMSTATE_UNUSED(8), - VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2), - VMSTATE_END_OF_LIST() - }, - .subsections =3D (const VMStateDescription*[]) { - &icount_vmstate_timers, - NULL - } -}; - -void cpu_ticks_init(void) -{ - seqlock_init(&timers_state.vm_clock_seqlock); - qemu_spin_init(&timers_state.vm_clock_lock); - vmstate_register(NULL, 0, &vmstate_timers, &timers_state); - cpu_throttle_init(); -} - -void configure_icount(QemuOpts *opts, Error **errp) -{ - const char *option =3D qemu_opt_get(opts, "shift"); - bool sleep =3D qemu_opt_get_bool(opts, "sleep", true); - bool align =3D qemu_opt_get_bool(opts, "align", false); - long time_shift =3D -1; - - if (!option) { - if (qemu_opt_get(opts, "align") !=3D NULL) { - error_setg(errp, "Please specify shift option when using align= "); - } - return; - } - - if (align && !sleep) { - error_setg(errp, "align=3Don and sleep=3Doff are incompatible"); - return; - } - - if (strcmp(option, "auto") !=3D 0) { - if (qemu_strtol(option, NULL, 0, &time_shift) < 0 - || time_shift < 0 || time_shift > MAX_ICOUNT_SHIFT) { - error_setg(errp, "icount: Invalid shift value"); - return; - } - } else if (icount_align_option) { - error_setg(errp, "shift=3Dauto and align=3Don are incompatible"); - return; - } else if (!icount_sleep) { - error_setg(errp, "shift=3Dauto and sleep=3Doff are incompatible"); - return; - } - - icount_sleep =3D sleep; - if (icount_sleep) { - timers_state.icount_warp_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL= _RT, - icount_timer_cb, NULL); - } - - icount_align_option =3D align; - - if (time_shift >=3D 0) { - timers_state.icount_time_shift =3D time_shift; - use_icount =3D 1; - return; - } - - use_icount =3D 2; - - /* 125MIPS seems a reasonable initial guess at the guest speed. - It will be corrected fairly quickly anyway. */ - timers_state.icount_time_shift =3D 3; - - /* Have both realtime and virtual time triggers for speed adjustment. - The realtime trigger catches emulated time passing too slowly, - the virtual time trigger catches emulated time passing too fast. - Realtime triggers occur even when idle, so use them less frequently - than VM triggers. */ - timers_state.vm_clock_warp_start =3D -1; - timers_state.icount_rt_timer =3D timer_new_ms(QEMU_CLOCK_VIRTUAL_RT, - icount_adjust_rt, NULL); - timer_mod(timers_state.icount_rt_timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000); - timers_state.icount_vm_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, - icount_adjust_vm, NULL); - timer_mod(timers_state.icount_vm_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - NANOSECONDS_PER_SECOND / 10); -} - /***********************************************************/ /* TCG vCPU kick timer * @@ -854,35 +171,6 @@ static void qemu_cpu_kick_rr_cpus(void) }; } =20 -static void do_nothing(CPUState *cpu, run_on_cpu_data unused) -{ -} - -void qemu_timer_notify_cb(void *opaque, QEMUClockType type) -{ - if (!use_icount || type !=3D QEMU_CLOCK_VIRTUAL) { - qemu_notify_event(); - return; - } - - if (qemu_in_vcpu_thread()) { - /* A CPU is currently running; kick it back out to the - * tcg_cpu_exec() loop so it will recalculate its - * icount deadline immediately. - */ - qemu_cpu_kick(current_cpu); - } else if (first_cpu) { - /* qemu_cpu_kick is not enough to kick a halted CPU out of - * qemu_tcg_wait_io_event. async_run_on_cpu, instead, - * causes cpu_thread_is_idle to return false. This way, - * handle_icount_deadline can run. - * If we have no CPUs at all for some reason, we don't - * need to do anything. - */ - async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL); - } -} - static void kick_tcg_thread(void *opaque) { timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); @@ -1272,7 +560,7 @@ static int64_t tcg_get_icount_limit(void) deadline =3D INT32_MAX; } =20 - return qemu_icount_round(deadline); + return icount_round(deadline); } else { return replay_get_instructions(); } @@ -1288,7 +576,7 @@ static void notify_aio_contexts(void) static void handle_icount_deadline(void) { assert(qemu_in_vcpu_thread()); - if (use_icount) { + if (icount_enabled()) { int64_t deadline =3D qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, QEMU_TIMER_ATTR_ALL); =20 @@ -1300,7 +588,7 @@ static void handle_icount_deadline(void) =20 static void prepare_icount_for_run(CPUState *cpu) { - if (use_icount) { + if (icount_enabled()) { int insns_left; =20 /* These should always be cleared by process_icount_data after @@ -1325,9 +613,9 @@ static void prepare_icount_for_run(CPUState *cpu) =20 static void process_icount_data(CPUState *cpu) { - if (use_icount) { + if (icount_enabled()) { /* Account for executed instructions */ - cpu_update_icount(cpu); + icount_update(cpu); =20 /* Reset the counters */ cpu_neg(cpu)->icount_decr.u16.low =3D 0; @@ -1428,7 +716,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg) replay_mutex_lock(); qemu_mutex_lock_iothread(); /* Account partial waits to QEMU_CLOCK_VIRTUAL. */ - qemu_account_warp_timer(); + icount_account_warp_timer(); =20 /* Run the timers here. This is much more efficient than * waking up the I/O thread and waiting for completion. @@ -1486,7 +774,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg) atomic_mb_set(&cpu->exit_request, 0); } =20 - if (use_icount && all_cpu_threads_idle()) { + 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. @@ -1639,7 +927,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) CPUState *cpu =3D arg; =20 assert(tcg_enabled()); - g_assert(!use_icount); + g_assert(!icount_enabled()); =20 rcu_register_thread(); tcg_register_thread(); @@ -2218,21 +1506,3 @@ void qmp_inject_nmi(Error **errp) nmi_monitor_handle(monitor_get_cpu_index(), errp); } =20 -void dump_drift_info(void) -{ - if (!use_icount) { - return; - } - - qemu_printf("Host - Guest clock %"PRIi64" ms\n", - (cpu_get_clock() - cpu_get_icount())/SCALE_MS); - if (icount_align_option) { - qemu_printf("Max guest delay %"PRIi64" ms\n", - -max_delay / SCALE_MS); - qemu_printf("Max guest advance %"PRIi64" ms\n", - max_advance / SCALE_MS); - } else { - qemu_printf("Max guest delay NA\n"); - qemu_printf("Max guest advance NA\n"); - } -} diff --git a/softmmu/icount.c b/softmmu/icount.c new file mode 100644 index 0000000000..d4fe48c1f2 --- /dev/null +++ b/softmmu/icount.c @@ -0,0 +1,497 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * 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 "qemu/cutils.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "exec/exec-all.h" +#include "sysemu/cpus.h" +#include "sysemu/qtest.h" +#include "qemu/main-loop.h" +#include "qemu/option.h" +#include "qemu/seqlock.h" +#include "sysemu/replay.h" +#include "sysemu/runstate.h" +#include "hw/core/cpu.h" +#include "sysemu/cpu-timers.h" +#include "sysemu/cpu-throttle.h" +#include "timers-state.h" + +/* + * ICOUNT: Instruction Counter + * + * this module is split off from cpu-timers because the icount part + * is TCG-specific, and does not need to be built for other accels. + */ +static bool icount_sleep =3D true; +/* Arbitrarily pick 1MIPS as the minimum allowable speed. */ +#define MAX_ICOUNT_SHIFT 10 + +/* + * 0 =3D Do not count executed instructions. + * 1 =3D Fixed conversion of insn to ns via "shift" option + * 2 =3D Runtime adaptive algorithm to compute shift + */ +static int use_icount; + +int icount_enabled(void) +{ + return use_icount; +} + +static void icount_enable_precise(void) +{ + use_icount =3D 1; +} + +static void icount_enable_adaptive(void) +{ + use_icount =3D 2; +} + +/* + * The current number of executed instructions is based on what we + * originally budgeted minus the current state of the decrementing + * icount counters in extra/u16.low. + */ +static int64_t icount_get_executed(CPUState *cpu) +{ + return (cpu->icount_budget - + (cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra)); +} + +/* + * Update the global shared timer_state.qemu_icount to take into + * account executed instructions. This is done by the TCG vCPU + * thread so the main-loop can see time has moved forward. + */ +static void icount_update_locked(CPUState *cpu) +{ + int64_t executed =3D icount_get_executed(cpu); + cpu->icount_budget -=3D executed; + + atomic_set_i64(&timers_state.qemu_icount, + timers_state.qemu_icount + executed); +} + +/* + * Update the global shared timer_state.qemu_icount to take into + * account executed instructions. This is done by the TCG vCPU + * thread so the main-loop can see time has moved forward. + */ +void icount_update(CPUState *cpu) +{ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + icount_update_locked(cpu); + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); +} + +static int64_t icount_get_raw_locked(void) +{ + CPUState *cpu =3D current_cpu; + + if (cpu && cpu->running) { + if (!cpu->can_do_io) { + error_report("Bad icount read"); + exit(1); + } + /* Take into account what has run */ + icount_update_locked(cpu); + } + /* The read is protected by the seqlock, but needs atomic64 to avoid U= B */ + return atomic_read_i64(&timers_state.qemu_icount); +} + +static int64_t icount_get_locked(void) +{ + int64_t icount =3D icount_get_raw_locked(); + return atomic_read_i64(&timers_state.qemu_icount_bias) + + icount_to_ns(icount); +} + +int64_t icount_get_raw(void) +{ + int64_t icount; + unsigned start; + + do { + start =3D seqlock_read_begin(&timers_state.vm_clock_seqlock); + icount =3D icount_get_raw_locked(); + } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); + + return icount; +} + +/* Return the virtual CPU time, based on the instruction counter. */ +int64_t icount_get(void) +{ + int64_t icount; + unsigned start; + + do { + start =3D seqlock_read_begin(&timers_state.vm_clock_seqlock); + icount =3D icount_get_locked(); + } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); + + return icount; +} + +int64_t icount_to_ns(int64_t icount) +{ + return icount << atomic_read(&timers_state.icount_time_shift); +} + +/* + * Correlation between real and virtual time is always going to be + * fairly approximate, so ignore small variation. + * When the guest is idle real and virtual time will be aligned in + * the IO wait loop. + */ +#define ICOUNT_WOBBLE (NANOSECONDS_PER_SECOND / 10) + +static void icount_adjust(void) +{ + int64_t cur_time; + int64_t cur_icount; + int64_t delta; + + /* Protected by TimersState mutex. */ + static int64_t last_delta; + + /* If the VM is not running, then do nothing. */ + if (!runstate_is_running()) { + return; + } + + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + cur_time =3D REPLAY_CLOCK_LOCKED(REPLAY_CLOCK_VIRTUAL_RT, + cpu_get_clock_locked()); + cur_icount =3D icount_get_locked(); + + delta =3D cur_icount - cur_time; + /* FIXME: This is a very crude algorithm, somewhat prone to oscillatio= n. */ + if (delta > 0 + && last_delta + ICOUNT_WOBBLE < delta * 2 + && timers_state.icount_time_shift > 0) { + /* The guest is getting too far ahead. Slow time down. */ + atomic_set(&timers_state.icount_time_shift, + timers_state.icount_time_shift - 1); + } + if (delta < 0 + && last_delta - ICOUNT_WOBBLE > delta * 2 + && timers_state.icount_time_shift < MAX_ICOUNT_SHIFT) { + /* The guest is getting too far behind. Speed time up. */ + atomic_set(&timers_state.icount_time_shift, + timers_state.icount_time_shift + 1); + } + last_delta =3D delta; + atomic_set_i64(&timers_state.qemu_icount_bias, + cur_icount - (timers_state.qemu_icount + << timers_state.icount_time_shift)); + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); +} + +static void icount_adjust_rt(void *opaque) +{ + timer_mod(timers_state.icount_rt_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000); + icount_adjust(); +} + +static void icount_adjust_vm(void *opaque) +{ + timer_mod(timers_state.icount_vm_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + NANOSECONDS_PER_SECOND / 10); + icount_adjust(); +} + +int64_t icount_round(int64_t count) +{ + int shift =3D atomic_read(&timers_state.icount_time_shift); + return (count + (1 << shift) - 1) >> shift; +} + +static void icount_warp_rt(void) +{ + unsigned seq; + int64_t warp_start; + + /* + * The icount_warp_timer is rescheduled soon after vm_clock_warp_start + * changes from -1 to another value, so the race here is okay. + */ + do { + seq =3D seqlock_read_begin(&timers_state.vm_clock_seqlock); + warp_start =3D timers_state.vm_clock_warp_start; + } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, seq)); + + if (warp_start =3D=3D -1) { + return; + } + + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + if (runstate_is_running()) { + int64_t clock =3D REPLAY_CLOCK_LOCKED(REPLAY_CLOCK_VIRTUAL_RT, + cpu_get_clock_locked()); + int64_t warp_delta; + + warp_delta =3D clock - timers_state.vm_clock_warp_start; + if (icount_enabled() =3D=3D 2) { + /* + * In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too + * far ahead of real time. + */ + int64_t cur_icount =3D icount_get_locked(); + int64_t delta =3D clock - cur_icount; + warp_delta =3D MIN(warp_delta, delta); + } + atomic_set_i64(&timers_state.qemu_icount_bias, + timers_state.qemu_icount_bias + warp_delta); + } + timers_state.vm_clock_warp_start =3D -1; + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + + if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) { + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + } +} + +static void icount_timer_cb(void *opaque) +{ + /* + * No need for a checkpoint because the timer already synchronizes + * with CHECKPOINT_CLOCK_VIRTUAL_RT. + */ + icount_warp_rt(); +} + +void icount_start_warp_timer(void) +{ + int64_t clock; + int64_t deadline; + + assert(icount_enabled()); + + /* + * Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers + * do not fire, so computing the deadline does not make sense. + */ + if (!runstate_is_running()) { + return; + } + + if (replay_mode !=3D REPLAY_MODE_PLAY) { + if (!all_cpu_threads_idle()) { + return; + } + + if (qtest_enabled()) { + /* When testing, qtest commands advance icount. */ + return; + } + + replay_checkpoint(CHECKPOINT_CLOCK_WARP_START); + } else { + /* warp clock deterministically in record/replay mode */ + if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_START)) { + /* + * vCPU is sleeping and warp can't be started. + * It is probably a race condition: notification sent + * to vCPU was processed in advance and vCPU went to sleep. + * Therefore we have to wake it up for doing someting. + */ + if (replay_has_checkpoint()) { + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + } + return; + } + } + + /* We want to use the earliest deadline from ALL vm_clocks */ + clock =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); + deadline =3D qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + ~QEMU_TIMER_ATTR_EXTERNAL); + if (deadline < 0) { + static bool notified; + if (!icount_sleep && !notified) { + warn_report("icount sleep disabled and no active timers"); + notified =3D true; + } + return; + } + + if (deadline > 0) { + /* + * Ensure QEMU_CLOCK_VIRTUAL proceeds even when the virtual CPU go= es to + * sleep. Otherwise, the CPU might be waiting for a future timer + * interrupt to wake it up, but the interrupt never comes because + * the vCPU isn't running any insns and thus doesn't advance the + * QEMU_CLOCK_VIRTUAL. + */ + if (!icount_sleep) { + /* + * We never let VCPUs sleep in no sleep icount mode. + * If there is a pending QEMU_CLOCK_VIRTUAL timer we just adva= nce + * to the next QEMU_CLOCK_VIRTUAL event and notify it. + * It is useful when we want a deterministic execution time, + * isolated from host latencies. + */ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + atomic_set_i64(&timers_state.qemu_icount_bias, + timers_state.qemu_icount_bias + deadline); + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + } else { + /* + * We do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL after = some + * "real" time, (related to the time left until the next event= ) has + * passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this. + * This avoids that the warps are visible externally; for exam= ple, + * you will not be sending network packets continuously instea= d of + * every 100ms. + */ + seqlock_write_lock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + if (timers_state.vm_clock_warp_start =3D=3D -1 + || timers_state.vm_clock_warp_start > clock) { + timers_state.vm_clock_warp_start =3D clock; + } + seqlock_write_unlock(&timers_state.vm_clock_seqlock, + &timers_state.vm_clock_lock); + timer_mod_anticipate(timers_state.icount_warp_timer, + clock + deadline); + } + } else if (deadline =3D=3D 0) { + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + } +} + +void icount_account_warp_timer(void) +{ + if (!use_icount || !icount_sleep) { + return; + } + + /* + * Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers + * do not fire, so computing the deadline does not make sense. + */ + if (!runstate_is_running()) { + return; + } + + /* warp clock deterministically in record/replay mode */ + if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_ACCOUNT)) { + return; + } + + timer_del(timers_state.icount_warp_timer); + icount_warp_rt(); +} + +void icount_configure(QemuOpts *opts, Error **errp) +{ + const char *option =3D qemu_opt_get(opts, "shift"); + bool sleep =3D qemu_opt_get_bool(opts, "sleep", true); + bool align =3D qemu_opt_get_bool(opts, "align", false); + long time_shift =3D -1; + + if (!option) { + if (qemu_opt_get(opts, "align") !=3D NULL) { + error_setg(errp, "Please specify shift option when using align= "); + } + return; + } + + if (align && !sleep) { + error_setg(errp, "align=3Don and sleep=3Doff are incompatible"); + return; + } + + if (strcmp(option, "auto") !=3D 0) { + if (qemu_strtol(option, NULL, 0, &time_shift) < 0 + || time_shift < 0 || time_shift > MAX_ICOUNT_SHIFT) { + error_setg(errp, "icount: Invalid shift value"); + return; + } + } else if (icount_align_option) { + error_setg(errp, "shift=3Dauto and align=3Don are incompatible"); + return; + } else if (!icount_sleep) { + error_setg(errp, "shift=3Dauto and sleep=3Doff are incompatible"); + return; + } + + icount_sleep =3D sleep; + if (icount_sleep) { + timers_state.icount_warp_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL= _RT, + icount_timer_cb, NULL); + } + + icount_align_option =3D align; + + if (time_shift >=3D 0) { + timers_state.icount_time_shift =3D time_shift; + icount_enable_precise(); + return; + } + + icount_enable_adaptive(); + + /* + * 125MIPS seems a reasonable initial guess at the guest speed. + * It will be corrected fairly quickly anyway. + */ + timers_state.icount_time_shift =3D 3; + + /* + * Have both realtime and virtual time triggers for speed adjustment. + * The realtime trigger catches emulated time passing too slowly, + * the virtual time trigger catches emulated time passing too fast. + * Realtime triggers occur even when idle, so use them less frequently + * than VM triggers. + */ + timers_state.vm_clock_warp_start =3D -1; + timers_state.icount_rt_timer =3D timer_new_ms(QEMU_CLOCK_VIRTUAL_RT, + icount_adjust_rt, NULL); + timer_mod(timers_state.icount_rt_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000); + timers_state.icount_vm_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + icount_adjust_vm, NULL); + timer_mod(timers_state.icount_vm_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + NANOSECONDS_PER_SECOND / 10); +} diff --git a/softmmu/qtest.c b/softmmu/qtest.c index 5672b75c35..737779ea7f 100644 --- a/softmmu/qtest.c +++ b/softmmu/qtest.c @@ -21,7 +21,7 @@ #include "exec/memory.h" #include "hw/irq.h" #include "sysemu/accel.h" -#include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "qemu/config-file.h" #include "qemu/option.h" #include "qemu/error-report.h" @@ -273,6 +273,38 @@ static void qtest_irq_handler(void *opaque, int n, int= level) } } =20 +static int64_t qtest_clock_counter; + +int64_t qtest_get_virtual_clock(void) +{ + return atomic_read_i64(&qtest_clock_counter); +} + +static void qtest_set_virtual_clock(int64_t count) +{ + atomic_set_i64(&qtest_clock_counter, count); +} + +static void qtest_clock_warp(int64_t dest) +{ + int64_t clock =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + AioContext *aio_context; + assert(qtest_enabled()); + aio_context =3D qemu_get_aio_context(); + while (clock < dest) { + int64_t deadline =3D qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); + int64_t warp =3D qemu_soonest_timeout(dest - clock, deadline); + + qtest_set_virtual_clock(qtest_get_virtual_clock() + warp); + + qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL); + timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]); + clock =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + } + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); +} + static void qtest_process_command(CharBackend *chr, gchar **words) { const gchar *command; diff --git a/softmmu/timers-state.h b/softmmu/timers-state.h new file mode 100644 index 0000000000..db4e60f18f --- /dev/null +++ b/softmmu/timers-state.h @@ -0,0 +1,69 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * 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. + */ + +#ifndef TIMERS_STATE_H +#define TIMERS_STATE_H + +/* timers state, for sharing between icount and cpu-timers */ + +typedef struct TimersState { + /* Protected by BQL. */ + int64_t cpu_ticks_prev; + int64_t cpu_ticks_offset; + + /* + * Protect fields that can be respectively read outside the + * BQL, and written from multiple threads. + */ + QemuSeqLock vm_clock_seqlock; + QemuSpin vm_clock_lock; + + int16_t cpu_ticks_enabled; + + /* Conversion factor from emulated instructions to virtual clock ticks= . */ + int16_t icount_time_shift; + + /* Compensate for varying guest execution speed. */ + int64_t qemu_icount_bias; + + int64_t vm_clock_warp_start; + int64_t cpu_clock_offset; + + /* Only written by TCG thread */ + int64_t qemu_icount; + + /* for adjusting icount */ + QEMUTimer *icount_rt_timer; + QEMUTimer *icount_vm_timer; + QEMUTimer *icount_warp_timer; +} TimersState; + +extern TimersState timers_state; + +/* + * icount needs this internal from cpu-timers when adjusting the icount sh= ift. + */ +int64_t cpu_get_clock_locked(void); + +#endif /* TIMERS_STATE_H */ diff --git a/softmmu/vl.c b/softmmu/vl.c index 4eb9d1f7fd..8e77df7bea 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -74,6 +74,7 @@ #include "hw/audio/soundhw.h" #include "audio/audio.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "migration/colo.h" #include "migration/postcopy-ram.h" #include "sysemu/kvm.h" @@ -2692,7 +2693,7 @@ static void user_register_global_props(void) =20 static int do_configure_icount(void *opaque, QemuOpts *opts, Error **errp) { - configure_icount(opts, errp); + icount_configure(opts, errp); return 0; } =20 @@ -2802,7 +2803,7 @@ static void configure_accelerators(const char *progna= me) error_report("falling back to %s", ac->name); } =20 - if (use_icount && !(tcg_enabled() || qtest_enabled())) { + if (icount_enabled() && !tcg_enabled()) { error_report("-icount is not allowed with hardware virtualization"= ); exit(1); } @@ -4237,7 +4238,11 @@ void qemu_init(int argc, char **argv, char **envp) semihosting_arg_fallback(kernel_filename, kernel_cmdline); } =20 - cpu_ticks_init(); + /* initialize cpu timers and VCPU throttle modules */ + cpu_timers_init(); + + /* spice needs the timers to be initialized by this point */ + qemu_spice_init(); =20 if (default_net) { QemuOptsList *net =3D qemu_find_opts("net"); diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index d42046afe4..e97ad407fa 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -1,7 +1,8 @@ stub-obj-y +=3D blk-commit-all.o stub-obj-y +=3D cmos.o stub-obj-y +=3D cpu-get-clock.o -stub-obj-y +=3D cpu-get-icount.o +stub-obj-y +=3D qemu-timer-notify-cb.o +stub-obj-y +=3D icount.o stub-obj-y +=3D dump.o stub-obj-y +=3D error-printf.o stub-obj-y +=3D fdset.o @@ -37,7 +38,6 @@ stub-obj-y +=3D arch_type.o stub-obj-y +=3D bdrv-next-monitor-owned.o stub-obj-y +=3D blockdev-close-all-bdrv-states.o stub-obj-y +=3D change-state-handler.o -stub-obj-y +=3D clock-warp.o stub-obj-y +=3D fd-register.o stub-obj-y +=3D fw_cfg.o stub-obj-y +=3D get-vm-name.o diff --git a/stubs/clock-warp.c b/stubs/clock-warp.c deleted file mode 100644 index b53e5dd94c..0000000000 --- a/stubs/clock-warp.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "qemu/osdep.h" -#include "qemu/timer.h" - -void qemu_start_warp_timer(void) -{ -} - diff --git a/stubs/cpu-get-clock.c b/stubs/cpu-get-clock.c index 5a92810e87..9e92404816 100644 --- a/stubs/cpu-get-clock.c +++ b/stubs/cpu-get-clock.c @@ -1,5 +1,6 @@ #include "qemu/osdep.h" -#include "qemu/timer.h" +#include "sysemu/cpu-timers.h" +#include "qemu/main-loop.h" =20 int64_t cpu_get_clock(void) { diff --git a/stubs/cpu-get-icount.c b/stubs/cpu-get-icount.c deleted file mode 100644 index b35f844638..0000000000 --- a/stubs/cpu-get-icount.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "qemu/osdep.h" -#include "qemu/timer.h" -#include "sysemu/cpus.h" -#include "qemu/main-loop.h" - -int use_icount; - -int64_t cpu_get_icount(void) -{ - abort(); -} - -int64_t cpu_get_icount_raw(void) -{ - abort(); -} - -void qemu_timer_notify_cb(void *opaque, QEMUClockType type) -{ - qemu_notify_event(); -} diff --git a/stubs/icount.c b/stubs/icount.c new file mode 100644 index 0000000000..3b35001051 --- /dev/null +++ b/stubs/icount.c @@ -0,0 +1,52 @@ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "sysemu/cpu-timers.h" + +/* icount - Instruction Counter API */ + +/* + * Return the icount enablement state: + * + * 0 =3D Disabled - Do not count executed instructions. + */ +int icount_enabled(void) +{ + return 0; +} +void icount_update(CPUState *cpu) +{ + abort(); +} +void icount_configure(QemuOpts *opts, Error **errp) +{ + /* signal error */ + error_setg(errp, "cannot configure icount, TCG support not available"); +} +int64_t icount_get_raw(void) +{ + abort(); + return 0; +} +int64_t icount_get(void) +{ + abort(); + return 0; +} +int64_t icount_to_ns(int64_t icount) +{ + abort(); + return 0; +} +int64_t icount_round(int64_t count) +{ + abort(); + return 0; +} +void icount_start_warp_timer(void) +{ + abort(); +} +void icount_account_warp_timer(void) +{ + abort(); +} diff --git a/stubs/qemu-timer-notify-cb.c b/stubs/qemu-timer-notify-cb.c new file mode 100644 index 0000000000..845e46f8e0 --- /dev/null +++ b/stubs/qemu-timer-notify-cb.c @@ -0,0 +1,8 @@ +#include "qemu/osdep.h" +#include "sysemu/cpu-timers.h" +#include "qemu/main-loop.h" + +void qemu_timer_notify_cb(void *opaque, QEMUClockType type) +{ + qemu_notify_event(); +} diff --git a/stubs/qtest.c b/stubs/qtest.c index 891eb954fb..4666a49d7d 100644 --- a/stubs/qtest.c +++ b/stubs/qtest.c @@ -18,3 +18,8 @@ bool qtest_driver(void) { return false; } + +int64_t qtest_get_virtual_clock(void) +{ + return 0; +} diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 8870284f57..36be602179 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "disas/disas.h" #include "qemu/host-utils.h" #include "exec/exec-all.h" @@ -1329,7 +1330,7 @@ static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv= va, int regno) case 249: /* VMTIME */ helper =3D gen_helper_get_vmtime; do_helper: - if (use_icount) { + if (icount_enabled()) { gen_io_start(); helper(va); return DISAS_PC_STALE; diff --git a/target/arm/helper.c b/target/arm/helper.c index 455c92b891..b04f4f9127 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -24,6 +24,7 @@ #include "hw/irq.h" #include "hw/semihosting/semihost.h" #include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "sysemu/kvm.h" #include "sysemu/tcg.h" #include "qemu/range.h" @@ -1206,17 +1207,17 @@ static int64_t cycles_ns_per(uint64_t cycles) =20 static bool instructions_supported(CPUARMState *env) { - return use_icount =3D=3D 1 /* Precise instruction counting */; + return icount_enabled() =3D=3D 1; /* Precise instruction counting */ } =20 static uint64_t instructions_get_count(CPUARMState *env) { - return (uint64_t)cpu_get_icount_raw(); + return (uint64_t)icount_get_raw(); } =20 static int64_t instructions_ns_per(uint64_t icount) { - return cpu_icount_to_ns((int64_t)icount); + return icount_to_ns((int64_t)icount); } #endif =20 diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 6a96a01b1c..ab2b230991 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -242,8 +242,8 @@ static int write_vstart(CPURISCVState *env, int csrno, = target_ulong val) static int read_instret(CPURISCVState *env, int csrno, target_ulong *val) { #if !defined(CONFIG_USER_ONLY) - if (use_icount) { - *val =3D cpu_get_icount(); + if (icount_enabled()) { + *val =3D icount_get(); } else { *val =3D cpu_get_host_ticks(); } @@ -257,8 +257,8 @@ static int read_instret(CPURISCVState *env, int csrno, = target_ulong *val) static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val) { #if !defined(CONFIG_USER_ONLY) - if (use_icount) { - *val =3D cpu_get_icount() >> 32; + if (icount_enabled()) { + *val =3D icount_get() >> 32; } else { *val =3D cpu_get_host_ticks() >> 32; } diff --git a/tests/ptimer-test-stubs.c b/tests/ptimer-test-stubs.c index ed393d9082..b4447a3e44 100644 --- a/tests/ptimer-test-stubs.c +++ b/tests/ptimer-test-stubs.c @@ -12,6 +12,7 @@ #include "qemu/main-loop.h" #include "sysemu/replay.h" #include "migration/vmstate.h" +#include "sysemu/cpu-timers.h" =20 #include "ptimer-test.h" =20 @@ -30,8 +31,10 @@ QEMUTimerListGroup main_loop_tlg; =20 int64_t ptimer_test_time_ns; =20 -/* Do not artificially limit period - see hw/core/ptimer.c. */ -int use_icount =3D 1; +int icount_enabled(void) +{ + return 0; +} bool qtest_allowed; =20 void timer_init_full(QEMUTimer *ts, diff --git a/tests/test-timed-average.c b/tests/test-timed-average.c index e2bcf5fe13..82c92500df 100644 --- a/tests/test-timed-average.c +++ b/tests/test-timed-average.c @@ -11,7 +11,7 @@ */ =20 #include "qemu/osdep.h" - +#include "sysemu/cpu-timers.h" #include "qemu/timed-average.h" =20 /* This is the clock for QEMU_CLOCK_VIRTUAL */ diff --git a/util/main-loop.c b/util/main-loop.c index f69f055013..744b42fc54 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -27,7 +27,7 @@ #include "qemu/cutils.h" #include "qemu/timer.h" #include "sysemu/qtest.h" -#include "sysemu/cpus.h" +#include "sysemu/cpu-timers.h" #include "sysemu/replay.h" #include "qemu/main-loop.h" #include "block/aio.h" @@ -517,9 +517,13 @@ void main_loop_wait(int nonblocking) mlpoll.state =3D ret < 0 ? MAIN_LOOP_POLL_ERR : MAIN_LOOP_POLL_OK; notifier_list_notify(&main_loop_poll_notifiers, &mlpoll); =20 - /* CPU thread can infinitely wait for event after - missing the warp */ - qemu_start_warp_timer(); + if (icount_enabled()) { + /* + * CPU thread can infinitely wait for event after + * missing the warp + */ + icount_start_warp_timer(); + } qemu_clock_run_all_timers(); } =20 diff --git a/util/qemu-timer.c b/util/qemu-timer.c index f62b4feecd..db51e68f25 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -26,8 +26,10 @@ #include "qemu/main-loop.h" #include "qemu/timer.h" #include "qemu/lockable.h" +#include "sysemu/cpu-timers.h" #include "sysemu/replay.h" #include "sysemu/cpus.h" +#include "sysemu/qtest.h" =20 #ifdef CONFIG_POSIX #include @@ -134,7 +136,7 @@ static void qemu_clock_init(QEMUClockType type, QEMUTim= erListNotifyCB *notify_cb =20 bool qemu_clock_use_for_deadline(QEMUClockType type) { - return !(use_icount && (type =3D=3D QEMU_CLOCK_VIRTUAL)); + return !(icount_enabled() && (type =3D=3D QEMU_CLOCK_VIRTUAL)); } =20 void qemu_clock_notify(QEMUClockType type) @@ -416,8 +418,8 @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_li= st, static void timerlist_rearm(QEMUTimerList *timer_list) { /* Interrupt execution to force deadline recalculation. */ - if (timer_list->clock->type =3D=3D QEMU_CLOCK_VIRTUAL) { - qemu_start_warp_timer(); + if (icount_enabled() && timer_list->clock->type =3D=3D QEMU_CLOCK_VIRT= UAL) { + icount_start_warp_timer(); } timerlist_notify(timer_list); } @@ -633,8 +635,10 @@ int64_t qemu_clock_get_ns(QEMUClockType type) return get_clock(); default: case QEMU_CLOCK_VIRTUAL: - if (use_icount) { - return cpu_get_icount(); + if (icount_enabled()) { + return icount_get(); + } else if (qtest_enabled()) { /* for qtest_clock_warp */ + return qtest_get_virtual_clock(); } else { return cpu_get_clock(); } --=20 2.16.4 From nobody Mon Jul 1 19:59:17 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=1597257260; cv=none; d=zohomail.com; s=zohoarc; b=PeK1IuJKZhLonfD0GwrXvCWc447llbyuPOyhljyzKr3kOSVh9w97GIzCOJq5h/7LDkRqCuAvKaGilVhiKANwdgDB8S3z6j9L5z+K92piggRKUihp7Vsgl0NQWl/KQuTbx5tN75vlvkGKsrmsjN2U+ndx3Im3JCUazJr1mAjL6KE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257260; 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=nESL2lwPYiPLmLGzO5C9nMQpzZArOezFKmB212u+3dw=; b=VefyY6plgwkrFvWEweIcKw/qZjXvhKYAkwibpA9Ogy8BJKDskDSrFIPhJwOuB4KlNkaibkw36WFpfg3N2AOzkAraNrC724+wzDz0MTTGz6q4k6+K9Ic/l6n1prQzr6LkZcWDBWXFF0pxH+jSaubiwVw6wGhfr6wG/2Wifqcmh/o= 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 1597257260632591.3434127725799; Wed, 12 Aug 2020 11:34:20 -0700 (PDT) Received: from localhost ([::1]:43038 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vZr-0001vZ-8e for importer@patchew.org; Wed, 12 Aug 2020 14:34:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46282) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYZ-0000G3-Nq for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:32:59 -0400 Received: from mx2.suse.de ([195.135.220.15]:40572) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYV-0002D2-HD for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:32:59 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 02522AE19; Wed, 12 Aug 2020 18:33:16 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 02/14] cpus: prepare new CpusAccel cpu accelerator interface Date: Wed, 12 Aug 2020 20:32:38 +0200 Message-Id: <20200812183250.9221-3-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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" The new interface starts unused, will start being used by the next patches. It provides methods for each accelerator to start a vcpu, kick a vcpu, synchronize state, get cpu virtual clock and elapsed ticks. In qemu_wait_io_event, make it clear that APC is used only for HAX on Windows. Signed-off-by: Claudio Fontana --- hw/core/cpu.c | 1 + hw/i386/x86.c | 2 +- include/sysemu/cpu-timers.h | 9 +- include/sysemu/cpus.h | 36 ++++++++ include/sysemu/hw_accel.h | 69 ++------------- softmmu/cpu-timers.c | 9 +- softmmu/cpus.c | 195 ++++++++++++++++++++++++++++++++-----= ---- stubs/Makefile.objs | 2 + stubs/cpu-synchronize-state.c | 15 ++++ stubs/cpus-get-virtual-clock.c | 8 ++ util/qemu-timer.c | 8 +- 11 files changed, 231 insertions(+), 123 deletions(-) create mode 100644 stubs/cpu-synchronize-state.c create mode 100644 stubs/cpus-get-virtual-clock.c diff --git a/hw/core/cpu.c b/hw/core/cpu.c index 594441a150..b389a312df 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/hw/i386/x86.c b/hw/i386/x86.c index 58cf2229d5..00c35bad7e 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -264,7 +264,7 @@ static long get_file_size(FILE *f) /* TSC handling */ uint64_t cpu_get_tsc(CPUX86State *env) { - return cpu_get_ticks(); + return cpus_get_elapsed_ticks(); } =20 /* IRQ handling */ diff --git a/include/sysemu/cpu-timers.h b/include/sysemu/cpu-timers.h index 07d724672f..cb83cc5584 100644 --- a/include/sysemu/cpu-timers.h +++ b/include/sysemu/cpu-timers.h @@ -64,9 +64,8 @@ void cpu_enable_ticks(void); void cpu_disable_ticks(void); =20 /* - * return the time elapsed in VM between vm_start and vm_stop. Unless - * icount is active, cpu_get_ticks() uses units of the host CPU cycle - * counter. + * return the time elapsed in VM between vm_start and vm_stop. + * cpu_get_ticks() uses units of the host CPU cycle counter. */ int64_t cpu_get_ticks(void); =20 @@ -78,4 +77,8 @@ int64_t cpu_get_clock(void); =20 void qemu_timer_notify_cb(void *opaque, QEMUClockType type); =20 +/* get the VIRTUAL clock and VM elapsed ticks via the cpus accel interface= */ +int64_t cpus_get_virtual_clock(void); +int64_t cpus_get_elapsed_ticks(void); + #endif /* SYSEMU_CPU_TIMERS_H */ diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index 149de000a0..db196dd96f 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -4,7 +4,43 @@ #include "qemu/timer.h" =20 /* cpus.c */ + +/* CPU execution threads */ + +typedef struct CpusAccel { + void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY */ + 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); + + int64_t (*get_virtual_clock)(void); + int64_t (*get_elapsed_ticks)(void); +} 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 e128f8b06b..ffed6192a3 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. * @@ -17,68 +17,9 @@ #include "sysemu/hvf.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 (hvf_enabled()) { - hvf_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 (hvf_enabled()) { - hvf_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 (hvf_enabled()) { - hvf_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 (hvf_enabled()) { - hvf_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/cpu-timers.c b/softmmu/cpu-timers.c index 64addb315d..3e1da79735 100644 --- a/softmmu/cpu-timers.c +++ b/softmmu/cpu-timers.c @@ -61,18 +61,13 @@ static int64_t cpu_get_ticks_locked(void) } =20 /* - * return the time elapsed in VM between vm_start and vm_stop. Unless - * icount is active, cpu_get_ticks() uses units of the host CPU cycle - * counter. + * return the time elapsed in VM between vm_start and vm_stop. + * cpu_get_ticks() uses units of the host CPU cycle counter. */ int64_t cpu_get_ticks(void) { int64_t ticks; =20 - if (icount_enabled()) { - return icount_get(); - } - qemu_spin_lock(&timers_state.vm_clock_lock); ticks =3D cpu_get_ticks_locked(); qemu_spin_unlock(&timers_state.vm_clock_lock); diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 54fdb2761c..2b15b5f86b 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -87,7 +87,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 +97,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; @@ -215,6 +215,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; @@ -251,6 +256,102 @@ void cpu_synchronize_all_pre_loadvm(void) } } =20 +void cpu_synchronize_state(CPUState *cpu) +{ + if (cpus_accel && cpus_accel->synchronize_state) { + 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 && cpus_accel->synchronize_post_reset) { + 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 && cpus_accel->synchronize_post_init) { + 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 && cpus_accel->synchronize_pre_loadvm) { + 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 (hvf_enabled()) { + hvf_cpu_synchronize_pre_loadvm(cpu); + } + if (whpx_enabled()) { + whpx_cpu_synchronize_pre_loadvm(cpu); + } +} + +int64_t cpus_get_virtual_clock(void) +{ + if (cpus_accel && cpus_accel->get_virtual_clock) { + return cpus_accel->get_virtual_clock(); + } + if (icount_enabled()) { + return icount_get(); + } else if (qtest_enabled()) { /* for qtest_clock_warp */ + return qtest_get_virtual_clock(); + } + return cpu_get_clock(); +} + +/* + * return the time elapsed in VM between vm_start and vm_stop. Unless + * icount is active, cpus_get_elapsed_ticks() uses units of the host CPU c= ycle + * counter. + */ +int64_t cpus_get_elapsed_ticks(void) +{ + if (cpus_accel && cpus_accel->get_elapsed_ticks) { + return cpus_accel->get_elapsed_ticks(); + } + if (icount_enabled()) { + return icount_get(); + } + return cpu_get_ticks(); +} + static int do_vm_stop(RunState state, bool send_stop) { int ret =3D 0; @@ -279,7 +380,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; @@ -290,7 +391,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(); @@ -396,7 +497,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) { @@ -421,7 +522,7 @@ static void qemu_tcg_rr_wait_io_event(void) } } =20 -static void qemu_wait_io_event(CPUState *cpu) +void qemu_wait_io_event(CPUState *cpu) { bool slept =3D false; =20 @@ -437,8 +538,8 @@ static void qemu_wait_io_event(CPUState *cpu) } =20 #ifdef _WIN32 - /* Eat dummy APC queued by qemu_cpu_kick_thread. */ - if (!tcg_enabled()) { + /* Eat dummy APC queued by cpus_kick_thread. */ + if (hax_enabled()) { SleepEx(0, TRUE); } #endif @@ -467,8 +568,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 { @@ -482,8 +582,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; @@ -511,8 +610,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 { @@ -660,8 +758,7 @@ static void deal_with_unplugged_cpus(void) 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); + cpu_thread_signal_destroyed(cpu); break; } } @@ -688,9 +785,8 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg) qemu_thread_get_self(cpu->thread); =20 cpu->thread_id =3D qemu_get_thread_id(); - cpu->created =3D true; cpu->can_do_io =3D 1; - qemu_cond_signal(&qemu_cpu_cond); + cpu_thread_signal_created(cpu); qemu_guest_random_seed_thread_part2(cpu->random_seed); =20 /* wait for initial kick-off after machine start */ @@ -800,11 +896,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 { @@ -843,8 +937,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 { @@ -858,8 +951,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; @@ -884,8 +976,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 { @@ -902,8 +993,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; @@ -936,10 +1026,9 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) qemu_thread_get_self(cpu->thread); =20 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); + cpu_thread_signal_created(cpu); qemu_guest_random_seed_thread_part2(cpu->random_seed); =20 /* process any pending work */ @@ -980,14 +1069,13 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) } while (!cpu->unplug || cpu_can_run(cpu)); =20 qemu_tcg_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; } =20 -static void qemu_cpu_kick_thread(CPUState *cpu) +void cpus_kick_thread(CPUState *cpu) { #ifndef _WIN32 int err; @@ -1017,7 +1105,10 @@ static void qemu_cpu_kick_thread(CPUState *cpu) void qemu_cpu_kick(CPUState *cpu) { qemu_cond_broadcast(cpu->halt_cond); - if (tcg_enabled()) { + + if (cpus_accel && cpus_accel->kick_vcpu_thread) { + cpus_accel->kick_vcpu_thread(cpu); + } else if (tcg_enabled()) { if (qemu_tcg_mttcg_enabled()) { cpu_exit(cpu); } else { @@ -1031,14 +1122,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) @@ -1088,6 +1179,21 @@ void qemu_cond_timedwait_iothread(QemuCond *cond, in= t 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; @@ -1163,9 +1269,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]; @@ -1286,6 +1389,13 @@ static void qemu_whpx_start_vcpu(CPUState *cpu) #endif } =20 +void cpus_register_accel(CpusAccel *ca) +{ + assert(ca !=3D NULL); + assert(ca->create_vcpu_thread !=3D NULL); /* mandatory */ + cpus_accel =3D ca; +} + static void qemu_dummy_start_vcpu(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; @@ -1316,7 +1426,10 @@ 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); diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index e97ad407fa..16345eec43 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -1,6 +1,7 @@ stub-obj-y +=3D blk-commit-all.o stub-obj-y +=3D cmos.o stub-obj-y +=3D cpu-get-clock.o +stub-obj-y +=3D cpus-get-virtual-clock.o stub-obj-y +=3D qemu-timer-notify-cb.o stub-obj-y +=3D icount.o stub-obj-y +=3D dump.o @@ -28,6 +29,7 @@ stub-obj-y +=3D trace-control.o stub-obj-y +=3D vmgenid.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) +{ +} diff --git a/stubs/cpus-get-virtual-clock.c b/stubs/cpus-get-virtual-clock.c new file mode 100644 index 0000000000..fd447d53f3 --- /dev/null +++ b/stubs/cpus-get-virtual-clock.c @@ -0,0 +1,8 @@ +#include "qemu/osdep.h" +#include "sysemu/cpu-timers.h" +#include "qemu/main-loop.h" + +int64_t cpus_get_virtual_clock(void) +{ + return cpu_get_clock(); +} diff --git a/util/qemu-timer.c b/util/qemu-timer.c index db51e68f25..50b325c65b 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -635,13 +635,7 @@ int64_t qemu_clock_get_ns(QEMUClockType type) return get_clock(); default: case QEMU_CLOCK_VIRTUAL: - if (icount_enabled()) { - return icount_get(); - } else if (qtest_enabled()) { /* for qtest_clock_warp */ - return qtest_get_virtual_clock(); - } else { - return cpu_get_clock(); - } + return cpus_get_virtual_clock(); case QEMU_CLOCK_HOST: return REPLAY_CLOCK(REPLAY_CLOCK_HOST, get_clock_realtime()); case QEMU_CLOCK_VIRTUAL_RT: --=20 2.16.4 From nobody Mon Jul 1 19:59:17 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=1597257407; cv=none; d=zohomail.com; s=zohoarc; b=MdbtxpAi2Px8/A9E5UNwxMNGdIdVcOSMmB/EicJ+ZDxVXDHcOmP4FQDHgdrrA1w7dDjvNbBSLn5MH0rE/yvIdYo/BfkIhs8r3WTxWrRUyzx136IM37WvhlExb75xaS16vfDCEvH21r3l/wTUbjUFsdY7QRj4lR90uNA+BwzNJrk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257407; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=d0glPr50+8+6jCC9ZY4pziHuai0KLD20T16Gls1rV3s=; b=PUpew5n9MoV8AajXgbHfFWwOYsi9L9HTRkEOu8KzqFNIiVpsK2lgmv5h6kpcm/oyUWdB7npFsttAFiiR0gigodX4UJLjfW6qOprIIHBGlKbVvtBoytOH5AdlU75Fj5A09XzRHaFgiS/ZGBoZWMJw95FnNR3V9yl4j215RpwGzQQ= 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 1597257407827469.56917452413086; Wed, 12 Aug 2020 11:36:47 -0700 (PDT) Received: from localhost ([::1]:54402 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vcE-0006Yw-Dd for importer@patchew.org; Wed, 12 Aug 2020 14:36:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46292) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYa-0000Ge-FE for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:01 -0400 Received: from mx2.suse.de ([195.135.220.15]:40602) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYW-0002D9-DF for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:00 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id A0FC1AE25; Wed, 12 Aug 2020 18:33:16 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 03/14] cpus: extract out TCG-specific code to accel/tcg Date: Wed, 12 Aug 2020 20:32:39 +0200 Message-Id: <20200812183250.9221-4-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-1-cfontana@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" TCG is the first accelerator to register a "CpusAccel" interface on initialization, providing functions for starting a vcpu, kicking a vcpu, sychronizing state and getting virtual clock and ticks. Signed-off-by: Claudio Fontana Reviewed-by: Philippe Mathieu-Daud=C3=A9 Tested-by: Philippe Mathieu-Daud=C3=A9 --- accel/tcg/Makefile.objs | 1 + accel/tcg/tcg-all.c | 12 +- accel/tcg/tcg-cpus.c | 541 ++++++++++++++++++++++++++++++++++++++++++++= ++++ accel/tcg/tcg-cpus.h | 17 ++ softmmu/cpus.c | 496 +------------------------------------------- 5 files changed, 567 insertions(+), 500 deletions(-) create mode 100644 accel/tcg/tcg-cpus.c create mode 100644 accel/tcg/tcg-cpus.h 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 f1feea20c8..01957b130d 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..c82d142523 --- /dev/null +++ b/accel/tcg/tcg-cpus.c @@ -0,0 +1,541 @@ +/* + * 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 int64_t tcg_get_virtual_clock(void) +{ + if (icount_enabled()) { + return icount_get(); + } + return cpu_get_clock(); +} + +static int64_t tcg_get_elapsed_ticks(void) +{ + if (icount_enabled()) { + return icount_get(); + } + return cpu_get_ticks(); +} + +CpusAccel tcg_cpus =3D { + .create_vcpu_thread =3D tcg_start_vcpu_thread, + .kick_vcpu_thread =3D tcg_kick_vcpu_thread, + .get_virtual_clock =3D tcg_get_virtual_clock, + .get_elapsed_ticks =3D tcg_get_elapsed_ticks, +}; 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/softmmu/cpus.c b/softmmu/cpus.c index 2b15b5f86b..a57cb4f28c 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" @@ -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, ...) { @@ -328,9 +247,7 @@ int64_t cpus_get_virtual_clock(void) if (cpus_accel && cpus_accel->get_virtual_clock) { return cpus_accel->get_virtual_clock(); } - if (icount_enabled()) { - return icount_get(); - } else if (qtest_enabled()) { /* for qtest_clock_warp */ + if (qtest_enabled()) { /* for qtest_clock_warp */ return qtest_get_virtual_clock(); } return cpu_get_clock(); @@ -346,9 +263,6 @@ int64_t cpus_get_elapsed_ticks(void) if (cpus_accel && cpus_accel->get_elapsed_ticks) { return cpus_accel->get_elapsed_ticks(); } - if (icount_enabled()) { - return icount_get(); - } return cpu_get_ticks(); } =20 @@ -482,10 +396,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)); @@ -506,22 +416,6 @@ 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); - } -} - void qemu_wait_io_event(CPUState *cpu) { bool slept =3D false; @@ -633,259 +527,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_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 *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->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(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; @@ -1005,76 +646,6 @@ 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->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; -} - void cpus_kick_thread(CPUState *cpu) { #ifndef _WIN32 @@ -1105,15 +676,8 @@ void cpus_kick_thread(CPUState *cpu) void qemu_cpu_kick(CPUState *cpu) { qemu_cond_broadcast(cpu->halt_cond); - if (cpus_accel && cpus_accel->kick_vcpu_thread) { cpus_accel->kick_vcpu_thread(cpu); - } else if (tcg_enabled()) { - if (qemu_tcg_mttcg_enabled()) { - cpu_exit(cpu); - } else { - qemu_cpu_kick_rr_cpus(); - } } else { if (hax_enabled()) { /* @@ -1269,62 +833,6 @@ void cpu_remove_sync(CPUState *cpu) qemu_mutex_lock_iothread(); } =20 -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]; @@ -1435,8 +943,6 @@ void qemu_init_vcpu(CPUState *cpu) 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 { --=20 2.16.4 From nobody Mon Jul 1 19:59:17 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=1597257259; cv=none; d=zohomail.com; s=zohoarc; b=aoyE85XrEvbWddXOaZ2pshestIsZ0kFGl5EeKL0rgAzs5pwUogGG2qdYxzwhza+h+G1KCEWBcgxTRYVSuvNw9qCCa8yQM96V/nR+Nf9+xmNL8H44I9ja1j1K7JR+eLVaADIT6ud1vTLSGogOWWlJelW41ouSdhsKTvJOqLugkSc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257259; 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=9pV00+oWjgIvVWEjrXKb871o9SNFB26LB/tKPYW6/Ek=; b=jyUIH5obveZubbm2G4ElGUhCtDAGtpd0bRbLJ35J8ueglHP3M0AKT4SWczGO7QivT4HkJtA+rNNnJfaTII7ijmcMnbQ34ygdKxZ8vlRw0Wi9Vha4OD+DKs+9TxUJFpumwo17vLNph1uwx6AW5LXKp3sOqwJePeQ0Jph/3wZftOY= 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 1597257259912776.1801258859203; Wed, 12 Aug 2020 11:34:19 -0700 (PDT) Received: from localhost ([::1]:43036 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vZq-0001vX-HO for importer@patchew.org; Wed, 12 Aug 2020 14:34:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46294) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYc-0000HO-Gy for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:02 -0400 Received: from mx2.suse.de ([195.135.220.15]:40630) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYX-0002DD-1w for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:01 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 4AD8AAEE0; Wed, 12 Aug 2020 18:33:17 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 04/14] cpus: extract out qtest-specific code to accel/qtest Date: Wed, 12 Aug 2020 20:32:40 +0200 Message-Id: <20200812183250.9221-5-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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 | 91 +++++++++++++++++++++++++++++++++++++++++++= ++++ accel/qtest/qtest-cpus.h | 17 +++++++++ accel/{ =3D> qtest}/qtest.c | 7 ++++ softmmu/cpus.c | 64 +-------------------------------- 7 files changed, 120 insertions(+), 65 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 7dcc3ef4c8..f8bac8cb64 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2442,7 +2442,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..ac10976ac6 --- /dev/null +++ b/accel/qtest/qtest-cpus.c @@ -0,0 +1,91 @@ +/* + * 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_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, + .get_virtual_clock =3D qtest_get_virtual_clock, +}; 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 a57cb4f28c..896d508c15 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" @@ -247,9 +246,6 @@ int64_t cpus_get_virtual_clock(void) if (cpus_accel && cpus_accel->get_virtual_clock) { return cpus_accel->get_virtual_clock(); } - if (qtest_enabled()) { /* for qtest_clock_warp */ - return qtest_get_virtual_clock(); - } return cpu_get_clock(); } =20 @@ -482,51 +478,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; @@ -904,19 +855,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()); @@ -946,7 +884,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 Mon Jul 1 19:59:17 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=1597257496; cv=none; d=zohomail.com; s=zohoarc; b=iAmC2I9qGu6EoOCxsq0s+cZLWD6njh0IrG6bqeFCyMnWAsNmgN1pvG92MysWJiJGaUsbNweriqkvo//7JvNx5KaiRE62wFDO3u1q1XqFdgMnSBTayFAjUnAhfjdaQb50Wg0yrAm5BnsT4fb7/4LHQEoRFqgEowFtkq4P7PkQLJY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257496; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=/hxKlihOEVMJN2GHcWtHhcO2udOpruhKuG3xaymDYPA=; b=AWSGi3QEUSDGSWpu4tsScTJVSJQAO9r/EVItfX3L32mb8qdLn5wzUHMH9oB2QosU2LTJVbxCdVAjlt7kqZDOvVxAaOM/tApTUD2hTY2pMhVebQfXti8FJSWqBfmqCM5iIW2hdmvenljMvOrdE1dBEYq5OjI5XMYc3TSvL/8+Hgc= 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 1597257496359334.2567541000126; Wed, 12 Aug 2020 11:38:16 -0700 (PDT) Received: from localhost ([::1]:60908 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vdf-0000in-2I for importer@patchew.org; Wed, 12 Aug 2020 14:38:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46358) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYm-0000PA-59 for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:12 -0400 Received: from mx2.suse.de ([195.135.220.15]:40682) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYY-0002DS-8Q for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:11 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id EB9A0AEFB; Wed, 12 Aug 2020 18:33:17 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 05/14] cpus: extract out kvm-specific code to accel/kvm Date: Wed, 12 Aug 2020 20:32:41 +0200 Message-Id: <20200812183250.9221-6-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-1-cfontana@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" register a "CpusAccel" interface for KVM as well. Signed-off-by: Claudio Fontana Reviewed-by: Philippe Mathieu-Daud=C3=A9 Tested-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Richard Henderson --- accel/kvm/Makefile.objs | 2 ++ accel/kvm/kvm-all.c | 14 +++++++- accel/kvm/kvm-cpus.c | 88 +++++++++++++++++++++++++++++++++++++++++++++= ++++ accel/kvm/kvm-cpus.h | 17 ++++++++++ accel/stubs/kvm-stub.c | 3 +- include/sysemu/kvm.h | 2 +- softmmu/cpus.c | 77 ------------------------------------------- 7 files changed, 122 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 63ef6af9a1..fbd82cb444 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -44,6 +44,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 @@ -378,7 +381,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; @@ -412,6 +415,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) assert(!ret); } =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..7866a2e9c3 --- /dev/null +++ b/accel/kvm/kvm-cpus.c @@ -0,0 +1,88 @@ +/* + * 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_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, + + .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 896d508c15..bd535c68e0 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -179,9 +179,6 @@ void cpu_synchronize_state(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_state) { cpus_accel->synchronize_state(cpu); } - if (kvm_enabled()) { - kvm_cpu_synchronize_state(cpu); - } if (hax_enabled()) { hax_cpu_synchronize_state(cpu); } @@ -195,9 +192,6 @@ void cpu_synchronize_post_reset(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_post_reset) { cpus_accel->synchronize_post_reset(cpu); } - if (kvm_enabled()) { - kvm_cpu_synchronize_post_reset(cpu); - } if (hax_enabled()) { hax_cpu_synchronize_post_reset(cpu); } @@ -211,9 +205,6 @@ void cpu_synchronize_post_init(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_post_init) { cpus_accel->synchronize_post_init(cpu); } - if (kvm_enabled()) { - kvm_cpu_synchronize_post_init(cpu); - } if (hax_enabled()) { hax_cpu_synchronize_post_init(cpu); } @@ -227,9 +218,6 @@ void cpu_synchronize_pre_loadvm(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_pre_loadvm) { cpus_accel->synchronize_pre_loadvm(cpu); } - if (kvm_enabled()) { - kvm_cpu_synchronize_pre_loadvm(cpu); - } if (hax_enabled()) { hax_cpu_synchronize_pre_loadvm(cpu); } @@ -384,14 +372,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)); @@ -436,48 +416,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; @@ -801,19 +739,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]; @@ -875,8 +800,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 Mon Jul 1 19:59:17 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=1597257358; cv=none; d=zohomail.com; s=zohoarc; b=LBKK1Jl1WbbTQfhHHlxHWCRemCtsrN91f6cuN6J23m2zuPqegaI+EDxZRE08OR0ateRxBaEwhZUf/bNuwf438otRtlir5Okl2jHFsyhhoOjfTr5h1BxbPiCp9EIBuyl3RTFw/0Oi5n0isZJ72Jfkut3lwZXaw3flYfsosGxhtf0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257358; 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=91501QpHj3pLrpwjLQCv3oc/FjkVl7Zuu0OVBeJmmA4=; b=O+DjPv+RU2ZNNZu4MMfy+jDOsaFkJg3RjBdnmmmM/4XB4bdzsiy/frVKDeFjrVJpHxBlyvAJNrQAfI7LFi/oWvcfX3Dv70rIRKTfLbYiteiIP/NNEbcvRu1tZ/22hxzK1UxwhLwvmFio2VjulTAvexbBq6Rre9IajCz3PYTzSkM= 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 1597257358013779.5603288150097; Wed, 12 Aug 2020 11:35:58 -0700 (PDT) Received: from localhost ([::1]:50988 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vbQ-00056c-K8 for importer@patchew.org; Wed, 12 Aug 2020 14:35:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46330) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYf-0000KV-Bj for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:06 -0400 Received: from mx2.suse.de ([195.135.220.15]:40684) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYY-0002DR-7P for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:05 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 932EEAF0C; Wed, 12 Aug 2020 18:33:18 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 06/14] cpus: extract out hax-specific code to target/i386/ Date: Wed, 12 Aug 2020 20:32:42 +0200 Message-Id: <20200812183250.9221-7-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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 Reviewed-by: Richard Henderson --- softmmu/cpus.c | 80 +------------------------------------------- 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, 145 insertions(+), 82 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 bd535c68e0..c314e22bd2 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" @@ -179,9 +178,6 @@ void cpu_synchronize_state(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_state) { cpus_accel->synchronize_state(cpu); } - if (hax_enabled()) { - hax_cpu_synchronize_state(cpu); - } if (whpx_enabled()) { whpx_cpu_synchronize_state(cpu); } @@ -192,9 +188,6 @@ void cpu_synchronize_post_reset(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_post_reset) { cpus_accel->synchronize_post_reset(cpu); } - if (hax_enabled()) { - hax_cpu_synchronize_post_reset(cpu); - } if (whpx_enabled()) { whpx_cpu_synchronize_post_reset(cpu); } @@ -205,9 +198,6 @@ void cpu_synchronize_post_init(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_post_init) { cpus_accel->synchronize_post_init(cpu); } - if (hax_enabled()) { - hax_cpu_synchronize_post_init(cpu); - } if (whpx_enabled()) { whpx_cpu_synchronize_post_init(cpu); } @@ -218,9 +208,6 @@ void cpu_synchronize_pre_loadvm(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_pre_loadvm) { cpus_accel->synchronize_pre_loadvm(cpu); } - if (hax_enabled()) { - hax_cpu_synchronize_pre_loadvm(cpu); - } if (hvf_enabled()) { hvf_cpu_synchronize_pre_loadvm(cpu); } @@ -416,35 +403,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) @@ -529,12 +487,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 @@ -553,10 +505,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 @@ -567,14 +515,7 @@ void qemu_cpu_kick(CPUState *cpu) qemu_cond_broadcast(cpu->halt_cond); if (cpus_accel && cpus_accel->kick_vcpu_thread) { 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; - } + } else { /* default */ cpus_kick_thread(cpu); } } @@ -722,23 +663,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]; @@ -800,8 +724,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 0b93143e27..ee5a8fd4b4 100644 --- a/target/i386/Makefile.objs +++ b/target/i386/Makefile.objs @@ -10,11 +10,12 @@ obj-y +=3D machine.o arch_memory_mapping.o arch_dump.o = monitor.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 5f9d1b803d..6fb7867d11 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 Mon Jul 1 19:59:17 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=1597257582; cv=none; d=zohomail.com; s=zohoarc; b=F99y/IqRyWscKlUzAeszZ4X2YI9xf/ybrnsI6gaUnYca6VaGC6P/MR46AMhfPQr8fPvaak67rncugS3FAJcdDpDAA6EYUykcEpuKeC83urcmIPPOCyUOjrZJVskAWOwXfz2o7AHUxP06UhGXI9mMmoVSy64cPXngvn2hVKFji3U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257582; 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=DoI6lqAcyyrMop2uaxfjslB3EtSFyyPCkoSGU+JWTZ8=; b=ebwwJDyy3pUNYYPdlmXZyBqGIsVYQIg8RrLLynjVINHrFsDj4AJKdhyrHCLTDjTHZOejJmgLzRtFEPAsnqal4n5EafRyL1ycoRiB8FQEl2xEU6Ix4x+zGZDqniN6Q7Fd+LTkMgSaa7GHdz6j2UwYtNAsKPhnG17PwDmlYTFFsuw= 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 1597257582384247.59836742516075; Wed, 12 Aug 2020 11:39:42 -0700 (PDT) Received: from localhost ([::1]:39078 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vf2-0003Hw-Po for importer@patchew.org; Wed, 12 Aug 2020 14:39:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46378) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYp-0000RC-24 for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:15 -0400 Received: from mx2.suse.de ([195.135.220.15]:40772) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYm-0002Dm-H7 for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:14 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 3D0CDAF22; Wed, 12 Aug 2020 18:33:19 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 07/14] cpus: extract out whpx-specific code to target/i386/ Date: Wed, 12 Aug 2020 20:32:43 +0200 Message-Id: <20200812183250.9221-8-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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 Reviewed-by: Richard Henderson --- MAINTAINERS | 1 + softmmu/cpus.c | 79 -------------------------------------- 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(+), 80 deletions(-) create mode 100644 target/i386/whpx-cpus.c create mode 100644 target/i386/whpx-cpus.h diff --git a/MAINTAINERS b/MAINTAINERS index f8bac8cb64..e38097a265 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -450,6 +450,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 c314e22bd2..c74dae6449 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" @@ -178,9 +177,6 @@ void cpu_synchronize_state(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_state) { cpus_accel->synchronize_state(cpu); } - if (whpx_enabled()) { - whpx_cpu_synchronize_state(cpu); - } } =20 void cpu_synchronize_post_reset(CPUState *cpu) @@ -188,9 +184,6 @@ void cpu_synchronize_post_reset(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_post_reset) { cpus_accel->synchronize_post_reset(cpu); } - if (whpx_enabled()) { - whpx_cpu_synchronize_post_reset(cpu); - } } =20 void cpu_synchronize_post_init(CPUState *cpu) @@ -198,9 +191,6 @@ void cpu_synchronize_post_init(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_post_init) { cpus_accel->synchronize_post_init(cpu); } - if (whpx_enabled()) { - whpx_cpu_synchronize_post_init(cpu); - } } =20 void cpu_synchronize_pre_loadvm(CPUState *cpu) @@ -211,9 +201,6 @@ void cpu_synchronize_pre_loadvm(CPUState *cpu) if (hvf_enabled()) { hvf_cpu_synchronize_pre_loadvm(cpu); } - if (whpx_enabled()) { - whpx_cpu_synchronize_pre_loadvm(cpu); - } } =20 int64_t cpus_get_virtual_clock(void) @@ -445,48 +432,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 @@ -501,12 +446,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 @@ -681,22 +620,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); @@ -726,8 +649,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 ee5a8fd4b4..606dec67d1 100644 --- a/target/i386/Makefile.objs +++ b/target/i386/Makefile.objs @@ -18,7 +18,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 Mon Jul 1 19:59:17 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=1597257352; cv=none; d=zohomail.com; s=zohoarc; b=foTv10hmJG1tDoxBHKKei1aa+ijnEey3xvOxmZ/HrZgRYtL7cK91rYd7vMgHZ1yY/ngETdsb12KIJypxxIdIRcjPu5LbxXu1S1z25fjlm7kL5U9CWtd+5WacCE8JfPr8rXrP51wk8krGbZIeZHKn58e72Hbsy+l7kCFLh28KD1A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257352; 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=FnnuZWmr2mAR1gHDw24Jrc1c4XeeGFFZAYERu411yrs=; b=RMSA/QIW+Yw/Ky6b0zatwGPMcx3wiB+1GCHJ0Kz/WIPe6KnDxAZyzNV08Qrn+htGnpUatc9eTJBZoSC4j3Hd/jn1Va5n4ojW2YkPKTUF193eIZxdxweCvY3herhyz+3f2PMc6655ucZZ/5p8x4Nt4TqTvpbQfqvwK/aUAz1ssw0= 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 1597257352462431.43853064732866; Wed, 12 Aug 2020 11:35:52 -0700 (PDT) Received: from localhost ([::1]:50580 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vbL-0004wh-34 for importer@patchew.org; Wed, 12 Aug 2020 14:35:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46354) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYj-0000M1-IO for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:09 -0400 Received: from mx2.suse.de ([195.135.220.15]:40778) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYd-0002Do-JE for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:09 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D98D6AF27; Wed, 12 Aug 2020 18:33:19 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 08/14] cpus: extract out hvf-specific code to target/i386/hvf/ Date: Wed, 12 Aug 2020 20:32:44 +0200 Message-Id: <20200812183250.9221-9-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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 Reviewed-by: Roman Bolshakov Reviewed-by: Richard Henderson --- softmmu/cpus.c | 66 --------------------- target/i386/hvf/Makefile.objs | 2 +- target/i386/hvf/hvf-cpus.c | 131 ++++++++++++++++++++++++++++++++++++++= ++++ target/i386/hvf/hvf-cpus.h | 17 ++++++ target/i386/hvf/hvf.c | 3 + 5 files changed, 152 insertions(+), 67 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 c74dae6449..f99942fd9d 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" @@ -198,9 +197,6 @@ void cpu_synchronize_pre_loadvm(CPUState *cpu) if (cpus_accel && cpus_accel->synchronize_pre_loadvm) { cpus_accel->synchronize_pre_loadvm(cpu); } - if (hvf_enabled()) { - hvf_cpu_synchronize_pre_loadvm(cpu); - } } =20 int64_t cpus_get_virtual_clock(void) @@ -390,48 +386,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 @@ -602,24 +556,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); @@ -647,8 +583,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..9540157f1e --- /dev/null +++ b/target/i386/hvf/hvf-cpus.c @@ -0,0 +1,131 @@ +/* + * 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_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, + + .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_pre_loadvm, +}; 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 d81f569aed..7ac6987c1b 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) @@ -894,6 +896,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 From nobody Mon Jul 1 19:59:17 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=1597257538; cv=none; d=zohomail.com; s=zohoarc; b=KHoWAC82uYfh1dJPtUGYadOsegHsUNgGRIakcUsfuSSdzCZEnfYghZkwcirrUFH4PyE2dOweMv8ILEPul4cUgeeo/jA+iXHGnO+xB3pu5kWAMPXb6LUFusfgcNsMtlowj1Cm4VoaH7Mnr9zot2GON9G6ybvrXxdRlMGdQWFVXZk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257538; 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=63kzHXeNMvL9ybYzcDu8bGZwe4MeABuj3Ie9ILBNKvY=; b=W636BoBvoMmkQwo2sJ71mvicCVdkv8+hmy7GfE3Nb5MB9wstJSoRJf791PGikn1yfiM2ucKHPFfVuTlc2fv0LMyv/nwdnt4l0saCZUbsc2UrZp76ToLpZ3BfFC4eq4dic1GuIKEl1Vw+KGs1DlKoz1t2SxR5S9RNsi9MDsjpnH0= 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 1597257537997140.3053455122017; Wed, 12 Aug 2020 11:38:57 -0700 (PDT) Received: from localhost ([::1]:35302 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5veK-0001lw-RI for importer@patchew.org; Wed, 12 Aug 2020 14:38:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46356) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYk-0000Mr-JR for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:10 -0400 Received: from mx2.suse.de ([195.135.220.15]:40782) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYd-0002Du-J5 for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:10 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 85603AF6D; Wed, 12 Aug 2020 18:33:20 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 09/14] cpus: cleanup now unneeded includes Date: Wed, 12 Aug 2020 20:32:45 +0200 Message-Id: <20200812183250.9221-10-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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" Signed-off-by: Claudio Fontana Reviewed-by: Richard Henderson --- softmmu/cpus.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/softmmu/cpus.c b/softmmu/cpus.c index f99942fd9d..1125fb5fc9 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -29,20 +29,13 @@ #include "qapi/qapi-commands-misc.h" #include "qapi/qapi-events-run-state.h" #include "qapi/qmp/qerror.h" -#include "sysemu/tcg.h" #include "exec/gdbstub.h" #include "sysemu/hw_accel.h" -#include "sysemu/kvm.h" #include "exec/exec-all.h" #include "qemu/thread.h" #include "qemu/plugin.h" #include "sysemu/cpus.h" -#include "qemu/main-loop.h" -#include "qemu/option.h" -#include "qemu/bitmap.h" -#include "qemu/seqlock.h" #include "qemu/guest-random.h" -#include "tcg/tcg.h" #include "hw/nmi.h" #include "sysemu/replay.h" #include "sysemu/runstate.h" --=20 2.16.4 From nobody Mon Jul 1 19:59:17 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=1597257654; cv=none; d=zohomail.com; s=zohoarc; b=L32Fhxd1EoIDA+Xqoq3WAknSbcU1iQ7edntfdiYUP3nVDrRzBio16bx6jZEYmckxTmCywUWiCKLTHts4bU/k4Pw8eU/tpo0JGqR/QH+A0FeA+uD42XUkPU5UTQRoAvMCDD3zUCP9d+bZfCttBjRYvOeKLJgOzQ9dUdaSMLJDZbM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257654; 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=Mjak7WasBNGkGEHlrlEn3prfG3hdY/cD80wb7VHsRzc=; b=XXMuCFb0uyHjiIsP2p6kMaxXu2jGQxt/X2gv/Mo9GkLkCa+1RUtJ9Px9NUqdlB0q9lcSRQDB42MfezdW6W95C3ItNo/M1nY77nlx1Hy3SPqd8DK2YiFXhfVDnZbdmASSbuOqCrm/yweRf/2mJjQJ4BVdYTRKWgZOyO34zwvfI6k= 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 1597257654993849.3717383516255; Wed, 12 Aug 2020 11:40:54 -0700 (PDT) Received: from localhost ([::1]:44268 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vgD-0005SS-Kt for importer@patchew.org; Wed, 12 Aug 2020 14:40:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46426) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYs-0000Z3-48 for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:18 -0400 Received: from mx2.suse.de ([195.135.220.15]:40792) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYo-0002Dw-OA for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:17 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 30F1BAF7F; Wed, 12 Aug 2020 18:33:21 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 10/14] cpus: add handle_interrupt to the CpusAccel interface Date: Wed, 12 Aug 2020 20:32:46 +0200 Message-Id: <20200812183250.9221-11-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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" kvm: uses the generic handler qtest: uses the generic handler whpx: changed to use the generic handler (identical implementation) hax: changed to use the generic handler (identical implementation) hvf: changed to use the generic handler (identical implementation) tcg: adapt tcg-cpus to point to the tcg-specific handler Signed-off-by: Claudio Fontana --- accel/tcg/tcg-all.c | 26 -------------------------- accel/tcg/tcg-cpus.c | 28 ++++++++++++++++++++++++++++ hw/core/cpu.c | 13 ------------- include/hw/core/cpu.h | 14 -------------- include/sysemu/cpus.h | 2 ++ softmmu/cpus.c | 18 ++++++++++++++++++ target/i386/hax-all.c | 10 ---------- target/i386/hvf/hvf.c | 9 --------- target/i386/whpx-all.c | 10 ---------- 9 files changed, 48 insertions(+), 82 deletions(-) diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index 01957b130d..af9bf5c5bb 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -47,31 +47,6 @@ typedef struct TCGState { #define TCG_STATE(obj) \ OBJECT_CHECK(TCGState, (obj), TYPE_TCG_ACCEL) =20 -/* mask must never be zero, except for A20 change call */ -static void tcg_handle_interrupt(CPUState *cpu, int mask) -{ - int old_mask; - g_assert(qemu_mutex_iothread_locked()); - - old_mask =3D cpu->interrupt_request; - cpu->interrupt_request |=3D mask; - - /* - * If called from iothread context, wake the target cpu in - * case its halted. - */ - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } else { - atomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1); - if (icount_enabled() && - !cpu->can_do_io - && (mask & ~old_mask) !=3D 0) { - cpu_abort(cpu, "Raised interrupt while not in I/O function"); - } - } -} - /* * We default to false if we know other options have been enabled * which are currently incompatible with MTTCG. Otherwise when each @@ -128,7 +103,6 @@ static int tcg_init(MachineState *ms) TCGState *s =3D TCG_STATE(current_accel()); =20 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); =20 diff --git a/accel/tcg/tcg-cpus.c b/accel/tcg/tcg-cpus.c index c82d142523..465d9955de 100644 --- a/accel/tcg/tcg-cpus.c +++ b/accel/tcg/tcg-cpus.c @@ -533,9 +533,37 @@ static int64_t tcg_get_elapsed_ticks(void) return cpu_get_ticks(); } =20 +/* mask must never be zero, except for A20 change call */ +static void tcg_handle_interrupt(CPUState *cpu, int mask) +{ + int old_mask; + g_assert(qemu_mutex_iothread_locked()); + + old_mask =3D cpu->interrupt_request; + cpu->interrupt_request |=3D mask; + + /* + * If called from iothread context, wake the target cpu in + * case its halted. + */ + if (!qemu_cpu_is_self(cpu)) { + qemu_cpu_kick(cpu); + } else { + atomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1); + if (icount_enabled() && + !cpu->can_do_io + && (mask & ~old_mask) !=3D 0) { + cpu_abort(cpu, "Raised interrupt while not in I/O function"); + } + } +} + CpusAccel tcg_cpus =3D { .create_vcpu_thread =3D tcg_start_vcpu_thread, .kick_vcpu_thread =3D tcg_kick_vcpu_thread, + + .handle_interrupt =3D tcg_handle_interrupt, + .get_virtual_clock =3D tcg_get_virtual_clock, .get_elapsed_ticks =3D tcg_get_elapsed_ticks, }; diff --git a/hw/core/cpu.c b/hw/core/cpu.c index b389a312df..06bec40042 100644 --- a/hw/core/cpu.c +++ b/hw/core/cpu.c @@ -35,8 +35,6 @@ #include "qemu/plugin.h" #include "sysemu/hw_accel.h" =20 -CPUInterruptHandler cpu_interrupt_handler; - CPUState *cpu_by_arch_id(int64_t id) { CPUState *cpu; @@ -394,17 +392,6 @@ static vaddr cpu_adjust_watchpoint_address(CPUState *c= pu, vaddr addr, int len) return addr; } =20 -static void generic_handle_interrupt(CPUState *cpu, int mask) -{ - cpu->interrupt_request |=3D mask; - - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } -} - -CPUInterruptHandler cpu_interrupt_handler =3D generic_handle_interrupt; - static void cpu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 8f145733ce..efd33d87fd 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -838,12 +838,6 @@ bool cpu_exists(int64_t id); */ CPUState *cpu_by_arch_id(int64_t id); =20 -#ifndef CONFIG_USER_ONLY - -typedef void (*CPUInterruptHandler)(CPUState *, int); - -extern CPUInterruptHandler cpu_interrupt_handler; - /** * cpu_interrupt: * @cpu: The CPU to set an interrupt on. @@ -851,17 +845,9 @@ extern CPUInterruptHandler cpu_interrupt_handler; * * Invokes the interrupt handler. */ -static inline void cpu_interrupt(CPUState *cpu, int mask) -{ - cpu_interrupt_handler(cpu, mask); -} - -#else /* USER_ONLY */ =20 void cpu_interrupt(CPUState *cpu, int mask); =20 -#endif /* USER_ONLY */ - #ifdef NEED_CPU_H =20 #ifdef CONFIG_SOFTMMU diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index db196dd96f..11ac0387e6 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -16,6 +16,8 @@ typedef struct CpusAccel { void (*synchronize_state)(CPUState *cpu); void (*synchronize_pre_loadvm)(CPUState *cpu); =20 + void (*handle_interrupt)(CPUState *cpu, int mask); + int64_t (*get_virtual_clock)(void); int64_t (*get_elapsed_ticks)(void); } CpusAccel; diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 1125fb5fc9..17531161fc 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -213,6 +213,24 @@ int64_t cpus_get_elapsed_ticks(void) return cpu_get_ticks(); } =20 +static void generic_handle_interrupt(CPUState *cpu, int mask) +{ + cpu->interrupt_request |=3D mask; + + if (!qemu_cpu_is_self(cpu)) { + qemu_cpu_kick(cpu); + } +} + +void cpu_interrupt(CPUState *cpu, int mask) +{ + if (cpus_accel && cpus_accel->handle_interrupt) { + cpus_accel->handle_interrupt(cpu, mask); + } else { + generic_handle_interrupt(cpu, mask); + } +} + static int do_vm_stop(RunState state, bool send_stop) { int ret =3D 0; diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c index b66ddeb8bf..fd1ab673d7 100644 --- a/target/i386/hax-all.c +++ b/target/i386/hax-all.c @@ -297,15 +297,6 @@ int hax_vm_destroy(struct hax_vm *vm) return 0; } =20 -static void hax_handle_interrupt(CPUState *cpu, int mask) -{ - cpu->interrupt_request |=3D mask; - - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } -} - static int hax_init(ram_addr_t ram_size, int max_cpus) { struct hax_state *hax =3D NULL; @@ -350,7 +341,6 @@ static int hax_init(ram_addr_t ram_size, int max_cpus) qversion.cur_version =3D hax_cur_version; qversion.min_version =3D hax_min_version; hax_notify_qemu_version(hax->vm->fd, &qversion); - cpu_interrupt_handler =3D hax_handle_interrupt; =20 return ret; error: diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 7ac6987c1b..ed9356565c 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -262,14 +262,6 @@ static void update_apic_tpr(CPUState *cpu) =20 #define VECTORING_INFO_VECTOR_MASK 0xff =20 -static void hvf_handle_interrupt(CPUState * cpu, int mask) -{ - cpu->interrupt_request |=3D mask; - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } -} - void hvf_handle_io(CPUArchState *env, uint16_t port, void *buffer, int direction, int size, int count) { @@ -894,7 +886,6 @@ static int hvf_accel_init(MachineState *ms) } =20 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; diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index 8b6986c864..b3d17fbe04 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -1413,15 +1413,6 @@ static void whpx_memory_init(void) memory_listener_register(&whpx_memory_listener, &address_space_memory); } =20 -static void whpx_handle_interrupt(CPUState *cpu, int mask) -{ - cpu->interrupt_request |=3D mask; - - if (!qemu_cpu_is_self(cpu)) { - qemu_cpu_kick(cpu); - } -} - /* * Load the functions from the given library, using the given handle. If a * handle is provided, it is used, otherwise the library is opened. The @@ -1576,7 +1567,6 @@ static int whpx_accel_init(MachineState *ms) =20 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"); --=20 2.16.4 From nobody Mon Jul 1 19:59:17 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=1597257439; cv=none; d=zohomail.com; s=zohoarc; b=DaRp9eO5kL7FrN5JRuMx9BYPtFkkPDGEUz6pK3ATPd0aAJlHBFO/7jINCWcopUc8FRezF1wCVmBFPpaf48yBqsorrzRSVmm+OcJqGDwNv0zdVIRcgYDGnUoEN+jm5S4RvwYbeG4YZUDD2y9iyjHxEUkfceViAnCsBLAicjYnr5s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257439; 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=RIVjnDyTgP5eal0QEglN6TLyDGutd4YX+5xt7k63mbw=; b=SWcuNRtM1QZfXPM6eIsdCa/iHnk201bbsVuVXsn5tkKdWcDawM/bR9IOYw7NSv7DRi8rNSTVPUSTXIoCK7/6azfHmW+ApNdfBkrb0t3z+4dRdNZ123Ko/sYMYFZGvXP0ZmR8bY1sVkOtwFyNHkUO4meXhU+mou7TFIvfdMFAgGk= 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 1597257439108568.0817829902638; Wed, 12 Aug 2020 11:37:19 -0700 (PDT) Received: from localhost ([::1]:57222 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vcj-0007fj-O3 for importer@patchew.org; Wed, 12 Aug 2020 14:37:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46350) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYh-0000L4-Bk for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:08 -0400 Received: from mx2.suse.de ([195.135.220.15]:40814) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYc-0002E9-8Z for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:07 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D456CAE0A; Wed, 12 Aug 2020 18:33:21 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 11/14] hvf: remove hvf specific functions from global includes Date: Wed, 12 Aug 2020 20:32:47 +0200 Message-Id: <20200812183250.9221-12-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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" Signed-off-by: Claudio Fontana Reviewed-by: Richard Henderson --- accel/stubs/Makefile.objs | 1 - accel/stubs/hvf-stub.c | 30 ------------------------------ include/sysemu/hvf.h | 8 -------- target/i386/hvf/hvf-cpus.h | 8 ++++++++ target/i386/hvf/x86hvf.c | 2 ++ target/i386/hvf/x86hvf.h | 1 - 6 files changed, 10 insertions(+), 40 deletions(-) delete mode 100644 accel/stubs/hvf-stub.c diff --git a/accel/stubs/Makefile.objs b/accel/stubs/Makefile.objs index bbd14e71fb..6630954f30 100644 --- a/accel/stubs/Makefile.objs +++ b/accel/stubs/Makefile.objs @@ -1,5 +1,4 @@ obj-$(call lnot,$(CONFIG_HAX)) +=3D hax-stub.o -obj-$(call lnot,$(CONFIG_HVF)) +=3D hvf-stub.o obj-$(call lnot,$(CONFIG_WHPX)) +=3D whpx-stub.o obj-$(call lnot,$(CONFIG_KVM)) +=3D kvm-stub.o obj-$(call lnot,$(CONFIG_TCG)) +=3D tcg-stub.o diff --git a/accel/stubs/hvf-stub.c b/accel/stubs/hvf-stub.c deleted file mode 100644 index e81dfe888c..0000000000 --- a/accel/stubs/hvf-stub.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * QEMU HVF support - * - * Copyright 2017 Red Hat, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2 or later, as published by the Free Software Foundatio= n, - * and may be copied, distributed, and modified under those terms. - * - * See the COPYING file in the top-level directory. - * - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "sysemu/hvf.h" - -int hvf_init_vcpu(CPUState *cpu) -{ - return -ENOSYS; -} - -int hvf_vcpu_exec(CPUState *cpu) -{ - return -ENOSYS; -} - -void hvf_vcpu_destroy(CPUState *cpu) -{ -} diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h index 6d3ee4fdb7..b4f7191dd9 100644 --- a/include/sysemu/hvf.h +++ b/include/sysemu/hvf.h @@ -23,14 +23,6 @@ extern bool hvf_allowed; #define hvf_get_supported_cpuid(func, idx, reg) 0 #endif /* !CONFIG_HVF */ =20 -int hvf_init_vcpu(CPUState *); -int hvf_vcpu_exec(CPUState *); -void hvf_cpu_synchronize_state(CPUState *); -void hvf_cpu_synchronize_post_reset(CPUState *); -void hvf_cpu_synchronize_post_init(CPUState *); -void hvf_cpu_synchronize_pre_loadvm(CPUState *); -void hvf_vcpu_destroy(CPUState *); - #define TYPE_HVF_ACCEL ACCEL_CLASS_NAME("hvf") =20 #define HVF_STATE(obj) \ diff --git a/target/i386/hvf/hvf-cpus.h b/target/i386/hvf/hvf-cpus.h index b66f4889b0..da4a990451 100644 --- a/target/i386/hvf/hvf-cpus.h +++ b/target/i386/hvf/hvf-cpus.h @@ -14,4 +14,12 @@ =20 extern CpusAccel hvf_cpus; =20 +int hvf_init_vcpu(CPUState *); +int hvf_vcpu_exec(CPUState *); +void hvf_cpu_synchronize_state(CPUState *); +void hvf_cpu_synchronize_post_reset(CPUState *); +void hvf_cpu_synchronize_post_init(CPUState *); +void hvf_cpu_synchronize_pre_loadvm(CPUState *); +void hvf_vcpu_destroy(CPUState *); + #endif /* HVF_CPUS_H */ diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index 5cbcb32ab6..b986213c0f 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -32,6 +32,8 @@ #include #include =20 +#include "hvf-cpus.h" + void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg, SegmentCache *qseg, bool is_tr) { diff --git a/target/i386/hvf/x86hvf.h b/target/i386/hvf/x86hvf.h index 79539f7282..4fabc6d582 100644 --- a/target/i386/hvf/x86hvf.h +++ b/target/i386/hvf/x86hvf.h @@ -35,5 +35,4 @@ void hvf_get_msrs(CPUState *cpu_state); void vmx_clear_int_window_exiting(CPUState *cpu); void hvf_get_segments(CPUState *cpu_state); void vmx_update_tpr(CPUState *cpu); -void hvf_cpu_synchronize_state(CPUState *cpu_state); #endif --=20 2.16.4 From nobody Mon Jul 1 19:59:17 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=1597257434; cv=none; d=zohomail.com; s=zohoarc; b=jOwQcIR5YLPh4KzDBjLbhgxm2DdEx2mIUb3P2kFVlFIoxuB7qddR8RMQZTmcC9aIqLNEUbNAJYgvTjw8Yj+unUwpx72RPQ7RY/waGdBS1Jde1+5CSaF6/8fy0oGF1dLKojJnjvk6bVz8d5zv3nyyQDhNz8O/bc8mbt+v0sI+c/A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257434; 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=KFhuQ/kMEPV3gLQV3Iqq5vZlUinzsAi+m97JYlWoGig=; b=acMm307n0w+Z5o7QswzPFwxwmhJGbwGrmaqM9PjMvV4LhTA7XgtImo8KRmBwZw+CKqT8yvbNLym3TrIZNfgLLzKFdU8+tR8ZWUyB6Gy918syCShqhl11gq5Dys9wTuIUEz7Im3sLTcOk/vUVFdmBhAWWWIuIdkQMg69KSrJa+XE= 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 1597257434422988.3114445226165; Wed, 12 Aug 2020 11:37:14 -0700 (PDT) Received: from localhost ([::1]:56808 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vcf-0007Vb-9z for importer@patchew.org; Wed, 12 Aug 2020 14:37:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46396) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYq-0000UX-AG for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:16 -0400 Received: from mx2.suse.de ([195.135.220.15]:40840) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYn-0002EC-TF for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:15 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 7A3EAAF90; Wed, 12 Aug 2020 18:33:22 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 12/14] whpx: remove whpx specific functions from global includes Date: Wed, 12 Aug 2020 20:32:48 +0200 Message-Id: <20200812183250.9221-13-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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" Signed-off-by: Claudio Fontana Reviewed-by: Richard Henderson --- accel/stubs/Makefile.objs | 1 - accel/stubs/whpx-stub.c | 47 -------------------------------------------= ---- include/sysemu/whpx.h | 19 ------------------- target/i386/whpx-cpus.h | 17 +++++++++++++++++ 4 files changed, 17 insertions(+), 67 deletions(-) delete mode 100644 accel/stubs/whpx-stub.c diff --git a/accel/stubs/Makefile.objs b/accel/stubs/Makefile.objs index 6630954f30..3c2a2fedc4 100644 --- a/accel/stubs/Makefile.objs +++ b/accel/stubs/Makefile.objs @@ -1,5 +1,4 @@ obj-$(call lnot,$(CONFIG_HAX)) +=3D hax-stub.o -obj-$(call lnot,$(CONFIG_WHPX)) +=3D whpx-stub.o obj-$(call lnot,$(CONFIG_KVM)) +=3D kvm-stub.o obj-$(call lnot,$(CONFIG_TCG)) +=3D tcg-stub.o obj-$(call lnot,$(CONFIG_XEN)) +=3D xen-stub.o diff --git a/accel/stubs/whpx-stub.c b/accel/stubs/whpx-stub.c deleted file mode 100644 index 1efb89f25e..0000000000 --- a/accel/stubs/whpx-stub.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * QEMU Windows Hypervisor Platform accelerator (WHPX) stub - * - * 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 "cpu.h" -#include "sysemu/whpx.h" - -int whpx_init_vcpu(CPUState *cpu) -{ - return -1; -} - -int whpx_vcpu_exec(CPUState *cpu) -{ - return -1; -} - -void whpx_destroy_vcpu(CPUState *cpu) -{ -} - -void whpx_vcpu_kick(CPUState *cpu) -{ -} - -void whpx_cpu_synchronize_state(CPUState *cpu) -{ -} - -void whpx_cpu_synchronize_post_reset(CPUState *cpu) -{ -} - -void whpx_cpu_synchronize_post_init(CPUState *cpu) -{ -} - -void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu) -{ -} diff --git a/include/sysemu/whpx.h b/include/sysemu/whpx.h index a84b49e749..59edf13742 100644 --- a/include/sysemu/whpx.h +++ b/include/sysemu/whpx.h @@ -13,18 +13,6 @@ #ifndef QEMU_WHPX_H #define QEMU_WHPX_H =20 - -int whpx_init_vcpu(CPUState *cpu); -int whpx_vcpu_exec(CPUState *cpu); -void whpx_destroy_vcpu(CPUState *cpu); -void whpx_vcpu_kick(CPUState *cpu); - - -void whpx_cpu_synchronize_state(CPUState *cpu); -void whpx_cpu_synchronize_post_reset(CPUState *cpu); -void whpx_cpu_synchronize_post_init(CPUState *cpu); -void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu); - #ifdef CONFIG_WHPX =20 int whpx_enabled(void); @@ -35,11 +23,4 @@ int whpx_enabled(void); =20 #endif /* CONFIG_WHPX */ =20 -/* state subset only touched by the VCPU itself during runtime */ -#define WHPX_SET_RUNTIME_STATE 1 -/* state subset modified during VCPU reset */ -#define WHPX_SET_RESET_STATE 2 -/* full state set, modified during initialization or on vmload */ -#define WHPX_SET_FULL_STATE 3 - #endif /* QEMU_WHPX_H */ diff --git a/target/i386/whpx-cpus.h b/target/i386/whpx-cpus.h index 60b7be3735..165e721589 100644 --- a/target/i386/whpx-cpus.h +++ b/target/i386/whpx-cpus.h @@ -14,4 +14,21 @@ =20 extern CpusAccel whpx_cpus; =20 +int whpx_init_vcpu(CPUState *cpu); +int whpx_vcpu_exec(CPUState *cpu); +void whpx_destroy_vcpu(CPUState *cpu); +void whpx_vcpu_kick(CPUState *cpu); + +void whpx_cpu_synchronize_state(CPUState *cpu); +void whpx_cpu_synchronize_post_reset(CPUState *cpu); +void whpx_cpu_synchronize_post_init(CPUState *cpu); +void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu); + +/* state subset only touched by the VCPU itself during runtime */ +#define WHPX_SET_RUNTIME_STATE 1 +/* state subset modified during VCPU reset */ +#define WHPX_SET_RESET_STATE 2 +/* full state set, modified during initialization or on vmload */ +#define WHPX_SET_FULL_STATE 3 + #endif /* WHPX_CPUS_H */ --=20 2.16.4 From nobody Mon Jul 1 19:59:17 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=1597257602; cv=none; d=zohomail.com; s=zohoarc; b=mwNj4vbs5j+JYF0YVsYDW9d7mWe00go56zfLTucnivuottHQE/g9kKBIns5TRIfNOOOKhhHsewUvBrLXTtRA6iN1zvBFTEF62Qxqo9EvyWr/nUEKZobwbuR9mdOpgl0MTFlcUomgfiDdwpLRzsZ68CqaQQRZBtMHnJCIb5eSuos= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257602; 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=RR3q8+bwjCNIRc7ZOfXX5nAa+W5CrAV3oOWDoOCRW5E=; b=JvScTJ8DbI7SS/HsxQYZSxg9mQX9z4McioD0dKj+JdetzOQroTATYwsN6Qn4OVce3J2viC9yY2zwDH2f3/OJGNO370hlx/dqPVzMAYp8lHbhP8c2sWvNTdVvKxUebRGX7HIYJiAJkEBGWEgn5nzWTx5X/7jHaTxkONJ1mmswNSQ= 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 1597257602381375.43587694892244; Wed, 12 Aug 2020 11:40:02 -0700 (PDT) Received: from localhost ([::1]:40882 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5vfN-0003zk-3D for importer@patchew.org; Wed, 12 Aug 2020 14:40:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46420) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYr-0000Y2-O2 for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:17 -0400 Received: from mx2.suse.de ([195.135.220.15]:40890) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYo-0002EL-Nv for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:17 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 215A5AF93; Wed, 12 Aug 2020 18:33:23 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 13/14] hax: remove hax specific functions from global includes Date: Wed, 12 Aug 2020 20:32:49 +0200 Message-Id: <20200812183250.9221-14-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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" Signed-off-by: Claudio Fontana Reviewed-by: Richard Henderson --- accel/stubs/hax-stub.c | 10 ---------- include/sysemu/hax.h | 17 ----------------- target/i386/hax-all.c | 1 - target/i386/hax-cpus.c | 1 - target/i386/hax-cpus.h | 16 ++++++++++++++++ target/i386/hax-mem.c | 2 +- target/i386/hax-posix.c | 3 +-- target/i386/hax-windows.c | 2 +- target/i386/hax-windows.h | 2 ++ 9 files changed, 21 insertions(+), 33 deletions(-) diff --git a/accel/stubs/hax-stub.c b/accel/stubs/hax-stub.c index 7ad190cae2..1a9da83185 100644 --- a/accel/stubs/hax-stub.c +++ b/accel/stubs/hax-stub.c @@ -21,13 +21,3 @@ int hax_sync_vcpus(void) { return 0; } - -int hax_init_vcpu(CPUState *cpu) -{ - return -ENOSYS; -} - -int hax_smp_cpu_exec(CPUState *cpu) -{ - return -ENOSYS; -} diff --git a/include/sysemu/hax.h b/include/sysemu/hax.h index 9b27e65cc7..12fb54f990 100644 --- a/include/sysemu/hax.h +++ b/include/sysemu/hax.h @@ -22,29 +22,12 @@ #ifndef QEMU_HAX_H #define QEMU_HAX_H =20 - int hax_sync_vcpus(void); -int hax_init_vcpu(CPUState *cpu); -int hax_smp_cpu_exec(CPUState *cpu); -int hax_populate_ram(uint64_t va, uint64_t size); - -void hax_cpu_synchronize_state(CPUState *cpu); -void hax_cpu_synchronize_post_reset(CPUState *cpu); -void hax_cpu_synchronize_post_init(CPUState *cpu); -void hax_cpu_synchronize_pre_loadvm(CPUState *cpu); =20 #ifdef CONFIG_HAX =20 int hax_enabled(void); =20 -#include "qemu/bitops.h" -#include "exec/memory.h" -int hax_vcpu_destroy(CPUState *cpu); -void hax_raise_event(CPUState *cpu); -void hax_reset_vcpu_state(void *opaque); -#include "target/i386/hax-interface.h" -#include "target/i386/hax-i386.h" - #else /* CONFIG_HAX */ =20 #define hax_enabled() (0) diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c index fd1ab673d7..fecfe8cd6e 100644 --- a/target/i386/hax-all.c +++ b/target/i386/hax-all.c @@ -28,7 +28,6 @@ #include "exec/address-spaces.h" =20 #include "qemu-common.h" -#include "hax-i386.h" #include "sysemu/accel.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" diff --git a/target/i386/hax-cpus.c b/target/i386/hax-cpus.c index 69a4162939..e89658ea33 100644 --- a/target/i386/hax-cpus.c +++ b/target/i386/hax-cpus.c @@ -22,7 +22,6 @@ #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" diff --git a/target/i386/hax-cpus.h b/target/i386/hax-cpus.h index ac3cf1f8ae..91937c8527 100644 --- a/target/i386/hax-cpus.h +++ b/target/i386/hax-cpus.h @@ -14,4 +14,20 @@ =20 extern CpusAccel hax_cpus; =20 +#include "hax-interface.h" +#include "hax-i386.h" + +int hax_init_vcpu(CPUState *cpu); +int hax_smp_cpu_exec(CPUState *cpu); +int hax_populate_ram(uint64_t va, uint64_t size); + +void hax_cpu_synchronize_state(CPUState *cpu); +void hax_cpu_synchronize_post_reset(CPUState *cpu); +void hax_cpu_synchronize_post_init(CPUState *cpu); +void hax_cpu_synchronize_pre_loadvm(CPUState *cpu); + +int hax_vcpu_destroy(CPUState *cpu); +void hax_raise_event(CPUState *cpu); +void hax_reset_vcpu_state(void *opaque); + #endif /* HAX_CPUS_H */ diff --git a/target/i386/hax-mem.c b/target/i386/hax-mem.c index 6bb5a24917..71e637cf16 100644 --- a/target/i386/hax-mem.c +++ b/target/i386/hax-mem.c @@ -13,7 +13,7 @@ #include "exec/address-spaces.h" #include "qemu/error-report.h" =20 -#include "target/i386/hax-i386.h" +#include "hax-cpus.h" #include "qemu/queue.h" =20 #define DEBUG_HAX_MEM 0 diff --git a/target/i386/hax-posix.c b/target/i386/hax-posix.c index 6fb7867d11..735a749d4b 100644 --- a/target/i386/hax-posix.c +++ b/target/i386/hax-posix.c @@ -14,9 +14,8 @@ #include "qemu/osdep.h" #include =20 -#include "target/i386/hax-i386.h" - #include "sysemu/cpus.h" +#include "hax-cpus.h" =20 hax_fd hax_mod_open(void) { diff --git a/target/i386/hax-windows.c b/target/i386/hax-windows.c index 469b48e608..6c82dfb54f 100644 --- a/target/i386/hax-windows.c +++ b/target/i386/hax-windows.c @@ -12,7 +12,7 @@ =20 #include "qemu/osdep.h" #include "cpu.h" -#include "hax-i386.h" +#include "hax-cpus.h" =20 /* * return 0 when success, -1 when driver not loaded, diff --git a/target/i386/hax-windows.h b/target/i386/hax-windows.h index 12cbd813dc..a5ce12d663 100644 --- a/target/i386/hax-windows.h +++ b/target/i386/hax-windows.h @@ -23,6 +23,8 @@ #include #include =20 +#include "hax-cpus.h" + #define HAX_INVALID_FD INVALID_HANDLE_VALUE =20 static inline void hax_mod_close(struct hax_state *hax) --=20 2.16.4 From nobody Mon Jul 1 19:59:17 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=1597257533; cv=none; d=zohomail.com; s=zohoarc; b=JNmReouVEAyo9/w8Ug+vzFLHVZ78Y/F29KGc6YrmlAX/axGdrU18xcqLgaEl0m4A7M6nRMjRGjENKM80m8a9OvAwBgExw5neozM+m9aMAWwzTwbs1Al3oO2zqZPk8eYnHtMCq+nPZ12DITP+PMl4ev5U/rhoGPIbaGCh8frQoyc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597257533; 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=4bBNrj3SQn5DzfGe3mp/CX1RQcxPxPe9rDtukhfQ/uE=; b=al+7YinYtryg9wxRmDRR+UA0OCzEyAUlr8XMDSefod+k5cLrvY3+FUvoC+5+Oq5+Olm3HHjmTBmIi5YgSP2C37JFdetk9wfcrX2makmdYsXMhIlEAnW604iuwzkv0fKdkpHBmsQgYQkcbi2sn2PEdWUk9JaG4cXRznwiAIZIC94= 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 15972575333311022.0605109216115; Wed, 12 Aug 2020 11:38:53 -0700 (PDT) Received: from localhost ([::1]:34856 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k5veF-0001bC-UU for importer@patchew.org; Wed, 12 Aug 2020 14:38:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46398) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYq-0000Un-Do for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:16 -0400 Received: from mx2.suse.de ([195.135.220.15]:40892) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k5vYo-0002EM-O3 for qemu-devel@nongnu.org; Wed, 12 Aug 2020 14:33:16 -0400 Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id BC259AF99; Wed, 12 Aug 2020 18:33:23 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Claudio Fontana To: Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Roman Bolshakov Subject: [PATCH v5 14/14] kvm: remove kvm specific functions from global includes Date: Wed, 12 Aug 2020 20:32:50 +0200 Message-Id: <20200812183250.9221-15-cfontana@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200812183250.9221-1-cfontana@suse.de> References: <20200812183250.9221-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/08/11 23:47:43 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=ham autolearn_force=no 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: Laurent Vivier , Thomas Huth , Eduardo Habkost , Pavel Dovgalyuk , Marcelo Tosatti , qemu-devel@nongnu.org, Markus Armbruster , Wenchao Wang , Colin Xu , Claudio Fontana , haxm-team@intel.com, Sunil Muthuswamy , Richard Henderson 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" Signed-off-by: Claudio Fontana Reviewed-by: Richard Henderson --- accel/kvm/kvm-cpus.h | 7 +++++++ accel/stubs/kvm-stub.c | 22 ---------------------- include/sysemu/kvm.h | 7 ------- 3 files changed, 7 insertions(+), 29 deletions(-) diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h index 62fbc911d9..2060a878f0 100644 --- a/accel/kvm/kvm-cpus.h +++ b/accel/kvm/kvm-cpus.h @@ -14,4 +14,11 @@ =20 extern CpusAccel kvm_cpus; =20 +int kvm_init_vcpu(CPUState *cpu); +int kvm_cpu_exec(CPUState *cpu); +void kvm_destroy_vcpu(CPUState *cpu); +void kvm_cpu_synchronize_post_reset(CPUState *cpu); +void kvm_cpu_synchronize_post_init(CPUState *cpu); +void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu); + #endif /* KVM_CPUS_H */ diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index 69f8a842da..680e099463 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -32,15 +32,6 @@ bool kvm_readonly_mem_allowed; bool kvm_ioeventfd_any_length_allowed; bool kvm_msi_use_devid; =20 -void kvm_destroy_vcpu(CPUState *cpu) -{ -} - -int kvm_init_vcpu(CPUState *cpu) -{ - return -ENOSYS; -} - void kvm_flush_coalesced_mmio_buffer(void) { } @@ -49,19 +40,6 @@ void kvm_cpu_synchronize_state(CPUState *cpu) { } =20 -void kvm_cpu_synchronize_post_reset(CPUState *cpu) -{ -} - -void kvm_cpu_synchronize_post_init(CPUState *cpu) -{ -} - -int kvm_cpu_exec(CPUState *cpu) -{ - abort(); -} - bool kvm_has_sync_mmu(void) { return false; diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 7a5f973b6f..bb03e0c68b 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -216,10 +216,6 @@ int kvm_has_many_ioeventfds(void); int kvm_has_gsi_routing(void); int kvm_has_intx_set_mask(void); =20 -int kvm_init_vcpu(CPUState *cpu); -int kvm_cpu_exec(CPUState *cpu); -void kvm_destroy_vcpu(CPUState *cpu); - /** * kvm_arm_supports_user_irq * @@ -479,9 +475,6 @@ int kvm_physical_memory_addr_from_host(KVMState *s, voi= d *ram_addr, #endif /* NEED_CPU_H */ =20 void kvm_cpu_synchronize_state(CPUState *cpu); -void kvm_cpu_synchronize_post_reset(CPUState *cpu); -void kvm_cpu_synchronize_post_init(CPUState *cpu); -void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu); =20 void kvm_init_cpu_signals(CPUState *cpu); =20 --=20 2.16.4