diff options
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/hax-all.c | 50 | ||||
-rw-r--r-- | target-i386/hax-darwin.c | 14 | ||||
-rw-r--r-- | target-i386/hax-darwin.h | 2 | ||||
-rw-r--r-- | target-i386/hax-i386.h | 2 | ||||
-rw-r--r-- | target-i386/hax-interface.h | 35 | ||||
-rw-r--r-- | target-i386/hax-windows.c | 30 | ||||
-rw-r--r-- | target-i386/hax-windows.h | 1 |
7 files changed, 133 insertions, 1 deletions
diff --git a/target-i386/hax-all.c b/target-i386/hax-all.c index 18d65d0..ac919c5 100644 --- a/target-i386/hax-all.c +++ b/target-i386/hax-all.c @@ -124,6 +124,37 @@ uint32_t hax_cur_version = 0x1; /* Least HAX kernel version */ uint32_t hax_lest_version = 0x1; +static int hax_get_capability(struct hax_state *hax) +{ + int ret; + struct hax_capabilityinfo capinfo, *cap = &capinfo; + + ret = hax_capability(hax, cap); + if (ret) + return -ENOSYS; + + if ( ((cap->wstatus & HAX_CAP_WORKSTATUS_MASK) == + HAX_CAP_STATUS_NOTWORKING )) + { + if (cap->winfo & HAX_CAP_FAILREASON_VT) + dprint("VT feature is not enabled, HAXM not working.\n"); + else if (cap->winfo & HAX_CAP_FAILREASON_NX) + dprint("NX feature is not enabled, HAXM not working.\n"); + return -ENXIO; + } + + if (cap->wstatus & HAX_CAP_MEMQUOTA) + { + if (cap->mem_quota < hax->mem_quota) + { + dprint("The memory needed by this VM exceeds the driver limit.\n"); + return -ENOSPC; + } + } + + return 0; +} + static int hax_version_support(struct hax_state *hax) { int ret; @@ -297,6 +328,16 @@ int hax_vm_destroy(struct hax_vm *vm) return 0; } +int hax_set_ramsize(uint64_t ramsize) +{ + struct hax_state *hax = &hax_global; + + memset(hax, 0, sizeof(struct hax_state)); + hax->mem_quota = ram_size; + + return 0; +} + int hax_init(int smp_cpus) { struct hax_state *hax = NULL; @@ -305,7 +346,6 @@ int hax_init(int smp_cpus) hax_support = 0; hax = &hax_global; - memset(hax, 0, sizeof(struct hax_state)); hax->fd = hax_mod_open(); if (hax_invalid_fd(hax->fd)) @@ -315,6 +355,14 @@ int hax_init(int smp_cpus) goto error; } + ret = hax_get_capability(hax); + /* In case HAXM have no such capability support */ + if (ret && (ret != -ENOSYS)) + { + ret = -EINVAL; + goto error; + } + if (!hax_version_support(hax)) { dprint("Incompatible HAX version. Qemu current version %x ", hax_cur_version ); diff --git a/target-i386/hax-darwin.c b/target-i386/hax-darwin.c index b6d27c3..2b460ce 100644 --- a/target-i386/hax-darwin.c +++ b/target-i386/hax-darwin.c @@ -85,6 +85,20 @@ int hax_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t return ret; } +int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap) +{ + int ret; + + ret = ioctl(hax->fd, HAX_IOCTL_CAPABILITY, cap); + if (ret == -1) + { + dprint("Failed to get HAX capability\n"); + return -errno; + } + + return 0; +} + int hax_mod_version(struct hax_state *hax, struct hax_module_version *version) { int ret; diff --git a/target-i386/hax-darwin.h b/target-i386/hax-darwin.h index 261cfd3..2c6129b 100644 --- a/target-i386/hax-darwin.h +++ b/target-i386/hax-darwin.h @@ -40,6 +40,8 @@ static inline void hax_close_fd(hax_fd fd) #define HAX_IOCTL_VERSION _IOWR(0, 0x20, struct hax_module_version) /* Create VM instance and return the vm_id */ #define HAX_IOCTL_CREATE_VM _IOWR(0, 0x21, int) +/* Get HAXM capability information */ +#define HAX_IOCTL_CAPABILITY _IOR(0, 0x23, struct hax_capabilityinfo) /* Pass down a VM_ID, create a VCPU instance for it */ #define HAX_VM_IOCTL_VCPU_CREATE _IOR(0, 0x80, int) diff --git a/target-i386/hax-i386.h b/target-i386/hax-i386.h index e55e584..27203cf 100644 --- a/target-i386/hax-i386.h +++ b/target-i386/hax-i386.h @@ -40,6 +40,7 @@ struct hax_state hax_fd fd; /* the global hax device interface */ uint32_t version; struct hax_vm *vm; + uint64_t mem_quota; }; #define HAX_MAX_VCPU 0x10 @@ -67,6 +68,7 @@ int hax_sync_vcpu_state(CPUState *env, struct vcpu_state_t *state, int set); int hax_sync_msr(CPUState *env, struct hax_msr_data *msrs, int set); int hax_sync_fpu(CPUState *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); /* 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 5a9ed31..569eeba 100644 --- a/target-i386/hax-interface.h +++ b/target-i386/hax-interface.h @@ -347,4 +347,39 @@ struct hax_set_ram_info uint64_t va; }; +/* + * We need to load the HAXM (HAX Manager) to tell if the host system has the + * required capabilities to operate, and we use hax_capabilityinfo to get such + * info from HAXM. + * + * To prevent HAXM from over-consuming RAM, we set the maximum amount of RAM + * that can be used for guests at HAX installation time. Once the quota is + * reached, HAXM will no longer attempt to allocate memory for guests. + * Detect that HAXM is out of quota can take the emulator to non-HAXM model + */ +struct hax_capabilityinfo +{ + /* bit 0: 1 - HAXM is working + * 0 - HAXM is not working possibly because VT/NX is disabled + NX means Non-eXecution, aks. XD (eXecution Disable) + * bit 1: 1 - HAXM has hard limit on how many RAM can be used as guest RAM + * 0 - HAXM has no memory limitation + */ +#define HAX_CAP_STATUS_WORKING 0x1 +#define HAX_CAP_STATUS_NOTWORKING 0x0 +#define HAX_CAP_WORKSTATUS_MASK 0x1 +#define HAX_CAP_MEMQUOTA 0x2 + uint16_t wstatus; + /* + * valid when HAXM is not working + * bit 0: HAXM is not working because VT is not enabeld + * bit 1: HAXM is not working because NX not enabled + */ +#define HAX_CAP_FAILREASON_VT 0x1 +#define HAX_CAP_FAILREASON_NX 0x2 + uint16_t winfo; + uint32_t pad; + uint64_t mem_quota; +}; + #endif diff --git a/target-i386/hax-windows.c b/target-i386/hax-windows.c index 683a227..346e5c0 100644 --- a/target-i386/hax-windows.c +++ b/target-i386/hax-windows.c @@ -133,6 +133,36 @@ int hax_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t return 0; } +int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap) +{ + int ret; + HANDLE hDevice = hax->fd; //handle to hax module + DWORD dSize = 0; + DWORD err = 0; + + if (hax_invalid_fd(hDevice)) { + dprint("Invalid fd for hax device!\n"); + return -ENODEV; + } + + ret = DeviceIoControl(hDevice, + HAX_IOCTL_CAPABILITY, + NULL, 0, + cap, sizeof(*cap), + &dSize, + (LPOVERLAPPED) NULL); + + if (!ret) { + err = GetLastError(); + if (err == ERROR_INSUFFICIENT_BUFFER || + err == ERROR_MORE_DATA) + dprint("hax capability is too long to hold.\n"); + dprint("Failed to get Hax capability:%d\n", err); + return -EFAULT; + } else + return 0; +} + int hax_mod_version(struct hax_state *hax, struct hax_module_version *version) { int ret; diff --git a/target-i386/hax-windows.h b/target-i386/hax-windows.h index b6d60b7..9e596d3 100644 --- a/target-i386/hax-windows.h +++ b/target-i386/hax-windows.h @@ -45,6 +45,7 @@ static inline int hax_invalid_fd(hax_fd fd) /* See comments for the ioctl in hax-darwin.h */ #define HAX_IOCTL_VERSION CTL_CODE(HAX_DEVICE_TYPE, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS) #define HAX_IOCTL_CREATE_VM CTL_CODE(HAX_DEVICE_TYPE, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_IOCTL_CAPABILITY CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS) #define HAX_VM_IOCTL_VCPU_CREATE CTL_CODE(HAX_DEVICE_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS) #define HAX_VM_IOCTL_ALLOC_RAM CTL_CODE(HAX_DEVICE_TYPE, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS) |