#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
}
/* 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;
goto error;
}
+ vcpu->vcpu_id = id;
vcpu->fd = hax_host_open_vcpu(hax_global.vm->id, id);
if (hax_invalid_fd(vcpu->fd))
{
static int hax_init(void)
{
struct hax_state *hax = NULL;
+ struct hax_qemu_version qversion;
int ret;
hax_support = 0;
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;
}
}
+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)
{
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;
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);
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
uint16_t done;
uint16_t pad[2];
struct vmx_msr entries[HAX_MAX_MSR_ARRAY];
-};
+} __attribute__ ((__packed__));
union interruptibility_state_t {
uint32 raw;
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:
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
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
{
uint8_t flags;
uint8_t pad[3];
uint64_t va;
-};
+}__attribute__ ((__packed__));
#define HAX_CAP_STATUS_WORKING 0x1
#define HAX_CAP_STATUS_NOTWORKING 0x0
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
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;
#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