]>
Commit | Line | Data |
---|---|---|
9659d8ac GKH |
1 | From 9d260ebc09a0ad6b5c73e17676df42c7bc75ff64 Mon Sep 17 00:00:00 2001 |
2 | From: Andreas Herrmann <herrmann.der.user@googlemail.com> | |
3 | Date: Wed, 16 Dec 2009 15:43:55 +0100 | |
4 | Subject: x86, amd: Get multi-node CPU info from NodeId MSR instead of PCI config space | |
5 | ||
6 | From: Andreas Herrmann <herrmann.der.user@googlemail.com> | |
7 | ||
8 | commit 9d260ebc09a0ad6b5c73e17676df42c7bc75ff64 upstream. | |
9 | ||
10 | Use NodeId MSR to get NodeId and number of nodes per processor. | |
11 | ||
12 | Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com> | |
13 | LKML-Reference: <20091216144355.GB28798@alberich.amd.com> | |
14 | Signed-off-by: H. Peter Anvin <hpa@zytor.com> | |
15 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
16 | ||
17 | --- | |
18 | arch/x86/include/asm/cpufeature.h | 1 | |
19 | arch/x86/include/asm/msr-index.h | 1 | |
20 | arch/x86/kernel/cpu/amd.c | 53 ++++++++++---------------------------- | |
21 | 3 files changed, 17 insertions(+), 38 deletions(-) | |
22 | ||
23 | --- a/arch/x86/include/asm/cpufeature.h | |
24 | +++ b/arch/x86/include/asm/cpufeature.h | |
25 | @@ -153,6 +153,7 @@ | |
26 | #define X86_FEATURE_SSE5 (6*32+11) /* SSE-5 */ | |
27 | #define X86_FEATURE_SKINIT (6*32+12) /* SKINIT/STGI instructions */ | |
28 | #define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */ | |
29 | +#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */ | |
30 | ||
31 | /* | |
32 | * Auxiliary flags: Linux defined - For features scattered in various | |
33 | --- a/arch/x86/include/asm/msr-index.h | |
34 | +++ b/arch/x86/include/asm/msr-index.h | |
35 | @@ -125,6 +125,7 @@ | |
36 | #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2 | |
37 | #define FAM10H_MMIO_CONF_BASE_MASK 0xfffffff | |
38 | #define FAM10H_MMIO_CONF_BASE_SHIFT 20 | |
39 | +#define MSR_FAM10H_NODE_ID 0xc001100c | |
40 | ||
41 | /* K8 MSRs */ | |
42 | #define MSR_K8_TOP_MEM1 0xc001001a | |
43 | --- a/arch/x86/kernel/cpu/amd.c | |
44 | +++ b/arch/x86/kernel/cpu/amd.c | |
45 | @@ -254,59 +254,36 @@ static int __cpuinit nearby_node(int api | |
46 | ||
47 | /* | |
48 | * Fixup core topology information for AMD multi-node processors. | |
49 | - * Assumption 1: Number of cores in each internal node is the same. | |
50 | - * Assumption 2: Mixed systems with both single-node and dual-node | |
51 | - * processors are not supported. | |
52 | + * Assumption: Number of cores in each internal node is the same. | |
53 | */ | |
54 | #ifdef CONFIG_X86_HT | |
55 | static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c) | |
56 | { | |
57 | -#ifdef CONFIG_PCI | |
58 | - u32 t, cpn; | |
59 | - u8 n, n_id; | |
60 | + unsigned long long value; | |
61 | + u32 nodes, cores_per_node; | |
62 | int cpu = smp_processor_id(); | |
63 | ||
64 | + if (!cpu_has(c, X86_FEATURE_NODEID_MSR)) | |
65 | + return; | |
66 | + | |
67 | /* fixup topology information only once for a core */ | |
68 | if (cpu_has(c, X86_FEATURE_AMD_DCM)) | |
69 | return; | |
70 | ||
71 | - /* check for multi-node processor on boot cpu */ | |
72 | - t = read_pci_config(0, 24, 3, 0xe8); | |
73 | - if (!(t & (1 << 29))) | |
74 | + rdmsrl(MSR_FAM10H_NODE_ID, value); | |
75 | + | |
76 | + nodes = ((value >> 3) & 7) + 1; | |
77 | + if (nodes == 1) | |
78 | return; | |
79 | ||
80 | set_cpu_cap(c, X86_FEATURE_AMD_DCM); | |
81 | + cores_per_node = c->x86_max_cores / nodes; | |
82 | ||
83 | - /* cores per node: each internal node has half the number of cores */ | |
84 | - cpn = c->x86_max_cores >> 1; | |
85 | - | |
86 | - /* even-numbered NB_id of this dual-node processor */ | |
87 | - n = c->phys_proc_id << 1; | |
88 | + /* store NodeID, use llc_shared_map to store sibling info */ | |
89 | + per_cpu(cpu_llc_id, cpu) = value & 7; | |
90 | ||
91 | - /* | |
92 | - * determine internal node id and assign cores fifty-fifty to | |
93 | - * each node of the dual-node processor | |
94 | - */ | |
95 | - t = read_pci_config(0, 24 + n, 3, 0xe8); | |
96 | - n = (t>>30) & 0x3; | |
97 | - if (n == 0) { | |
98 | - if (c->cpu_core_id < cpn) | |
99 | - n_id = 0; | |
100 | - else | |
101 | - n_id = 1; | |
102 | - } else { | |
103 | - if (c->cpu_core_id < cpn) | |
104 | - n_id = 1; | |
105 | - else | |
106 | - n_id = 0; | |
107 | - } | |
108 | - | |
109 | - /* compute entire NodeID, use llc_shared_map to store sibling info */ | |
110 | - per_cpu(cpu_llc_id, cpu) = (c->phys_proc_id << 1) + n_id; | |
111 | - | |
112 | - /* fixup core id to be in range from 0 to cpn */ | |
113 | - c->cpu_core_id = c->cpu_core_id % cpn; | |
114 | -#endif | |
115 | + /* fixup core id to be in range from 0 to (cores_per_node - 1) */ | |
116 | + c->cpu_core_id = c->cpu_core_id % cores_per_node; | |
117 | } | |
118 | #endif | |
119 |