All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: Vincent Palatin <vpalatin@chromium.org>
Subject: [Qemu-devel] [PULL 31/35] Plumb the HAXM-based hardware acceleration support
Date: Fri, 20 Jan 2017 14:31:35 +0100	[thread overview]
Message-ID: <20170120133139.31080-32-pbonzini@redhat.com> (raw)
In-Reply-To: <20170120133139.31080-1-pbonzini@redhat.com>

From: Vincent Palatin <vpalatin@chromium.org>

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 <david.j.chou@intel.com>

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
Message-Id: <7b9cae28a0c379ab459c7a8545c9a39762bd394f.1484045952.git.vpalatin@chromium.org>
[Drop hax_populate_ram stub. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile.target           |  1 +
 configure                 | 18 +++++++++++
 cpus.c                    | 78 ++++++++++++++++++++++++++++++++++++++++++++++-
 hax-stub.c                |  5 ---
 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 +++++++--
 11 files changed, 141 insertions(+), 12 deletions(-)

diff --git a/Makefile.target b/Makefile.target
index 9e8edd9..fa2b151 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 9879c65..091ae05 100755
--- a/configure
+++ b/configure
@@ -228,6 +228,7 @@ vhost_net="no"
 vhost_scsi="no"
 vhost_vsock="no"
 kvm="no"
+hax="no"
 rdma=""
 gprof="no"
 debug_tcg="no"
@@ -561,6 +562,7 @@ CYGWIN*)
 ;;
 MINGW32*)
   mingw32="yes"
+  hax="yes"
   audio_possible_drivers="dsound sdl"
   if check_include dsound.h; then
     audio_drv_list="dsound"
@@ -610,6 +612,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"
@@ -919,6 +922,10 @@ for opt do
   ;;
   --enable-kvm) kvm="yes"
   ;;
+  --disable-hax) hax="no"
+  ;;
+  --enable-hax) hax="yes"
+  ;;
   --disable-tcg-interpreter) tcg_interpreter="no"
   ;;
   --enable-tcg-interpreter) tcg_interpreter="yes"
@@ -1367,6 +1374,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
   rdma            RDMA-based migration support
   vde             support for vde network
   netmap          support for netmap network
@@ -5056,6 +5064,7 @@ echo "Linux AIO support $linux_aio"
 echo "ATTR/XATTR support $attr"
 echo "Install blobs     $blobs"
 echo "KVM support       $kvm"
+echo "HAX support       $hax"
 echo "RDMA support      $rdma"
 echo "TCG interpreter   $tcg_interpreter"
 echo "fdt support       $fdt"
@@ -6039,6 +6048,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 fc78502..71a82e5 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/hax-stub.c b/hax-stub.c
index a532dba..c0e6f89 100644
--- a/hax-stub.c
+++ b/hax-stub.c
@@ -23,11 +23,6 @@ int hax_sync_vcpus(void)
     return 0;
 }
 
-int hax_populate_ram(uint64_t va, uint32_t size)
-{
-    return -ENOSYS;
-}
-
 int hax_init_vcpu(CPUState *cpu)
 {
     return -ENOSYS;
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index d78c885..3945dfd 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 3f79a8e..ca4d0fb 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 03812cf..c9b3105 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 b62d2d7..80df526 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 b223d79..acbe7b0 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 728e76b..95d4ba4 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 a52c5f2..a260f30 100644
--- a/vl.c
+++ b/vl.c
@@ -93,6 +93,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"
@@ -1913,7 +1914,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
@@ -3679,6 +3680,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");
@@ -4373,8 +4378,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);
@@ -4510,6 +4515,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);
-- 
2.9.3

  parent reply	other threads:[~2017-01-20 13:32 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-20 13:31 [Qemu-devel] [PULL v3 00/32] Misc patches for 2017-01-11 Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 01/35] bugfix: vm halt when in reset looping Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 02/35] megasas: fix guest-triggered memory leak Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 03/35] qom: Make all interface types abstract Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 04/35] smbios: filter based on CONFIG_SMBIOS rather than TARGET Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 05/35] stubs: merge all monitor stubs in one file, remove monitor_cur_is_qmp stub Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 06/35] stubs: move smbios stubs to hw/smbios Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 07/35] stubs: move acpi stubs to hw/acpi Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 08/35] stubs: remove unused stub for serial_hd Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 09/35] hw: move reset handlers from vl.c to hw/core Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 10/35] stubs: group stubs for user-mode emulation Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 11/35] stubs: group all monitor_fdset_* functions in a single file Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 12/35] stubs: move vhost stubs to stubs/vhost.o Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 13/35] event_notifier: cleanups around event_notifier_set_handler Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 14/35] build: remove --enable-colo/--disable-colo Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 15/35] stubs: remove stubs/kvm.c Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 16/35] acpi: filter based on CONFIG_ACPI_X86 rather than TARGET Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 17/35] pc: fix crash in rtc_set_memory() if initial cpu is marked as hotplugged Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 18/35] scsi-block: fix direction of BYTCHK test for VERIFY commands Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 19/35] serial: fix memory leak in serial exit Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 20/35] qemu-thread: fix qemu_thread_set_name() race in qemu_thread_create() Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 21/35] hxtool: emit Texinfo headings as @subsection Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 22/35] x86: ioapic: add traces for ioapic Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 23/35] x86: ioapic: dump version for "info ioapic" Paolo Bonzini
2017-01-30 14:07   ` Peter Maydell
2017-01-30 19:33     ` Paolo Bonzini
2017-02-03  7:12       ` Peter Xu
2017-01-20 13:31 ` [Qemu-devel] [PULL 24/35] x86: ioapic: fix fail migration when irqchip=split Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 25/35] exec: Add missing rcu_read_unlock Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 26/35] char: fix ctrl-a b not working Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 27/35] ramblock-notifier: new Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 28/35] KVM: PPC: eliminate unnecessary duplicate constants Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 29/35] kvm: move cpu synchronization code Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 30/35] target/i386: Add Intel HAX files Paolo Bonzini
2017-01-20 13:31 ` Paolo Bonzini [this message]
2017-01-20 13:31 ` [Qemu-devel] [PULL 32/35] hax: add Darwin support Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 33/35] Revert "win32: don't run subprocess tests on Mingw32 platform" Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 34/35] bitmap: assert that start and nr are non negative Paolo Bonzini
2017-01-20 13:31 ` [Qemu-devel] [PULL 35/35] pc.h: move x-mach-use-reliable-get-clock compat entry to PC_COMPAT_2_8 Paolo Bonzini
2017-01-20 15:16 ` [Qemu-devel] [PULL v3 00/32] Misc patches for 2017-01-11 no-reply
2017-01-20 17:16 ` Paolo Bonzini
2017-01-23 10:07 ` Peter Maydell
2017-01-23 14:02   ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170120133139.31080-32-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=vpalatin@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.