[HVM][VMX] Provide right view of cpuid to the HVM guests.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 12 Jun 2006 08:45:03 +0000 (09:45 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 12 Jun 2006 08:45:03 +0000 (09:45 +0100)
Some of the CPU features such as APIC, PAE, MTRR, HT are virtualized;
while others are not virtualized yet such as TM1, TM2, MCA and there are
some features which do not need virtualization such as MMX. With the
patch Guest sees only those processor features in the cpuid which are
virtualized in the hyper visor, or do not need any virtualization in
hypervisor.

Signed-off-by: Nitin A Kamble <nitin.a.kamble@intel.com>
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Asit Mallick <asit.k.mallick@intel.com>
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/vmx/cpu.h

index 70f291a27f7ae8989e621d5d17b372aa6286f2db..2b5d0eb53658d17aad9034bb0a65e7430aeca72a 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/hvm/support.h>
 #include <asm/hvm/vmx/vmx.h>
 #include <asm/hvm/vmx/vmcs.h>
+#include <asm/hvm/vmx/cpu.h>
 #include <asm/shadow.h>
 #if CONFIG_PAGING_LEVELS >= 3
 #include <asm/shadow_64.h>
@@ -749,9 +750,7 @@ static void vmx_do_no_device_fault(void)
     }
 }
 
-/* Reserved bits: [31:15], [12:11], [9], [6], [2:1] */
-#define VMX_VCPU_CPUID_L1_RESERVED 0xffff9a46
-
+#define bitmaskof(idx) (1U << ((idx)&31))
 static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
 {
     unsigned int input = (unsigned int)regs->eax;
@@ -768,50 +767,74 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
                 (unsigned long)regs->ecx, (unsigned long)regs->edx,
                 (unsigned long)regs->esi, (unsigned long)regs->edi);
 
-    if ( input == 4 )
+    if ( input == CPUID_LEAF_0x4 )
+    {
         cpuid_count(input, count, &eax, &ebx, &ecx, &edx);
+        eax &= NUM_CORES_RESET_MASK;  
+    }
     else
+    {
         cpuid(input, &eax, &ebx, &ecx, &edx);
 
-    if ( input == 1 )
-    {
-        if ( !hvm_apic_support(v->domain) ||
-             !vlapic_global_enabled((VLAPIC(v))) )
+        if ( input == CPUID_LEAF_0x1 )
         {
-            clear_bit(X86_FEATURE_APIC, &edx);
-            /* Since the apic is disabled, avoid any confusion about SMP cpus being available */
-            clear_bit(X86_FEATURE_HT, &edx);  /* clear the hyperthread bit */
-            ebx &= 0xFF00FFFF;  /* set the logical processor count to 1 */
-            ebx |= 0x00010000;
-        }
+            /* mask off reserved bits */
+            ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED; 
 
+            if ( !hvm_apic_support(v->domain) ||
+                 !vlapic_global_enabled((VLAPIC(v))) )
+            {
+                /* Since the apic is disabled, avoid any 
+                confusion about SMP cpus being available */
 
+                clear_bit(X86_FEATURE_APIC, &edx);
+            }
+    
 #if CONFIG_PAGING_LEVELS < 3
-        clear_bit(X86_FEATURE_PAE, &edx);
-        clear_bit(X86_FEATURE_PSE, &edx);
-        clear_bit(X86_FEATURE_PSE36, &edx);
+            edx &= ~(bitmaskof(X86_FEATURE_PAE)  |
+                     bitmaskof(X86_FEATURE_PSE)  |
+                     bitmaskof(X86_FEATURE_PSE36)); 
 #else
-        if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
-        {
-            if ( !v->domain->arch.hvm_domain.pae_enabled )
-                clear_bit(X86_FEATURE_PAE, &edx);
-            clear_bit(X86_FEATURE_PSE, &edx);
-            clear_bit(X86_FEATURE_PSE36, &edx);
-        }
+            if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
+            {
+                if ( !v->domain->arch.hvm_domain.pae_enabled )
+                    clear_bit(X86_FEATURE_PAE, &edx);
+                clear_bit(X86_FEATURE_PSE, &edx);
+                clear_bit(X86_FEATURE_PSE36, &edx);
+            }
 #endif
 
-        /* Unsupportable for virtualised CPUs. */
-        ecx &= ~VMX_VCPU_CPUID_L1_RESERVED; /* mask off reserved bits */
-        clear_bit(X86_FEATURE_VMXE & 31, &ecx);
-        clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
-    }
+            ebx &= NUM_THREADS_RESET_MASK;  
+
+            /* Unsupportable for virtualised CPUs. */
+            ecx &= ~(bitmaskof(X86_FEATURE_VMXE)  |
+                     bitmaskof(X86_FEATURE_EST)   |
+                     bitmaskof(X86_FEATURE_TM2)   |
+                     bitmaskof(X86_FEATURE_CID)   |
+                     bitmaskof(X86_FEATURE_MWAIT) );
+
+            edx &= ~( bitmaskof(X86_FEATURE_HT)   |
+                     bitmaskof(X86_FEATURE_MCA)   |
+                     bitmaskof(X86_FEATURE_MCE)   |
+                     bitmaskof(X86_FEATURE_ACPI)  |
+                     bitmaskof(X86_FEATURE_ACC) );
+        }
+        else if (  ( input == CPUID_LEAF_0x6 ) 
+                || ( input == CPUID_LEAF_0x9 )
+                || ( input == CPUID_LEAF_0xA ))
+        {
+            eax = ebx = ecx = edx = 0x0;
+        }
 #ifdef __i386__
-    else if ( input == 0x80000001 )
-    {
-        /* Mask feature for Intel ia32e or AMD long mode. */
-        clear_bit(X86_FEATURE_LM & 31, &edx);
-    }
+        else if ( input == CPUID_LEAF_0x80000001 )
+        {
+            clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx);
+
+            clear_bit(X86_FEATURE_LM & 31, &edx);
+            clear_bit(X86_FEATURE_SYSCALL & 31, &edx);
+        }
 #endif
+    }
 
     regs->eax = (unsigned long) eax;
     regs->ebx = (unsigned long) ebx;
index 40161b72315f1639328152451de196c72f6cefee..8c214ae1ce5cae8416fb0d21e6738972572dd9a7 100644 (file)
@@ -32,4 +32,21 @@ struct arch_state_struct {
 #define VMX_MF_32       1
 #define VMX_MF_64       2
 
+#define CPUID_LEAF_0x1        0x1
+#define CPUID_LEAF_0x4        0x4
+#define CPUID_LEAF_0x6        0x6
+#define CPUID_LEAF_0x9        0x9
+#define CPUID_LEAF_0xA        0xA
+#define CPUID_LEAF_0x80000001 0x80000001
+
+#define NUM_CORES_RESET_MASK                 0x00003FFF
+#define NUM_THREADS_RESET_MASK               0xFF00FFFF
+
+#define VMX_VCPU_CPUID_L1_ECX_RESERVED_18    0x00040000
+#define VMX_VCPU_CPUID_L1_ECX_RESERVED_6     0x00000040
+
+#define VMX_VCPU_CPUID_L1_ECX_RESERVED             \
+            ( VMX_VCPU_CPUID_L1_ECX_RESERVED_18  | \
+              VMX_VCPU_CPUID_L1_ECX_RESERVED_6   )
+
 #endif /* __ASM_X86_HVM_VMX_CPU_H__ */