Subject: Re: Athlon 64 X2 is "Unknown"
To: None <current-users@NetBSD.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: current-users
Date: 01/14/2007 16:08:20
In article <20061206094800.GB2121@serpens.de>
zza@serpens.de wrote:
> My dual core Athlon X2 64 is "identified" as
> "AMD Unknown K7 (Athlon) (686-class)". How can I fix this?
How about the attached patch?
(though I'm not sure if it's really worth
because we also have cpu_brand_string already)
---
Izumi Tsutsui
Index: arch/i386/i386/identcpu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/identcpu.c,v
retrieving revision 1.52
diff -u -r1.52 identcpu.c
--- arch/i386/i386/identcpu.c 1 Jan 2007 20:56:58 -0000 1.52
+++ arch/i386/i386/identcpu.c 14 Jan 2007 06:52:35 -0000
@@ -148,6 +148,7 @@
static void intel_family_new_probe(struct cpu_info *);
static const char *intel_family6_name(struct cpu_info *);
+static const char *amd_amd64_name(struct cpu_info *);
static void transmeta_cpu_info(struct cpu_info *);
@@ -339,7 +340,7 @@
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- "Unknown K7 (Athlon)" /* Default */
+ "Unknown K8 (Athlon)" /* Default */
},
NULL,
amd_family6_probe,
@@ -739,6 +740,126 @@
return ret;
}
+/*
+ * Identify AMD64 CPU names from cpuid.
+ *
+ * Based on "Revision Guide for AMD Athlon 64 and AMD Opteron Processors"
+ * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25759.pdf
+ */
+const char *
+amd_amd64_name(struct cpu_info *ci)
+{
+ int extfamily, extmodel, model;
+ const char *ret = NULL;
+
+ model = CPUID2MODEL(ci->ci_signature);
+ extfamily = CPUID2EXTFAMILY(ci->ci_signature);
+ extmodel = CPUID2EXTMODEL(ci->ci_signature);
+
+ if (extfamily == 0x00) {
+ switch (model) {
+ case 0x1:
+ switch (extmodel) {
+ case 0x2: /* rev JH-E1/E6 */
+ ret = "Dual-Core Opteron";
+ break;
+ }
+ break;
+ case 0x3:
+ switch (extmodel) {
+ case 0x2: /* rev JH-E6 (Toledo) */
+ ret = "Dual-Core Opteron or Athlon 64 X2";
+ break;
+ }
+ break;
+ case 0x4:
+ switch (extmodel) {
+ case 0x0: /* rev SH-B0/C0/CG (ClawHammer) */
+ case 0x1: /* rev SH-D0 */
+ ret = "Athlon 64";
+ break;
+ case 0x2: /* rev SH-E5 (Lancaster?) */
+ ret = "Mobile Athlon 64 or Turion 64";
+ break;
+ }
+ break;
+ case 0x5:
+ switch (extmodel) {
+ case 0x0: /* rev SH-B0/B3/C0/CG (SledgeHammer?) */
+ ret = "Opteron or Athlon 64 FX";
+ break;
+ case 0x1: /* rev SH-D0 */
+ case 0x2: /* rev SH-E4 */
+ ret = "Opteron";
+ break;
+ }
+ break;
+ case 0x7:
+ switch (extmodel) {
+ case 0x0: /* rev SH-CG (ClawHammer) */
+ case 0x1: /* rev SH-D0 */
+ ret = "Athlon 64";
+ break;
+ case 0x2: /* rev DH-E4, SH-E4 */
+ ret = "Athlon 64 or Athlon 64 FX or Opteron";
+ break;
+ }
+ break;
+ case 0x8:
+ switch (extmodel) {
+ case 0x0: /* rev CH-CG */
+ case 0x1: /* rev CH-D0 */
+ ret = "Athlon 64 or Sempron";
+ break;
+ }
+ break;
+ case 0xb:
+ switch (extmodel) {
+ case 0x0: /* rev CH-CG */
+ case 0x1: /* rev CH-D0 */
+ ret = "Athlon 64";
+ break;
+ case 0x2: /* rev BH-E4 (Manchester) */
+ ret = "Athlon 64 X2";
+ break;
+ }
+ break;
+ case 0xc:
+ switch (extmodel) {
+ case 0x0: /* rev DH-CG (Newcastle) */
+ case 0x1: /* rev DH-D0 (Winchester) */
+ ret = "Athlon 64 or Sempron";
+ break;
+ case 0x2: /* rev DH-E3/E6 */
+ ret = "Sempron";
+ break;
+ }
+ break;
+ case 0xe:
+ switch (extmodel) {
+ case 0x0: /* rev DH-CG (Newcastle?) */
+ ret = "Athlon 64 or Sempron";
+ break;
+ }
+ break;
+ case 0xf:
+ switch (extmodel) {
+ case 0x0: /* rev DH-CG (Newcastle) */
+ case 0x1: /* rev DH-D0 (Winchester) */
+ case 0x2: /* rev DH-E3/E6 (Venice) */
+ case 0x4: /* rev F2 (socekt AM2) */
+ ret = "Athlon 64 or Sempron";
+ break;
+ }
+ break;
+ default:
+ ret = "Unknown AMD64 CPU";
+ }
+ }
+
+ return ret;
+}
+
static void
cpu_probe_base_features(struct cpu_info *ci)
{
@@ -1365,17 +1486,30 @@
i386_intel_brand[ci->ci_brand_id];
}
- if (vendor == CPUVENDOR_AMD && family == 6 &&
- model >= 6) {
- if (ci->ci_brand_id == 1)
- /*
- * It's Duron. We override the
- * name, since it might have been
- * misidentified as Athlon.
+ if (vendor == CPUVENDOR_AMD) {
+ if (family == 6 && model >= 6) {
+ if (ci->ci_brand_id == 1)
+ /*
+ * It's Duron. We override the
+ * name, since it might have
+ * been misidentified as Athlon.
+ */
+ name =
+ amd_brand[ci->ci_brand_id];
+ else
+ brand = amd_brand_name;
+ }
+ if (CPUID2FAMILY(ci->ci_signature) == 0xf) {
+ /*
+ * Identify AMD64 CPU names.
+ * Note family value is clipped by
+ * CPU_MAXFAMILY.
*/
- name = amd_brand[ci->ci_brand_id];
- else
- brand = amd_brand_name;
+ const char *tmp;
+ tmp = amd_amd64_name(ci);
+ if (tmp != NULL)
+ name = tmp;
+ }
}
if (vendor == CPUVENDOR_IDT && family >= 6)
Index: arch/x86/include/specialreg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/specialreg.h,v
retrieving revision 1.13
diff -u -r1.13 specialreg.h
--- arch/x86/include/specialreg.h 11 Jan 2007 17:24:30 -0000 1.13
+++ arch/x86/include/specialreg.h 14 Jan 2007 06:52:35 -0000
@@ -169,9 +169,13 @@
#define CPUID2_FLAGS "\20\1SSE3\4MONITOR\5DS-CPL\6VMX\10EST\11TM2\13CID\17xTPR"
-#define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 15)
-#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15)
-#define CPUID2STEPPING(cpuid) ((cpuid) & 15)
+#define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 0xf)
+#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 0xf)
+#define CPUID2STEPPING(cpuid) ((cpuid) & 0xf)
+
+/* Extended family and model are defined on amd64 processors */
+#define CPUID2EXTFAMILY(cpuid) (((cpuid) >> 20) & 0xff)
+#define CPUID2EXTMODEL(cpuid) (((cpuid) >> 16) & 0xf)
#define CPUID(code, eax, ebx, ecx, edx) \
__asm("cpuid" \