]> git.ozlabs.org Git - ccan/commitdiff
Merge branch 'master' of ozlabs.org:ccan
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 28 Oct 2013 11:20:58 +0000 (21:50 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 28 Oct 2013 11:20:58 +0000 (21:50 +1030)
ccan/cpuid/cpuid.c
ccan/cpuid/cpuid.h
ccan/cpuid/test/run.c

index 153f52d4a4ad513b7898095f880d2777d44d9b5e..57883e2bd0982b17fccdeaf34fd5da945c1134ea 100644 (file)
@@ -92,6 +92,8 @@ static struct {
 
 bool cpuid_is_supported(void)
 {
+       int ret = 0;
+#if defined(__GNUC__) || defined(__clang__)
        /* The following assembly code uses EAX as the return value,
         * but we store the value of EAX into ret since GCC uses EAX
         * as the return register for every C function.  That's a double
@@ -115,16 +117,15 @@ bool cpuid_is_supported(void)
 #define ASM_POPF       "popfq\n\t"
 #define ASM_PUSHEAX    "pushq %%rax\n\t"
 #define ASM_POPEAX     "popq %%rax\n\t"
-#define ASM_PUSHECX    "popq %%rcx\n\t"
+#define ASM_PUSHECX    "pushq %%rcx\n\t"
 #elif UINTPTR_MAX == 0xffffffff
 #define ASM_PUSHF      "pushfl\n\t"
 #define ASM_POPF       "popfl\n\t"
 #define ASM_PUSHEAX    "pushl %%eax\n\t"
 #define ASM_POPEAX     "popl %%eax\n\t"
-#define ASM_PUSHECX    "popl %%ecx\n\t"
+#define ASM_PUSHECX    "pushl %%ecx\n\t"
 #endif
 
-       int ret = 0;
        asm volatile(
                ASM_PUSHF
                ASM_POPEAX
@@ -147,7 +148,26 @@ bool cpuid_is_supported(void)
 #undef ASM_PUSHEAX
 #undef ASM_POPEAX
 #undef ASM_PUSHECX
-
+#elif defined _MSC_VER
+       __asm {
+               pushfd
+               pop eax
+               mov ecx, eax
+               xor eax, 0x200000
+               push eax
+               popfd
+
+               pushfd
+               pop eax
+               xor eax, ecx
+               shr eax, 0x21
+               and eax, 0x1
+               push ecx
+               popfd
+
+               mov eax, ret
+       };
+#endif
        return !!ret;
 }
 
@@ -220,9 +240,14 @@ cputype_t cpuid_get_cpu_type(void)
        return cputype;
 }
 
-const char *cpuid_get_cpu_type_string(const cputype_t cputype)
+bool cpuid_sprintf_cputype(const cputype_t cputype, char *buf)
 {
-       return cpuids[(int)cputype];
+       if (cputype == CT_NONE)
+               return false;
+
+       memcpy(buf, cpuids[(int)cputype], 12);
+       buf[12] = '\0';
+       return true;
 }
 
 uint32_t cpuid_highest_ext_func_supported(void)
@@ -230,11 +255,19 @@ uint32_t cpuid_highest_ext_func_supported(void)
        static uint32_t highest;
 
        if (!highest) {
+#if defined(__GNUC__) || defined(__clang__)
                asm volatile(
                        "cpuid\n\t"
                        : "=a" (highest)
                        : "a" (CPU_HIGHEST_EXTENDED_FUNCTION_SUPPORTED)
                );
+#elif defined _MSC_VER
+               __asm {
+                       mov eax, CPU_HIGHEST_EXTENDED_FUNCTION_SUPPORTED
+                       cpuid
+                       mov highest, eax
+               };
+#endif
        }
 
        return highest;
@@ -298,13 +331,16 @@ void cpuid(cpuid_t info, uint32_t *buf)
                        buf[3] = edx;
                        break;
                case CPU_EXTENDED_L2_CACHE_FEATURES:
-                       *buf = ecx;
+                       buf[0] = ecx & 0xFF;            /* Line size.  */
+                       buf[1] = (ecx >> 12) & 0xFF;    /* Associativity.  */
+                       buf[2] = ecx >> 16;             /* Cache size.  */
                        break;
                case CPU_ADV_POWER_MGT_INFO:
                        *buf = edx;
                        break;
                case CPU_VIRT_PHYS_ADDR_SIZES:
-                       *buf = eax;
+                       buf[0] = eax & 0xFF;            /* physical.  */
+                       buf[1] = (eax >> 8) & 0xFF;     /* virtual.  */
                        break;
                default:
                        *buf = 0xbaadf00d;
index 0a9fc9d91ac84bb1d98cc27e80bb1b5ae5a914da..7bf903a6db397af69c454cd20eab3a061d1b084a 100644 (file)
@@ -26,7 +26,7 @@
 #include <stdint.h>
 
 /**
- * enum cpuid - stuff to get information on from the CPU.
+ * enum cpuid - stuff to get information about from the CPU.
  *
  * This is used as a parameter in cpuid().
  *
@@ -124,14 +124,17 @@ typedef enum cputype {
  *
  * See also: cpuid_get_cpu_type_string()
  */
+#define is_intel_cpu()         cpuid_get_cpu_type() == CT_INTEL
+#define is_amd_cpu()   cpuid_get_cpu_type() == CT_AMDK5 || cpuid_get_cpu_type() == CT_AMD
 cputype_t cpuid_get_cpu_type(void);
 
 /**
- * cpuid_get_cpu_type_string - Get CPU Type string
+ * cpuid_sprintf_cputype - Get CPU Type string
+ * @cputype: a char of atleast 12 bytes in it.
  *
- * Returns the CPU type string based off cputype_t.
+ * Returns true on success, false on failure
  */
-const char *cpuid_get_cpu_type_string(const cputype_t cputype);
+bool cpuid_sprintf_cputype(const cputype_t cputype, char *buf);
 
 /**
  * cpuid_is_supported - test if the CPUID instruction is supported
@@ -205,8 +208,14 @@ uint32_t cpuid_highest_ext_func_supported(void);
  * For CPU_EXTENDED_PROC_INFO_FEATURE_BITS:
  *     Returns them in buf[0] and buf[1].
  *
+ * For CPU_EXTENDED_L2_CACHE_FEATURES:
+ *     buf[0]: Line size
+ *     buf[1]: Associativity
+ *     buf[2]: Cache size.
+ *
  * For CPU_VIRT_PHYS_ADDR_SIZES:
- *     Returns it as an integer in *buf.
+ *     buf[0]: Physical
+ *     buf[1]: Virtual
  *
  * For CPU_PROC_BRAND_STRING:
  *     Have a char array with at least 48 bytes assigned to it.
@@ -269,4 +278,3 @@ bool cpuid_has_feature(int feature, bool extended);
 
 #endif
 #endif
-
index 85b1497043727f584762d671cafe830329ab65fa..843389fa2a7733178b4399bfb6d6fe3e2c07dd5d 100644 (file)
@@ -10,7 +10,9 @@ int main(void)
                return 1;
        }
 
-       printf ("Vendor ID: %s\n", cpuid_get_cpu_type_string (cpuid_get_cpu_type ()));
+       char cputype[12];
+       if (cpuid_sprintf_cputype(cpuid_get_cpu_type(), cputype))
+               printf ("Vendor ID: %s\n", cputype);
 
        char buf[48];
        cpuid(CPU_PROC_BRAND_STRING, (uint32_t *)buf);
@@ -18,39 +20,21 @@ int main(void)
 
        printf ("Highest extended function supported: %#010x\n", cpuid_highest_ext_func_supported());
 
-       union {
-               struct {
-                       uint32_t phys_bits : 8;
-                       uint32_t virt_bits : 8;
-                       uint32_t reserved  : 16;
-               };
-               uint32_t w;
-       } s;
-       cpuid(CPU_VIRT_PHYS_ADDR_SIZES, &s.w);
-       printf ("Physical address size: %d\nVirtual address size: %d\n", s.phys_bits, s.virt_bits);
+       uint32_t phys_virt[2];
+       cpuid(CPU_VIRT_PHYS_ADDR_SIZES, phys_virt);
+       printf ("Physical address size: %d\nVirtual address size: %d\n", phys_virt[0], phys_virt[1]);
 
        uint32_t extfeatures[2];
        cpuid(CPU_EXTENDED_PROC_INFO_FEATURE_BITS, extfeatures);
        printf ("Extended processor info and feature bits: %d %d\n", extfeatures[0], extfeatures[1]);
 
-       union {
-               struct {
-                       uint32_t line_size : 8;
-                       uint32_t reserved : 4;
-                       uint32_t assoc : 4;
-                       uint32_t cache_size : 16;
-               };
-
-               uint32_t w;
-       } l2c;
-
-       cpuid(CPU_EXTENDED_L2_CACHE_FEATURES, &l2c.w);
-       printf ("L2 Cache Size: %u KB\tLine Size: %u bytes\tAssociativity: %02xh\n",
-                       l2c.cache_size, l2c.line_size, l2c.assoc);
+       uint32_t l2c[3];
+       cpuid(CPU_EXTENDED_L2_CACHE_FEATURES, l2c);
+       printf("L2 Line size: %u bytes\tAssociativity: %02xh\tCache Size: %u KB\n",
+               l2c[0], l2c[1], l2c[2]);
 
        uint32_t invalid;
        cpuid(0x0ffffffUL, &invalid);
        printf ("Testing invalid: %#010x\n", invalid);
        return 0;
 }
-