Module Name: src Committed By: martin Date: Sun Mar 6 17:58:22 UTC 2016
Modified Files: src/sys/arch/x86/x86 [netbsd-7]: procfs_machdep.c Log Message: Pull up the following revisions, requested by msaitoh in ticket #1119: sys/arch/x86/x86/procfs_machdep.c 1.7-1.11 x86's /proc/cpuinfo fixes: - Always output 2 digits for the cpu frequency decimal part. - Update x86's feature bits in /proc/cpuinfo (PR#49246). - Fix a bug that /proc/cpuinfo's CPU model was incorrect on many newer CPUs and CPU family was incorrect on some AMD CPUs. - Add comment. Fix comment. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.6.4.1 src/sys/arch/x86/x86/procfs_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/x86/procfs_machdep.c diff -u src/sys/arch/x86/x86/procfs_machdep.c:1.6 src/sys/arch/x86/x86/procfs_machdep.c:1.6.4.1 --- src/sys/arch/x86/x86/procfs_machdep.c:1.6 Sat Apr 5 18:43:09 2014 +++ src/sys/arch/x86/x86/procfs_machdep.c Sun Mar 6 17:58:22 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_machdep.c,v 1.6 2014/04/05 18:43:09 christos Exp $ */ +/* $NetBSD: procfs_machdep.c,v 1.6.4.1 2016/03/06 17:58:22 martin Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_machdep.c,v 1.6 2014/04/05 18:43:09 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_machdep.c,v 1.6.4.1 2016/03/06 17:58:22 martin Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -56,50 +56,97 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_machd #include <machine/reg.h> #include <machine/specialreg.h> -static const char * const x86_features[] = { - /* Intel-defined */ +/* + * The feature table. The order is the same as Linux's + * x86/include/asm/cpufeatures.h. + */ +static const char * const x86_features[][32] = { + { /* (0) Common */ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", - "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL, -#ifdef __x86_64__ - /* AMD-defined */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL, - NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow", - - /* Transmeta-defined */ - "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Linux-defined */ - "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL, - "constant_tsc", NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Intel-defined */ - "pni", NULL, NULL, "monitor", "ds_cpi", "vmx", NULL, "est", - "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* VIA/Cyrix/Centaur-defined */ - NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* AMD defined */ - "lahf_lm", "cmp_legacy", "svm", NULL, "cr8_legacy", NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#endif + "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe"}, + + { /* (1) AMD-defined: 80000001 edx */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, + NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext","3dnow"}, + + { /* (2) Transmeta-defined */ + "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + + { /* (3) Linux mapping */ + "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL, + "constant_tsc", NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + + { /* (4) Intel-defined: 80000001 ecx */ + "pni", "pclmulqdq", "dtes64", "monitor", "ds_cpl", "vmx", "smx", "est", + "tm2", "ssse3", "cid", "sdbg", "fma", "cx16", "xtpr", "pdcm", + NULL, "pcid", "dca", "sse4_1", "sse4_2", "x2apic", "movbe", "popcnt", + "tsc_deadline_timer", "aes", "xsave", NULL, + "avx", "f16c", "rdrand", "hypervisor"}, + + { /* (5) VIA/Cyrix/Centaur-defined */ + NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + + { /* (6) AMD defined 80000001 ecx */ + "lahf_lm", "cmp_legacy", "svm", "extapic", + "cr8_legacy", "abm", "sse4a", "misalignsse", + "3dnowprefetch", "osvw", "ibs", "xop", "skinit", "wdt", NULL, "lwp", + "fma4", "tce", NULL, "nodeid_msr", + NULL, "tbm", "topoext", "perfctr_core", + "perfctr_nb", NULL, "bpext", NULL, "perfctr_l2", "mwaitx", NULL, NULL}, + + { /* (7) Linux mapping */ + "ida", "arat", "cpb", "ebp", NULL, "pln", "pts", "dtherm", + "hw_pstate", "proc_feedback", "hwp", "hwp_notify", "hwp_act_window", + "hwp_epp", "hwp_pkg_req", "intel_pt", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + + { /* (8) Linux mapping */ + "tpr_shadow", "vnmi", "flexpriority", "ept", + "vpid", "npt", "lbrv", "svm_lock", + "nrip_save", "tsc_scale", "vmcb_clean", "flushbyasid", + "decodeassists", "pausefilter", "pfthreshold", "vmmcall", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + + { /* (9) Intel-defined: 00000007 ebx */ + "fsgsbase", "tsc_adjust", NULL, "bmi1", "hle", "avx2", NULL, "smep", + "bmi2", "erms", "invpcid", "rtm", "cqm", NULL, "mpx", NULL, + "avx512f", NULL, "rdseed", "adx", + "smap", NULL, "pcommit", "clflushopt", + "clwb", NULL, "avx512pf", "avx512er", + "avx512cd", "sha_ni", NULL, NULL}, + + { /* (10) 0000000d eax */ + "xsaveopt", "xsavec", "xgetbv1", "xsaves", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + + { /* (11) 0x0000000f:0 edx */ + NULL, "cqm_llc", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + + { /* (12) 0x0000000f:1 edx */ + "cqm_occup_llc", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, }; static int procfs_getonecpu(int, struct cpu_info *, char *, size_t *); @@ -119,7 +166,7 @@ procfs_getcpuinfstr(char *bf, size_t *le i = total = 0; used = size = *len; - + for (CPU_INFO_FOREACH(cii, ci)) { procfs_getonecpu(i++, ci, bf, &used); total += used + 1; @@ -137,25 +184,85 @@ procfs_getcpuinfstr(char *bf, size_t *le } static int -procfs_getonecpu(int xcpu, struct cpu_info *ci, char *bf, size_t *len) +procfs_getonefeatreg(uint32_t reg, const char * const *table, char *p, + size_t *left) { - size_t left, l, size; - char featurebuf[1024], *p; + size_t l; - p = featurebuf; - left = sizeof(featurebuf); - size = *len; for (size_t i = 0; i < 32; i++) { - if ((ci->ci_feat_val[0] & (1 << i)) && x86_features[i]) { - l = snprintf(p, left, "%s ", x86_features[i]); - if (l < left) { - left -= l; + if ((reg & (1 << i)) && table[i]) { + l = snprintf(p, *left, "%s ", table[i]); + if (l < *left) { + *left -= l; p += l; } else break; } } + return 0; /* XXX */ +} + +/* + * Print feature bits. The code assume that unused entry of x86_features[] + * is zero-cleared. + * + * XXX This function will be rewritten when all of linux entries are + * decoded. + */ +static int +procfs_getonecpufeatures(struct cpu_info *ci, char *p, size_t *left) +{ + size_t last = *left; + size_t diff; + + procfs_getonefeatreg(ci->ci_feat_val[0], x86_features[0], p, left); + diff = last - *left; + + procfs_getonefeatreg(ci->ci_feat_val[2], x86_features[1], p + diff, + left); + diff = last - *left; + + /* x86_features[2] is for Transmeta */ + /* x86_features[3] is Linux defined mapping */ + + procfs_getonefeatreg(ci->ci_feat_val[1], x86_features[4], p + diff, + left); + diff = last - *left; + + procfs_getonefeatreg(ci->ci_feat_val[4], x86_features[5], p + diff, + left); + diff = last - *left; + + procfs_getonefeatreg(ci->ci_feat_val[3], x86_features[6], p + diff, + left); + diff = last - *left; + + /* x86_features[7] is Linux defined mapping */ + /* x86_features[8] is Linux defined mapping */ + + procfs_getonefeatreg(ci->ci_feat_val[5], x86_features[9], p + diff, + left); + diff = last - *left; + + /* (10) 0000000d eax */ + /* (11) 0x0000000f(ecx=0) edx */ + /* (12) 0x0000000f(ecx=1) edx */ + + return 0; /* XXX */ +} + +static int +procfs_getonecpu(int xcpu, struct cpu_info *ci, char *bf, size_t *len) +{ + size_t left, l, size; + char featurebuf[1024], *p; + + p = featurebuf; + left = sizeof(featurebuf); + size = *len; + procfs_getonecpufeatures(ci, p, &left); + p = bf; left = *len; size = 0; @@ -168,8 +275,8 @@ procfs_getonecpu(int xcpu, struct cpu_in "stepping\t: ", xcpu, (char *)ci->ci_vendor, - cpuid_level >= 0 ? ((ci->ci_signature >> 8) & 15) : cpu_class + 3, - cpuid_level >= 0 ? ((ci->ci_signature >> 4) & 15) : 0, + CPUID_TO_FAMILY(ci->ci_signature), + CPUID_TO_MODEL(ci->ci_signature), cpu_brand_string ); size += l; @@ -180,7 +287,8 @@ procfs_getonecpu(int xcpu, struct cpu_in left = 0; if (cpuid_level >= 0) - l = snprintf(p, left, "%d\n", ci->ci_signature & 15); + l = snprintf(p, left, "%d\n", + CPUID_TO_STEPPING(ci->ci_signature)); else l = snprintf(p, left, "unknown\n"); @@ -196,8 +304,8 @@ procfs_getonecpu(int xcpu, struct cpu_in freq = (ci->ci_data.cpu_cc_freq + 4999) / 1000000; fraq = ((ci->ci_data.cpu_cc_freq + 4999) / 10000) % 100; - l = snprintf(p, left, "cpu MHz\t\t: %" PRIu64 ".%" PRIu64 "\n", - freq, fraq); + l = snprintf(p, left, "cpu MHz\t\t: %" PRIu64 ".%02" PRIu64 + "\n", freq, fraq); } else l = snprintf(p, left, "cpu MHz\t\t: unknown\n");