aboutsummaryrefslogtreecommitdiffstats
path: root/target-i386
diff options
context:
space:
mode:
authorJiang, Yunhong <yunhong.jiang@intel.com>2012-02-23 06:31:12 +0800
committerJiang, Yunhong <yunhong.jiang@intel.com>2012-02-23 23:11:12 +0800
commit4a5a0efd49f100c7d53920807c83d9c74304ecd8 (patch)
tree44b171204d5d07b8ec4c2788cf107fa63fd4c211 /target-i386
parenta3338e7214cd0c69912866c6d71d8700c6ab35e2 (diff)
downloadexternal_qemu-4a5a0efd49f100c7d53920807c83d9c74304ecd8.zip
external_qemu-4a5a0efd49f100c7d53920807c83d9c74304ecd8.tar.gz
external_qemu-4a5a0efd49f100c7d53920807c83d9c74304ecd8.tar.bz2
Check HAXM capability in QEMU
Checking HAXM capability to check if emulator can use HAXM virtalization. Currently two possibility that HAXM not work. Firstly is VT/NX is not enabled in the system, seconly is HAXM have used up the memory quota. See code comemnts for the memry quota explaination. Checking the capability in advance can give user more information that why HAXM is not working and be more user friendly. Change-Id: I13f73734cf783398f485fabd19cce43364b571c3 Signed-off-by: Xin, Xiaohui <xiaohui.xin@intel.com> Signed-off-by: Gao, Fengqian <fengqian.gao@intel.com> Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/hax-all.c50
-rw-r--r--target-i386/hax-darwin.c14
-rw-r--r--target-i386/hax-darwin.h2
-rw-r--r--target-i386/hax-i386.h2
-rw-r--r--target-i386/hax-interface.h35
-rw-r--r--target-i386/hax-windows.c30
-rw-r--r--target-i386/hax-windows.h1
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)