Skip to content

Commit b0cb0a6

Browse files
vpalatinbonzini
authored andcommitted
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 <[email protected]> Signed-off-by: Vincent Palatin <[email protected]> Message-Id: <7b9cae28a0c379ab459c7a8545c9a39762bd394f.1484045952.git.vpalatin@chromium.org> [Drop hax_populate_ram stub. - Paolo] Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 47c1c8c commit b0cb0a6

File tree

11 files changed

+141
-12
lines changed

11 files changed

+141
-12
lines changed

Makefile.target

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ obj-y += target/$(TARGET_BASE_ARCH)/
9797
obj-y += disas.o
9898
obj-y += tcg-runtime.o
9999
obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
100+
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
100101
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
101102

102103
obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decContext.o

configure

+18
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ vhost_net="no"
228228
vhost_scsi="no"
229229
vhost_vsock="no"
230230
kvm="no"
231+
hax="no"
231232
rdma=""
232233
gprof="no"
233234
debug_tcg="no"
@@ -561,6 +562,7 @@ CYGWIN*)
561562
;;
562563
MINGW32*)
563564
mingw32="yes"
565+
hax="yes"
564566
audio_possible_drivers="dsound sdl"
565567
if check_include dsound.h; then
566568
audio_drv_list="dsound"
@@ -610,6 +612,7 @@ OpenBSD)
610612
Darwin)
611613
bsd="yes"
612614
darwin="yes"
615+
hax="yes"
613616
LDFLAGS_SHARED="-bundle -undefined dynamic_lookup"
614617
if [ "$cpu" = "x86_64" ] ; then
615618
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
@@ -919,6 +922,10 @@ for opt do
919922
;;
920923
--enable-kvm) kvm="yes"
921924
;;
925+
--disable-hax) hax="no"
926+
;;
927+
--enable-hax) hax="yes"
928+
;;
922929
--disable-tcg-interpreter) tcg_interpreter="no"
923930
;;
924931
--enable-tcg-interpreter) tcg_interpreter="yes"
@@ -1367,6 +1374,7 @@ disabled with --disable-FEATURE, default is enabled if available:
13671374
fdt fdt device tree
13681375
bluez bluez stack connectivity
13691376
kvm KVM acceleration support
1377+
hax HAX acceleration support
13701378
rdma RDMA-based migration support
13711379
vde support for vde network
13721380
netmap support for netmap network
@@ -5056,6 +5064,7 @@ echo "Linux AIO support $linux_aio"
50565064
echo "ATTR/XATTR support $attr"
50575065
echo "Install blobs $blobs"
50585066
echo "KVM support $kvm"
5067+
echo "HAX support $hax"
50595068
echo "RDMA support $rdma"
50605069
echo "TCG interpreter $tcg_interpreter"
50615070
echo "fdt support $fdt"
@@ -6039,6 +6048,15 @@ case "$target_name" in
60396048
fi
60406049
fi
60416050
esac
6051+
if test "$hax" = "yes" ; then
6052+
if test "$target_softmmu" = "yes" ; then
6053+
case "$target_name" in
6054+
i386|x86_64)
6055+
echo "CONFIG_HAX=y" >> $config_target_mak
6056+
;;
6057+
esac
6058+
fi
6059+
fi
60426060
if test "$target_bigendian" = "yes" ; then
60436061
echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
60446062
fi

cpus.c

+77-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "sysemu/dma.h"
3636
#include "sysemu/hw_accel.h"
3737
#include "sysemu/kvm.h"
38+
#include "sysemu/hax.h"
3839
#include "qmp-commands.h"
3940
#include "exec/exec-all.h"
4041

@@ -1221,6 +1222,46 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
12211222
return NULL;
12221223
}
12231224

1225+
static void *qemu_hax_cpu_thread_fn(void *arg)
1226+
{
1227+
CPUState *cpu = arg;
1228+
int r;
1229+
qemu_thread_get_self(cpu->thread);
1230+
qemu_mutex_lock(&qemu_global_mutex);
1231+
1232+
cpu->thread_id = qemu_get_thread_id();
1233+
cpu->created = true;
1234+
cpu->halted = 0;
1235+
current_cpu = cpu;
1236+
1237+
hax_init_vcpu(cpu);
1238+
qemu_cond_signal(&qemu_cpu_cond);
1239+
1240+
while (1) {
1241+
if (cpu_can_run(cpu)) {
1242+
r = hax_smp_cpu_exec(cpu);
1243+
if (r == EXCP_DEBUG) {
1244+
cpu_handle_guest_debug(cpu);
1245+
}
1246+
}
1247+
1248+
while (cpu_thread_is_idle(cpu)) {
1249+
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
1250+
}
1251+
#ifdef _WIN32
1252+
SleepEx(0, TRUE);
1253+
#endif
1254+
qemu_wait_io_event_common(cpu);
1255+
}
1256+
return NULL;
1257+
}
1258+
1259+
#ifdef _WIN32
1260+
static void CALLBACK dummy_apc_func(ULONG_PTR unused)
1261+
{
1262+
}
1263+
#endif
1264+
12241265
static void qemu_cpu_kick_thread(CPUState *cpu)
12251266
{
12261267
#ifndef _WIN32
@@ -1236,7 +1277,13 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
12361277
exit(1);
12371278
}
12381279
#else /* _WIN32 */
1239-
abort();
1280+
if (!qemu_cpu_is_self(cpu)) {
1281+
if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) {
1282+
fprintf(stderr, "%s: QueueUserAPC failed with error %lu\n",
1283+
__func__, GetLastError());
1284+
exit(1);
1285+
}
1286+
}
12401287
#endif
12411288
}
12421289

@@ -1259,6 +1306,13 @@ void qemu_cpu_kick(CPUState *cpu)
12591306
if (tcg_enabled()) {
12601307
qemu_cpu_kick_no_halt();
12611308
} else {
1309+
if (hax_enabled()) {
1310+
/*
1311+
* FIXME: race condition with the exit_request check in
1312+
* hax_vcpu_hax_exec
1313+
*/
1314+
cpu->exit_request = 1;
1315+
}
12621316
qemu_cpu_kick_thread(cpu);
12631317
}
12641318
}
@@ -1419,6 +1473,26 @@ static void qemu_tcg_init_vcpu(CPUState *cpu)
14191473
}
14201474
}
14211475

1476+
static void qemu_hax_start_vcpu(CPUState *cpu)
1477+
{
1478+
char thread_name[VCPU_THREAD_NAME_SIZE];
1479+
1480+
cpu->thread = g_malloc0(sizeof(QemuThread));
1481+
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
1482+
qemu_cond_init(cpu->halt_cond);
1483+
1484+
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HAX",
1485+
cpu->cpu_index);
1486+
qemu_thread_create(cpu->thread, thread_name, qemu_hax_cpu_thread_fn,
1487+
cpu, QEMU_THREAD_JOINABLE);
1488+
#ifdef _WIN32
1489+
cpu->hThread = qemu_thread_get_handle(cpu->thread);
1490+
#endif
1491+
while (!cpu->created) {
1492+
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
1493+
}
1494+
}
1495+
14221496
static void qemu_kvm_start_vcpu(CPUState *cpu)
14231497
{
14241498
char thread_name[VCPU_THREAD_NAME_SIZE];
@@ -1469,6 +1543,8 @@ void qemu_init_vcpu(CPUState *cpu)
14691543

14701544
if (kvm_enabled()) {
14711545
qemu_kvm_start_vcpu(cpu);
1546+
} else if (hax_enabled()) {
1547+
qemu_hax_start_vcpu(cpu);
14721548
} else if (tcg_enabled()) {
14731549
qemu_tcg_init_vcpu(cpu);
14741550
} else {

hax-stub.c

-5
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ int hax_sync_vcpus(void)
2323
return 0;
2424
}
2525

26-
int hax_populate_ram(uint64_t va, uint32_t size)
27-
{
28-
return -ENOSYS;
29-
}
30-
3126
int hax_init_vcpu(CPUState *cpu)
3227
{
3328
return -ENOSYS;

hw/intc/apic_common.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "hw/i386/apic.h"
2727
#include "hw/i386/apic_internal.h"
2828
#include "trace.h"
29+
#include "sysemu/hax.h"
2930
#include "sysemu/kvm.h"
3031
#include "hw/qdev.h"
3132
#include "hw/sysbus.h"
@@ -316,7 +317,7 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
316317

317318
/* Note: We need at least 1M to map the VAPIC option ROM */
318319
if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
319-
ram_size >= 1024 * 1024) {
320+
!hax_enabled() && ram_size >= 1024 * 1024) {
320321
vapic = sysbus_create_simple("kvmvapic", -1, NULL);
321322
}
322323
s->vapic = vapic;

include/qom/cpu.h

+5
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ struct CPUWatchpoint {
227227
struct KVMState;
228228
struct kvm_run;
229229

230+
struct hax_vcpu_state;
231+
230232
#define TB_JMP_CACHE_BITS 12
231233
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
232234

@@ -392,6 +394,9 @@ struct CPUState {
392394
(absolute value) offset as small as possible. This reduces code
393395
size, especially for hosts without large memory offsets. */
394396
uint32_t tcg_exit_req;
397+
398+
bool hax_vcpu_dirty;
399+
struct hax_vcpu_state *hax_vcpu;
395400
};
396401

397402
QTAILQ_HEAD(CPUTailQ, CPUState);

include/sysemu/hw_accel.h

+9
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,29 @@ static inline void cpu_synchronize_state(CPUState *cpu)
2020
if (kvm_enabled()) {
2121
kvm_cpu_synchronize_state(cpu);
2222
}
23+
if (hax_enabled()) {
24+
hax_cpu_synchronize_state(cpu);
25+
}
2326
}
2427

2528
static inline void cpu_synchronize_post_reset(CPUState *cpu)
2629
{
2730
if (kvm_enabled()) {
2831
kvm_cpu_synchronize_post_reset(cpu);
2932
}
33+
if (hax_enabled()) {
34+
hax_cpu_synchronize_post_reset(cpu);
35+
}
3036
}
3137

3238
static inline void cpu_synchronize_post_init(CPUState *cpu)
3339
{
3440
if (kvm_enabled()) {
3541
kvm_cpu_synchronize_post_init(cpu);
3642
}
43+
if (hax_enabled()) {
44+
hax_cpu_synchronize_post_init(cpu);
45+
}
3746
}
3847

3948
#endif /* QEMU_HW_ACCEL_H */

qemu-options.hx

+11
Original file line numberDiff line numberDiff line change
@@ -3280,6 +3280,17 @@ Enable KVM full virtualization support. This option is only available
32803280
if KVM support is enabled when compiling.
32813281
ETEXI
32823282
3283+
DEF("enable-hax", 0, QEMU_OPTION_enable_hax, \
3284+
"-enable-hax enable HAX virtualization support\n", QEMU_ARCH_I386)
3285+
STEXI
3286+
@item -enable-hax
3287+
@findex -enable-hax
3288+
Enable HAX (Hardware-based Acceleration eXecution) support. This option
3289+
is only available if HAX support is enabled when compiling. HAX is only
3290+
applicable to MAC and Windows platform, and thus does not conflict with
3291+
KVM.
3292+
ETEXI
3293+
32833294
DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid,
32843295
"-xen-domid id specify xen guest domain id\n", QEMU_ARCH_ALL)
32853296
DEF("xen-create", 0, QEMU_OPTION_xen_create,

target/i386/Makefile.objs

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ obj-y += gdbstub.o
55
obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o monitor.o
66
obj-$(CONFIG_KVM) += kvm.o hyperv.o
77
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
8+
# HAX support
9+
ifdef CONFIG_WIN32
10+
obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-windows.o
11+
endif

util/qemu-thread-win32.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -497,8 +497,8 @@ HANDLE qemu_thread_get_handle(QemuThread *thread)
497497

498498
EnterCriticalSection(&data->cs);
499499
if (!data->exited) {
500-
handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE,
501-
thread->tid);
500+
handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME |
501+
THREAD_SET_CONTEXT, FALSE, thread->tid);
502502
} else {
503503
handle = NULL;
504504
}

vl.c

+12-3
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ int main(int argc, char **argv)
9393
#include "sysemu/cpus.h"
9494
#include "migration/colo.h"
9595
#include "sysemu/kvm.h"
96+
#include "sysemu/hax.h"
9697
#include "qapi/qmp/qjson.h"
9798
#include "qemu/option.h"
9899
#include "qemu/config-file.h"
@@ -1913,7 +1914,7 @@ static void main_loop(void)
19131914
int64_t ti;
19141915
#endif
19151916
do {
1916-
nonblocking = !kvm_enabled() && !xen_enabled() && last_io > 0;
1917+
nonblocking = tcg_enabled() && last_io > 0;
19171918
#ifdef CONFIG_PROFILER
19181919
ti = profile_getclock();
19191920
#endif
@@ -3679,6 +3680,10 @@ int main(int argc, char **argv, char **envp)
36793680
olist = qemu_find_opts("machine");
36803681
qemu_opts_parse_noisily(olist, "accel=kvm", false);
36813682
break;
3683+
case QEMU_OPTION_enable_hax:
3684+
olist = qemu_find_opts("machine");
3685+
qemu_opts_parse_noisily(olist, "accel=hax", false);
3686+
break;
36823687
case QEMU_OPTION_M:
36833688
case QEMU_OPTION_machine:
36843689
olist = qemu_find_opts("machine");
@@ -4373,8 +4378,8 @@ int main(int argc, char **argv, char **envp)
43734378

43744379
cpu_ticks_init();
43754380
if (icount_opts) {
4376-
if (kvm_enabled() || xen_enabled()) {
4377-
error_report("-icount is not allowed with kvm or xen");
4381+
if (!tcg_enabled()) {
4382+
error_report("-icount is not allowed with hardware virtualization");
43784383
exit(1);
43794384
}
43804385
configure_icount(icount_opts, &error_abort);
@@ -4510,6 +4515,10 @@ int main(int argc, char **argv, char **envp)
45104515

45114516
numa_post_machine_init();
45124517

4518+
if (hax_enabled()) {
4519+
hax_sync_vcpus();
4520+
}
4521+
45134522
if (qemu_opts_foreach(qemu_find_opts("fw_cfg"),
45144523
parse_fw_cfg, fw_cfg_find(), NULL) != 0) {
45154524
exit(1);

0 commit comments

Comments
 (0)