diff mbox

[RFC] Nested VMX support - userspace

Message ID 1250516916-19493-2-git-send-email-oritw@il.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

oritw@il.ibm.com Aug. 17, 2009, 1:48 p.m. UTC
From: Orit Wasserman <oritw@il.ibm.com>

This patch adds nested VMX. It exposes VMX capabilities in the CPU
required for running a nested hypervisor.

Signed-off-by: Orit Wasserman <oritw@il.ibm.com>
---
 qemu-kvm-x86.c |   37 +++++++++++++++++++++++++++++++++++--
 1 files changed, 35 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 492dbc5..92dd184 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -1254,6 +1254,18 @@  static void kvm_trim_features(uint32_t *features, uint32_t supported)
     }
 }
 
+static inline void set_bit(int bit, uint32_t *field)
+{
+    field[bit >> 5] |= 1 << (bit & 0x1F);
+}
+
+static inline int is_vendor_intel(struct kvm_cpuid_entry2 *ent)
+{
+	return ent->ebx == 0x756e6547 &&  /* "Genu" */
+		ent->ecx == 0x6c65746e && /* "ineI" */
+		ent->edx == 0x49656e69;   /* "ntel" */
+}
+
 int kvm_arch_qemu_init_env(CPUState *cenv)
 {
     struct kvm_cpuid_entry2 cpuid_ent[100];
@@ -1299,6 +1311,9 @@  int kvm_arch_qemu_init_env(CPUState *cenv)
     kvm_trim_features(&cenv->cpuid_ext3_features,
                       kvm_arch_get_supported_cpuid(cenv, 0x80000001, R_ECX));
 
+    struct kvm_cpuid_entry2 *vmx_ent = NULL;
+    int is_intel = 0;
+
     copy = *cenv;
 
     copy.regs[R_EAX] = 0;
@@ -1322,8 +1337,26 @@  int kvm_arch_qemu_init_env(CPUState *cenv)
                 if (i == 0xd && copy.regs[R_EAX] == 0)
                     break;
             }
-        } else
-            do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, &copy);
+	} else {
+		do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, &copy);
+		/* check if this is intel  */
+		if (cpuid_ent[cpuid_nent - 1].function == 0x00000000)
+			is_intel = is_vendor_intel(&cpuid_ent[cpuid_nent - 1]);
+		else if (cpuid_ent[cpuid_nent - 1].function == 0x00000001)
+			vmx_ent = &cpuid_ent[cpuid_nent - 1];
+	}
+    }
+
+    /* simulate vmx support for Intel only */
+    if (is_intel) {
+	    /* No entry for 0x00000001 function was found ,creating a new one */
+	    if (!vmx_ent && cpuid_nent < 100) {
+		    vmx_ent = &cpuid_ent[cpuid_nent++];
+		    memset(vmx_ent, 0, sizeof(*vmx_ent));
+		    vmx_ent->function = 0x00000001;
+	    }
+	    if (vmx_ent)
+		    set_bit(5, &vmx_ent->ecx);
     }
 
     copy.regs[R_EAX] = 0x80000000;