From: yucheng yu Date: Fri, 5 Sep 2014 00:20:28 +0000 (-0700) Subject: Added fast mmio support for haxm. X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.2~641^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f4796e2eecb5bc725cea576c8f16e0086df255d3;p=sdk%2Femulator%2Fqemu.git Added fast mmio support for haxm. Change-Id: I98e8f5ec33cfaf1539c8c108985eb7dd0b4d21ff --- diff --git a/target-i386/hax-all.c b/target-i386/hax-all.c index 9b9449f2ae..89af6225cb 100644 --- a/target-i386/hax-all.c +++ b/target-i386/hax-all.c @@ -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; diff --git a/target-i386/hax-i386.h b/target-i386/hax-i386.h index 655e8bd47a..e00c5b23c3 100644 --- a/target-i386/hax-i386.h +++ b/target-i386/hax-i386.h @@ -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); diff --git a/target-i386/hax-interface.h b/target-i386/hax-interface.h index ca0f958ca6..36f9c9cc94 100644 --- a/target-i386/hax-interface.h +++ b/target-i386/hax-interface.h @@ -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 diff --git a/target-i386/hax-windows.c b/target-i386/hax-windows.c index 10d49bcff7..1538db93aa 100644 --- a/target-i386/hax-windows.c +++ b/target-i386/hax-windows.c @@ -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; diff --git a/target-i386/hax-windows.h b/target-i386/hax-windows.h index eb561febc2..e017a6ef2a 100644 --- a/target-i386/hax-windows.h +++ b/target-i386/hax-windows.h @@ -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