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 */
}