[Title] First introduce of HAX
authorsyeon.hwang <syeon.hwang@samsung.com>
Tue, 20 Mar 2012 05:23:41 +0000 (14:23 +0900)
committersyeon.hwang <syeon.hwang@samsung.com>
Tue, 20 Mar 2012 05:23:41 +0000 (14:23 +0900)
[Type]
[Module] Emulator/
[Priority]
[CQ#]
[Redmine#]
[Problem]
[Cause]
[Solution]
[TestCase]

16 files changed:
Makefile.target
arch_init.c
arch_init.h
config.h
configure
cpu-defs.h
cpu-exec.c
cpus.c
exec.c
fpu/softfloat.h
kvm.h
main-loop.c
qemu-options.hx
target-i386/translate.c
tizen/qemu_configure.sh
vl.c

index f5a18ec..b19e96e 100755 (executable)
@@ -220,6 +220,16 @@ obj-$(CONFIG_NO_XEN) += xen-stub.o
 
 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)
index a411fdf..7995c27 100644 (file)
@@ -735,3 +735,12 @@ int xen_available(void)
     return 0;
 #endif
 }
+
+int hax_available(void)
+{
+#ifdef CONFIG_HAX
+    return 1;
+#else
+    return 0;
+#endif
+}
index a74187a..f538758 100644 (file)
@@ -31,5 +31,5 @@ void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus);
 int tcg_available(void);
 int kvm_available(void);
 int xen_available(void);
-
+int hax_available(void);
 #endif
index e20f786..82c0ab2 100644 (file)
--- a/config.h
+++ b/config.h
@@ -1,2 +1,2 @@
 #include "config-host.h"
-#include "config-target.h"
+#include "i386-softmmu/config-target.h"
index bf38d56..494bcb5 100755 (executable)
--- a/configure
+++ b/configure
@@ -134,6 +134,7 @@ xfs=""
 
 vhost_net="no"
 kvm="no"
+hax="no"
 gprof="no"
 debug_tcg="no"
 debug_mon="no"
@@ -674,6 +675,10 @@ for opt do
   ;;
   --enable-gl) gl="yes"
   ;;
+  --disable-hax) hax="no"
+  ;;
+  --enable-hax) hax="yes"
+  ;;
   --disable-tcg-interpreter) tcg_interpreter="no"
   ;;
   --enable-tcg-interpreter) tcg_interpreter="yes"
@@ -1038,6 +1043,11 @@ echo "  --disable-slirp          disable SLIRP userspace network connectivity"
 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"
@@ -2852,6 +2862,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 "GL support        $gl"
 echo "TCG interpreter   $tcg_interpreter"
 echo "fdt support       $fdt"
@@ -3581,6 +3592,15 @@ case "$target_arch2" in
       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
index db48a7a..5e22d83 100644 (file)
@@ -218,6 +218,8 @@ typedef struct CPUWatchpoint {
     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
index a9fa608..989f28e 100644 (file)
@@ -20,6 +20,7 @@
 #include "cpu.h"
 #include "disas.h"
 #include "tcg.h"
+#include "hax.h"
 #include "qemu-barrier.h"
 
 int tb_invalidated_flag;
@@ -181,6 +182,24 @@ static void cpu_handle_debug_exception(CPUState *env)
 
 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;
@@ -260,10 +279,15 @@ int cpu_exec(CPUState *env)
                 }
             }
 
+#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;
@@ -593,6 +617,11 @@ int cpu_exec(CPUState *env)
                     }
                 }
                 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(;;) */
diff --git a/cpus.c b/cpus.c
index 82530c4..6d0ad82 100644 (file)
--- a/cpus.c
+++ b/cpus.c
@@ -30,6 +30,7 @@
 #include "gdbstub.h"
 #include "dma.h"
 #include "kvm.h"
+#include "hax.h"
 #include "qmp-commands.h"
 
 #include "qemu-thread.h"
@@ -422,7 +423,8 @@ static bool cpu_thread_is_idle(CPUState *env)
         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;
@@ -540,6 +542,7 @@ static void qemu_init_sigbus(void)
 static void qemu_kvm_eat_signals(CPUState *env)
 {
 }
+
 #endif /* !CONFIG_LINUX */
 
 #ifndef _WIN32
@@ -598,6 +601,7 @@ static void qemu_kvm_init_cpu_signals(CPUState *env)
 static void qemu_tcg_init_cpu_signals(void)
 {
 }
+
 #endif /* _WIN32 */
 
 QemuMutex qemu_global_mutex;
@@ -805,7 +809,7 @@ void qemu_cpu_kick(void *_env)
     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;
     }
@@ -904,6 +908,10 @@ static void qemu_tcg_init_vcpu(void *_env)
 {
     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));
@@ -941,9 +949,9 @@ void qemu_init_vcpu(void *_env)
     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)
@@ -1136,3 +1144,13 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 
     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
diff --git a/exec.c b/exec.c
index 6c206ff..a027be9 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -31,6 +31,7 @@
 #include "hw/qdev.h"
 #include "osdep.h"
 #include "kvm.h"
+#include "hax.h"
 #include "hw/xen.h"
 #include "qemu-timer.h"
 #include "memory.h"
@@ -2672,6 +2673,7 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
     subpage_t *subpage;
 
     assert(size);
+
     cpu_notify_set_memory(start_addr, size, phys_offset, log_dirty);
 
     if (phys_offset == IO_MEM_UNASSIGNED) {
@@ -2974,6 +2976,23 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
                 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);
index 07c2929..063d3dd 100644 (file)
@@ -57,7 +57,7 @@ typedef uint8_t flag;
 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;
diff --git a/kvm.h b/kvm.h
index 243b063..e764682 100644 (file)
--- a/kvm.h
+++ b/kvm.h
@@ -164,12 +164,19 @@ void kvm_cpu_synchronize_post_reset(CPUState *env);
 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)
@@ -177,6 +184,9 @@ 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)
@@ -184,6 +194,9 @@ 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
 }
 
 
index dd31c17..cd5a352 100644 (file)
@@ -183,8 +183,13 @@ static int qemu_event_init(void)
     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());
index a3117a7..2ec5722 100644 (file)
@@ -2255,6 +2255,24 @@ special libGL installed on the guest OS.
 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,
index 8321bf3..475614c 100644 (file)
@@ -30,6 +30,7 @@
 #include "helper.h"
 #define GEN_HELPER 1
 #include "helper.h"
+#include "hax.h"
 
 #define PREFIX_REPZ   0x01
 #define PREFIX_REPNZ  0x02
@@ -7827,6 +7828,14 @@ static inline void gen_intermediate_code_internal(CPUState *env,
 
         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;
index 94fc6cd..1a0d421 100755 (executable)
@@ -27,11 +27,12 @@ MINGW*)
 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
diff --git a/vl.c b/vl.c
index 82148f0..b33bd30 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -153,6 +153,7 @@ int qemu_main(int argc, char **argv, char **envp);
 #include "audio/audio.h"
 #include "migration.h"
 #include "kvm.h"
+#include "hax.h"
 #include "qjson.h"
 #include "qemu-option.h"
 #include "qemu-config.h"
@@ -233,6 +234,7 @@ const char *vnc_display;
 #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;
@@ -289,6 +291,7 @@ static NotifierList machine_init_done_notifiers =
 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;
@@ -1499,8 +1502,13 @@ static void main_loop(void)
 #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
@@ -2028,7 +2036,18 @@ static QEMUMachine *machine_parse(const char *name)
 
 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;
 }
 
@@ -2042,6 +2061,7 @@ static struct {
     { "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)
@@ -2905,9 +2925,9 @@ int main(int argc, char **argv, char **envp)
                 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");
@@ -3136,6 +3156,14 @@ int main(int argc, char **argv, char **envp)
                     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);
             }
@@ -3143,7 +3171,7 @@ int main(int argc, char **argv, char **envp)
     }
     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");
@@ -3158,7 +3186,7 @@ int main(int argc, char **argv, char **envp)
                        }
                }
        }
-#endif\r
+#endif
        
        
     /* Open the logfile at this point, if necessary. We can't open the logfile
@@ -3302,6 +3330,10 @@ int main(int argc, char **argv, char **envp)
         ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
     }
 
+#ifdef CONFIG_HAX
+    hax_pre_init(ram_size);
+#endif
+
     configure_accelerator();
 
     qemu_init_cpu_loop();
@@ -3328,7 +3360,7 @@ int main(int argc, char **argv, char **envp)
         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);
     }
@@ -3455,6 +3487,11 @@ int main(int argc, char **argv, char **envp)
 
     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)