Tue May 26 01:42:02 2009 UTC ()
Add CPU topology detection support for AMD processors.
Tested on the following AMD CPUs:
- Family 15, model 65
- Family 15, model 67
- Family 15, model 75
- Family 16, model 2
- Family 17, model 3

Reviewed (slightly older version of patch) by <yamt>.


(rmind)
diff -r1.35 -r1.36 src/sys/arch/x86/include/specialreg.h
diff -r1.1 -r1.2 src/sys/arch/x86/x86/cpu_topology.c

cvs diff -r1.35 -r1.36 src/sys/arch/x86/include/specialreg.h (expand / switch to unified diff)

--- src/sys/arch/x86/include/specialreg.h 2009/05/16 13:36:44 1.35
+++ src/sys/arch/x86/include/specialreg.h 2009/05/26 01:42:02 1.36
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: specialreg.h,v 1.35 2009/05/16 13:36:44 pgoyette Exp $ */ 1/* $NetBSD: specialreg.h,v 1.36 2009/05/26 01:42:02 rmind Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991 The Regents of the University of California. 4 * Copyright (c) 1991 The Regents of the University of California.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -414,26 +414,27 @@ @@ -414,26 +414,27 @@
414#define VMCR_SVMED 0x00000010 /* SVME Disable */ 414#define VMCR_SVMED 0x00000010 /* SVME Disable */
415#define MSR_SVMLOCK 0xc0010118 /* SVM Lock key */ 415#define MSR_SVMLOCK 0xc0010118 /* SVM Lock key */
416 416
417/* 417/*
418 * These require a 'passcode' for access. See cpufunc.h. 418 * These require a 'passcode' for access. See cpufunc.h.
419 */ 419 */
420#define MSR_HWCR 0xc0010015 420#define MSR_HWCR 0xc0010015
421#define HWCR_TLBCACHEDIS 0x00000008 421#define HWCR_TLBCACHEDIS 0x00000008
422#define HWCR_FFDIS 0x00000040 422#define HWCR_FFDIS 0x00000040
423 423
424#define MSR_NB_CFG 0xc001001f 424#define MSR_NB_CFG 0xc001001f
425#define NB_CFG_DISIOREQLOCK 0x0000000000000004ULL 425#define NB_CFG_DISIOREQLOCK 0x0000000000000004ULL
426#define NB_CFG_DISDATMSK 0x0000001000000000ULL 426#define NB_CFG_DISDATMSK 0x0000001000000000ULL
 427#define NB_CFG_INITAPICCPUIDLO (1ULL << 54)
427 428
428#define MSR_LS_CFG 0xc0011020 429#define MSR_LS_CFG 0xc0011020
429#define LS_CFG_DIS_LS2_SQUISH 0x02000000 430#define LS_CFG_DIS_LS2_SQUISH 0x02000000
430 431
431#define MSR_IC_CFG 0xc0011021 432#define MSR_IC_CFG 0xc0011021
432#define IC_CFG_DIS_SEQ_PREFETCH 0x00000800 433#define IC_CFG_DIS_SEQ_PREFETCH 0x00000800
433 434
434#define MSR_DC_CFG 0xc0011022 435#define MSR_DC_CFG 0xc0011022
435#define DC_CFG_DIS_CNV_WC_SSO 0x00000004 436#define DC_CFG_DIS_CNV_WC_SSO 0x00000004
436#define DC_CFG_DIS_SMC_CHK_BUF 0x00000400 437#define DC_CFG_DIS_SMC_CHK_BUF 0x00000400
437#define DC_CFG_ERRATA_261 0x01000000 438#define DC_CFG_ERRATA_261 0x01000000
438 439
439#define MSR_BU_CFG 0xc0011023 440#define MSR_BU_CFG 0xc0011023

cvs diff -r1.1 -r1.2 src/sys/arch/x86/x86/cpu_topology.c (expand / switch to unified diff)

--- src/sys/arch/x86/x86/cpu_topology.c 2009/04/30 00:07:23 1.1
+++ src/sys/arch/x86/x86/cpu_topology.c 2009/05/26 01:42:02 1.2
@@ -1,90 +1,173 @@ @@ -1,90 +1,173 @@
1/* $NetBSD: cpu_topology.c,v 1.1 2009/04/30 00:07:23 rmind Exp $ */ 1/* $NetBSD: cpu_topology.c,v 1.2 2009/05/26 01:42:02 rmind Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c)2008 YAMAMOTO Takashi, 4 * Copyright (c) 2009 Mindaugas Rasiukevicius <rmind at NetBSD org>,
 5 * Copyright (c) 2008 YAMAMOTO Takashi,
5 * All rights reserved. 6 * All rights reserved.
6 * 7 *
7 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
9 * are met: 10 * are met:
10 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
15 * 16 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 27 * SUCH DAMAGE.
27 */ 28 */
28 29
 30/*
 31 * x86 CPU topology detection.
 32 *
 33 * References:
 34 * - 53668.pdf (7.10.2), 276613.pdf
 35 * - 31116.pdf, 41256.pdf, 25481.pdf
 36 */
 37
29#include <sys/cdefs.h> 38#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: cpu_topology.c,v 1.1 2009/04/30 00:07:23 rmind Exp $"); 39__KERNEL_RCSID(0, "$NetBSD: cpu_topology.c,v 1.2 2009/05/26 01:42:02 rmind Exp $");
31 40
32#include <sys/param.h> 41#include <sys/param.h>
33#include <sys/bitops.h> 42#include <sys/bitops.h>
34 43
35#include <machine/specialreg.h> 44#include <machine/specialreg.h>
36#include <machine/cpu.h> 45#include <machine/cpu.h>
37 46
38#include <x86/cpufunc.h> 47#include <x86/cpufunc.h>
39#include <x86/cputypes.h> 48#include <x86/cputypes.h>
40#include <x86/cpuvar.h> 49#include <x86/cpuvar.h>
41 50
42void 51void
43x86_cpu_toplogy(struct cpu_info *ci) 52x86_cpu_toplogy(struct cpu_info *ci)
44{ 53{
45 u_int lp_max = 1; /* logical processors per package */ 54 u_int lp_max; /* Logical processors per package */
46 u_int smt_max; /* smt per core */ 55 u_int core_max; /* Core per package */
47 u_int core_max = 1; /* core per package */ 56 int n, cpu_family, apic_id, smt_bits, core_bits = 0;
48 int smt_bits, core_bits; 57 uint32_t descs[4], lextmode;
49 uint32_t descs[4]; 58
 59 apic_id = ci->ci_initapicid;
 60 cpu_family = CPUID2FAMILY(ci->ci_signature);
 61
 62 /* Initial values. */
 63 ci->ci_packageid = apic_id;
 64 ci->ci_coreid = 0;
 65 ci->ci_smtid = 0;
50 66
51 if (cpu_vendor != CPUVENDOR_INTEL || 67 switch (cpu_vendor) {
52 CPUID2FAMILY(ci->ci_signature) < 6) 68 case CPUVENDOR_INTEL:
 69 if (cpu_family < 6)
 70 return;
 71 break;
 72 case CPUVENDOR_AMD:
 73 if (cpu_family < 0xf)
 74 return;
 75 break;
 76 default:
53 return; 77 return;
 78 }
54 79
55 /* Determine the extended feature flags. */ 80 /* Determine the extended feature flags. */
56 x86_cpuid(0x80000000, descs); 81 x86_cpuid(0x80000000, descs);
57 if (descs[0] >= 0x80000001) { 82 lextmode = descs[0];
 83 if (lextmode >= 0x80000001) {
58 x86_cpuid(0x80000001, descs); 84 x86_cpuid(0x80000001, descs);
59 ci->ci_feature3_flags |= descs[3]; /* %edx */ 85 ci->ci_feature3_flags |= descs[3]; /* edx */
60 } 86 }
61 87
62 /* Determine topology. 253668.pdf 7.10.2. */ 88 /* Check for HTT support. See notes below regarding AMD. */
63 ci->ci_packageid = ci->ci_initapicid; 
64 ci->ci_coreid = 0; 
65 ci->ci_smtid = 0; 
66 if ((ci->ci_feature_flags & CPUID_HTT) != 0) { 89 if ((ci->ci_feature_flags & CPUID_HTT) != 0) {
 90 /* Maximum number of LPs sharing a cache (ebx[23:16]). */
67 x86_cpuid(1, descs); 91 x86_cpuid(1, descs);
68 lp_max = (descs[1] >> 16) & 0xff; 92 lp_max = (descs[1] >> 16) & 0xff;
 93 } else {
 94 lp_max = 1;
69 } 95 }
70 x86_cpuid(0, descs); 96
71 if (descs[0] >= 4) { 97 switch (cpu_vendor) {
72 x86_cpuid2(4, 0, descs); 98 case CPUVENDOR_INTEL:
73 core_max = (descs[0] >> 26) + 1; 99 /* Check for leaf 4 support. */
 100 x86_cpuid(0, descs);
 101 if (descs[0] >= 4) {
 102 /* Maximum number of Cores per package (eax[31:26]). */
 103 x86_cpuid2(4, 0, descs);
 104 core_max = (descs[0] >> 26) + 1;
 105 } else {
 106 core_max = 1;
 107 }
 108 break;
 109 case CPUVENDOR_AMD:
 110 /* In a case of AMD, HTT flag means CMP support. */
 111 if ((ci->ci_feature_flags & CPUID_HTT) == 0) {
 112 core_max = 1;
 113 break;
 114 }
 115 /* Legacy Method, LPs represent Cores. */
 116 if (cpu_family < 0x10 || lextmode < 0x80000008) {
 117 core_max = lp_max;
 118 break;
 119 }
 120 /* Number of Cores (NC) per package (ecx[7:0]). */
 121 x86_cpuid(0x80000008, descs);
 122 core_max = (descs[2] & 0xff) + 1;
 123 /* Amount of bits representing Core ID (ecx[15:12]). */
 124 n = (descs[2] >> 12) & 0x0f;
 125 if (n != 0) {
 126 /*
 127 * Extended Method.
 128 * core_bits = 2 ^ n (power of two)
 129 */
 130 core_bits = 1 << n;
 131 }
 132 break;
 133 default:
 134 core_max = 1;
74 } 135 }
 136
75 KASSERT(lp_max >= core_max); 137 KASSERT(lp_max >= core_max);
76 smt_max = lp_max / core_max; 138 smt_bits = ilog2((lp_max / core_max) - 1) + 1;
77 smt_bits = ilog2(smt_max - 1) + 1; 139 if (core_bits == 0) {
78 core_bits = ilog2(core_max - 1) + 1; 140 core_bits = ilog2(core_max - 1) + 1;
 141 }
 142
 143 /*
 144 * Family 0xf and 0x10 processors may have different structure of
 145 * APIC ID. Detect that via special MSR register and move the bits,
 146 * if necessary (ref: InitApicIdCpuIdLo).
 147 */
 148 if (cpu_vendor == CPUVENDOR_AMD && cpu_family < 0x11) { /* XXX */
 149 const uint64_t reg = rdmsr(MSR_NB_CFG);
 150 if ((reg & NB_CFG_INITAPICCPUIDLO) == 0) {
 151 /*
 152 * 0xf: { CoreId, NodeId[2:0] }
 153 * 0x10: { CoreId[1:0], 000b, NodeId[2:0] }
 154 */
 155 const u_int node_id = apic_id & __BITS(0, 2);
 156 apic_id = (cpu_family == 0xf) ?
 157 (apic_id >> core_bits) | (node_id << core_bits) :
 158 (apic_id >> 5) | (node_id << 2);
 159 }
 160 }
 161
79 if (smt_bits + core_bits) { 162 if (smt_bits + core_bits) {
80 ci->ci_packageid = ci->ci_initapicid >> (smt_bits + core_bits); 163 ci->ci_packageid = apic_id >> (smt_bits + core_bits);
81 } 164 }
82 if (core_bits) { 165 if (core_bits) {
83 u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1); 166 u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1);
84 ci->ci_coreid = __SHIFTOUT(ci->ci_initapicid, core_mask); 167 ci->ci_coreid = __SHIFTOUT(apic_id, core_mask);
85 } 168 }
86 if (smt_bits) { 169 if (smt_bits) {
87 u_int smt_mask = __BITS(0, smt_bits - 1); 170 u_int smt_mask = __BITS(0, smt_bits - 1);
88 ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid, smt_mask); 171 ci->ci_smtid = __SHIFTOUT(apic_id, smt_mask);
89 } 172 }
90} 173}