From patchwork Tue Jan 10 10:59:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Palatin X-Patchwork-Id: 713218 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tyTcQ659Fz9t0X for ; Tue, 10 Jan 2017 22:01:58 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="JQT3C5DY"; dkim-atps=neutral Received: from localhost ([::1]:46298 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cQuBg-0006Hj-F2 for incoming@patchwork.ozlabs.org; Tue, 10 Jan 2017 06:01:56 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32912) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cQuAJ-0005ND-Ki for qemu-devel@nongnu.org; Tue, 10 Jan 2017 06:00:33 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cQuAD-0003qW-07 for qemu-devel@nongnu.org; Tue, 10 Jan 2017 06:00:31 -0500 Received: from mail-wj0-x234.google.com ([2a00:1450:400c:c01::234]:35357) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cQuAC-0003qI-MH for qemu-devel@nongnu.org; Tue, 10 Jan 2017 06:00:24 -0500 Received: by mail-wj0-x234.google.com with SMTP id i20so80179266wjn.2 for ; Tue, 10 Jan 2017 03:00:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=BTtz7bvWkvNH7U5alWKXQ2xVSE3NQmEMxvpOCYQ4lLs=; b=JQT3C5DYbemvp8Mr6iJdQk/kLNIznghjIHRDdejZ75aXzsfBuGdcqsO0hYhmjrELHH ZXg7SZTS+o4LJ+kftG5TZWKeF6O8k4U6v6cxNqgFu+YhM2zsVJbYJVcDeHHdb+pWLGjb MoF5ODTfFNktDgOzWcOEL6xOD5hCC9jeiuIJHkceB2dCXo+Ei/IuA/PNsd+BjPLUvHaP AsdWzupw5lVTZna1Mpt2EaRyn1qfAKE43xRSzoGb1Q+6d0a3iNJkgRyJ47hsSyN85p1U Hl2FbnV3tB3eqivM8RLybR5nSUrTMagMzZFimSeDrPDlA5gY4Q+0koGjIvYKw3onoiIn zGmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:in-reply-to:references; bh=BTtz7bvWkvNH7U5alWKXQ2xVSE3NQmEMxvpOCYQ4lLs=; b=dpZo/8jqeuoKhNOzwwnAJUA2MChYzXVuGvCyKtd2KJdfKrcN/9bLJ5427fKl9aGUgH lEggKwMlN/+kaiwOuCU0j7rxuOZVXUqKxTGWQhGQrb1DpDXe4dSaXL+zTyHzRC86Vtay Dz7mxbP3FZsALCjxUq5zwsx1hf/UtqMLBTcbaOKgz+Lbk71HuuKFdRl53LB3V6ssJGMH oBYQuKr3FdfvcWBUZRnQejudSXCELs2AN1y6WKdtWNQnKjUM9c/DwWKDmq116VBiq58B 57NE2ItUdYc9OkO9hirfej5k+fhrOlgxf7nJikU2wFLuXUBbTHtFRRFk2ZjQ++rtddM7 uMoQ== X-Gm-Message-State: AIkVDXL43fW5Mx818A3WwzrLi7en6use9aTyCeNx6EmieCetZIfalbIdRJYkSa+uPgPis2dI X-Received: by 10.194.84.175 with SMTP id a15mr1395394wjz.113.1484046023263; Tue, 10 Jan 2017 03:00:23 -0800 (PST) Received: from vpalatin.zrh.corp.google.com ([172.16.114.40]) by smtp.gmail.com with ESMTPSA id ks1sm1585992wjb.26.2017.01.10.03.00.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 10 Jan 2017 03:00:22 -0800 (PST) From: Vincent Palatin To: qemu-devel Date: Tue, 10 Jan 2017 11:59:57 +0100 Message-Id: <7b9cae28a0c379ab459c7a8545c9a39762bd394f.1484045952.git.vpalatin@chromium.org> X-Mailer: git-send-email 2.11.0.390.gc69c2f50cf-goog In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c01::234 Subject: [Qemu-devel] [PATCH v6 3/4] Plumb the HAXM-based hardware acceleration support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yu Ning , Vincent Palatin , Eduardo Habkost , "Michael S . Tsirkin" , Stefan Weil , Marcelo Tosatti , Paolo Bonzini Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Use the Intel HAX is kernel-based hardware acceleration module for Windows (similar to KVM on Linux). Based on the "target/i386: Add Intel HAX to android emulator" patch from David Chou Signed-off-by: Vincent Palatin --- Makefile.target | 1 + configure | 18 +++++++++++ cpus.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++- hw/intc/apic_common.c | 3 +- include/qom/cpu.h | 5 +++ include/sysemu/hw_accel.h | 9 ++++++ qemu-options.hx | 11 +++++++ target/i386/Makefile.objs | 4 +++ util/qemu-thread-win32.c | 4 +-- vl.c | 15 +++++++-- 10 files changed, 141 insertions(+), 7 deletions(-) diff --git a/Makefile.target b/Makefile.target index 8ae82cb311..c62e2acee3 100644 --- a/Makefile.target +++ b/Makefile.target @@ -97,6 +97,7 @@ obj-y += target/$(TARGET_BASE_ARCH)/ obj-y += disas.o obj-y += tcg-runtime.o obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o +obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decContext.o diff --git a/configure b/configure index 86f5214dd0..249faa164d 100755 --- a/configure +++ b/configure @@ -228,6 +228,7 @@ vhost_net="no" vhost_scsi="no" vhost_vsock="no" kvm="no" +hax="no" colo="yes" rdma="" gprof="no" @@ -562,6 +563,7 @@ CYGWIN*) ;; MINGW32*) mingw32="yes" + hax="yes" audio_possible_drivers="dsound sdl" if check_include dsound.h; then audio_drv_list="dsound" @@ -611,6 +613,7 @@ OpenBSD) Darwin) bsd="yes" darwin="yes" + hax="yes" LDFLAGS_SHARED="-bundle -undefined dynamic_lookup" if [ "$cpu" = "x86_64" ] ; then QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS" @@ -920,6 +923,10 @@ for opt do ;; --enable-kvm) kvm="yes" ;; + --disable-hax) hax="no" + ;; + --enable-hax) hax="yes" + ;; --disable-colo) colo="no" ;; --enable-colo) colo="yes" @@ -1372,6 +1379,7 @@ disabled with --disable-FEATURE, default is enabled if available: fdt fdt device tree bluez bluez stack connectivity kvm KVM acceleration support + hax HAX acceleration support colo COarse-grain LOck-stepping VM for Non-stop Service rdma RDMA-based migration support vde support for vde network @@ -5063,6 +5071,7 @@ echo "ATTR/XATTR support $attr" echo "Install blobs $blobs" echo "KVM support $kvm" echo "COLO support $colo" +echo "HAX support $hax" echo "RDMA support $rdma" echo "TCG interpreter $tcg_interpreter" echo "fdt support $fdt" @@ -6050,6 +6059,15 @@ case "$target_name" in fi fi esac +if test "$hax" = "yes" ; then + if test "$target_softmmu" = "yes" ; then + case "$target_name" in + i386|x86_64) + echo "CONFIG_HAX=y" >> $config_target_mak + ;; + esac + fi +fi if test "$target_bigendian" = "yes" ; then echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak fi diff --git a/cpus.c b/cpus.c index fc78502ce5..71a82e5004 100644 --- a/cpus.c +++ b/cpus.c @@ -35,6 +35,7 @@ #include "sysemu/dma.h" #include "sysemu/hw_accel.h" #include "sysemu/kvm.h" +#include "sysemu/hax.h" #include "qmp-commands.h" #include "exec/exec-all.h" @@ -1221,6 +1222,46 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) return NULL; } +static void *qemu_hax_cpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + int r; + qemu_thread_get_self(cpu->thread); + qemu_mutex_lock(&qemu_global_mutex); + + cpu->thread_id = qemu_get_thread_id(); + cpu->created = true; + cpu->halted = 0; + current_cpu = cpu; + + hax_init_vcpu(cpu); + qemu_cond_signal(&qemu_cpu_cond); + + while (1) { + if (cpu_can_run(cpu)) { + r = hax_smp_cpu_exec(cpu); + if (r == EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + + while (cpu_thread_is_idle(cpu)) { + qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); + } +#ifdef _WIN32 + SleepEx(0, TRUE); +#endif + qemu_wait_io_event_common(cpu); + } + return NULL; +} + +#ifdef _WIN32 +static void CALLBACK dummy_apc_func(ULONG_PTR unused) +{ +} +#endif + static void qemu_cpu_kick_thread(CPUState *cpu) { #ifndef _WIN32 @@ -1236,7 +1277,13 @@ static void qemu_cpu_kick_thread(CPUState *cpu) exit(1); } #else /* _WIN32 */ - abort(); + 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); + } + } #endif } @@ -1259,6 +1306,13 @@ void qemu_cpu_kick(CPUState *cpu) if (tcg_enabled()) { qemu_cpu_kick_no_halt(); } else { + if (hax_enabled()) { + /* + * FIXME: race condition with the exit_request check in + * hax_vcpu_hax_exec + */ + cpu->exit_request = 1; + } qemu_cpu_kick_thread(cpu); } } @@ -1419,6 +1473,26 @@ static void qemu_tcg_init_vcpu(CPUState *cpu) } } +static void qemu_hax_start_vcpu(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + cpu->thread = g_malloc0(sizeof(QemuThread)); + cpu->halt_cond = 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 = qemu_thread_get_handle(cpu->thread); +#endif + while (!cpu->created) { + qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); + } +} + static void qemu_kvm_start_vcpu(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; @@ -1469,6 +1543,8 @@ void qemu_init_vcpu(CPUState *cpu) if (kvm_enabled()) { qemu_kvm_start_vcpu(cpu); + } else if (hax_enabled()) { + qemu_hax_start_vcpu(cpu); } else if (tcg_enabled()) { qemu_tcg_init_vcpu(cpu); } else { diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index d78c885509..3945dfd7b9 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -26,6 +26,7 @@ #include "hw/i386/apic.h" #include "hw/i386/apic_internal.h" #include "trace.h" +#include "sysemu/hax.h" #include "sysemu/kvm.h" #include "hw/qdev.h" #include "hw/sysbus.h" @@ -316,7 +317,7 @@ static void apic_common_realize(DeviceState *dev, Error **errp) /* Note: We need at least 1M to map the VAPIC option ROM */ if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK && - ram_size >= 1024 * 1024) { + !hax_enabled() && ram_size >= 1024 * 1024) { vapic = sysbus_create_simple("kvmvapic", -1, NULL); } s->vapic = vapic; diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 3f79a8e955..ca4d0fb1b4 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -227,6 +227,8 @@ struct CPUWatchpoint { struct KVMState; struct kvm_run; +struct hax_vcpu_state; + #define TB_JMP_CACHE_BITS 12 #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) @@ -392,6 +394,9 @@ struct CPUState { (absolute value) offset as small as possible. This reduces code size, especially for hosts without large memory offsets. */ uint32_t tcg_exit_req; + + bool hax_vcpu_dirty; + struct hax_vcpu_state *hax_vcpu; }; QTAILQ_HEAD(CPUTailQ, CPUState); diff --git a/include/sysemu/hw_accel.h b/include/sysemu/hw_accel.h index 03812cfeb3..c9b3105bc7 100644 --- a/include/sysemu/hw_accel.h +++ b/include/sysemu/hw_accel.h @@ -20,6 +20,9 @@ static inline void cpu_synchronize_state(CPUState *cpu) if (kvm_enabled()) { kvm_cpu_synchronize_state(cpu); } + if (hax_enabled()) { + hax_cpu_synchronize_state(cpu); + } } static inline void cpu_synchronize_post_reset(CPUState *cpu) @@ -27,6 +30,9 @@ 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); + } } static inline void cpu_synchronize_post_init(CPUState *cpu) @@ -34,6 +40,9 @@ 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); + } } #endif /* QEMU_HW_ACCEL_H */ diff --git a/qemu-options.hx b/qemu-options.hx index c534a2f7f9..7fc2807206 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3280,6 +3280,17 @@ Enable KVM full virtualization support. This option is only available if KVM support is enabled when compiling. ETEXI +DEF("enable-hax", 0, QEMU_OPTION_enable_hax, \ + "-enable-hax enable HAX virtualization support\n", QEMU_ARCH_I386) +STEXI +@item -enable-hax +@findex -enable-hax +Enable HAX (Hardware-based Acceleration eXecution) support. This option +is only available if HAX support is enabled when compiling. HAX is only +applicable to MAC and Windows platform, and thus does not conflict with +KVM. +ETEXI + DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid, "-xen-domid id specify xen guest domain id\n", QEMU_ARCH_ALL) DEF("xen-create", 0, QEMU_OPTION_xen_create, diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs index b223d7932b..acbe7b0752 100644 --- a/target/i386/Makefile.objs +++ b/target/i386/Makefile.objs @@ -5,3 +5,7 @@ obj-y += gdbstub.o obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o monitor.o obj-$(CONFIG_KVM) += kvm.o hyperv.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o +# HAX support +ifdef CONFIG_WIN32 +obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-windows.o +endif diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c index 728e76b5b2..95d4ba4f60 100644 --- a/util/qemu-thread-win32.c +++ b/util/qemu-thread-win32.c @@ -497,8 +497,8 @@ HANDLE qemu_thread_get_handle(QemuThread *thread) EnterCriticalSection(&data->cs); if (!data->exited) { - handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE, - thread->tid); + handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME | + THREAD_SET_CONTEXT, FALSE, thread->tid); } else { handle = NULL; } diff --git a/vl.c b/vl.c index a23de18fa9..b617ab4016 100644 --- a/vl.c +++ b/vl.c @@ -92,6 +92,7 @@ int main(int argc, char **argv) #include "sysemu/cpus.h" #include "migration/colo.h" #include "sysemu/kvm.h" +#include "sysemu/hax.h" #include "qapi/qmp/qjson.h" #include "qemu/option.h" #include "qemu/config-file.h" @@ -1959,7 +1960,7 @@ static void main_loop(void) int64_t ti; #endif do { - nonblocking = !kvm_enabled() && !xen_enabled() && last_io > 0; + nonblocking = tcg_enabled() && last_io > 0; #ifdef CONFIG_PROFILER ti = profile_getclock(); #endif @@ -3725,6 +3726,10 @@ int main(int argc, char **argv, char **envp) olist = qemu_find_opts("machine"); qemu_opts_parse_noisily(olist, "accel=kvm", false); break; + case QEMU_OPTION_enable_hax: + olist = qemu_find_opts("machine"); + qemu_opts_parse_noisily(olist, "accel=hax", false); + break; case QEMU_OPTION_M: case QEMU_OPTION_machine: olist = qemu_find_opts("machine"); @@ -4419,8 +4424,8 @@ int main(int argc, char **argv, char **envp) cpu_ticks_init(); if (icount_opts) { - if (kvm_enabled() || xen_enabled()) { - error_report("-icount is not allowed with kvm or xen"); + if (!tcg_enabled()) { + error_report("-icount is not allowed with hardware virtualization"); exit(1); } configure_icount(icount_opts, &error_abort); @@ -4556,6 +4561,10 @@ int main(int argc, char **argv, char **envp) numa_post_machine_init(); + if (hax_enabled()) { + hax_sync_vcpus(); + } + if (qemu_opts_foreach(qemu_find_opts("fw_cfg"), parse_fw_cfg, fw_cfg_find(), NULL) != 0) { exit(1);