Added fast mmio support for haxm. 27/27127/1
authoryucheng yu <yu-cheng.yu@intel.com>
Fri, 5 Sep 2014 00:20:28 +0000 (17:20 -0700)
committeryucheng yu <yu-cheng.yu@intel.com>
Fri, 5 Sep 2014 00:21:40 +0000 (17:21 -0700)
Change-Id: I98e8f5ec33cfaf1539c8c108985eb7dd0b4d21ff

target-i386/hax-all.c
target-i386/hax-i386.h
target-i386/hax-interface.h
target-i386/hax-windows.c
target-i386/hax-windows.h

index 9b9449f2aeece027bd590b8e646e79c6bc994eb7..89af6225cbd35404ed2b744eed0e2bac2e4d1293 100644 (file)
@@ -27,6 +27,8 @@
 #include "strings.h"
 #include "hax-i386.h"
 #include "sysemu/kvm.h"
+#include "exec/address-spaces.h"
+#include "qemu/main-loop.h"
 
 #define HAX_EMUL_ONE    0x1
 #define HAX_EMUL_REAL   0x2
@@ -145,7 +147,7 @@ hax_fd hax_vcpu_get_fd(CPUArchState *env)
 }
 
 /* Current version */
-uint32_t hax_cur_version = 0x1;
+uint32_t hax_cur_version = 0x2; // ver 2.0: support fast mmio
 /* Least HAX kernel version */
 uint32_t hax_lest_version = 0x1;
 
@@ -228,6 +230,7 @@ int hax_vcpu_create(int id)
         goto error;
     }
 
+    vcpu->vcpu_id = id;
     vcpu->fd = hax_host_open_vcpu(hax_global.vm->id, id);
     if (hax_invalid_fd(vcpu->fd))
     {
@@ -466,6 +469,7 @@ int hax_pre_init(uint64_t ram_size)
 static int hax_init(void)
 {
     struct hax_state *hax = NULL;
+    struct hax_qemu_version qversion;
     int ret;
 
     hax_support = 0;
@@ -506,8 +510,11 @@ static int hax_init(void)
         goto error;
     }
 
-    memory_listener_register(&hax_memory_listener, NULL);
+    memory_listener_register(&hax_memory_listener, &address_space_memory);
 
+    qversion.cur_version = hax_cur_version;
+    qversion.least_version = hax_lest_version;
+    hax_notify_qemu_version(hax->vm->fd, &qversion);
     hax_support = 1;
 
     return ret;
@@ -539,6 +546,31 @@ int hax_accel_init(void)
     }
 }
 
+int  hax_handle_fastmmio(CPUArchState *env, struct hax_fastmmio *hft)
+{
+    uint64_t buf = 0;
+    /*
+     * With fast MMIO, QEMU need not sync vCPU state with HAXM
+     * driver because it will only invoke MMIO handler
+     * However, some MMIO operations utilize virtual address like qemu_pipe
+     * Thus we need to sync the CR0, CR3 and CR4 so that QEMU
+     * can translate the guest virtual address to guest physical
+     * address
+     */
+    env->cr[0] = hft->_cr0;
+    env->cr[2] = hft->_cr2;
+    env->cr[3] = hft->_cr3;
+    env->cr[4] = hft->_cr4;
+
+    buf = hft->value;
+
+    cpu_physical_memory_rw(hft->gpa, (uint8_t *)&buf, hft->size, hft->direction);
+    if (hft->direction == 0)
+        hft->value = buf;
+
+    return 0;
+}
+
 int hax_handle_io(CPUArchState *env, uint32_t df, uint16_t port, int direction,
   int size, int count, void *buffer)
 {
@@ -695,6 +727,10 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
             case HAX_EXIT_MMIO:
                 ret = HAX_EMUL_ONE;
                 break;
+            case HAX_EXIT_FAST_MMIO:
+                ret = hax_handle_fastmmio(env,
+                        (struct hax_fastmmio *)vcpu->iobuf);
+                break;
             case HAX_EXIT_REAL:
                 ret = HAX_EMUL_REAL;
                 break;
index 655e8bd47a9a382dcca8dad9b299d2b09194371f..e00c5b23c302fd97298451d8e527956920464d00 100644 (file)
@@ -71,6 +71,7 @@ int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set);
 
 int hax_vm_destroy(struct hax_vm *vm);
 int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap);
+int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion);
 
 /* Common host function */
 int hax_host_create_vm(struct hax_state *hax, int *vm_id);
index ca0f958ca6b144f5a88c41ce9649f0fe9cfbc6ae..36f9c9cc94fd3cf82268947e155db9a0ce590532 100644 (file)
@@ -45,12 +45,12 @@ struct fx_layout {
     uint8       mmx_1[8][16];
     uint8       mmx_2[8][16];
     uint8       pad[96];
-};
+}  __attribute__ ((aligned (8)));
 
 struct vmx_msr {
     uint64 entry;
     uint64 value;
-};
+} __attribute__ ((__packed__));
 
 /*
  * Fixed array is not good, but it makes Mac support a bit easier by avoiding
@@ -63,7 +63,7 @@ struct hax_msr_data
     uint16_t done;
     uint16_t pad[2];
     struct vmx_msr entries[HAX_MAX_MSR_ARRAY];
-};
+} __attribute__ ((__packed__));
 
 union interruptibility_state_t {
     uint32 raw;
@@ -249,6 +249,7 @@ enum exit_status {
     HAX_EXIT_STATECHANGE,
     /* the vcpu is now only paused when destroy, so simply return to hax */
     HAX_EXIT_PAUSED,
+    HAX_EXIT_FAST_MMIO,
 };
 
 /* The interface definition:
@@ -287,13 +288,22 @@ struct hax_tunnel
         struct {
         } state;
     };
-};
+} __attribute__ ((__packed__));
 
 struct hax_module_version
 {
     uint32_t compat_version;
     uint32_t cur_version;
-};
+} __attribute__ ((__packed__));
+
+/* This interface is support only after API version 2 */
+struct hax_qemu_version
+{
+    /* Current API version in QEMU*/
+    uint32_t cur_version;
+    /* The least API version supported by QEMU */
+    uint32_t least_version;
+}__attribute__ ((__packed__));
 
 /* The mac specfic interface to qemu, mostly is ioctl related */
 struct hax_tunnel_info
@@ -302,14 +312,14 @@ struct hax_tunnel_info
     uint64_t io_va;
     uint16_t size;
     uint16_t pad[3];
-};
+} __attribute__ ((__packed__));
 
 struct hax_alloc_ram_info
 {
     uint32_t size;
     uint32_t pad;
     uint64_t va;
-};
+}__attribute__ ((__packed__));
 #define HAX_RAM_INFO_ROM 0x1
 struct hax_set_ram_info
 {
@@ -318,7 +328,7 @@ struct hax_set_ram_info
     uint8_t flags;
     uint8_t pad[3];
     uint64_t va;
-};
+}__attribute__ ((__packed__));
 
 #define HAX_CAP_STATUS_WORKING  0x1
 #define HAX_CAP_STATUS_NOTWORKING  0x0
@@ -343,6 +353,19 @@ struct hax_capabilityinfo
     uint16_t winfo;
     uint32_t pad;
     uint64_t mem_quota;
-};
+}__attribute__ ((__packed__));
 
+struct hax_fastmmio
+{
+    uint64_t gpa;
+    uint64_t value;
+    uint8_t size;
+    uint8_t direction;
+    uint16_t reg_index;
+    uint32_t pad0;
+    uint64_t _cr0;
+    uint64_t _cr2;
+    uint64_t _cr3;
+    uint64_t _cr4;
+} __attribute__ ((__packed__));
 #endif
index 10d49bcff781dd0d3d1812f455649931f33ae0b3..1538db93aab87c9a87ed48752f08b7c4a57e26dc 100644 (file)
@@ -286,6 +286,26 @@ hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
     return hDeviceVM;
 }
 
+int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
+{
+    int ret;
+    DWORD dSize = 0;
+    if (hax_invalid_fd(vm_fd))
+        return -EINVAL;
+    ret = DeviceIoControl(vm_fd,
+      HAX_VM_IOCTL_NOTIFY_QEMU_VERSION,
+      qversion, sizeof(struct hax_qemu_version),
+      NULL, 0,
+      &dSize,
+      (LPOVERLAPPED) NULL);
+    if (!ret)
+    {
+        dprint("Failed to notify qemu API version\n");
+        return -1;
+    }
+    return 0;
+}
+
 int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
 {
     int ret;
index eb561febc2ad9439384af89b3665b818f1400eb9..e017a6ef2a8cf2fd2b689ce80371609da8fbfd70 100644 (file)
@@ -67,5 +67,5 @@ static inline int hax_invalid_fd(hax_fd fd)
 #define HAX_VCPU_IOCTL_INTERRUPT        CTL_CODE(HAX_DEVICE_TYPE, 0x90c, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define HAX_VCPU_SET_REGS               CTL_CODE(HAX_DEVICE_TYPE, 0x90d, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define HAX_VCPU_GET_REGS               CTL_CODE(HAX_DEVICE_TYPE, 0x90e, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
+#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #endif