Source-Changes-HG archive

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

[src/trunk]: src/usr.sbin/cpuctl/arch CPUID leaf 2 and 4 are only for Intel p...



details:   https://anonhg.NetBSD.org/src/rev/74ed6ef6defe
branches:  trunk
changeset: 792148:74ed6ef6defe
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Mon Dec 23 11:17:20 2013 +0000

description:
CPUID leaf 2 and 4 are only for Intel processors.

diffstat:

 usr.sbin/cpuctl/arch/i386.c |  218 ++++++++++++++++++++++++-------------------
 1 files changed, 121 insertions(+), 97 deletions(-)

diffs (truncated from 320 to 300 lines):

diff -r 06bb28f94111 -r 74ed6ef6defe usr.sbin/cpuctl/arch/i386.c
--- a/usr.sbin/cpuctl/arch/i386.c       Mon Dec 23 10:13:59 2013 +0000
+++ b/usr.sbin/cpuctl/arch/i386.c       Mon Dec 23 11:17:20 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: i386.c,v 1.51 2013/12/23 10:13:59 msaitoh Exp $        */
+/*     $NetBSD: i386.c,v 1.52 2013/12/23 11:17:20 msaitoh Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: i386.c,v 1.51 2013/12/23 10:13:59 msaitoh Exp $");
+__RCSID("$NetBSD: i386.c,v 1.52 2013/12/23 11:17:20 msaitoh Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -94,6 +94,7 @@
        const char      *ci_dev;
        int32_t         ci_cpu_type;     /* for cpu's without cpuid */
        int32_t         ci_cpuid_level;  /* highest cpuid supported */
+       uint32_t        ci_cpuid_extlevel; /* highest cpuid extended func lv */
        uint32_t        ci_signature;    /* X86 cpuid type */
        uint32_t        ci_family;       /* from ci_signature */
        uint32_t        ci_model;        /* from ci_signature */
@@ -212,6 +213,7 @@
 static void    intel_family_new_probe(struct cpu_info *);
 static void    via_cpu_probe(struct cpu_info *);
 /* (Cache) Info functions */
+static void    intel_cpu_cacheinfo(struct cpu_info *);
 static void    amd_cpu_cacheinfo(struct cpu_info *);
 static void    via_cpu_cacheinfo(struct cpu_info *);
 static void    tmx86_get_longrun_status(u_int *, u_int *, u_int *);
@@ -285,7 +287,7 @@
                        "486",          /* Default */
                        NULL,
                        NULL,
-                       NULL,
+                       intel_cpu_cacheinfo,
                },
                /* Family 5 */
                {
@@ -300,7 +302,7 @@
                        "Pentium",      /* Default */
                        NULL,
                        NULL,
-                       NULL,
+                       intel_cpu_cacheinfo,
                },
                /* Family 6 */
                {
@@ -363,7 +365,7 @@
                        "Pentium Pro, II or III",       /* Default */
                        NULL,
                        intel_family_new_probe,
-                       NULL,
+                       intel_cpu_cacheinfo,
                },
                /* Family > 6 */
                {
@@ -375,7 +377,7 @@
                        "Pentium 4",    /* Default */
                        NULL,
                        intel_family_new_probe,
-                       NULL,
+                       intel_cpu_cacheinfo,
                } }
        },
        {
@@ -956,6 +958,103 @@
                }
 }
 
+static void
+intel_cpu_cacheinfo(struct cpu_info *ci)
+{
+       const struct x86_cache_info *cai;
+       u_int descs[4];
+       int iterations, i, j;
+       int type, level;
+       int ways, partitions, linesize, sets;
+       int caitype = -1;
+       int totalsize;
+       uint8_t desc;
+
+       /* Return if the cpu is old pre-cpuid instruction cpu */
+       if (ci->ci_cpu_type >= 0)
+               return;
+
+       if (ci->ci_cpuid_level < 2)
+               return;
+
+       /*
+        * Parse the cache info from `cpuid leaf 2', if we have it.
+        * XXX This is kinda ugly, but hey, so is the architecture...
+        */
+       x86_cpuid(2, descs);
+       iterations = descs[0] & 0xff;
+       while (iterations-- > 0) {
+               for (i = 0; i < 4; i++) {
+                       if (descs[i] & 0x80000000)
+                               continue;
+                       for (j = 0; j < 4; j++) {
+                               if (i == 0 && j == 0)
+                                       continue;
+                               desc = (descs[i] >> (j * 8)) & 0xff;
+                               if (desc == 0)
+                                       continue;
+                               cai = cache_info_lookup(intel_cpuid_cache_info,
+                                   desc);
+                               if (cai != NULL)
+                                       ci->ci_cinfo[cai->cai_index] = *cai;
+                       }
+               }
+               x86_cpuid(2, descs);
+       }
+
+       if (ci->ci_cpuid_level < 4)
+               return;
+
+       /* Parse the cache info from `cpuid leaf 4', if we have it. */
+       for (i = 0; ; i++) {
+               x86_cpuid2(4, i, descs);
+               type = __SHIFTOUT(descs[0], CPUID_DCP_CACHETYPE);
+               if (type == CPUID_DCP_CACHETYPE_N)
+                       break;
+               level = __SHIFTOUT(descs[0], CPUID_DCP_CACHELEVEL);
+               switch (level) {
+               case 1:
+                       if (type == CPUID_DCP_CACHETYPE_I)
+                               caitype = CAI_ICACHE;
+                       else if (type == CPUID_DCP_CACHETYPE_D)
+                               caitype = CAI_DCACHE;
+                       else
+                               caitype = -1;
+                       break;
+               case 2:
+                       if (type == CPUID_DCP_CACHETYPE_U)
+                               caitype = CAI_L2CACHE;
+                       else
+                               caitype = -1;
+                       break;
+               case 3:
+                       if (type == CPUID_DCP_CACHETYPE_U)
+                               caitype = CAI_L3CACHE;
+                       else
+                               caitype = -1;
+                       break;
+               default:
+                       caitype = -1;
+                       break;
+               }
+               if (caitype == -1) {
+                       printf("unknown cache level&type (%d & %d)\n",
+                           level, type);
+                       continue;
+               }
+               ways = __SHIFTOUT(descs[1], CPUID_DCP_WAYS) + 1;
+               partitions =__SHIFTOUT(descs[1], CPUID_DCP_PARTITIONS)
+                   + 1;
+               linesize = __SHIFTOUT(descs[1], CPUID_DCP_LINESIZE)
+                   + 1;
+               sets = descs[2] + 1;
+               totalsize = ways * partitions * linesize * sets;
+               ci->ci_cinfo[caitype].cai_totalsize = totalsize;
+               ci->ci_cinfo[caitype].cai_associativity = ways;
+               ci->ci_cinfo[caitype].cai_linesize = linesize;
+       }
+}
+
 static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = 
     AMD_L2CACHE_INFO;
 
@@ -1302,14 +1401,8 @@
 static void
 cpu_probe_base_features(struct cpu_info *ci, const char *cpuname)
 {
-       const struct x86_cache_info *cai;
        u_int descs[4];
-       int iterations, i, j;
-       int type, level;
-       int ways, partitions, linesize, sets;
-       int caitype = -1;
-       int totalsize;
-       uint8_t desc;
+       int i;
        uint32_t brand[12];
 
        memset(ci, 0, sizeof(*ci));
@@ -1341,11 +1434,22 @@
        ci->ci_vendor[3] = 0;
 
        /*
+        * Fn8000_0000:
+        * - Get cpuid extended function's max level.
+        */
+       x86_cpuid(0x80000000, descs);
+       if (descs[0] >=  0x80000000)
+               ci->ci_cpuid_extlevel = descs[0];
+       else {
+               /* Set lower value than 0x80000000 */
+               ci->ci_cpuid_extlevel = 0;
+       }
+
+       /*
         * Fn8000_000[2-4]:
         * - Save brand string.
         */
-       x86_cpuid(0x80000000, brand);
-       if (brand[0] >= 0x80000004) {
+       if (ci->ci_cpuid_extlevel >= 0x80000004) {
                x86_cpuid(0x80000002, brand);
                x86_cpuid(0x80000003, brand + 4);
                x86_cpuid(0x80000004, brand + 8);
@@ -1362,6 +1466,8 @@
         * Fn0000_0001:
         * - Get CPU family, model and stepping (from eax).
         * - Initial local APIC ID and brand ID (from ebx)
+        * - CPUID2 (from ecx)
+        * - CPUID (from edx)
         */
        x86_cpuid(1, descs);
        ci->ci_signature = descs[0];
@@ -1378,36 +1484,6 @@
        ci->ci_feat_val[1] = descs[2];
        ci->ci_feat_val[0] = descs[3];
 
-       if (ci->ci_cpuid_level < 2)
-               return;
-
-       /*
-        * Parse the cache info from `cpuid leaf 2', if we have it.
-        * XXX This is kinda ugly, but hey, so is the architecture...
-        */
-
-       x86_cpuid(2, descs);
-
-       iterations = descs[0] & 0xff;
-       while (iterations-- > 0) {
-               for (i = 0; i < 4; i++) {
-                       if (descs[i] & 0x80000000)
-                               continue;
-                       for (j = 0; j < 4; j++) {
-                               if (i == 0 && j == 0)
-                                       continue;
-                               desc = (descs[i] >> (j * 8)) & 0xff;
-                               if (desc == 0)
-                                       continue;
-                               cai = cache_info_lookup(intel_cpuid_cache_info,
-                                   desc);
-                               if (cai != NULL)
-                                       ci->ci_cinfo[cai->cai_index] = *cai;
-                       }
-               }
-               x86_cpuid(2, descs);
-       }
-
        if (ci->ci_cpuid_level < 3)
                return;
 
@@ -1422,58 +1498,6 @@
                ci->ci_cpu_serial[1] = descs[3];
        }
 
-       if (ci->ci_cpuid_level < 4)
-               return;
-
-       /* Parse the cache info from `cpuid leaf 4', if we have it. */
-       for (i = 0; ; i++) {
-               x86_cpuid2(4, i, descs);
-               type = __SHIFTOUT(descs[0], CPUID_DCP_CACHETYPE);
-               if (type == CPUID_DCP_CACHETYPE_N)
-                       break;
-               level = __SHIFTOUT(descs[0], CPUID_DCP_CACHELEVEL);
-               switch (level) {
-               case 1:
-                       if (type == CPUID_DCP_CACHETYPE_I)
-                               caitype = CAI_ICACHE;
-                       else if (type == CPUID_DCP_CACHETYPE_D)
-                               caitype = CAI_DCACHE;
-                       else
-                               caitype = -1;
-                       break;
-               case 2:
-                       if (type == CPUID_DCP_CACHETYPE_U)
-                               caitype = CAI_L2CACHE;
-                       else
-                               caitype = -1;
-                       break;
-               case 3:
-                       if (type == CPUID_DCP_CACHETYPE_U)
-                               caitype = CAI_L3CACHE;
-                       else
-                               caitype = -1;
-                       break;
-               default:
-                       caitype = -1;
-                       break;
-               }



Home | Main Index | Thread Index | Old Index