Split CPUID from op_helper
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 5 Nov 2008 15:34:06 +0000 (15:34 +0000)
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 5 Nov 2008 15:34:06 +0000 (15:34 +0000)
KVM needs to call CPUID from outside of the TCG code.  This patch
splits out the CPUID logic into a separate helper that both the op
helper and KVM can call.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5626 c046a42c-6fe2-441c-8c8c-71466251a162

target-i386/cpu.h
target-i386/helper.c
target-i386/op_helper.c

index b1678efd8cedff9bf4728bccd047638b8e931509..263a477765ddb8f6f44b1a8f3f15114d7827da9a 100644 (file)
@@ -730,6 +730,10 @@ void cpu_smm_update(CPUX86State *env);
 /* will be suppressed */
 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
 
+void cpu_x86_cpuid(CPUX86State *env, uint32_t index,
+                   uint32_t *eax, uint32_t *ebx,
+                   uint32_t *ecx, uint32_t *edx);
+
 /* used to debug */
 #define X86_DUMP_FPU  0x0001 /* dump FPU state too */
 #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
index 7569c7e20a427fed82d378fbad7c83300aac528a..bcf5e7f70558a74aa1bd81b753bed35203b2279a 100644 (file)
@@ -1287,3 +1287,169 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return paddr;
 }
 #endif /* !CONFIG_USER_ONLY */
+
+void cpu_x86_cpuid(CPUX86State *env, uint32_t index,
+                   uint32_t *eax, uint32_t *ebx,
+                   uint32_t *ecx, uint32_t *edx)
+{
+    /* test if maximum index reached */
+    if (index & 0x80000000) {
+        if (index > env->cpuid_xlevel)
+            index = env->cpuid_level;
+    } else {
+        if (index > env->cpuid_level)
+            index = env->cpuid_level;
+    }
+
+    switch(index) {
+    case 0:
+        *eax = env->cpuid_level;
+        *ebx = env->cpuid_vendor1;
+        *edx = env->cpuid_vendor2;
+        *ecx = env->cpuid_vendor3;
+        break;
+    case 1:
+        *eax = env->cpuid_version;
+        *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
+        *ecx = env->cpuid_ext_features;
+        *edx = env->cpuid_features;
+        break;
+    case 2:
+        /* cache info: needed for Pentium Pro compatibility */
+        *eax = 1;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0x2c307d;
+        break;
+    case 4:
+        /* cache info: needed for Core compatibility */
+        switch (*ecx) {
+            case 0: /* L1 dcache info */
+                *eax = 0x0000121;
+                *ebx = 0x1c0003f;
+                *ecx = 0x000003f;
+                *edx = 0x0000001;
+                break;
+            case 1: /* L1 icache info */
+                *eax = 0x0000122;
+                *ebx = 0x1c0003f;
+                *ecx = 0x000003f;
+                *edx = 0x0000001;
+                break;
+            case 2: /* L2 cache info */
+                *eax = 0x0000143;
+                *ebx = 0x3c0003f;
+                *ecx = 0x0000fff;
+                *edx = 0x0000001;
+                break;
+            default: /* end of info */
+                *eax = 0;
+                *ebx = 0;
+                *ecx = 0;
+                *edx = 0;
+                break;
+        }
+
+        break;
+    case 5:
+        /* mwait info: needed for Core compatibility */
+        *eax = 0; /* Smallest monitor-line size in bytes */
+        *ebx = 0; /* Largest monitor-line size in bytes */
+        *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
+        *edx = 0;
+        break;
+    case 6:
+        /* Thermal and Power Leaf */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 9:
+        /* Direct Cache Access Information Leaf */
+        *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 0xA:
+        /* Architectural Performance Monitoring Leaf */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 0x80000000:
+        *eax = env->cpuid_xlevel;
+        *ebx = env->cpuid_vendor1;
+        *edx = env->cpuid_vendor2;
+        *ecx = env->cpuid_vendor3;
+        break;
+    case 0x80000001:
+        *eax = env->cpuid_features;
+        *ebx = 0;
+        *ecx = env->cpuid_ext3_features;
+        *edx = env->cpuid_ext2_features;
+        break;
+    case 0x80000002:
+    case 0x80000003:
+    case 0x80000004:
+        *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
+        *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
+        *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
+        *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
+        break;
+    case 0x80000005:
+        /* cache info (L1 cache) */
+        *eax = 0x01ff01ff;
+        *ebx = 0x01ff01ff;
+        *ecx = 0x40020140;
+        *edx = 0x40020140;
+        break;
+    case 0x80000006:
+        /* cache info (L2 cache) */
+        *eax = 0;
+        *ebx = 0x42004200;
+        *ecx = 0x02008140;
+        *edx = 0;
+        break;
+    case 0x80000008:
+        /* virtual & phys address size in low 2 bytes. */
+/* XXX: This value must match the one used in the MMU code. */ 
+        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
+            /* 64 bit processor */
+#if defined(USE_KQEMU)
+            *eax = 0x00003020; /* 48 bits virtual, 32 bits physical */
+#else
+/* XXX: The physical address space is limited to 42 bits in exec.c. */
+            *eax = 0x00003028; /* 48 bits virtual, 40 bits physical */
+#endif
+        } else {
+#if defined(USE_KQEMU)
+            *eax = 0x00000020; /* 32 bits physical */
+#else
+            if (env->cpuid_features & CPUID_PSE36)
+                *eax = 0x00000024; /* 36 bits physical */
+            else
+                *eax = 0x00000020; /* 32 bits physical */
+#endif
+        }
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 0x8000000A:
+        *eax = 0x00000001; /* SVM Revision */
+        *ebx = 0x00000010; /* nr of ASIDs */
+        *ecx = 0;
+        *edx = 0; /* optional features */
+        break;
+    default:
+        /* reserved values: zero */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    }
+}
index d0919d95ffdb122b463ed9761e782a4b2db9db21..c9c0936a70c04c2cce23b14782fc2ccb91f62894 100644 (file)
@@ -1885,171 +1885,15 @@ void helper_single_step(void)
 
 void helper_cpuid(void)
 {
-    uint32_t index;
+    uint32_t eax, ebx, ecx, edx;
 
     helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
-    
-    index = (uint32_t)EAX;
-    /* test if maximum index reached */
-    if (index & 0x80000000) {
-        if (index > env->cpuid_xlevel)
-            index = env->cpuid_level;
-    } else {
-        if (index > env->cpuid_level)
-            index = env->cpuid_level;
-    }
 
-    switch(index) {
-    case 0:
-        EAX = env->cpuid_level;
-        EBX = env->cpuid_vendor1;
-        EDX = env->cpuid_vendor2;
-        ECX = env->cpuid_vendor3;
-        break;
-    case 1:
-        EAX = env->cpuid_version;
-        EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
-        ECX = env->cpuid_ext_features;
-        EDX = env->cpuid_features;
-        break;
-    case 2:
-        /* cache info: needed for Pentium Pro compatibility */
-        EAX = 1;
-        EBX = 0;
-        ECX = 0;
-        EDX = 0x2c307d;
-        break;
-    case 4:
-        /* cache info: needed for Core compatibility */
-        switch (ECX) {
-            case 0: /* L1 dcache info */
-                EAX = 0x0000121;
-                EBX = 0x1c0003f;
-                ECX = 0x000003f;
-                EDX = 0x0000001;
-                break;
-            case 1: /* L1 icache info */
-                EAX = 0x0000122;
-                EBX = 0x1c0003f;
-                ECX = 0x000003f;
-                EDX = 0x0000001;
-                break;
-            case 2: /* L2 cache info */
-                EAX = 0x0000143;
-                EBX = 0x3c0003f;
-                ECX = 0x0000fff;
-                EDX = 0x0000001;
-                break;
-            default: /* end of info */
-                EAX = 0;
-                EBX = 0;
-                ECX = 0;
-                EDX = 0;
-                break;
-        }
-
-        break;
-    case 5:
-        /* mwait info: needed for Core compatibility */
-        EAX = 0; /* Smallest monitor-line size in bytes */
-        EBX = 0; /* Largest monitor-line size in bytes */
-        ECX = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
-        EDX = 0;
-        break;
-    case 6:
-        /* Thermal and Power Leaf */
-        EAX = 0;
-        EBX = 0;
-        ECX = 0;
-        EDX = 0;
-        break;
-    case 9:
-        /* Direct Cache Access Information Leaf */
-        EAX = 0; /* Bits 0-31 in DCA_CAP MSR */
-        EBX = 0;
-        ECX = 0;
-        EDX = 0;
-        break;
-    case 0xA:
-        /* Architectural Performance Monitoring Leaf */
-        EAX = 0;
-        EBX = 0;
-        ECX = 0;
-        EDX = 0;
-        break;
-    case 0x80000000:
-        EAX = env->cpuid_xlevel;
-        EBX = env->cpuid_vendor1;
-        EDX = env->cpuid_vendor2;
-        ECX = env->cpuid_vendor3;
-        break;
-    case 0x80000001:
-        EAX = env->cpuid_features;
-        EBX = 0;
-        ECX = env->cpuid_ext3_features;
-        EDX = env->cpuid_ext2_features;
-        break;
-    case 0x80000002:
-    case 0x80000003:
-    case 0x80000004:
-        EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
-        EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
-        ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
-        EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
-        break;
-    case 0x80000005:
-        /* cache info (L1 cache) */
-        EAX = 0x01ff01ff;
-        EBX = 0x01ff01ff;
-        ECX = 0x40020140;
-        EDX = 0x40020140;
-        break;
-    case 0x80000006:
-        /* cache info (L2 cache) */
-        EAX = 0;
-        EBX = 0x42004200;
-        ECX = 0x02008140;
-        EDX = 0;
-        break;
-    case 0x80000008:
-        /* virtual & phys address size in low 2 bytes. */
-/* XXX: This value must match the one used in the MMU code. */ 
-        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
-            /* 64 bit processor */
-#if defined(USE_KQEMU)
-            EAX = 0x00003020;  /* 48 bits virtual, 32 bits physical */
-#else
-/* XXX: The physical address space is limited to 42 bits in exec.c. */
-            EAX = 0x00003028;  /* 48 bits virtual, 40 bits physical */
-#endif
-        } else {
-#if defined(USE_KQEMU)
-            EAX = 0x00000020;  /* 32 bits physical */
-#else
-            if (env->cpuid_features & CPUID_PSE36)
-                EAX = 0x00000024; /* 36 bits physical */
-            else
-                EAX = 0x00000020; /* 32 bits physical */
-#endif
-        }
-        EBX = 0;
-        ECX = 0;
-        EDX = 0;
-        break;
-    case 0x8000000A:
-        EAX = 0x00000001; /* SVM Revision */
-        EBX = 0x00000010; /* nr of ASIDs */
-        ECX = 0;
-        EDX = 0; /* optional features */
-        break;
-    default:
-        /* reserved values: zero */
-        EAX = 0;
-        EBX = 0;
-        ECX = 0;
-        EDX = 0;
-        break;
-    }
+    cpu_x86_cpuid(env, (uint32_t)EAX, &eax, &ebx, &ecx, &edx);
+    EAX = eax;
+    EBX = ebx;
+    ECX = ecx;
+    EDX = edx;
 }
 
 void helper_enter_level(int level, int data32, target_ulong t1)