obj-i386-$(CONFIG_XEN) += xen_platform.o
+
+# HAX support
+ifeq ($(TARGET_ARCH), i386)
+ifdef CONFIG_WIN32
+obj-$(CONFIG_HAX) += \
+ hax-all.o \
+ hax-windows.o
+endif
+endif
+
# Inter-VM PCI shared memory
CONFIG_IVSHMEM =
ifeq ($(CONFIG_KVM), y)
return 0;
#endif
}
+
+int hax_available(void)
+{
+#ifdef CONFIG_HAX
+ return 1;
+#else
+ return 0;
+#endif
+}
int tcg_available(void);
int kvm_available(void);
int xen_available(void);
-
+int hax_available(void);
#endif
#include "config-host.h"
-#include "config-target.h"
+#include "i386-softmmu/config-target.h"
vhost_net="no"
kvm="no"
+hax="no"
gprof="no"
debug_tcg="no"
debug_mon="no"
;;
--enable-gl) gl="yes"
;;
+ --disable-hax) hax="no"
+ ;;
+ --enable-hax) hax="yes"
+ ;;
--disable-tcg-interpreter) tcg_interpreter="no"
;;
--enable-tcg-interpreter) tcg_interpreter="yes"
echo " --disable-kvm disable KVM acceleration support"
echo " --enable-kvm enable KVM acceleration support"
echo " --disable-gl disable GL acceleration support"
+
+echo " --disable-hax disable HAX acceleration support"
+echo " --enable-hax enable HAX acceleration support"
+
+echo " --disable-gl disable GL acceleration support"
echo " --enable-gl enable GL acceleration support"
echo " --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)"
echo " --disable-nptl disable usermode NPTL support"
echo "ATTR/XATTR support $attr"
echo "Install blobs $blobs"
echo "KVM support $kvm"
+echo "HAX support $hax"
echo "GL support $gl"
echo "TCG interpreter $tcg_interpreter"
echo "fdt support $fdt"
fi
fi
esac
+
+case "$target_arch2" in
+ i386|x86_64)
+ if test "$hax" = "yes" ; then
+ echo "CONFIG_HAX=y" >> $config_target_mak
+ echo "CONFIG_HAX=y" >> $config_host_mak
+ fi
+esac
+
if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
echo "CONFIG_PSERIES=y" >> $config_target_mak
fi
struct KVMState *kvm_state; \
struct kvm_run *kvm_run; \
int kvm_fd; \
- int kvm_vcpu_dirty;
+ int kvm_vcpu_dirty; \
+ int hax_vcpu_dirty; \
+ struct hax_vcpu_state *hax_vcpu;
#endif
#include "cpu.h"
#include "disas.h"
#include "tcg.h"
+#include "hax.h"
#include "qemu-barrier.h"
int tb_invalidated_flag;
volatile sig_atomic_t exit_request;
+/*
+ * 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
+ */
+int need_handle_intr_request(CPUState *env)
+{
+#ifdef CONFIG_HAX
+ if (!hax_enabled() || hax_vcpu_emulation_mode(env))
+ return env->interrupt_request;
+ return 0;
+#else
+ return env->interrupt_request;
+#endif
+}
+
+
int cpu_exec(CPUState *env)
{
int ret, interrupt_request;
}
}
+#ifdef CONFIG_HAX
+ if (hax_enabled() && !hax_vcpu_exec(env))
+ longjmp(env->jmp_env, 1);
+#endif
+
next_tb = 0; /* force lookup of first TB */
for(;;) {
interrupt_request = env->interrupt_request;
- if (unlikely(interrupt_request)) {
+ if (unlikely(need_handle_intr_request(env))) {
if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
/* Mask out external interrupts for this step. */
interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
}
}
env->current_tb = NULL;
+#ifdef CONFIG_HAX
+ if (hax_enabled() && hax_stop_emulation(env))
+ cpu_loop_exit(env);
+#endif
+
/* reset soft MMU for next block (it can currently
only be set by a memory fault) */
} /* for(;;) */
#include "gdbstub.h"
#include "dma.h"
#include "kvm.h"
+#include "hax.h"
#include "qmp-commands.h"
#include "qemu-thread.h"
return true;
}
if (!env->halted || qemu_cpu_has_work(env) ||
- (kvm_enabled() && kvm_irqchip_in_kernel())) {
+ (kvm_enabled() && kvm_irqchip_in_kernel()) ||
+ hax_enabled()) {
return false;
}
return true;
static void qemu_kvm_eat_signals(CPUState *env)
{
}
+
#endif /* !CONFIG_LINUX */
#ifndef _WIN32
static void qemu_tcg_init_cpu_signals(void)
{
}
+
#endif /* _WIN32 */
QemuMutex qemu_global_mutex;
CPUState *env = _env;
qemu_cond_broadcast(env->halt_cond);
- if (kvm_enabled() && !env->thread_kicked) {
+ if ((kvm_enabled()) && !env->thread_kicked) {
qemu_cpu_kick_thread(env);
env->thread_kicked = true;
}
{
CPUState *env = _env;
+#ifdef CONFIG_HAX
+ if (hax_enabled())
+ hax_init_vcpu(env);
+#endif
/* share a single thread for all cpus with TCG */
if (!tcg_cpu_thread) {
env->thread = g_malloc0(sizeof(QemuThread));
env->stopped = 1;
if (kvm_enabled()) {
qemu_kvm_start_vcpu(env);
- } else {
- qemu_tcg_init_vcpu(env);
}
+ else
+ qemu_tcg_init_vcpu(env);
}
void cpu_stop_current(void)
return head;
}
+
+#ifdef CONFIG_HAX
+void qemu_notify_hax_event(void)
+{
+ CPUState *env = cpu_single_env;
+
+ if (hax_enabled() && env)
+ hax_raise_event(env);
+}
+#endif
#include "hw/qdev.h"
#include "osdep.h"
#include "kvm.h"
+#include "hax.h"
#include "hw/xen.h"
#include "qemu-timer.h"
#include "memory.h"
subpage_t *subpage;
assert(size);
+
cpu_notify_set_memory(start_addr, size, phys_offset, log_dirty);
if (phys_offset == IO_MEM_UNASSIGNED) {
xen_ram_alloc(new_block->offset, size);
} else {
new_block->host = qemu_vmalloc(size);
+#ifdef CONFIG_HAX
+ /*
+ * 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)new_block->host, size);
+ if (ret < 0)
+ {
+ fprintf(stderr, "Hax failed to populate ram\n");
+ exit(-1);
+ }
+ }
+#endif
}
#endif
qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
typedef uint8_t uint8;
typedef int8_t int8;
#ifndef _AIX
-typedef int uint16;
+typedef int16_t uint16;
typedef int int16;
#endif
typedef unsigned int uint32;
void kvm_cpu_synchronize_post_init(CPUState *env);
/* generic hooks - to be moved/refactored once there are more users */
-
+#ifdef CONFIG_HAX
+void hax_cpu_synchronize_state(CPUState *env);
+void hax_cpu_synchronize_post_reset(CPUState *env);
+void hax_cpu_synchronize_post_init(CPUState *env);
+#endif
static inline void cpu_synchronize_state(CPUState *env)
{
if (kvm_enabled()) {
kvm_cpu_synchronize_state(env);
}
+#ifdef CONFIG_HAX
+ hax_cpu_synchronize_state(env);
+#endif
}
static inline void cpu_synchronize_post_reset(CPUState *env)
if (kvm_enabled()) {
kvm_cpu_synchronize_post_reset(env);
}
+#ifdef CONFIG_HAX
+ hax_cpu_synchronize_post_reset(env);
+#endif
}
static inline void cpu_synchronize_post_init(CPUState *env)
if (kvm_enabled()) {
kvm_cpu_synchronize_post_init(env);
}
+#ifdef CONFIG_HAX
+ hax_cpu_synchronize_post_init(env);
+#endif
}
return 0;
}
+extern void qemu_notify_hax_event(void);
+
void qemu_notify_event(void)
{
+#ifdef CONFIG_HAX
+ qemu_notify_hax_event();
+#endif
if (!SetEvent(qemu_event_handle)) {
fprintf(stderr, "qemu_notify_event: SetEvent failed: %ld\n",
GetLastError());
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. When HAX support detected, emulator will enable it by default. This option will disable the default action
+HAX is only supported in MAC and Windows platform and is not conflict with KVM.
+ETEXI
+
+DEF("disable-hax", 0, QEMU_OPTION_disable_hax, \
+ "-disable-hax Disable HAX full virtualization support\n", QEMU_ARCH_I386)
+STEXI
+@item -disable-hax
+@findex -disable-hax
+Disable HAX (Hardware-based Acceleration eXecution) support. When HAX support detected, emulator will enable it by default. This option will disable the default action
+HAX is only supported in MAC and Windows platform and is 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,
#include "helper.h"
#define GEN_HELPER 1
#include "helper.h"
+#include "hax.h"
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
pc_ptr = disas_insn(dc, pc_ptr);
num_insns++;
+#ifdef CONFIG_HAX
+ if (hax_enabled() && hax_stop_translate(env))
+ {
+ gen_jmp_im(pc_ptr - dc->cs_base);
+ gen_eob(dc);
+ break;
+ }
+#endif
/* stop translation if indicated */
if (dc->is_jmp)
break;
echo "checking for os... targetos $targetos"
exec ./configure \
--target-list=i386-softmmu \
- --audio-drv-list=dsound \
+ --audio-drv-list=winwave \
--enable-mixemu \
--disable-vnc-tls \
--audio-card-list=ac97 \
--enable-ldst-optimization \
+ --enable-hax \
--enable-maru \
--enable-gl
# --enable-ffmpeg
#include "audio/audio.h"
#include "migration.h"
#include "kvm.h"
+#include "hax.h"
#include "qjson.h"
#include "qemu-option.h"
#include "qemu-config.h"
#endif
int acpi_enabled = 1;
int no_hpet = 0;
+int hax_disabled = 0;
int fd_bootchk = 1;
int no_reboot = 0;
int no_shutdown = 0;
static int tcg_allowed = 1;
int kvm_allowed = 0;
int xen_allowed = 0;
+int hax_allowed = 0;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
static int tcg_tb_size;
#ifdef CONFIG_PROFILER
int64_t ti;
#endif
+
+#ifdef CONFIG_HAX
+ hax_sync_vcpus();
+#endif
+
do {
- nonblocking = !kvm_enabled() && last_io > 0;
+ nonblocking = !(kvm_enabled()|| hax_enabled()) && last_io > 0;
#ifdef CONFIG_PROFILER
ti = profile_getclock();
#endif
static int tcg_init(void)
{
+ int ret = 0;
tcg_exec_init(tcg_tb_size * 1024 * 1024);
+#ifdef CONFIG_HAX
+ if (!hax_disabled)
+ {
+ ret = hax_init();
+ dprint("HAX is %s and emulator runs in %s mode\n",
+ !ret ? "working" : "not working",
+ !ret ? "fast virt" : "emulation");
+ } else
+ dprint("HAX is disabled and emulator runs in emulation mode.\n");
+#endif
return 0;
}
{ "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
{ "xen", "Xen", xen_available, xen_init, &xen_allowed },
{ "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed },
+ //{ "hax", "HAX", hax_available, hax_init, &hax_allowed },
};
static int configure_accelerator(void)
qemu_opts_parse(olist, "accel=kvm", 0);
break;
case QEMU_OPTION_enable_gl:
-#ifndef _WIN32\r
+#ifndef _WIN32
enable_gl = 1;
-#endif\r
+#endif
break;
case QEMU_OPTION_machine:
olist = qemu_find_opts("machine");
fclose(fp);
break;
}
+ case QEMU_OPTION_enable_hax:
+ olist = qemu_find_opts("machine");
+ qemu_opts_reset(olist);
+ //qemu_opts_parse(olist, "accel=hax", 0);
+ break;
+ case QEMU_OPTION_disable_hax:
+ hax_disabled = 1;
+ break;
default:
os_parse_cmd_args(popt->index, optarg);
}
}
loc_set_none();
-#ifndef _WIN32\r
+#ifndef _WIN32
if (enable_gl && (gl_acceleration_capability_check () != 0)) {
enable_gl = 0;
fprintf (stderr, "Warn: GL acceleration was disabled due to the fail of GL check!\n");
}
}
}
-#endif\r
+#endif
/* Open the logfile at this point, if necessary. We can't open the logfile
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
}
+#ifdef CONFIG_HAX
+ hax_pre_init(ram_size);
+#endif
+
configure_accelerator();
qemu_init_cpu_loop();
exit(1);
}
- if (icount_option && (kvm_enabled() || xen_enabled())) {
+ if (icount_option && (kvm_enabled() || xen_enabled() || hax_enabled())) {
fprintf(stderr, "-icount is not allowed with kvm or xen\n");
exit(1);
}
current_machine = machine;
+#ifdef CONFIG_HAX
+ if (hax_enabled())
+ hax_sync_vcpus();
+#endif
+
/* init USB devices */
if (usb_enabled) {
if (foreach_device_config(DEV_USB, usb_parse) < 0)