tech-userlevel archive

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

usr.sbin/cpuctl changes for new Intel 45nm processors



Folks,

Attached are diffs that implement the following changes in cpuctl:

1. Properly identify new Intel 45nm processors, Core i7, Atom, and the
   45nm Xeon MP (PR bin/41289)

2. Properly decode several new Intel cahce descriptors, as listed in the
   most recent (March 2009) edition of Intel's Application Note 485 (I
   haven't filed a PR for this.)

3. Break the bitwise decode of features2 into two lines to avoid line
   wrap (the Core i7 has _a_lot_ of bits set!). (PR bin/41290)

I've also included a .tgz file containing before and after output examples, from both Intel and AMD processors. This is mostly to show that I haven't badly broken other sutff in the process of making these changes.

I'd appreciate any and all feedback (and any suggestions on whether or not these should be pulled up to NetBSD-5). I'll hold off on actually committing these changes until next week.


-------------------------------------------------------------------------
|   Paul Goyette   | PGP DSS Key fingerprint: |  E-mail addresses:      |
| Customer Service | FA29 0E3B 35AF E8AE 6651 |  paul at whooppee.com   |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette at juniper.net |
| Kernel Developer |                          | pgoyette at netbsd.org  |
-------------------------------------------------------------------------

Attachment: cpuctl.output.tgz
Description: Binary data

Index: sys/arch/x86/include/cacheinfo.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/cacheinfo.h,v
retrieving revision 1.10
diff -u -p -r1.10 cacheinfo.h
--- cacheinfo.h 15 Apr 2009 05:56:36 -0000      1.10
+++ cacheinfo.h 28 Apr 2009 22:17:56 -0000
@@ -199,6 +199,10 @@ struct x86_cache_info {
 #define __CI_TBL(a,b,c,d,e,f) { a, b, c, d, e, f }
 #endif
 
+/*
+ * XXX Currently organized mostly by cache type, but would be
+ * XXX easier to maintain if it were in descriptor type order.
+ */
 #define INTEL_CACHE_INFO { \
 __CI_TBL(CAI_ITLB,     0x01,    4, 32,        4 * 1024, NULL), \
 __CI_TBL(CAI_ITLB,     0xb0,    4,128,        4 * 1024, NULL), \
@@ -211,14 +215,23 @@ __CI_TBL(CAI_DTLB2,    0x05,    4, 32, 4
 __CI_TBL(CAI_ITLB,     0x50, 0xff, 64,        4 * 1024, "4K/4M: 64 entries"), \
 __CI_TBL(CAI_ITLB,     0x51, 0xff, 64,        4 * 1024, "4K/4M: 128 entries"),\
 __CI_TBL(CAI_ITLB,     0x52, 0xff, 64,        4 * 1024, "4K/4M: 256 entries"),\
+__CI_TBL(CAI_ITLB,     0x55, 0xff, 64,        4 * 1024, "2M/4M: 7 entries"), \
+__CI_TBL(CAI_DTLB2,    0x56,    4, 16, 4 * 1024 * 1024, NULL), \
+__CI_TBL(CAI_DTLB2,    0x57,    4, 16,        4 * 1024, NULL), \
+__CI_TBL(CAI_DTLB,     0x5a, 0xff, 64,        4 * 1024, "2M/4M: 32 entries 
(L0)"), \
 __CI_TBL(CAI_DTLB,     0x5b, 0xff, 64,        4 * 1024, "4K/4M: 64 entries"), \
 __CI_TBL(CAI_DTLB,     0x5c, 0xff, 64,        4 * 1024, "4K/4M: 128 entries"),\
 __CI_TBL(CAI_DTLB,     0x5d, 0xff, 64,        4 * 1024, "4K/4M: 256 entries"),\
+__CI_TBL(CAI_ITLB,     0xb1,    4, 64,               0, "8 2M/4 4M entries"), \
+__CI_TBL(CAI_ITLB,     0xb2,    4, 64,        4 * 1024, NULL), \
 __CI_TBL(CAI_ICACHE,   0x06,    4,        8 * 1024, 32, NULL), \
 __CI_TBL(CAI_ICACHE,   0x08,    4,       16 * 1024, 32, NULL), \
+__CI_TBL(CAI_ICACHE,   0x09,    4,       32 * 1024, 64, NULL), \
 __CI_TBL(CAI_ICACHE,   0x30,    8,       32 * 1024, 64, NULL), \
 __CI_TBL(CAI_DCACHE,   0x0a,    2,        8 * 1024, 32, NULL), \
 __CI_TBL(CAI_DCACHE,   0x0c,    4,       16 * 1024, 32, NULL), \
+__CI_TBL(CAI_DCACHE,   0x0d,    4,       16 * 1024, 32, NULL), \
+__CI_TBL(CAI_L2CACHE,  0x21,    8,      256 * 1024, 64, NULL), /* L2 (MLC) */ \
 __CI_TBL(CAI_L2CACHE,  0x39,    4,      128 * 1024, 64, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x3a,    6,      192 * 1024, 64, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x3b,    2,      128 * 1024, 64, NULL), \
@@ -231,6 +244,9 @@ __CI_TBL(CAI_L2CACHE,  0x42,    4,      
 __CI_TBL(CAI_L2CACHE,  0x43,    4,      512 * 1024, 32, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x44,    4, 1 * 1024 * 1024, 32, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x45,    4, 2 * 1024 * 1024, 32, NULL), \
+__CI_TBL(CAI_L2CACHE,  0x48,   12, 3 * 1024 * 1024, 64, NULL), \
+                                                               \
+/* 0x49 Is L2 on Xeon MP (Failym 0f, Model 06), L3 otherwise */        \
 __CI_TBL(CAI_L2CACHE,  0x49,   16, 4 * 1024 * 1024, 64, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x4e,   24, 6 * 1024 * 1024, 64, NULL), \
 __CI_TBL(CAI_DCACHE,   0x60,    8,       16 * 1024, 64, NULL), \
@@ -255,6 +271,32 @@ __CI_TBL(CAI_L2CACHE,  0x84,    8, 1 * 1
 __CI_TBL(CAI_L2CACHE,  0x85,    8, 2 * 1024 * 1024, 32, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x86,    4,      512 * 1024, 64, NULL), \
 __CI_TBL(CAI_L2CACHE,  0x87,    8, 1 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x22, 0xff,      512 * 1024, 64, "sectored, 4-way "), \
+__CI_TBL(CAI_L3CACHE,  0x23, 0xff, 1 * 1024 * 1024, 64, "sectored, 8-way "), \
+__CI_TBL(CAI_L3CACHE,  0x25, 0xff, 2 * 1024 * 1024, 64, "sectored, 8-way "), \
+__CI_TBL(CAI_L3CACHE,  0x29, 0xff, 4 * 1024 * 1024, 64, "sectored, 8-way "), \
+__CI_TBL(CAI_L3CACHE,  0x46,    4, 4 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x47,    8, 8 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x49,   16, 4 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x4a,   12, 6 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x4b,   16, 8 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x4c,   12,12 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0x4d,   16,16 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd0,    4,      512 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd1,    4, 1 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd2,    4, 2 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd6,    8, 1 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd7,    8, 2 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xd8,    8, 4 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xdc,   12, 3 *  512 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xdd,   12, 3 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xde,   12, 6 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xe2,   16, 2 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xe3,   16, 4 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xe4,   16, 8 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xea,   24,12 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xeb,   24,24 * 1024 * 1024, 64, NULL), \
+__CI_TBL(CAI_L3CACHE,  0xec,   24,24 * 1024 * 1024, 64, NULL), \
 __CI_TBL(0,               0,    0,               0,  0, NULL)  \
 }
 
Index: sys/arch/x86/include/specialreg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/specialreg.h,v
retrieving revision 1.33
diff -u -p -r1.33 specialreg.h
--- specialreg.h        12 Mar 2009 09:08:40 -0000      1.33
+++ specialreg.h        28 Apr 2009 22:17:56 -0000
@@ -246,9 +246,12 @@
 #define        CPUID2_X2APIC   0x00200000      /* xAPIC Extensions */
 #define        CPUID2_POPCNT   0x00800000      
 
-#define CPUID2_FLAGS "\20\1SSE3\3DTES64\4MONITOR\5DS-CPL\6VMX\7SMX\10EST" \
-                       "\11TM2\12SSSE3\13CID\16CX16\17xTPR\20PDCM\23DCA" \
-                       "\24SSE41\25SSE42\26X2APIC\30POPCNT"
+#define CPUID2_FLAGS1 "\20\1SSE3\3DTES64\4MONITOR\5DS-CPL\6VMX\7SMX\10EST" \
+                       "\11TM2\12SSE3"
+#define        CPUID2_MASK1    0x000003ff
+#define        CPUID2_FLAGS2 
"\20\13CID\16CX16\17xTPR\20PDCM\23DCA\24SSE41\25SSE42" \
+                       "\26X2APIC\30POPCNT"
+#define        CPUID2_MASK2    0xfffffc00
 
 #define CPUID2FAMILY(cpuid)    (((cpuid) >> 8) & 0xf)
 #define CPUID2MODEL(cpuid)     (((cpuid) >> 4) & 0xf)
Index: usr.sbin/cpuctl/arch/i386.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/cpuctl/arch/i386.c,v
retrieving revision 1.17
diff -u -p -r1.17 i386.c
--- arch/i386.c 22 Apr 2009 18:10:38 -0000      1.17
+++ arch/i386.c 28 Apr 2009 22:16:36 -0000
@@ -122,6 +122,10 @@ struct cpu_nocpuid_nameclass {
        void (*cpu_info)(struct cpu_info *);
 };
 
+struct cpu_extend_nameclass {
+       int ext_model;
+       const char *cpu_models[CPU_MAXMODEL+1];
+};
 
 struct cpu_cpuid_nameclass {
        const char *cpu_id;
@@ -133,6 +137,7 @@ struct cpu_cpuid_nameclass {
                void (*cpu_setup)(struct cpu_info *);
                void (*cpu_probe)(struct cpu_info *);
                void (*cpu_info)(struct cpu_info *);
+               struct cpu_extend_nameclass *cpu_extended_names;
        } cpu_family[CPU_MAXFAMILY - CPU_MINFAMILY + 1];
 };
 
@@ -237,6 +242,19 @@ const char *modifiers[] = {
        ""
 };
 
+struct cpu_extend_nameclass intel_family6_ext_models[] = {
+       { /* Extended models 01xx */
+               0x01, { NULL,   NULL,   NULL,   NULL,
+                       NULL,   NULL,   NULL,   NULL,
+                       NULL,   NULL,   "Core i7", NULL,
+                       "Atom", "XeonMP", NULL, NULL} },
+       { /* End of list */
+               0x00, { NULL, NULL, NULL, NULL,
+                       NULL, NULL, NULL, NULL,
+                       NULL, NULL, NULL, NULL,
+                       NULL, NULL, NULL, NULL} }
+};
+
 const struct cpu_cpuid_nameclass i386_cpuid_cpus[] = {
        {
                "GenuineIntel",
@@ -254,6 +272,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family 5 */
                {
@@ -269,6 +288,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family 6 */
                {
@@ -291,6 +311,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        intel_family_new_probe,
                        NULL,
+                       &intel_family6_ext_models[0],
                },
                /* Family > 6 */
                {
@@ -303,6 +324,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        intel_family_new_probe,
                        NULL,
+                       NULL,
                } }
        },
        {
@@ -324,6 +346,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family 5 */
                {
@@ -337,6 +360,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        amd_family5_setup,
                        NULL,
                        amd_cpu_cacheinfo,
+                       NULL,
                },
                /* Family 6 */
                {
@@ -351,6 +375,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        amd_family6_probe,
                        amd_cpu_cacheinfo,
+                       NULL,
                },
                /* Family > 6 */
                {
@@ -363,6 +388,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        amd_family6_probe,
                        amd_cpu_cacheinfo,
+                       NULL,
                } }
        },
        {
@@ -381,6 +407,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        cyrix6x86_cpu_setup, /* XXX ?? */
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family 5 */
                {
@@ -394,6 +421,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        cyrix6x86_cpu_setup,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family 6 */
                {
@@ -406,6 +434,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        cyrix6x86_cpu_setup,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family > 6 */
                {
@@ -418,6 +447,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                } }
        },
        {       /* MediaGX is now owned by National Semiconductor */
@@ -435,6 +465,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family 5: Geode family, formerly MediaGX */
                {
@@ -448,6 +479,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        cyrix6x86_cpu_setup,
                        NULL,
                        amd_cpu_cacheinfo,
+                       NULL,
                },
                /* Family 6, not yet available from NSC */
                {
@@ -460,6 +492,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family > 6, not yet available from NSC */
                {
@@ -472,6 +505,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                } }
        },
        {
@@ -489,6 +523,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family 5 */
                {
@@ -501,6 +536,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        winchip_cpu_setup,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family 6, VIA acquired IDT Centaur design subsidiary */
                {
@@ -514,6 +550,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        via_cpu_probe,
                        via_cpu_cacheinfo,
+                       NULL,
                },
                /* Family > 6, not yet available from VIA */
                {
@@ -526,6 +563,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                } }
        },
        {
@@ -543,6 +581,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family 5 */
                {
@@ -555,6 +594,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        transmeta_cpu_info,
+                       NULL,
                },
                /* Family 6, not yet available from Transmeta */
                {
@@ -567,6 +607,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                },
                /* Family > 6, not yet available from Transmeta */
                {
@@ -579,6 +620,7 @@ const struct cpu_cpuid_nameclass i386_cp
                        NULL,
                        NULL,
                        NULL,
+                       NULL,
                } }
        }
 };
@@ -1181,9 +1223,10 @@ transmeta_cpu_info(struct cpu_info *ci)
 void
 identifycpu(const char *cpuname)
 {
-       const char *name, *modifier, *vendorname, *brand = "";
+       const char *name = "", *modifier, *vendorname, *brand = "";
        int class = CPUCLASS_386, i, xmax;
-       int modif, family, model;
+       int modif, family, model, ext_model;
+       const struct cpu_extend_nameclass *modlist;
        const struct cpu_cpuid_nameclass *cpup = NULL;
        const struct cpu_cpuid_family *cpufam;
        const char *feature_str[5];
@@ -1217,6 +1260,7 @@ identifycpu(const char *cpuname)
                if (family < CPU_MINFAMILY)
                        errx(1, "identifycpu: strange family value");
                model = CPUID2MODEL(ci->ci_signature);
+               ext_model = CPUID2EXTMODEL(ci->ci_signature);
 
                for (i = 0; i < xmax; i++) {
                        if (!strncmp((char *)ci->ci_vendor,
@@ -1245,11 +1289,29 @@ identifycpu(const char *cpuname)
                        if (family > CPU_MAXFAMILY) {
                                family = CPU_MAXFAMILY;
                                model = CPU_DEFMODEL;
-                       } else if (model > CPU_MAXMODEL)
+                       } else if (model > CPU_MAXMODEL) {
                                model = CPU_DEFMODEL;
+                               ext_model = 0;
+                       }
                        cpufam = &cpup->cpu_family[family - CPU_MINFAMILY];
-                       name = cpufam->cpu_models[model];
-                       if (name == NULL)
+                       if (cpufam->cpu_extended_names == NULL ||
+                           ext_model == 0)
+                               name = cpufam->cpu_models[model];
+                       else {
+                               /*
+                                * Scan list(s) of extended model names
+                                */
+                               modlist = cpufam->cpu_extended_names;
+                               while (modlist->ext_model != 0) {
+                                       if (modlist->ext_model == ext_model) {
+                                               name =
+                                                    modlist->cpu_models[model];
+                                               break;
+                                       }
+                                       modlist++;
+                               }
+                       }
+                       if (name == NULL || *name == '\0')
                            name = cpufam->cpu_models[CPU_DEFMODEL];
                        class = cpufam->cpu_class;
                        ci->ci_info = cpufam->cpu_info;
@@ -1360,8 +1422,16 @@ identifycpu(const char *cpuname)
        }
 
        if (ci->ci_feature2_flags) {
-               snprintb(buf, sizeof(buf), CPUID2_FLAGS, ci->ci_feature2_flags);
-               aprint_verbose("%s: features2 %s\n", cpuname, buf);
+               if ((ci->ci_feature2_flags & CPUID2_MASK1) != 0) {
+                       snprintb(buf, sizeof(buf), CPUID2_FLAGS1,
+                           ci->ci_feature2_flags);
+                       aprint_verbose("%s: features2 %s\n", cpuname, buf);
+               }
+               if ((ci->ci_feature2_flags & CPUID2_MASK2) != 0) {
+                       snprintb(buf, sizeof(buf), CPUID2_FLAGS2,
+                           ci->ci_feature2_flags);
+                       aprint_verbose("%s: features2 %s\n", cpuname, buf);
+               }
        }
 
        if (ci->ci_feature3_flags) {


Home | Main Index | Thread Index | Old Index