Add HAX support
cover Add HAX support
I took a stab at trying to rebase/upstream the support for Intel HAXM. (Hardware Accelerated Execution Manager).
Intel HAX is kernel-based hardware acceleration module for Windows and MacOSX.
I have based my work on the last version of the source code I found:
the emu-2.2-release branch in the external/qemu-android repository as used by the Android emulator.
In patch 2/3, I have forward-ported the core HAX code mostly unmodified from there, I just did some minor touch up to make it build and run properly. So it might contain some outdated constructs and probably requires more attention (thus the 'RFC' for this patchset).
In patch 3/3, I have put the plumbing into the QEMU code base, I did some clean up there and it is reasonably intrusive: i.e.
Makefile.target | 1 + configure | 18 +++++++ cpu-exec.c | 23 ++++++++- cpus.c | 125 ++++++++++++++++++++++++++++++++++++++++------ exec.c | 16 ++++++ 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 | 7 +++ target-i386/seg_helper.c | 5 ++ target-i386/translate.c | 8 +++ vl.c | 17 +++++-- 13 files changed, 229 insertions(+), 19 deletions(-)
I'm not so happy with the qemu_cpu_kick_thread mess in cpus.c, if somebody can help/advise.
The patch 1/3 just extracts from KVM specific header the cpu_synchronize_ functions that HAX is also using.
I have tested the end result on a Windows 10 Pro machine (with UG support) with the Intel HAXM module 6.0.4 and a large ChromiumOS x86_64 image to exercise various code paths. It looks stable.
I also did a quick regression testing of the integration by running a Linux build with KVM enabled.
Vincent Palatin (3):
kvm: move cpu synchronization code
target-i386: Add Intel HAX files
Plumb the HAXM-based hardware acceleration support
Makefile.target | 1 + configure | 18 + cpu-exec.c | 23 +- cpus.c | 126 +++- exec.c | 16 + gdbstub.c | 1 + hax-stub.c | 66 ++ hw/i386/kvm/apic.c | 1 + hw/i386/kvmvapic.c | 1 + hw/intc/apic_common.c | 3 +- hw/misc/vmport.c | 2 +- include/qom/cpu.h | 5 + include/sysemu/hax.h | 66 ++ include/sysemu/hw_accel.h | 48 ++ include/sysemu/kvm.h | 23 - monitor.c | 2 +- qemu-options.hx | 11 + qom/cpu.c | 2 +- target-arm/cpu.c | 2 +- target-i386/Makefile.objs | 7 + target-i386/hax-all.c | 1449 +++++++++++++++++++++++++++++++++++++++++++ target-i386/hax-darwin.c | 315 ++++++++++ target-i386/hax-darwin.h | 63 ++ target-i386/hax-i386.h | 94 +++ target-i386/hax-interface.h | 357 +++++++++++ target-i386/hax-slot.c | 332 ++++++++++ target-i386/hax-slot.h | 58 ++ target-i386/hax-windows.c | 478 ++++++++++++++ target-i386/hax-windows.h | 89 +++ target-i386/helper.c | 1 + target-i386/kvm.c | 1 + target-i386/seg_helper.c | 5 + target-i386/translate.c | 8 + vl.c | 17 +- 34 files changed, 3645 insertions(+), 46 deletions(-) create mode 100644 hax-stub.c create mode 100644 include/sysemu/hax.h create mode 100644 include/sysemu/hw_accel.h create mode 100644 target-i386/hax-all.c create mode 100644 target-i386/hax-darwin.c create mode 100644 target-i386/hax-darwin.h create mode 100644 target-i386/hax-i386.h create mode 100644 target-i386/hax-interface.h create mode 100644 target-i386/hax-slot.c create mode 100644 target-i386/hax-slot.h create mode 100644 target-i386/hax-windows.c create mode 100644 target-i386/hax-windows.h
Signature · 1 line
2.8.0.rc3.226.g39d4020
PATCH 1/3 kvm: move cpu synchronization code
Move the generic cpu_synchronize_ functions to the common hw_accel.h header, in order to prepare for the addition of a second hardware accelerator.
--- cpus.c | 1 + gdbstub.c | 1 + hw/i386/kvm/apic.c | 1 + hw/i386/kvmvapic.c | 1 + hw/misc/vmport.c | 2 +- include/sysemu/hw_accel.h | 39 +++++++++++++++++++++++++++++++++++++++ include/sysemu/kvm.h | 23 ----------------------- monitor.c | 2 +- qom/cpu.c | 2 +- target-arm/cpu.c | 2 +- target-i386/helper.c | 1 + target-i386/kvm.c | 1 + 12 files changed, 49 insertions(+), 27 deletions(-) create mode 100644 include/sysemu/hw_accel.h
cpus.c +1 -0
@@ -33,6 +33,7 @@#include "sysemu/block-backend.h" #include "exec/gdbstub.h" #include "sysemu/dma.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "qmp-commands.h" #include "exec/exec-all.h"
gdbstub.c +1 -0
@@ -32,6 +32,7 @@#define MAX_PACKET_LENGTH 4096#include "qemu/sockets.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "exec/semihost.h" #include "exec/exec-all.h"
hw/i386/kvm/apic.c +1 -0
@@ -14,6 +14,7 @@#include "cpu.h" #include "hw/i386/apic_internal.h" #include "hw/pci/msi.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "target-i386/kvm_i386.h"
hw/i386/kvmvapic.c +1 -0
@@ -14,6 +14,7 @@#include "exec/exec-all.h" #include "sysemu/sysemu.h" #include "sysemu/cpus.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "hw/i386/apic_internal.h" #include "hw/sysbus.h"
hw/misc/vmport.c +1 -1
@@ -25,7 +25,7 @@#include "hw/hw.h" #include "hw/isa/isa.h" #include "hw/i386/pc.h" -#include "sysemu/kvm.h" +#include "sysemu/hw_accel.h" #include "hw/qdev.h" //#define VMPORT_DEBUG
include/sysemu/hw_accel.h new file +39 -0
@@ -0,0 +1,39 @@ +/* +* QEMU Hardware accelertors support +* +* Copyright 2016 Google, Inc. +* +* This work is licensed under the terms of the GNU GPL, version 2 or later. +* See the COPYING file in the top-level directory. +* +*/ + +#ifndef QEMU_HW_ACCEL_H +#define QEMU_HW_ACCEL_H + +#include "qom/cpu.h" +#include "sysemu/hax.h" +#include "sysemu/kvm.h" + +static inline void cpu_synchronize_state (CPUState *cpu) +{ +if (kvm_enabled ()) { +kvm_cpu_synchronize_state (cpu); + } +} + +static inline void cpu_synchronize_post_reset (CPUState *cpu) +{ +if (kvm_enabled ()) { +kvm_cpu_synchronize_post_reset (cpu); + } +} + +static inline void cpu_synchronize_post_init (CPUState *cpu) +{ +if (kvm_enabled ()) { +kvm_cpu_synchronize_post_init (cpu); + } +} + +#endif /* QEMU_HW_ACCEL_H */
include/sysemu/kvm.h +0 -23
@@ -461,29 +461,6 @@ void kvm_cpu_synchronize_state(CPUState *cpu);void kvm_cpu_synchronize_post_reset (CPUState *cpu);void kvm_cpu_synchronize_post_init (CPUState *cpu); -/* generic hooks - to be moved/refactored once there are more users */ - -static inline void cpu_synchronize_state (CPUState *cpu) -{ -if (kvm_enabled ()) { -kvm_cpu_synchronize_state (cpu); - } -} - -static inline void cpu_synchronize_post_reset (CPUState *cpu) -{ -if (kvm_enabled ()) { -kvm_cpu_synchronize_post_reset (cpu); - } -} - -static inline void cpu_synchronize_post_init (CPUState *cpu) -{ -if (kvm_enabled ()) { -kvm_cpu_synchronize_post_init (cpu); - } -} -/** * kvm_irqchip_add_msi_route - Add MSI route for specific vector * @s: KVM state
monitor.c +1 -1
@@ -50,7 +50,7 @@#include "sysemu/balloon.h" #include "qemu/timer.h" #include "migration/migration.h" -#include "sysemu/kvm.h" +#include "sysemu/hw_accel.h" #include "qemu/acl.h" #include "sysemu/tpm.h" #include "qapi/qmp/qerror.h"
qom/cpu.c +1 -1
@@ -22,7 +22,7 @@#include "qapi/error.h" #include "qemu-common.h" #include "qom/cpu.h" -#include "sysemu/kvm.h" +#include "sysemu/hw_accel.h" #include "qemu/notify.h" #include "qemu/log.h" #include "exec/log.h"
target-arm/cpu.c +1 -1
@@ -31,7 +31,7 @@#endif #include "hw/arm/arm.h" #include "sysemu/sysemu.h" -#include "sysemu/kvm.h" +#include "sysemu/hw_accel.h" #include "kvm_arm.h" static void arm_cpu_set_pc (CPUState *cs,vaddr value)
target-i386/helper.c +1 -0
@@ -24,6 +24,7 @@#include "kvm_i386.h" #ifndef CONFIG_USER_ONLY #include "sysemu/sysemu.h" +#include "sysemu/hw_accel.h" #include "monitor/monitor.h" #include "hw/i386/apic_internal.h" #endif
target-i386/kvm.c +1 -0
@@ -23,6 +23,7 @@#include "qemu-common.h" #include "cpu.h" #include "sysemu/sysemu.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm_int.h" #include "kvm_i386.h" #include "hyperv.h"
Signature · 1 line
2.8.0.rc3.226.g39d4020
Re: [Qemu-devel] [PATCH 1/3] kvm: move cpu synchronization code
Quoted 217 lines · Vincent Palatin
Move the generic
cpu_synchronize_functions to the commonhw_accel.hheader, in order to prepare for the addition of a second hardware accelerator.Signed-off-by Vincent Palatin <[email protected]>--- cpus.c | 1 + gdbstub.c | 1 + hw/i386/kvm/apic.c | 1 + hw/i386/kvmvapic.c | 1 + hw/misc/vmport.c | 2 +- include/sysemu/hw_accel.h | 39 +++++++++++++++++++++++++++++++++++++++ include/sysemu/kvm.h | 23 ----------------------- monitor.c | 2 +- qom/cpu.c | 2 +- target-arm/cpu.c | 2 +- target-i386/helper.c | 1 + target-i386/kvm.c | 1 + 12 files changed, 49 insertions(+), 27 deletions(-) create mode 100644 include/sysemu/hw_accel.hcpus.c +1
-0@@ -33,6 +33,7 @@#include "sysemu/block-backend.h" #include "exec/gdbstub.h" #include "sysemu/dma.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "qmp-commands.h" #include "exec/exec-all.h" gdbstub.c +1
-0@@ -32,6 +32,7 @@#define MAX_PACKET_LENGTH 4096#include "qemu/sockets.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "exec/semihost.h" #include "exec/exec-all.h" hw/i386/kvm/apic.c +1
-0@@ -14,6 +14,7 @@#include "cpu.h" #include "hw/i386/apic_internal.h" #include "hw/pci/msi.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "target-i386/kvm_i386.h" hw/i386/kvmvapic.c +1
-0@@ -14,6 +14,7 @@#include "exec/exec-all.h" #include "sysemu/sysemu.h" #include "sysemu/cpus.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "hw/i386/apic_internal.h" #include "hw/sysbus.h" hw/misc/vmport.c +1
-1@@ -25,7 +25,7 @@#include "hw/hw.h" #include "hw/isa/isa.h" #include "hw/i386/pc.h" -#include "sysemu/kvm.h" +#include "sysemu/hw_accel.h" #include "hw/qdev.h" //#define VMPORT_DEBUG include/sysemu/hw_accel.h new file +39
-0@@ -0,0 +1,39 @@ +/* +* QEMU Hardware accelertors support +* +* Copyright 2016 Google, Inc. +* +* This work is licensed under the terms of the GNU GPL, version 2 or later. +* See the COPYING file in the top-level directory. +* +*/ + +#ifndef QEMU_HW_ACCEL_H +#define QEMU_HW_ACCEL_H + +#include "qom/cpu.h" +#include "sysemu/hax.h" +#include "sysemu/kvm.h" + +static inline void cpu_synchronize_state (CPUState *cpu) +{ +if (kvm_enabled ()) { +kvm_cpu_synchronize_state (cpu); + } +} + +static inline void cpu_synchronize_post_reset (CPUState *cpu) +{ +if (kvm_enabled ()) { +kvm_cpu_synchronize_post_reset (cpu); + } +} + +static inline void cpu_synchronize_post_init (CPUState *cpu) +{ +if (kvm_enabled ()) { +kvm_cpu_synchronize_post_init (cpu); + } +} + +#endif /* QEMU_HW_ACCEL_H */ include/sysemu/kvm.h +0
-23@@ -461,29 +461,6 @@ void kvm_cpu_synchronize_state(CPUState *cpu);void kvm_cpu_synchronize_post_reset (CPUState *cpu);void kvm_cpu_synchronize_post_init (CPUState *cpu); -/* generic hooks - to be moved/refactored once there are more users */ - -static inline void cpu_synchronize_state (CPUState *cpu) -{ -if (kvm_enabled ()) { -kvm_cpu_synchronize_state (cpu); - } -} - -static inline void cpu_synchronize_post_reset (CPUState *cpu) -{ -if (kvm_enabled ()) { -kvm_cpu_synchronize_post_reset (cpu); - } -} - -static inline void cpu_synchronize_post_init (CPUState *cpu) -{ -if (kvm_enabled ()) { -kvm_cpu_synchronize_post_init (cpu); - } -} -/** * kvm_irqchip_add_msi_route - Add MSI route for specific vector * @s: KVM state monitor.c +1
-1@@ -50,7 +50,7 @@#include "sysemu/balloon.h" #include "qemu/timer.h" #include "migration/migration.h" -#include "sysemu/kvm.h" +#include "sysemu/hw_accel.h" #include "qemu/acl.h" #include "sysemu/tpm.h" #include "qapi/qmp/qerror.h" qom/cpu.c +1
-1@@ -22,7 +22,7 @@#include "qapi/error.h" #include "qemu-common.h" #include "qom/cpu.h" -#include "sysemu/kvm.h" +#include "sysemu/hw_accel.h" #include "qemu/notify.h" #include "qemu/log.h" #include "exec/log.h" target-arm/cpu.c +1
-1@@ -31,7 +31,7 @@#endif #include "hw/arm/arm.h" #include "sysemu/sysemu.h" -#include "sysemu/kvm.h" +#include "sysemu/hw_accel.h" #include "kvm_arm.h" static void arm_cpu_set_pc (CPUState *cs,vaddr value)target-i386/helper.c +1
-0@@ -24,6 +24,7 @@#include "kvm_i386.h" #ifndef CONFIG_USER_ONLY #include "sysemu/sysemu.h" +#include "sysemu/hw_accel.h" #include "monitor/monitor.h" #include "hw/i386/apic_internal.h" #endif target-i386/kvm.c +0
-0
target-i386/kvm.c line 29
Quoted 7 lines
target-i386/kvm.c +1
-0@@ -23,6 +23,7 @@#include "qemu-common.h" #include "cpu.h" #include "sysemu/sysemu.h" +#include "sysemu/hw_accel.h" #include "sysemu/kvm_int.h" #include "kvm_i386.h" #include "hyperv.h"
PATCH 2/3 target-i386: Add Intel HAX files
In reply to Vincent PalatinThat's a forward port of the core HAX interface code mostly unmodified from emu-2.2-release branch in the external/qemu-android repository as used by the Android emulator.
The original commit was "target-i386: Add Intel HAX to android emulator" saying:
"""
Backport of 2b3098ff27bab079caab9b46b58546b5036f5c0c
from studio-1.4-dev into emu-master-dev
Intel HAX (harware acceleration) will enhance android emulator performance in Windows and Mac OS X in the systems powered by Intel processors with "Intel Hardware Accelerated Execution Manager" package installed when user runs android emulator with Intel target.
"""
It has minor modifications to build and run along with the current code base.
--- hax-stub.c | 66 ++ include/sysemu/hax.h | 66 ++ target-i386/hax-all.c | 1449 +++++++++++++++++++++++++++++++++++++++++++ target-i386/hax-darwin.c | 315 ++++++++++ target-i386/hax-darwin.h | 63 ++ target-i386/hax-i386.h | 94 +++ target-i386/hax-interface.h | 357 +++++++++++ target-i386/hax-slot.c | 332 ++++++++++ target-i386/hax-slot.h | 58 ++ target-i386/hax-windows.c | 478 ++++++++++++++ target-i386/hax-windows.h | 89 +++ 11 files changed, 3367 insertions(+) create mode 100644 hax-stub.c create mode 100644 include/sysemu/hax.h create mode 100644 target-i386/hax-all.c create mode 100644 target-i386/hax-darwin.c create mode 100644 target-i386/hax-darwin.h create mode 100644 target-i386/hax-i386.h create mode 100644 target-i386/hax-interface.h create mode 100644 target-i386/hax-slot.c create mode 100644 target-i386/hax-slot.h create mode 100644 target-i386/hax-windows.c create mode 100644 target-i386/hax-windows.h
hax-stub.c new file +66 -0
@@ -0,0 +1,66 @@ +/* +* QEMU HAXM support +* +* Copyright (c) 2015, Intel Corporation +* +* Copyright 2016 Google, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* See the COPYING file in the top-level directory. +* +*/ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "sysemu/hax.h" + +int hax_sync_vcpus (void ) +{ +return 0 ; +} + +void hax_disable (int disable) +{ +return ; +} + +int hax_pre_init (uint64_t ram_size) +{ +return 0 ; +} + +int hax_get_max_ram (uint64_t *max_ram) { +return 0 ; +} + +int hax_populate_ram (uint64_t va,uint32_t size) { +return -ENOSYS ; +} + +int hax_init_vcpu (CPUState *cpu) { +return -ENOSYS ; +} + +int hax_smp_cpu_exec (CPUState *cpu) { +return -ENOSYS ; +} + +int hax_vcpu_exec (CPUState *cpu) { +return -ENOSYS ; +} + +int hax_vcpu_emulation_mode (CPUState *cpu) { +return 0 ; +} + +int hax_stop_emulation (CPUState *cpu) { +return 0 ; +} + +int hax_stop_translate (CPUState *cpu) { +return 0 ; +}
include/sysemu/hax.h new file +66 -0
66 lines not on this page · raw message
target-i386/hax-all.c new file +1449 -0
1,449 lines not on this page · raw message
target-i386/hax-darwin.c new file +315 -0
315 lines not on this page · raw message
target-i386/hax-darwin.h new file +63 -0
63 lines not on this page · raw message
target-i386/hax-i386.h new file +94 -0
94 lines not on this page · raw message
target-i386/hax-interface.h new file +357 -0
357 lines not on this page · raw message
target-i386/hax-slot.c new file +332 -0
332 lines not on this page · raw message
target-i386/hax-slot.h new file +58 -0
58 lines not on this page · raw message
target-i386/hax-windows.c new file +478 -0
200 lines not on this page · raw message
target-i386/hax-windows.h new file +89 -0
89 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.8.0.rc3.226.g39d4020
Part of the diff is not shown here. View the raw message.
Re: [Qemu-devel] [PATCH 2/3] target-i386: Add Intel HAX files
target-i386/hax-all.c line 607
Quoted 4 lines · Vincent Palatin
target-i386/hax-all.c new file +4
-0+/* need tcg for non-UG platform in real mode */ +if (!hax_ug_platform ()) +tcg_exec_init (tcg_tb_size *1024 *1024 ); +
Oh, it does support unrestricted guest, and in fact without unrestricted guest you don't even have SMP!
Would you post a v2 that removes (after this patch 2) as much code as possible related to non-UG platforms?
Paolo
Re: [Qemu-devel] [PATCH 2/3] target-i386: Add Intel HAX files
Quoted 8 lines · Paolo Bonzini
target-i386/hax-all.c line 607
Quoted 4 lines · Vincent Palatin
target-i386/hax-all.c new file +4
-0+/* need tcg for non-UG platform in real mode */ +if (!hax_ug_platform ()) +tcg_exec_init (tcg_tb_size *1024 *1024 ); +
Quoted 5 lines
Oh, it does support unrestricted guest, and in fact without unrestricted guest you don't even have SMP!
Would you post a v2 that removes (after this patch 2) as much code as possible related to non-UG platforms?
Yes I can do this.
Signature · 1 line
Vincent
Re: [Qemu-devel] [PATCH 2/3] target-i386: Add Intel HAX files
In reply to Paolo BonziniQuoted 8 lines · Paolo Bonzini
target-i386/hax-all.c line 607
Quoted 4 lines · Vincent Palatin
target-i386/hax-all.c new file +4
-0+/* need tcg for non-UG platform in real mode */ +if (!hax_ug_platform ()) +tcg_exec_init (tcg_tb_size *1024 *1024 ); +
Quoted 5 lines
Oh, it does support unrestricted guest, and in fact without unrestricted guest you don't even have SMP!
Would you post a v2 that removes (after this patch 2) as much code as possible related to non-UG platforms?
I have prepared this, I will post it soon as part of my v2 series.
Signature · 1 line
Vincent
Re: [Qemu-devel] [PATCH 2/3] target-i386: Add Intel HAX files
In reply to Vincent PalatinOn Tue, Nov 08, 2016 at 04:39:28PM +0100, Vincent Palatin wrote:
Please run scripts/checkpatch.pl to verify that the code follows the QEMU coding style.
target-i386/hax-darwin.c line 224
Quoted 13 lines
target-i386/hax-darwin.c new file +13
-0+hax_fd hax_host_open_vcpu (int vmid,int vcpuid) +{ +char *devfs_path =NULL ; +hax_fd fd; + + devfs_path =hax_vcpu_devfs_string (vmid, vcpuid); +if (!devfs_path) { +fprintf (stderr,"Failed to get the devfs\n" ); +return -EINVAL ; + } + + fd =open (devfs_path,O_RDWR ); +qemu_vfree (devfs_path);
g_malloc(), g_new(), g_strdup(), etc must be matched with g_free(), not qemu_vfree(). There are probably other instances of this issue in the patches.
target-i386/hax-slot.c line 32
Quoted 9 lines
target-i386/hax-slot.c new file +9
-0+//#define DEBUG_HAX_SLOT + +#ifdef DEBUG_HAX_SLOT +#define DPRINTF (fmt, ...) \ + do { fprintf(stdout, fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF (fmt, ...) \ + do { } while (0) +#endif
Please consider using tracing instead of debug printfs. See docs/tracing.txt.
If you really want to keep macros, please use:
#define DEBUG_HAX_SLOT 0
#define DPRINTF(fmt, ...) \
do { \
if (DEBUG_HAX_SLOT) { \
fprintf(stdout, fmt, ## __VA_ARGS__); \
} \
} while (0)This approach prevents bitrot because it allows the compiler to syntax check the format string and arguments even when the printf is compiled out.
Re: [Qemu-devel] [PATCH 2/3] target-i386: Add Intel HAX files
Quoted 4 lines · Stefan Hajnoczi
On Tue, Nov 08, 2016 at 04:39:28PM +0100, Vincent Palatin wrote:
Please run
scripts/checkpatch.plto verify that the code follows the QEMU coding style.
My original plan was to import those files unmodified but this ship has probably long-sailed.
Fixed in the v2 of this patch.
Quoted 10 lines
Quoted 10 lines
target-i386/hax-darwin.c new file +9
-0+hax_fd hax_host_open_vcpu (int vmid,int vcpuid) +{ +char *devfs_path =NULL ; +hax_fd fd; + + devfs_path =hax_vcpu_devfs_string (vmid, vcpuid); +if (!devfs_path) { +fprintf (stderr,"Failed to get the devfs\n" ); +return -EINVAL ;
Quoted 8 lines
target-i386/hax-darwin.c line 224
Quoted 4 lines
target-i386/hax-darwin.c new file +4
-0+ } + + fd =open (devfs_path,O_RDWR ); +qemu_vfree (devfs_path);
g_malloc(),g_new(),g_strdup(), etc must be matched withg_free(), notqemu_vfree(). There are probably other instances of this issue in the patches.
Found 2 instances by grepping and fixed them.
Quoted 23 lines
target-i386/hax-slot.c line 32
Quoted 10 lines
target-i386/hax-slot.c new file +9
-0+//#define DEBUG_HAX_SLOT + +#ifdef DEBUG_HAX_SLOT +#define DPRINTF (fmt, ...) \ + do { fprintf(stdout, fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF (fmt, ...) \ + do { } while (0) +#endif Please consider using tracing instead of debug printfs. See
docs/tracing.txt.If you really want to keep macros, please use:
#define
DEBUG_HAX_SLOT0#define DPRINTF(fmt, ...) \ do { \ if (DEBUG_HAX_SLOT) { \ fprintf(stdout, fmt, ## __VA_ARGS__); \ } \ } while (0)
Quoted 3 lines
This approach prevents bitrot because it allows the compiler to syntax check the format string and arguments even when the printf is compiled out.
For the v2 of this patch, I will keep the macros and do your approach. Then I will review all the debug print statements, see what I should do with them in another patch (convert to tracing / remove).
PATCH 3/3 Plumb the HAXM-based hardware acceleration support
In reply to Vincent PalatinUse the Intel HAX is kernel-based hardware acceleration module for Windows and MacOSX (similar to KVM on Linux).
Based on the "target-i386: Add Intel HAX to android emulator" patch from David Chou <[email protected]>
--- Makefile.target | 1 + configure | 18 +++++++ cpu-exec.c | 23 ++++++++- cpus.c | 125 ++++++++++++++++++++++++++++++++++++++++------ exec.c | 16 ++++++ 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 | 7 +++ target-i386/seg_helper.c | 5 ++ target-i386/translate.c | 8 +++ vl.c | 17 +++++-- 13 files changed, 229 insertions(+), 19 deletions(-)
Makefile.target +1 -0
@@ -96,6 +96,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
configure +18 -0
@@ -230,6 +230,7 @@ vhost_net="no" vhost_scsi="no" vhost_vsock="no" kvm="no" +hax="no" colo="yes" rdma="" gprof="no"
@@ -563,6 +564,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-colo) colo="no" ;; --enable-colo) colo="yes"
@@ -1371,6 +1378,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
@@ -5038,6 +5046,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"
@@ -6022,6 +6031,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
cpu-exec.c +22 -1
@@ -25,6 +25,7 @@#include "qemu/atomic.h" #include "sysemu/qtest.h" #include "qemu/timer.h" +#include "sysemu/hax.h" #include "exec/address-spaces.h" #include "qemu/rcu.h" #include "exec/tb-hash.h"
@@ -461,11 +462,24 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)return false; } +/* +* QEMU emulate can happens because of MMIO or emulation mode, i.e. non-PG mode, +* when it's because of MMIO, the MMIO, the interrupt should not be emulated, +* because MMIO is emulated for only one instruction now and then back to +* HAX kernel +*/ +static int need_handle_intr_request (CPUState *cpu) +{ +if (!hax_enabled () ||hax_vcpu_emulation_mode (cpu)) +return cpu->interrupt_request; +return 0 ; +} +static inline void cpu_handle_interrupt (CPUState *cpu,TranslationBlock **last_tb) {CPUClass *cc =CPU_GET_CLASS (cpu); -int interrupt_request = cpu->interrupt_request; +int interrupt_request =need_handle_intr_request (cpu);if (unlikely (interrupt_request)) {if (unlikely (cpu->singlestep_enabled &SSTEP_NOIRQ )) {
@@ -632,10 +646,17 @@ int cpu_exec(CPUState *cpu)break ; } +if (hax_enabled () && !hax_vcpu_exec (cpu)) +longjmp (cpu->jmp_env,1 ); +for (;;) {cpu_handle_interrupt (cpu, &last_tb); tb =tb_find (cpu, last_tb, tb_exit);cpu_loop_exec_tb (cpu, tb, &last_tb, &tb_exit, &sc); + +if (hax_enabled () &&hax_stop_emulation (cpu)) +cpu_loop_exit (cpu); +/* Try to align the host and virtual clocks if the guest is in advance */ align_clocks (&sc, cpu);
cpus.c +111 -14
175 lines not on this page · raw message
exec.c +16 -0
@@ -31,6 +31,7 @@#include "hw/xen/xen.h" #endif #include "sysemu/kvm.h" +#include "sysemu/hax.h" #include "sysemu/sysemu.h" #include "qemu/timer.h" #include "qemu/config-file.h"
@@ -1617,6 +1618,21 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) }else { new_block->host =phys_mem_alloc (new_block->max_length, &new_block->mr->align); +/* +* In Hax, the qemu allocate the virtual address, and HAX kernel +* populate the memory with physical memory. Currently we have no +* paging, so user should make sure enough free memory in advance +*/ +if (hax_enabled ()) { +int ret; + ret =hax_populate_ram ((uint64_t )(uintptr_t )new_block->host, + new_block->max_length); +if (ret <0 ) { +error_setg (errp,"Hax failed to populate ram" ); +return ; + } + } +if (!new_block->host) { error_setg_errno(errp, errno, "cannot set up guest memory '%s'",
hw/intc/apic_common.c +2 -1
@@ -316,9 +316,10 @@ 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 ) { +kvm_enabled () && ram_size >=1024 *1024 ) { vapic =sysbus_create_simple ("kvmvapic" ,-1 ,NULL ); } + s->vapic = vapic;if (apic_report_tpr_access && info->enable_tpr_reporting) { info->enable_tpr_reporting (s, true);
include/qom/cpu.h +5 -0
@@ -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);
include/sysemu/hw_accel.h +9 -0
@@ -20,6 +20,9 @@ static inline void cpu_synchronize_state(CPUState *cpu)if (kvm_enabled ()) {kvm_cpu_synchronize_state (cpu); } +if (hax_enabled () &&hax_ug_platform ()) { +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_ug_platform ()) { +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_ug_platform ()) { +hax_cpu_synchronize_post_init (cpu); + } }#endif /* QEMU_HW_ACCEL_H */
qemu-options.hx +11 -0
@@ -3259,6 +3259,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,
target-i386/Makefile.objs +7 -0
@@ -5,3 +5,10 @@ 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-slot.o hax-windows.o +endif +ifdef CONFIG_DARWIN +obj-$(CONFIG_HAX) += hax-all.o hax-slot.o hax-darwin.o +endif
target-i386/seg_helper.c +5 -0
@@ -25,6 +25,7 @@#include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "exec/log.h" +#include "sysemu/hax.h" //#define DEBUG_PCALL
@@ -1336,6 +1337,10 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) !(env->hflags & HF_SMM_MASK)) {cpu_svm_check_intercept_param (env,SVM_EXIT_SMI ,0 ); cs->interrupt_request &= ~CPU_INTERRUPT_SMI ; +#ifdef CONFIG_HAX +if (hax_enabled ()) + cs->hax_vcpu->resync =1 ; +#endif do_smm_enter (cpu); ret = true; } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
target-i386/translate.c +8 -0
@@ -30,6 +30,7 @@#include "trace-tcg.h" #include "exec/log.h" +#include "sysemu/hax.h" #define PREFIX_REPZ 0x01
@@ -8421,6 +8422,13 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) } pc_ptr =disas_insn (env, dc, pc_ptr); + +if (hax_enabled () &&hax_stop_translate (cs)) { +gen_jmp_im (pc_ptr - dc->cs_base); +gen_eob (dc); +break ; + } +/* stop translation if indicated */ if (dc->is_jmp)break ;
vl.c +14 -3
@@ -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 = !kvm_enabled() && !xen_enabled() && !hax_enabled() && last_io > 0; #ifdef CONFIG_PROFILER ti = profile_getclock(); #endif
@@ -3724,6 +3725,11 @@ 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); +hax_disable (0 ); +break ;case QEMU_OPTION_M :case QEMU_OPTION_machine: olist =qemu_find_opts ("machine" );
@@ -4060,6 +4066,7 @@ int main(int argc, char **argv, char **envp) machine_class =select_machine ();set_memory_options (&ram_slots, &maxram_size, machine_class); +hax_pre_init (ram_size);os_daemonize ();
@@ -4418,8 +4425,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 (kvm_enabled () ||xen_enabled () ||hax_enabled ()) { +error_report ("-icount is not allowed with kvm or xen or hax" );exit (1 ); }configure_icount (icount_opts, &error_abort);
@@ -4555,6 +4562,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 );
Signature · 1 line
2.8.0.rc3.226.g39d4020
Re: [Qemu-devel] [PATCH 3/3] Plumb the HAXM-based hardware acceleration support
cpu-exec.c
Quoted 5 lines
cpu-exec.c +0
-0
All this should not be needed anymore with unrestricted guest support.
Quoted 79 lines
cpus.c +47
-9@@ -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,52 @@ 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); + } + +qemu_wait_io_event_common (cpu); + } +return NULL ; +} + + +static void qemu_cpu_kick_no_halt (void ) +{ +CPUState *cpu; +/* Ensure whatever caused the exit has reached the CPU threads before +* writing exit_request. +*/ +atomic_mb_set (&exit_request,1 ); + cpu =atomic_mb_read (&tcg_current_cpu); +if (cpu) { +cpu_exit (cpu); + } +} +static void qemu_cpu_kick_thread (CPUState *cpu) {#ifndef _WIN32@@ -1235,28 +1282,52 @@ static void qemu_cpu_kick_thread(CPUState *cpu)fprintf (stderr,"qemu:%s: %s" , __func__,strerror (err));exit (1 ); } -#else /* _WIN32 */ -abort (); -#endif -} -static void qemu_cpu_kick_no_halt (void ) -{ -CPUState *cpu; -/* Ensure whatever caused the exit has reached the CPU threads before -* writing exit_request.
cpus.c static void qemu_cpu_kick_thread(CPUState *cpu) · line 1291
Quoted 10 lines
cpus.c +5
-4+#ifdef CONFIG_DARWIN +/* The cpu thread cannot catch it reliably when shutdown the guest on Mac. +* We can double check it and resend it */ -atomic_mb_set (&exit_request,1 ); - cpu =atomic_mb_read (&tcg_current_cpu); -if (cpu) { -cpu_exit (cpu); +if (!exit_request) +qemu_cpu_kick_no_halt ();
This must be a conflict resolved wrong. exit_request is never read by the HAX code.
Quoted 20 lines
cpus.c +20
-0+if (hax_enabled () &&hax_ug_platform ()) + cpu->exit_request =1 ; +#endif +#else /* _WIN32 */ +if (!qemu_cpu_is_self (cpu)) { +CONTEXT tcgContext; + +if (SuspendThread (cpu->hThread) == (DWORD )-1 ) { +fprintf (stderr,"qemu:%s: GetLastError:%lu\n" , __func__, +GetLastError ()); +exit (1 ); + } + +/* On multi-core systems, we are not sure that the thread is actually +* suspended until we can get the context. +*/ + tcgContext.ContextFlags =CONTEXT_CONTROL ; +while (GetThreadContext (cpu->hThread, &tcgContext) !=0 ) { +continue ; + }
cpus.c static void qemu_cpu_kick_thread(CPUState *cpu) · line 1322
Quoted 10 lines
cpus.c +10
-0+ +qemu_cpu_kick_no_halt (); +if (hax_enabled () &&hax_ug_platform ()) + cpu->exit_request =1 ; + +if (ResumeThread (cpu->hThread) == (DWORD )-1 ) { +fprintf (stderr,"qemu:%s: GetLastError:%lu\n" , __func__, +GetLastError ()); +exit (1 ); + }
This is weird too. The SuspendThread/ResumeThread dance comes from an old version of QEMU. It is not needed anymore and, again, qemu_cpu_kick_no_halt would only be useful if hax_ug_platform() is false.
Here, Linux/KVM uses a signal and pthread_kill. It's probably good for HAX on Darwin too, but not on Windows. It's possible that SuspendThread/ResumeThread just does the right thing (sort of by chance), in which case you can just keep it (removing qemu_cpu_kick_no_halt). However, there is a hax_raise_event in patch 2 that is unused. If you can figure out how to use it it would be better.
Quoted 8 lines
cpus.c +4
-0@@ -1617,6 +1618,21 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) }else { new_block->host =phys_mem_alloc (new_block->max_length, &new_block->mr->align); +/* +* In Hax, the qemu allocate the virtual address, and HAX kernel +* populate the memory with physical memory. Currently we have no +* paging, so user should make sure enough free memory in advance
cpus.c static void ram_block_add(RAMBlock *new_block, Error **errp) · line 1634
Quoted 10 lines
cpus.c +10
-0+*/ +if (hax_enabled ()) { +int ret; + ret =hax_populate_ram ((uint64_t )(uintptr_t )new_block->host, + new_block->max_length); +if (ret <0 ) { +error_setg (errp,"Hax failed to populate ram" ); +return ; + } + }
Please try removing this block and instead starting QEMU with -mem-prealloc. If it works, remove hax_populate_ram and just set mem_prealloc to 1 in hax_accel_init.
hw/intc/apic_common.c static void apic_common_realize(DeviceState *dev, Error **errp) · line 319
Quoted 13 lines
cpus.c +0
-0if (!new_block->host) { error_setg_errno(errp, errno, "cannot set up guest memory '%s'",hw/intc/apic_common.c +1
-1@@ -316,9 +316,10 @@ 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 ) { +kvm_enabled () && ram_size >=1024 *1024 ) {
This should rather be !hax_enabled(), despite the historical name mentions KVM.
Quoted 19 lines
hw/intc/apic_common.c +1
-0vapic =sysbus_create_simple ("kvmvapic" ,-1 ,NULL ); } + s->vapic = vapic;if (apic_report_tpr_access && info->enable_tpr_reporting) { info->enable_tpr_reporting (s, true);target-i386/seg_helper.c +1
-0@@ -25,6 +25,7 @@#include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "exec/log.h" +#include "sysemu/hax.h" //#define DEBUG_PCALL
target-i386/seg_helper.c bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) · line 1343
Quoted 7 lines
target-i386/seg_helper.c +4
-0@@ -1336,6 +1337,10 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) !(env->hflags & HF_SMM_MASK)) {cpu_svm_check_intercept_param (env,SVM_EXIT_SMI ,0 ); cs->interrupt_request &= ~CPU_INTERRUPT_SMI ; +#ifdef CONFIG_HAX +if (hax_enabled ()) + cs->hax_vcpu->resync =1 ; +#endif
Not needed for UG mode.
target-i386/translate.c
Quoted 7 lines
target-i386/seg_helper.c +0
-0do_smm_enter (cpu); ret = true; } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&target-i386/translate.c +0
-0
Same.
target-i386/translate.c int main(int argc, char **argv, char **envp) · line 4069
Quoted 5 lines
target-i386/translate.c +1
-0@@ -4060,6 +4066,7 @@ int main(int argc, char **argv, char **envp) machine_class =select_machine ();set_memory_options (&ram_slots, &maxram_size, machine_class); +hax_pre_init (ram_size);
It should be possible to merge this with hax_accel_init.
target-i386/translate.c int main(int argc, char **argv, char **envp) · line 4429
Quoted 10 lines
target-i386/translate.c +2
-2os_daemonize ();@@ -4418,8 +4425,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 (kvm_enabled () ||xen_enabled () ||hax_enabled ()) { +error_report ("-icount is not allowed with kvm or xen or hax" );
Let's say it's only allowed with TCG. :) Again, thanks to UG mode if hax_enabled() you'll have !tcg_enabled().
Paolo
Quoted 15 lines
target-i386/translate.c +4
-0exit (1 ); }configure_icount (icount_opts, &error_abort);@@ -4555,6 +4562,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 );
Re: [Qemu-devel] [PATCH 3/3] Plumb the HAXM-based hardware acceleration support
Quoted 7 lines · Paolo Bonzini
cpu-exec.c
Quoted 5 lines
cpu-exec.c +0
-0All this should not be needed anymore with unrestricted guest support.
Removed in v2
Quoted 85 lines
Quoted 85 lines
cpus.c +50
-10@@ -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,52 @@ 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); + } + +qemu_wait_io_event_common (cpu); + } +return NULL ; +} + + +static void qemu_cpu_kick_no_halt (void ) +{ +CPUState *cpu; +/* Ensure whatever caused the exit has reached the CPU threads before +* writing exit_request. +*/ +atomic_mb_set (&exit_request,1 ); + cpu =atomic_mb_read (&tcg_current_cpu); +if (cpu) { +cpu_exit (cpu); + } +} +static void qemu_cpu_kick_thread (CPUState *cpu) {#ifndef _WIN32@@ -1235,28 +1282,52 @@ static void qemu_cpu_kick_thread(CPUState *cpu)fprintf (stderr,"qemu:%s: %s" , __func__,strerror (err));exit (1 ); } -#else /* _WIN32 */ -abort (); -#endif -} -static void qemu_cpu_kick_no_halt (void ) -{ -CPUState *cpu; -/* Ensure whatever caused the exit has reached the CPU threads before -* writing exit_request. +#ifdef CONFIG_DARWIN +/* The cpu thread cannot catch it reliably when shutdown the guest on Mac. +* We can double check it and resend it */ -atomic_mb_set (&exit_request,1 );
Quoted 8 lines
cpus.c static void qemu_cpu_kick_thread(CPUState *cpu) · line 1291
Quoted 5 lines
cpus.c +2
-3- cpu =atomic_mb_read (&tcg_current_cpu); -if (cpu) { -cpu_exit (cpu); +if (!exit_request) +qemu_cpu_kick_no_halt ();This must be a conflict resolved wrong.
exit_requestis never read by the HAX code.
Maybe, it already exists in the predating Android branch. I will need to sort out this.
Quoted 26 lines
Quoted 26 lines
cpus.c +25
-0+if (hax_enabled () &&hax_ug_platform ()) + cpu->exit_request =1 ; +#endif +#else /* _WIN32 */ +if (!qemu_cpu_is_self (cpu)) { +CONTEXT tcgContext; + +if (SuspendThread (cpu->hThread) == (DWORD )-1 ) { +fprintf (stderr,"qemu:%s: GetLastError:%lu\n" , __func__, +GetLastError ()); +exit (1 ); + } + +/* On multi-core systems, we are not sure that the thread is actually +* suspended until we can get the context. +*/ + tcgContext.ContextFlags =CONTEXT_CONTROL ; +while (GetThreadContext (cpu->hThread, &tcgContext) !=0 ) { +continue ; + } + +qemu_cpu_kick_no_halt (); +if (hax_enabled () &&hax_ug_platform ()) + cpu->exit_request =1 ; +
Quoted 8 lines
cpus.c static void qemu_cpu_kick_thread(CPUState *cpu) · line 1322
Quoted 5 lines
cpus.c +5
-0+if (ResumeThread (cpu->hThread) == (DWORD )-1 ) { +fprintf (stderr,"qemu:%s: GetLastError:%lu\n" , __func__, +GetLastError ()); +exit (1 ); + }This is weird too. The SuspendThread/ResumeThread dance comes from an old version of QEMU. It is not needed anymore and,
Yes I knew I was re-introducing removed code, that's why my original message was reading "I'm not so happy with the qemu_cpu_kick_thread mess in cpus.c, if somebody can help/advise."
To be fair, your original commit message removing it was saying that this code was no longer useful for TCG, as there is no working support for KVM on Windows, I was not sure whether it might be useful in this case.
Quoted 9 lines
again,
qemu_cpu_kick_no_haltwould only be useful ifhax_ug_platform()is false.Here, Linux/KVM uses a signal and
pthread_kill. It's probably good for HAX on Darwin too, but not on Windows. It's possible that SuspendThread/ResumeThread just does the right thing (sort of by chance), in which case you can just keep it (removingqemu_cpu_kick_no_halt). However, there is ahax_raise_eventin patch 2 that is unused. If you can figure out how to use it it would be better.
I still need to figure out this mess, I haven't made a working solution yet.
Quoted 16 lines
Quoted 16 lines
cpus.c +10
-0@@ -1617,6 +1618,21 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) }else { new_block->host =phys_mem_alloc (new_block->max_length, &new_block->mr->align); +/* +* In Hax, the qemu allocate the virtual address, and HAX kernel +* populate the memory with physical memory. Currently we have no +* paging, so user should make sure enough free memory in advance +*/ +if (hax_enabled ()) { +int ret; + ret =hax_populate_ram ((uint64_t )(uintptr_t )new_block->host, + new_block->max_length); +if (ret <0 ) {
Quoted 8 lines
cpus.c static void ram_block_add(RAMBlock *new_block, Error **errp) · line 1634
Quoted 4 lines
cpus.c +4
-0+error_setg (errp,"Hax failed to populate ram" ); +return ; + } + }Please try removing this block and instead starting QEMU with -mem-prealloc. If it works, remove
hax_populate_ramand just setmem_preallocto 1 inhax_accel_init.
it's not working, later hax_set_ram() is unhappy about what it is finding the mappings.
By the way, even if it had worked at startup, under memory pressure, Windows might have evicted the physical pages (which is not supported by the HAXM kernel module)
I can try to move this in os_mem_prealloc() if you feel it's cleaner.
Quoted 10 lines
Quoted 10 lines
cpus.c +0
-0if (!new_block->host) { error_setg_errno(errp, errno, "cannot set up guest memory '%s'",hw/intc/apic_common.c +0
-0@@ -316,9 +316,10 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
Quoted 7 lines
hw/intc/apic_common.c static void apic_common_realize(DeviceState *dev, Error **errp) · line 319
Quoted 4 lines
hw/intc/apic_common.c +1
-1/* Note: We need at least 1M to map the VAPIC option ROM */ if (!vapic && s->vapic_control &VAPIC_ENABLE_MASK && - ram_size >=1024 *1024 ) { +kvm_enabled () && ram_size >=1024 *1024 ) {This should rather be !hax_enabled(), despite the historical name mentions KVM.
Updated in v2, thanks for the hint.
Quoted 19 lines
Quoted 19 lines
hw/intc/apic_common.c +1
-0vapic =sysbus_create_simple ("kvmvapic" ,-1 ,NULL ); } + s->vapic = vapic;if (apic_report_tpr_access && info->enable_tpr_reporting) { info->enable_tpr_reporting (s, true);target-i386/seg_helper.c +1
-0@@ -25,6 +25,7 @@#include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "exec/log.h" +#include "sysemu/hax.h" //#define DEBUG_PCALL
Quoted 10 lines
target-i386/seg_helper.c bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) · line 1343
Quoted 8 lines
target-i386/seg_helper.c +4
-0@@ -1336,6 +1337,10 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) !(env->hflags & HF_SMM_MASK)) {cpu_svm_check_intercept_param (env,SVM_EXIT_SMI ,0 ); cs->interrupt_request &= ~CPU_INTERRUPT_SMI ; +#ifdef CONFIG_HAX +if (hax_enabled ()) + cs->hax_vcpu->resync =1 ; +#endif Not needed for UG mode.
Removed in v2.
Quoted 11 lines
target-i386/translate.c
Quoted 8 lines
target-i386/seg_helper.c +0
-0do_smm_enter (cpu); ret = true; } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&target-i386/translate.c +0
-0Same.
Quoted 7 lines
target-i386/translate.c int main(int argc, char **argv, char **envp) · line 4069
Quoted 5 lines
target-i386/translate.c +1
-0@@ -4060,6 +4066,7 @@ int main(int argc, char **argv, char **envp) machine_class =select_machine ();set_memory_options (&ram_slots, &maxram_size, machine_class); +hax_pre_init (ram_size);It should be possible to merge this with
hax_accel_init.
Done in v2, I have added a new patch simplifying the init (i have also realized it contained Android specific code leftovers and was misusing the 'allowed' property of the AccelClass)
Quoted 5 lines
Quoted 5 lines
target-i386/translate.c +0
-0os_daemonize ();@@ -4418,8 +4425,8 @@ int main(int argc, char **argv, char **envp)
Quoted 9 lines
target-i386/translate.c int main(int argc, char **argv, char **envp) · line 4429
Quoted 6 lines
target-i386/translate.c +2
-2cpu_ticks_init ();if (icount_opts) { -if (kvm_enabled () ||xen_enabled ()) { -error_report ("-icount is not allowed with kvm or xen" ); +if (kvm_enabled () ||xen_enabled () ||hax_enabled ()) { +error_report ("-icount is not allowed with kvm or xen or hax" );Let's say it's only allowed with TCG. :) Again, thanks to UG mode if
hax_enabled()you'll have !tcg_enabled().
Updated in v2.
I actually did not realize earlier that the interpreter mode was running with tcg_enabled
Quoted 18 lines
Paolo
Quoted 15 lines
target-i386/translate.c +4
-0exit (1 ); }configure_icount (icount_opts, &error_abort);@@ -4555,6 +4562,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 );
Re: [Qemu-devel] [PATCH 3/3] Plumb the HAXM-based hardware acceleration support
Quoted 10 lines · Vincent Palatin
Quoted 3 lines
Quoted 3 lines
Please try removing this block and instead starting QEMU with -mem-prealloc. If it works, remove
hax_populate_ramand just setmem_preallocto 1 inhax_accel_init.it's not working, later
hax_set_ram()is unhappy about what it is finding the mappings.
By the way, even if it had worked at startup, under memory pressure, Windows might have evicted the physical pages (which is not supported by the HAXM kernel module)I can try to move this in
os_mem_prealloc()if you feel it's cleaner.
Yes, that would work!
Paolo
Re: [Qemu-devel] [PATCH 3/3] Plumb the HAXM-based hardware acceleration support
Quoted 12 lines · Paolo Bonzini
Quoted 9 lines · Vincent Palatin
Quoted 3 lines
Quoted 3 lines
Please try removing this block and instead starting QEMU with -mem-prealloc. If it works, remove
hax_populate_ramand just setmem_preallocto 1 inhax_accel_init.it's not working, later
hax_set_ram()is unhappy about what it is finding the mappings.
By the way, even if it had worked at startup, under memory pressure, Windows might have evicted the physical pages (which is not supported by the HAXM kernel module)
Quoted 3 lines
Quoted 1 line
I can try to move this in
os_mem_prealloc()if you feel it's cleaner.Yes, that would work!
Actually, os_mem_prealloc seems mostly no-op in the win32 version, I have postponed this change for after my v2 patchset.
Signature · 1 line
Vincent
Re: [Qemu-devel] [PATCH 3/3] Plumb the HAXM-based hardware acceleration support
Quoted 13 lines · Vincent Palatin
Quoted 12 lines · Paolo Bonzini
Quoted 9 lines · Vincent Palatin
Quoted 3 lines
Quoted 3 lines
Please try removing this block and instead starting QEMU with -mem-prealloc. If it works, remove
hax_populate_ramand just setmem_preallocto 1 inhax_accel_init.it's not working, later
hax_set_ram()is unhappy about what it is finding the mappings.
By the way, even if it had worked at startup, under memory pressure, Windows might have evicted the physical pages (which is not supported by the HAXM kernel module)
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
I can try to move this in
os_mem_prealloc()if you feel it's cleaner.Yes, that would work!
Actually,
os_mem_preallocseems mostly no-op in the win32 version, I have postponed this change for after my v2 patchset.
Good, we'll sort it out during review.
Paolo
Quoted 11 lines · Vincent Palatin
I took a stab at trying to rebase/upstream the support for Intel HAXM. (Hardware Accelerated Execution Manager).
Intel HAX is kernel-based hardware acceleration module for Windows and MacOSX.I have based my work on the last version of the source code I found:
the emu-2.2-release branch in the external/qemu-android repository as used by the Android emulator.
In patch 2/3, I have forward-ported the core HAX code mostly unmodified from there, I just did some minor touch up to make it build and run properly. So it might contain some outdated constructs and probably requires more attention (thus the 'RFC' for this patchset).
Does HAXM support the "unrestricted guest" feature in Westmere and more recent processors? If so, I think we should only support those processors and slash all the part related to HAX_EMULATE_STATE_INITIAL and HAX_EMULATE_STATE_REAL. This would probably let us make patch 3 much less intrusive.
That said, patch 3's cpu-exec.c surgery is much nicer on the surface than if you look in depth, :) and since you don't look in depth if you steer clear of target-i386/hax*, I think it's okay to start with your patches and clean up progressively. Others may disagree... Also, we're now in soft freeze so the patches wouldn't be merged anyway for a few weeks.
Paolo
Quoted 16 lines · Paolo Bonzini
Quoted 11 lines · Vincent Palatin
I took a stab at trying to rebase/upstream the support for Intel HAXM. (Hardware Accelerated Execution Manager).
Intel HAX is kernel-based hardware acceleration module for Windows and MacOSX.I have based my work on the last version of the source code I found:
the emu-2.2-release branch in the external/qemu-android repository as used by the Android emulator.
In patch 2/3, I have forward-ported the core HAX code mostly unmodified from there, I just did some minor touch up to make it build and run properly. So it might contain some outdated constructs and probably requires more attention (thus the 'RFC' for this patchset).
Quoted 2 lines
Does HAXM support the "unrestricted guest" feature in Westmere and more recent processors?
Yes it does, as mentioned in the last paragraph of my message, I have actually done a fair chunk of my testing in UG mode.
Quoted 5 lines
If so, I think we should only support those
processors and slash all the part related toHAX_EMULATE_STATE_INITIALandHAX_EMULATE_STATE_REAL. This would probably let us make patch 3 much less intrusive.
Sure the whole patchset would be lighter, not sure which proportion of user have VT machines without UG support though.
Quoted 8 lines
That said, patch 3's
cpu-exec.csurgery is much nicer on the surface than if you look in depth, :) and since you don't look in depth if you steer clear of target-i386/hax*, I think it's okay to start with your patches and clean up progressively. Others may disagree... Also, we're now in soft freeze so the patches wouldn't be merged anyway for a few weeks.Paolo
Quoted 7 lines · Vincent Palatin
Quoted 4 lines
If so, I think we should only support those
processors and slash all the part related toHAX_EMULATE_STATE_INITIALandHAX_EMULATE_STATE_REAL. This would probably let us make patch 3 much less intrusive.Sure the whole patchset would be lighter, not sure which proportion of user have VT machines without UG support though.
All Intel machines sold after ~2010 should have unrestricted guest support. (HAX doesn't support AMD, but anyway AMD's virt extensions have always had the equivalent feature).
I'm not sure we want !UG support at all but, if we do, QEMU 2.9 will have multithreaded TCG so it would be possible to make it less intrusive. So it's worth starting with the minimum patchset and see what happens.
Thanks for working on this!
Paolo