Module Name: src Committed By: dsl Date: Sat Feb 22 17:48:08 UTC 2014
Modified Files: src/sys/arch/x86/include: cpu.h src/sys/arch/x86/x86: cpu_topology.c identcpu.c Log Message: Re-use the unused ci_cpu_serial[3] to save the highest cpuid values for the normal and extended leafs. (The 'normal' one might be luring in the global cpulevel.) Read the 'extended feature' from cpuid.80000001.%ecx/edx into ci_feat_val[3/2] just after saving cpuid.1.%ecx/dx in ci_feat_val[1/0] instead of doing it separately for amd k678 and via c3 processors in their probe functions and repeating it for all cpus a few instructions later when x86_cpu_topology() is called. x86_cpu_topology() is only called from cpu_probe() and really doesn't deserve its own source file. Chasing the setup code is bad enough anyway. To generate a diff of this commit: cvs rdiff -u -r1.63 -r1.64 src/sys/arch/x86/include/cpu.h cvs rdiff -u -r1.8 -r1.9 src/sys/arch/x86/x86/cpu_topology.c cvs rdiff -u -r1.39 -r1.40 src/sys/arch/x86/x86/identcpu.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/include/cpu.h diff -u src/sys/arch/x86/include/cpu.h:1.63 src/sys/arch/x86/include/cpu.h:1.64 --- src/sys/arch/x86/include/cpu.h:1.63 Thu Feb 20 18:14:11 2014 +++ src/sys/arch/x86/include/cpu.h Sat Feb 22 17:48:08 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.63 2014/02/20 18:14:11 dsl Exp $ */ +/* $NetBSD: cpu.h,v 1.64 2014/02/22 17:48:08 dsl Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -150,18 +150,20 @@ struct cpu_info { uint32_t ci_ipis; /* interprocessor interrupts pending */ uint32_t sc_apic_version; /* local APIC version */ - uint32_t ci_signature; /* X86 cpuid type */ + uint32_t ci_signature; /* X86 cpuid type (cpuid.1.%eax) */ uint32_t ci_vendor[4]; /* vendor string */ - uint32_t ci_cpu_serial[3]; /* PIII serial number */ + uint32_t _unused2; + uint32_t ci_max_cpuid; /* cpuid.0:%eax */ + uint32_t ci_max_ext_cpuid; /* cpuid.80000000:%eax */ volatile uint32_t ci_lapic_counter; - uint32_t ci_feat_val[5]; /* X86 CPUID feature bits - * [0] basic features %edx - * [1] basic features %ecx - * [2] extended features %edx - * [3] extended features %ecx - * [4] VIA padlock features - */ + uint32_t ci_feat_val[5]; /* X86 CPUID feature bits */ + /* [0] basic features cpuid.1:%edx + * [1] basic features cpuid.1:%ecx (CPUID2_xxx bits) + * [2] extended features cpuid:80000001:%edx + * [3] extended features cpuid:80000001:%ecx + * [4] VIA padlock features + */ const struct cpu_functions *ci_func; /* start/stop functions */ struct trapframe *ci_ddb_regs; Index: src/sys/arch/x86/x86/cpu_topology.c diff -u src/sys/arch/x86/x86/cpu_topology.c:1.8 src/sys/arch/x86/x86/cpu_topology.c:1.9 --- src/sys/arch/x86/x86/cpu_topology.c:1.8 Fri Nov 15 08:47:55 2013 +++ src/sys/arch/x86/x86/cpu_topology.c Sat Feb 22 17:48:08 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu_topology.c,v 1.8 2013/11/15 08:47:55 msaitoh Exp $ */ +/* $NetBSD: cpu_topology.c,v 1.9 2014/02/22 17:48:08 dsl Exp $ */ /*- * Copyright (c) 2009 Mindaugas Rasiukevicius <rmind at NetBSD org>, @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu_topology.c,v 1.8 2013/11/15 08:47:55 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu_topology.c,v 1.9 2014/02/22 17:48:08 dsl Exp $"); #include <sys/param.h> #include <sys/bitops.h> @@ -54,7 +54,7 @@ x86_cpu_topology(struct cpu_info *ci) u_int lp_max; /* Logical processors per package (node) */ u_int core_max; /* Core per package */ int n, cpu_family, apic_id, smt_bits, core_bits = 0; - uint32_t descs[4], lextmode; + uint32_t descs[4]; apic_id = ci->ci_initapicid; cpu_family = CPUID_TO_FAMILY(ci->ci_signature); @@ -77,15 +77,6 @@ x86_cpu_topology(struct cpu_info *ci) return; } - /* Determine the extended feature flags. */ - x86_cpuid(0x80000000, descs); - lextmode = descs[0]; - if (lextmode >= 0x80000001) { - x86_cpuid(0x80000001, descs); - ci->ci_feat_val[2] = descs[3]; /* edx */ - ci->ci_feat_val[3] = descs[2]; /* ecx */ - } - /* Check for HTT support. See notes below regarding AMD. */ if ((ci->ci_feat_val[0] & CPUID_HTT) != 0) { /* Maximum number of LPs sharing a cache (ebx[23:16]). */ @@ -98,8 +89,7 @@ x86_cpu_topology(struct cpu_info *ci) switch (cpu_vendor) { case CPUVENDOR_INTEL: /* Check for leaf 4 support. */ - x86_cpuid(0, descs); - if (descs[0] >= 4) { + if (ci->ci_max_cpuid >= 4) { /* Maximum number of Cores per package (eax[31:26]). */ x86_cpuid2(4, 0, descs); core_max = (descs[0] >> 26) + 1; @@ -114,7 +104,7 @@ x86_cpu_topology(struct cpu_info *ci) break; } /* Legacy Method, LPs represent Cores. */ - if (cpu_family < 0x10 || lextmode < 0x80000008) { + if (cpu_family < 0x10 || ci->ci_max_ext_cpuid < 0x80000008) { core_max = lp_max; break; } Index: src/sys/arch/x86/x86/identcpu.c diff -u src/sys/arch/x86/x86/identcpu.c:1.39 src/sys/arch/x86/x86/identcpu.c:1.40 --- src/sys/arch/x86/x86/identcpu.c:1.39 Mon Dec 23 11:40:57 2013 +++ src/sys/arch/x86/x86/identcpu.c Sat Feb 22 17:48:08 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: identcpu.c,v 1.39 2013/12/23 11:40:57 msaitoh Exp $ */ +/* $NetBSD: identcpu.c,v 1.40 2014/02/22 17:48:08 dsl Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.39 2013/12/23 11:40:57 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.40 2014/02/22 17:48:08 dsl Exp $"); #include "opt_xen.h" @@ -135,7 +135,7 @@ cpu_probe_intel_cache(struct cpu_info *c int ways, partitions, linesize, sets; int caitype = -1; int totalsize; - + /* Parse the cache info from `cpuid leaf 4', if we have it. */ for (i = 0; ; i++) { x86_cpuid2(4, i, descs); @@ -359,20 +359,11 @@ cpu_probe_k5(struct cpu_info *ci) static void cpu_probe_k678(struct cpu_info *ci) { - uint32_t descs[4]; if (cpu_vendor != CPUVENDOR_AMD || CPUID_TO_FAMILY(ci->ci_signature) < 6) return; - /* Determine the extended feature flags. */ - x86_cpuid(0x80000000, descs); - if (descs[0] >= 0x80000001) { - x86_cpuid(0x80000001, descs); - ci->ci_feat_val[3] = descs[2]; /* %ecx */ - ci->ci_feat_val[2] = descs[3]; /* %edx */ - } - cpu_probe_amd_cache(ci); } @@ -515,12 +506,6 @@ cpu_probe_c3(struct cpu_info *ci) x86_cpuid(0x80000000, descs); lfunc = descs[0]; - /* Determine the extended feature flags. */ - if (lfunc >= 0x80000001) { - x86_cpuid(0x80000001, descs); - ci->ci_feat_val[2] = descs[3]; - } - if (family > 6 || model > 0x9 || (model == 0x9 && stepping >= 3)) { /* Nehemiah or Esther */ x86_cpuid(0xc0000000, descs); @@ -575,7 +560,7 @@ cpu_probe_c3(struct cpu_info *ci) msr = rdmsr(MSR_VIA_ACE); wrmsr(MSR_VIA_ACE, msr | MSR_VIA_ACE_ENABLE); } - + } } @@ -616,7 +601,7 @@ cpu_probe_c3(struct cpu_info *ci) /* Erratum: stepping 8 reports 4 when it should be 2 */ cai->cai_associativity = 2; } - + /* * Determine L2 cache/TLB info. */ @@ -712,6 +697,8 @@ cpu_probe(struct cpu_info *ci) x86_cpuid(0, descs); cpuid_level = descs[0]; + ci->ci_max_cpuid = descs[0]; + ci->ci_vendor[0] = descs[1]; ci->ci_vendor[2] = descs[2]; ci->ci_vendor[1] = descs[3]; @@ -734,18 +721,6 @@ cpu_probe(struct cpu_info *ci) else cpu_vendor = CPUVENDOR_UNKNOWN; - x86_cpuid(0x80000000, brand); - if (brand[0] >= 0x80000004) { - x86_cpuid(0x80000002, brand); - x86_cpuid(0x80000003, brand + 4); - x86_cpuid(0x80000004, brand + 8); - for (i = 0; i < 48; i++) { - if (((char *) brand)[i] != ' ') - break; - } - memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i); - } - if (cpuid_level >= 1) { x86_cpuid(1, descs); ci->ci_signature = descs[0]; @@ -765,6 +740,36 @@ cpu_probe(struct cpu_info *ci) ci->ci_initapicid = (miscbytes >> 24) & 0xff; } + /* + * Get the basic information from the extended cpuid leafs. + * These were first implemented by amd, but most of the values + * match with those generated by modern intel cpus. + */ + x86_cpuid(0x80000000, descs); + if (descs[0] == 0x80000000) + ci->ci_max_ext_cpuid = descs[0]; + else + ci->ci_max_ext_cpuid = 0; + + if (ci->ci_max_ext_cpuid >= 0x80000001) { + /* Determine the extended feature flags. */ + x86_cpuid(0x80000001, descs); + ci->ci_feat_val[3] = descs[2]; /* %ecx */ + ci->ci_feat_val[2] = descs[3]; /* %edx */ + } + + if (ci->ci_max_ext_cpuid >= 0x80000004) { + x86_cpuid(0x80000002, brand); + x86_cpuid(0x80000003, brand + 4); + x86_cpuid(0x80000004, brand + 8); + /* Skip leading spaces on brand */ + for (i = 0; i < 48; i++) { + if (((char *) brand)[i] != ' ') + break; + } + memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i); + } + cpu_probe_intel(ci); cpu_probe_k5(ci); cpu_probe_k678(ci); @@ -873,7 +878,13 @@ cpu_identify(struct cpu_info *ci) i386_has_sse = 1; if (cpu_feature[0] & CPUID_SSE2) i386_has_sse2 = 1; - } else + } else { i386_use_fxsave = 0; + } +#else + /* + * i386_use_fxsave, i386_has_sse and i386_has_sse2 are + * #defined to 1. + */ #endif /* i386 */ }