[RFC] Nested VMX support - userspace

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Orit Wasserman <oritw@xxxxxxxxxx>

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

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

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;
-- 
1.6.0.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux