Plumb the HAXM-based hardware acceleration support
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>
This commit is contained in:
parent
47c1c8c12f
commit
b0cb0a66d6
@ -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
|
||||
|
18
configure
vendored
18
configure
vendored
@ -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
|
||||
|
78
cpus.c
78
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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
15
vl.c
15
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);
|
||||
|
Loading…
Reference in New Issue
Block a user