Merge branch 'x86/ras' into x86/core, to fix conflicts
[deliverable/linux.git] / arch / x86 / kernel / cpu / intel_cacheinfo.c
CommitLineData
1da177e4 1/*
3f79410c 2 * Routines to identify caches on Intel CPU.
1da177e4 3 *
cdcf772e
IM
4 * Changes:
5 * Venkatesh Pallipadi : Adding cache identification through cpuid(4)
8bdbd962 6 * Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
67cddd94 7 * Andi Kleen / Andreas Herrmann : CPUID4 emulation on AMD.
1da177e4
LT
8 */
9
1da177e4 10#include <linux/slab.h>
0d55ba46 11#include <linux/cacheinfo.h>
1da177e4 12#include <linux/cpu.h>
4e57b681 13#include <linux/sched.h>
0d55ba46 14#include <linux/sysfs.h>
a24e8d36 15#include <linux/pci.h>
1da177e4
LT
16
17#include <asm/processor.h>
23ac4ae8 18#include <asm/amd_nb.h>
dcf39daf 19#include <asm/smp.h>
1da177e4
LT
20
21#define LVL_1_INST 1
22#define LVL_1_DATA 2
23#define LVL_2 3
24#define LVL_3 4
25#define LVL_TRACE 5
26
8bdbd962 27struct _cache_table {
1da177e4
LT
28 unsigned char descriptor;
29 char cache_type;
30 short size;
31};
32
2ca49b2f
DJ
33#define MB(x) ((x) * 1024)
34
8bdbd962
AC
35/* All the cache descriptor types we care about (no TLB or
36 trace cache entries) */
37
148f9bb8 38static const struct _cache_table cache_table[] =
1da177e4
LT
39{
40 { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */
41 { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */
9a8ecae8 42 { 0x09, LVL_1_INST, 32 }, /* 4-way set assoc, 64 byte line size */
1da177e4
LT
43 { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */
44 { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */
9a8ecae8 45 { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */
fb87ec38 46 { 0x0e, LVL_1_DATA, 24 }, /* 6-way set assoc, 64 byte line size */
9a8ecae8 47 { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */
1da177e4 48 { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
2ca49b2f
DJ
49 { 0x23, LVL_3, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */
50 { 0x25, LVL_3, MB(2) }, /* 8-way set assoc, sectored cache, 64 byte line size */
51 { 0x29, LVL_3, MB(4) }, /* 8-way set assoc, sectored cache, 64 byte line size */
1da177e4
LT
52 { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */
53 { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */
54 { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */
6fe8f479 55 { 0x3a, LVL_2, 192 }, /* 6-way set assoc, sectored cache, 64 byte line size */
1da177e4
LT
56 { 0x3b, LVL_2, 128 }, /* 2-way set assoc, sectored cache, 64 byte line size */
57 { 0x3c, LVL_2, 256 }, /* 4-way set assoc, sectored cache, 64 byte line size */
6fe8f479
DJ
58 { 0x3d, LVL_2, 384 }, /* 6-way set assoc, sectored cache, 64 byte line size */
59 { 0x3e, LVL_2, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
04fa11ea 60 { 0x3f, LVL_2, 256 }, /* 2-way set assoc, 64 byte line size */
1da177e4
LT
61 { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */
62 { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */
63 { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */
2ca49b2f
DJ
64 { 0x44, LVL_2, MB(1) }, /* 4-way set assoc, 32 byte line size */
65 { 0x45, LVL_2, MB(2) }, /* 4-way set assoc, 32 byte line size */
66 { 0x46, LVL_3, MB(4) }, /* 4-way set assoc, 64 byte line size */
67 { 0x47, LVL_3, MB(8) }, /* 8-way set assoc, 64 byte line size */
fb87ec38 68 { 0x48, LVL_2, MB(3) }, /* 12-way set assoc, 64 byte line size */
2ca49b2f
DJ
69 { 0x49, LVL_3, MB(4) }, /* 16-way set assoc, 64 byte line size */
70 { 0x4a, LVL_3, MB(6) }, /* 12-way set assoc, 64 byte line size */
71 { 0x4b, LVL_3, MB(8) }, /* 16-way set assoc, 64 byte line size */
72 { 0x4c, LVL_3, MB(12) }, /* 12-way set assoc, 64 byte line size */
73 { 0x4d, LVL_3, MB(16) }, /* 16-way set assoc, 64 byte line size */
74 { 0x4e, LVL_2, MB(6) }, /* 24-way set assoc, 64 byte line size */
1da177e4
LT
75 { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */
76 { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */
77 { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */
78 { 0x68, LVL_1_DATA, 32 }, /* 4-way set assoc, sectored cache, 64 byte line size */
79 { 0x70, LVL_TRACE, 12 }, /* 8-way set assoc */
80 { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */
81 { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */
6fe8f479 82 { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */
2ca49b2f
DJ
83 { 0x78, LVL_2, MB(1) }, /* 4-way set assoc, 64 byte line size */
84 { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */
85 { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */
86 { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */
87 { 0x7c, LVL_2, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */
88 { 0x7d, LVL_2, MB(2) }, /* 8-way set assoc, 64 byte line size */
89 { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */
fb87ec38 90 { 0x80, LVL_2, 512 }, /* 8-way set assoc, 64 byte line size */
2ca49b2f
DJ
91 { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */
92 { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */
93 { 0x84, LVL_2, MB(1) }, /* 8-way set assoc, 32 byte line size */
94 { 0x85, LVL_2, MB(2) }, /* 8-way set assoc, 32 byte line size */
95 { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */
96 { 0x87, LVL_2, MB(1) }, /* 8-way set assoc, 64 byte line size */
97 { 0xd0, LVL_3, 512 }, /* 4-way set assoc, 64 byte line size */
98 { 0xd1, LVL_3, MB(1) }, /* 4-way set assoc, 64 byte line size */
99 { 0xd2, LVL_3, MB(2) }, /* 4-way set assoc, 64 byte line size */
100 { 0xd6, LVL_3, MB(1) }, /* 8-way set assoc, 64 byte line size */
101 { 0xd7, LVL_3, MB(2) }, /* 8-way set assoc, 64 byte line size */
102 { 0xd8, LVL_3, MB(4) }, /* 12-way set assoc, 64 byte line size */
103 { 0xdc, LVL_3, MB(2) }, /* 12-way set assoc, 64 byte line size */
104 { 0xdd, LVL_3, MB(4) }, /* 12-way set assoc, 64 byte line size */
105 { 0xde, LVL_3, MB(8) }, /* 12-way set assoc, 64 byte line size */
106 { 0xe2, LVL_3, MB(2) }, /* 16-way set assoc, 64 byte line size */
107 { 0xe3, LVL_3, MB(4) }, /* 16-way set assoc, 64 byte line size */
108 { 0xe4, LVL_3, MB(8) }, /* 16-way set assoc, 64 byte line size */
109 { 0xea, LVL_3, MB(12) }, /* 24-way set assoc, 64 byte line size */
110 { 0xeb, LVL_3, MB(18) }, /* 24-way set assoc, 64 byte line size */
111 { 0xec, LVL_3, MB(24) }, /* 24-way set assoc, 64 byte line size */
1da177e4
LT
112 { 0x00, 0, 0}
113};
114
115
8bdbd962 116enum _cache_type {
0d55ba46
SH
117 CTYPE_NULL = 0,
118 CTYPE_DATA = 1,
119 CTYPE_INST = 2,
120 CTYPE_UNIFIED = 3
1da177e4
LT
121};
122
123union _cpuid4_leaf_eax {
124 struct {
125 enum _cache_type type:5;
126 unsigned int level:3;
127 unsigned int is_self_initializing:1;
128 unsigned int is_fully_associative:1;
129 unsigned int reserved:4;
130 unsigned int num_threads_sharing:12;
131 unsigned int num_cores_on_die:6;
132 } split;
133 u32 full;
134};
135
136union _cpuid4_leaf_ebx {
137 struct {
138 unsigned int coherency_line_size:12;
139 unsigned int physical_line_partition:10;
140 unsigned int ways_of_associativity:10;
141 } split;
142 u32 full;
143};
144
145union _cpuid4_leaf_ecx {
146 struct {
147 unsigned int number_of_sets:32;
148 } split;
149 u32 full;
150};
151
b7d11a76 152struct _cpuid4_info_regs {
1da177e4
LT
153 union _cpuid4_leaf_eax eax;
154 union _cpuid4_leaf_ebx ebx;
155 union _cpuid4_leaf_ecx ecx;
156 unsigned long size;
d2946041 157 struct amd_northbridge *nb;
f9b90566
MT
158};
159
240cd6a8
AK
160unsigned short num_cache_leaves;
161
162/* AMD doesn't have CPUID4. Emulate it here to report the same
163 information to the user. This makes some assumptions about the machine:
67cddd94 164 L2 not shared, no SMT etc. that is currently true on AMD CPUs.
240cd6a8
AK
165
166 In theory the TLBs could be reported as fake type (they are in "dummy").
167 Maybe later */
168union l1_cache {
169 struct {
8bdbd962
AC
170 unsigned line_size:8;
171 unsigned lines_per_tag:8;
172 unsigned assoc:8;
173 unsigned size_in_kb:8;
240cd6a8
AK
174 };
175 unsigned val;
176};
177
178union l2_cache {
179 struct {
8bdbd962
AC
180 unsigned line_size:8;
181 unsigned lines_per_tag:4;
182 unsigned assoc:4;
183 unsigned size_in_kb:16;
240cd6a8
AK
184 };
185 unsigned val;
186};
187
67cddd94
AK
188union l3_cache {
189 struct {
8bdbd962
AC
190 unsigned line_size:8;
191 unsigned lines_per_tag:4;
192 unsigned assoc:4;
193 unsigned res:2;
194 unsigned size_encoded:14;
67cddd94
AK
195 };
196 unsigned val;
197};
198
148f9bb8 199static const unsigned short assocs[] = {
6265ff19
AH
200 [1] = 1,
201 [2] = 2,
202 [4] = 4,
203 [6] = 8,
204 [8] = 16,
205 [0xa] = 32,
206 [0xb] = 48,
67cddd94 207 [0xc] = 64,
6265ff19
AH
208 [0xd] = 96,
209 [0xe] = 128,
210 [0xf] = 0xffff /* fully associative - no way to show this currently */
67cddd94
AK
211};
212
148f9bb8
PG
213static const unsigned char levels[] = { 1, 1, 2, 3 };
214static const unsigned char types[] = { 1, 2, 3, 3 };
240cd6a8 215
0d55ba46
SH
216static const enum cache_type cache_type_map[] = {
217 [CTYPE_NULL] = CACHE_TYPE_NOCACHE,
218 [CTYPE_DATA] = CACHE_TYPE_DATA,
219 [CTYPE_INST] = CACHE_TYPE_INST,
220 [CTYPE_UNIFIED] = CACHE_TYPE_UNIFIED,
221};
222
148f9bb8 223static void
cdcf772e
IM
224amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
225 union _cpuid4_leaf_ebx *ebx,
226 union _cpuid4_leaf_ecx *ecx)
240cd6a8
AK
227{
228 unsigned dummy;
229 unsigned line_size, lines_per_tag, assoc, size_in_kb;
230 union l1_cache l1i, l1d;
231 union l2_cache l2;
67cddd94
AK
232 union l3_cache l3;
233 union l1_cache *l1 = &l1d;
240cd6a8
AK
234
235 eax->full = 0;
236 ebx->full = 0;
237 ecx->full = 0;
238
239 cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val);
67cddd94 240 cpuid(0x80000006, &dummy, &dummy, &l2.val, &l3.val);
240cd6a8 241
67cddd94
AK
242 switch (leaf) {
243 case 1:
244 l1 = &l1i;
245 case 0:
246 if (!l1->val)
247 return;
a326e948 248 assoc = assocs[l1->assoc];
240cd6a8
AK
249 line_size = l1->line_size;
250 lines_per_tag = l1->lines_per_tag;
251 size_in_kb = l1->size_in_kb;
67cddd94
AK
252 break;
253 case 2:
254 if (!l2.val)
255 return;
a326e948 256 assoc = assocs[l2.assoc];
240cd6a8
AK
257 line_size = l2.line_size;
258 lines_per_tag = l2.lines_per_tag;
259 /* cpu_data has errata corrections for K7 applied */
7b543a53 260 size_in_kb = __this_cpu_read(cpu_info.x86_cache_size);
67cddd94
AK
261 break;
262 case 3:
263 if (!l3.val)
264 return;
a326e948 265 assoc = assocs[l3.assoc];
67cddd94
AK
266 line_size = l3.line_size;
267 lines_per_tag = l3.lines_per_tag;
268 size_in_kb = l3.size_encoded * 512;
a326e948
AH
269 if (boot_cpu_has(X86_FEATURE_AMD_DCM)) {
270 size_in_kb = size_in_kb >> 1;
271 assoc = assoc >> 1;
272 }
67cddd94
AK
273 break;
274 default:
275 return;
240cd6a8
AK
276 }
277
67cddd94
AK
278 eax->split.is_self_initializing = 1;
279 eax->split.type = types[leaf];
280 eax->split.level = levels[leaf];
a326e948 281 eax->split.num_threads_sharing = 0;
7b543a53 282 eax->split.num_cores_on_die = __this_cpu_read(cpu_info.x86_max_cores) - 1;
67cddd94
AK
283
284
a326e948 285 if (assoc == 0xffff)
240cd6a8
AK
286 eax->split.is_fully_associative = 1;
287 ebx->split.coherency_line_size = line_size - 1;
a326e948 288 ebx->split.ways_of_associativity = assoc - 1;
240cd6a8
AK
289 ebx->split.physical_line_partition = lines_per_tag - 1;
290 ecx->split.number_of_sets = (size_in_kb * 1024) / line_size /
291 (ebx->split.ways_of_associativity + 1) - 1;
292}
1da177e4 293
f76e39c5 294#if defined(CONFIG_AMD_NB) && defined(CONFIG_SYSFS)
0d55ba46 295
ba06edb6
BP
296/*
297 * L3 cache descriptors
298 */
148f9bb8 299static void amd_calc_l3_indices(struct amd_northbridge *nb)
048a8774 300{
d2946041 301 struct amd_l3_cache *l3 = &nb->l3_cache;
048a8774 302 unsigned int sc0, sc1, sc2, sc3;
cb19060a 303 u32 val = 0;
048a8774 304
d2946041 305 pci_read_config_dword(nb->misc, 0x1C4, &val);
048a8774
BP
306
307 /* calculate subcache sizes */
9350f982
BP
308 l3->subcaches[0] = sc0 = !(val & BIT(0));
309 l3->subcaches[1] = sc1 = !(val & BIT(4));
77e75fc7
FA
310
311 if (boot_cpu_data.x86 == 0x15) {
312 l3->subcaches[0] = sc0 += !(val & BIT(1));
313 l3->subcaches[1] = sc1 += !(val & BIT(5));
314 }
315
9350f982
BP
316 l3->subcaches[2] = sc2 = !(val & BIT(8)) + !(val & BIT(9));
317 l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
318
732eacc0 319 l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1;
ba06edb6
BP
320}
321
8cc1176e
BP
322/*
323 * check whether a slot used for disabling an L3 index is occupied.
324 * @l3: L3 cache descriptor
325 * @slot: slot number (0..1)
326 *
327 * @returns: the disabled index if used or negative value if slot free.
328 */
d2946041 329int amd_get_l3_disable_slot(struct amd_northbridge *nb, unsigned slot)
8cc1176e
BP
330{
331 unsigned int reg = 0;
332
d2946041 333 pci_read_config_dword(nb->misc, 0x1BC + slot * 4, &reg);
8cc1176e
BP
334
335 /* check whether this slot is activated already */
336 if (reg & (3UL << 30))
337 return reg & 0xfff;
338
339 return -1;
340}
341
0d55ba46 342static ssize_t show_cache_disable(struct cacheinfo *this_leaf, char *buf,
59d3b388 343 unsigned int slot)
cb19060a 344{
8cc1176e 345 int index;
0d55ba46 346 struct amd_northbridge *nb = this_leaf->priv;
cb19060a 347
0d55ba46 348 index = amd_get_l3_disable_slot(nb, slot);
8cc1176e
BP
349 if (index >= 0)
350 return sprintf(buf, "%d\n", index);
cb19060a 351
8cc1176e 352 return sprintf(buf, "FREE\n");
cb19060a
BP
353}
354
59d3b388 355#define SHOW_CACHE_DISABLE(slot) \
cb19060a 356static ssize_t \
0d55ba46
SH
357cache_disable_##slot##_show(struct device *dev, \
358 struct device_attribute *attr, char *buf) \
cb19060a 359{ \
0d55ba46 360 struct cacheinfo *this_leaf = dev_get_drvdata(dev); \
59d3b388 361 return show_cache_disable(this_leaf, buf, slot); \
cb19060a
BP
362}
363SHOW_CACHE_DISABLE(0)
364SHOW_CACHE_DISABLE(1)
365
d2946041 366static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu,
59d3b388
BP
367 unsigned slot, unsigned long idx)
368{
369 int i;
370
371 idx |= BIT(30);
372
373 /*
374 * disable index in all 4 subcaches
375 */
376 for (i = 0; i < 4; i++) {
377 u32 reg = idx | (i << 20);
378
d2946041 379 if (!nb->l3_cache.subcaches[i])
59d3b388
BP
380 continue;
381
d2946041 382 pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
59d3b388
BP
383
384 /*
385 * We need to WBINVD on a core on the node containing the L3
386 * cache which indices we disable therefore a simple wbinvd()
387 * is not sufficient.
388 */
389 wbinvd_on_cpu(cpu);
390
391 reg |= BIT(31);
d2946041 392 pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
59d3b388
BP
393 }
394}
395
8cc1176e
BP
396/*
397 * disable a L3 cache index by using a disable-slot
398 *
399 * @l3: L3 cache descriptor
400 * @cpu: A CPU on the node containing the L3 cache
401 * @slot: slot number (0..1)
402 * @index: index to disable
403 *
404 * @return: 0 on success, error status on failure
405 */
d2946041 406int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot,
8cc1176e 407 unsigned long index)
cb19060a 408{
8cc1176e 409 int ret = 0;
cb19060a 410
42be4505 411 /* check if @slot is already used or the index is already disabled */
d2946041 412 ret = amd_get_l3_disable_slot(nb, slot);
8cc1176e 413 if (ret >= 0)
a720b2dd 414 return -EEXIST;
cb19060a 415
d2946041 416 if (index > nb->l3_cache.indices)
8cc1176e
BP
417 return -EINVAL;
418
42be4505 419 /* check whether the other slot has disabled the same index already */
d2946041 420 if (index == amd_get_l3_disable_slot(nb, !slot))
a720b2dd 421 return -EEXIST;
8cc1176e 422
d2946041 423 amd_l3_disable_index(nb, cpu, slot, index);
8cc1176e
BP
424
425 return 0;
426}
427
0d55ba46
SH
428static ssize_t store_cache_disable(struct cacheinfo *this_leaf,
429 const char *buf, size_t count,
430 unsigned int slot)
8cc1176e
BP
431{
432 unsigned long val = 0;
433 int cpu, err = 0;
0d55ba46 434 struct amd_northbridge *nb = this_leaf->priv;
8cc1176e 435
cb19060a
BP
436 if (!capable(CAP_SYS_ADMIN))
437 return -EPERM;
438
0d55ba46 439 cpu = cpumask_first(&this_leaf->shared_cpu_map);
cb19060a 440
164109e3 441 if (kstrtoul(buf, 10, &val) < 0)
cb19060a
BP
442 return -EINVAL;
443
0d55ba46 444 err = amd_set_l3_disable_slot(nb, cpu, slot, val);
8cc1176e
BP
445 if (err) {
446 if (err == -EEXIST)
a720b2dd
SB
447 pr_warning("L3 slot %d in use/index already disabled!\n",
448 slot);
8cc1176e
BP
449 return err;
450 }
cb19060a
BP
451 return count;
452}
453
59d3b388 454#define STORE_CACHE_DISABLE(slot) \
cb19060a 455static ssize_t \
0d55ba46
SH
456cache_disable_##slot##_store(struct device *dev, \
457 struct device_attribute *attr, \
458 const char *buf, size_t count) \
cb19060a 459{ \
0d55ba46 460 struct cacheinfo *this_leaf = dev_get_drvdata(dev); \
59d3b388 461 return store_cache_disable(this_leaf, buf, count, slot); \
8cb22bcb 462}
cb19060a
BP
463STORE_CACHE_DISABLE(0)
464STORE_CACHE_DISABLE(1)
465
0d55ba46
SH
466static ssize_t subcaches_show(struct device *dev,
467 struct device_attribute *attr, char *buf)
cabb5bd7 468{
0d55ba46
SH
469 struct cacheinfo *this_leaf = dev_get_drvdata(dev);
470 int cpu = cpumask_first(&this_leaf->shared_cpu_map);
cabb5bd7
HR
471
472 return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
473}
474
0d55ba46
SH
475static ssize_t subcaches_store(struct device *dev,
476 struct device_attribute *attr,
477 const char *buf, size_t count)
cabb5bd7 478{
0d55ba46
SH
479 struct cacheinfo *this_leaf = dev_get_drvdata(dev);
480 int cpu = cpumask_first(&this_leaf->shared_cpu_map);
cabb5bd7
HR
481 unsigned long val;
482
483 if (!capable(CAP_SYS_ADMIN))
484 return -EPERM;
485
164109e3 486 if (kstrtoul(buf, 16, &val) < 0)
cabb5bd7
HR
487 return -EINVAL;
488
489 if (amd_set_subcaches(cpu, val))
490 return -EINVAL;
491
492 return count;
493}
494
0d55ba46
SH
495static DEVICE_ATTR_RW(cache_disable_0);
496static DEVICE_ATTR_RW(cache_disable_1);
497static DEVICE_ATTR_RW(subcaches);
498
499static umode_t
500cache_private_attrs_is_visible(struct kobject *kobj,
501 struct attribute *attr, int unused)
502{
503 struct device *dev = kobj_to_dev(kobj);
504 struct cacheinfo *this_leaf = dev_get_drvdata(dev);
505 umode_t mode = attr->mode;
506
507 if (!this_leaf->priv)
508 return 0;
509
510 if ((attr == &dev_attr_subcaches.attr) &&
511 amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
512 return mode;
513
514 if ((attr == &dev_attr_cache_disable_0.attr ||
515 attr == &dev_attr_cache_disable_1.attr) &&
516 amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
517 return mode;
518
519 return 0;
520}
521
522static struct attribute_group cache_private_group = {
523 .is_visible = cache_private_attrs_is_visible,
524};
525
526static void init_amd_l3_attrs(void)
527{
528 int n = 1;
529 static struct attribute **amd_l3_attrs;
530
531 if (amd_l3_attrs) /* already initialized */
532 return;
533
534 if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
535 n += 2;
536 if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
537 n += 1;
538
539 amd_l3_attrs = kcalloc(n, sizeof(*amd_l3_attrs), GFP_KERNEL);
540 if (!amd_l3_attrs)
541 return;
542
543 n = 0;
544 if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) {
545 amd_l3_attrs[n++] = &dev_attr_cache_disable_0.attr;
546 amd_l3_attrs[n++] = &dev_attr_cache_disable_1.attr;
547 }
548 if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
549 amd_l3_attrs[n++] = &dev_attr_subcaches.attr;
cabb5bd7 550
0d55ba46
SH
551 cache_private_group.attrs = amd_l3_attrs;
552}
553
554const struct attribute_group *
555cache_get_priv_group(struct cacheinfo *this_leaf)
556{
557 struct amd_northbridge *nb = this_leaf->priv;
558
37dea8c5 559 if (this_leaf->level < 3 || !nb)
0d55ba46
SH
560 return NULL;
561
562 if (nb && nb->l3_cache.indices)
563 init_amd_l3_attrs();
564
565 return &cache_private_group;
566}
567
568static void amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int index)
569{
570 int node;
571
572 /* only for L3, and not in virtualized environments */
573 if (index < 3)
574 return;
575
576 node = amd_get_nb_id(smp_processor_id());
577 this_leaf->nb = node_to_amd_nb(node);
578 if (this_leaf->nb && !this_leaf->nb->l3_cache.indices)
579 amd_calc_l3_indices(this_leaf->nb);
580}
f76e39c5 581#else
f658bcfb 582#define amd_init_l3_cache(x, y)
f76e39c5 583#endif /* CONFIG_AMD_NB && CONFIG_SYSFS */
8cb22bcb 584
7a4983bb 585static int
148f9bb8 586cpuid4_cache_lookup_regs(int index, struct _cpuid4_info_regs *this_leaf)
1da177e4 587{
cabb5bd7
HR
588 union _cpuid4_leaf_eax eax;
589 union _cpuid4_leaf_ebx ebx;
590 union _cpuid4_leaf_ecx ecx;
240cd6a8 591 unsigned edx;
1da177e4 592
8cb22bcb 593 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
2e8458df
AH
594 if (cpu_has_topoext)
595 cpuid_count(0x8000001d, index, &eax.full,
596 &ebx.full, &ecx.full, &edx);
597 else
598 amd_cpuid4(index, &eax, &ebx, &ecx);
f658bcfb 599 amd_init_l3_cache(this_leaf, index);
7a4983bb
IM
600 } else {
601 cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
602 }
603
0d55ba46 604 if (eax.split.type == CTYPE_NULL)
e2cac789 605 return -EIO; /* better error ? */
1da177e4 606
240cd6a8
AK
607 this_leaf->eax = eax;
608 this_leaf->ebx = ebx;
609 this_leaf->ecx = ecx;
7a4983bb
IM
610 this_leaf->size = (ecx.split.number_of_sets + 1) *
611 (ebx.split.coherency_line_size + 1) *
612 (ebx.split.physical_line_partition + 1) *
613 (ebx.split.ways_of_associativity + 1);
1da177e4
LT
614 return 0;
615}
616
148f9bb8 617static int find_num_cache_leaves(struct cpuinfo_x86 *c)
1da177e4 618{
04a15418 619 unsigned int eax, ebx, ecx, edx, op;
1da177e4 620 union _cpuid4_leaf_eax cache_eax;
d16aafff 621 int i = -1;
1da177e4 622
04a15418
AH
623 if (c->x86_vendor == X86_VENDOR_AMD)
624 op = 0x8000001d;
625 else
626 op = 4;
627
d16aafff
SS
628 do {
629 ++i;
04a15418
AH
630 /* Do cpuid(op) loop to find out num_cache_leaves */
631 cpuid_count(op, i, &eax, &ebx, &ecx, &edx);
1da177e4 632 cache_eax.full = eax;
0d55ba46 633 } while (cache_eax.split.type != CTYPE_NULL);
d16aafff 634 return i;
1da177e4
LT
635}
636
148f9bb8 637void init_amd_cacheinfo(struct cpuinfo_x86 *c)
04a15418
AH
638{
639
640 if (cpu_has_topoext) {
641 num_cache_leaves = find_num_cache_leaves(c);
642 } else if (c->extended_cpuid_level >= 0x80000006) {
643 if (cpuid_edx(0x80000006) & 0xf000)
644 num_cache_leaves = 4;
645 else
646 num_cache_leaves = 3;
647 }
648}
649
148f9bb8 650unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c)
1da177e4 651{
8bdbd962
AC
652 /* Cache sizes */
653 unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0;
1da177e4
LT
654 unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
655 unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
1e9f28fa 656 unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
c8e56d20 657#ifdef CONFIG_SMP
92cb7612 658 unsigned int cpu = c->cpu_index;
1e9f28fa 659#endif
1da177e4 660
f2d0d263 661 if (c->cpuid_level > 3) {
1da177e4
LT
662 static int is_initialized;
663
664 if (is_initialized == 0) {
665 /* Init num_cache_leaves from boot CPU */
04a15418 666 num_cache_leaves = find_num_cache_leaves(c);
1da177e4
LT
667 is_initialized++;
668 }
669
670 /*
671 * Whenever possible use cpuid(4), deterministic cache
672 * parameters cpuid leaf to find the cache details
673 */
674 for (i = 0; i < num_cache_leaves; i++) {
719038de 675 struct _cpuid4_info_regs this_leaf = {};
1da177e4
LT
676 int retval;
677
f9b90566 678 retval = cpuid4_cache_lookup_regs(i, &this_leaf);
719038de
BP
679 if (retval < 0)
680 continue;
681
682 switch (this_leaf.eax.split.level) {
683 case 1:
0d55ba46 684 if (this_leaf.eax.split.type == CTYPE_DATA)
719038de 685 new_l1d = this_leaf.size/1024;
0d55ba46 686 else if (this_leaf.eax.split.type == CTYPE_INST)
719038de
BP
687 new_l1i = this_leaf.size/1024;
688 break;
689 case 2:
690 new_l2 = this_leaf.size/1024;
691 num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
692 index_msb = get_count_order(num_threads_sharing);
693 l2_id = c->apicid & ~((1 << index_msb) - 1);
694 break;
695 case 3:
696 new_l3 = this_leaf.size/1024;
697 num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
698 index_msb = get_count_order(num_threads_sharing);
699 l3_id = c->apicid & ~((1 << index_msb) - 1);
700 break;
701 default:
702 break;
1da177e4
LT
703 }
704 }
705 }
b06be912
SL
706 /*
707 * Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for
708 * trace cache
709 */
710 if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) {
1da177e4 711 /* supports eax=2 call */
c1666e66
HH
712 int j, n;
713 unsigned int regs[4];
1da177e4 714 unsigned char *dp = (unsigned char *)regs;
b06be912
SL
715 int only_trace = 0;
716
717 if (num_cache_leaves != 0 && c->x86 == 15)
718 only_trace = 1;
1da177e4
LT
719
720 /* Number of times to iterate */
721 n = cpuid_eax(2) & 0xFF;
722
8bdbd962 723 for (i = 0 ; i < n ; i++) {
1da177e4
LT
724 cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);
725
726 /* If bit 31 is set, this is an unknown format */
8bdbd962
AC
727 for (j = 0 ; j < 3 ; j++)
728 if (regs[j] & (1 << 31))
729 regs[j] = 0;
1da177e4
LT
730
731 /* Byte 0 is level count, not a descriptor */
8bdbd962 732 for (j = 1 ; j < 16 ; j++) {
1da177e4
LT
733 unsigned char des = dp[j];
734 unsigned char k = 0;
735
736 /* look up this descriptor in the table */
8bdbd962 737 while (cache_table[k].descriptor != 0) {
1da177e4 738 if (cache_table[k].descriptor == des) {
b06be912
SL
739 if (only_trace && cache_table[k].cache_type != LVL_TRACE)
740 break;
1da177e4
LT
741 switch (cache_table[k].cache_type) {
742 case LVL_1_INST:
743 l1i += cache_table[k].size;
744 break;
745 case LVL_1_DATA:
746 l1d += cache_table[k].size;
747 break;
748 case LVL_2:
749 l2 += cache_table[k].size;
750 break;
751 case LVL_3:
752 l3 += cache_table[k].size;
753 break;
754 case LVL_TRACE:
755 trace += cache_table[k].size;
756 break;
757 }
758
759 break;
760 }
761
762 k++;
763 }
764 }
765 }
b06be912 766 }
1da177e4 767
b06be912
SL
768 if (new_l1d)
769 l1d = new_l1d;
1da177e4 770
b06be912
SL
771 if (new_l1i)
772 l1i = new_l1i;
1da177e4 773
b06be912
SL
774 if (new_l2) {
775 l2 = new_l2;
c8e56d20 776#ifdef CONFIG_SMP
b6278470 777 per_cpu(cpu_llc_id, cpu) = l2_id;
1e9f28fa 778#endif
b06be912 779 }
1da177e4 780
b06be912
SL
781 if (new_l3) {
782 l3 = new_l3;
c8e56d20 783#ifdef CONFIG_SMP
b6278470 784 per_cpu(cpu_llc_id, cpu) = l3_id;
1e9f28fa 785#endif
1da177e4
LT
786 }
787
c8e56d20 788#ifdef CONFIG_SMP
2a226155
PZ
789 /*
790 * If cpu_llc_id is not yet set, this means cpuid_level < 4 which in
791 * turns means that the only possibility is SMT (as indicated in
792 * cpuid1). Since cpuid2 doesn't specify shared caches, and we know
793 * that SMT shares all caches, we can unconditionally set cpu_llc_id to
794 * c->phys_proc_id.
795 */
796 if (per_cpu(cpu_llc_id, cpu) == BAD_APICID)
797 per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
798#endif
799
b06be912
SL
800 c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
801
1da177e4
LT
802 return l2;
803}
804
0d55ba46
SH
805static int __cache_amd_cpumap_setup(unsigned int cpu, int index,
806 struct _cpuid4_info_regs *base)
1da177e4 807{
0d55ba46
SH
808 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
809 struct cacheinfo *this_leaf;
27d3a8a2 810 int i, sibling;
1da177e4 811
27d3a8a2
AH
812 if (cpu_has_topoext) {
813 unsigned int apicid, nshared, first, last;
814
0d55ba46
SH
815 this_leaf = this_cpu_ci->info_list + index;
816 nshared = base->eax.split.num_threads_sharing + 1;
27d3a8a2
AH
817 apicid = cpu_data(cpu).apicid;
818 first = apicid - (apicid % nshared);
819 last = first + nshared - 1;
820
821 for_each_online_cpu(i) {
0d55ba46
SH
822 this_cpu_ci = get_cpu_cacheinfo(i);
823 if (!this_cpu_ci->info_list)
824 continue;
825
27d3a8a2
AH
826 apicid = cpu_data(i).apicid;
827 if ((apicid < first) || (apicid > last))
828 continue;
0d55ba46
SH
829
830 this_leaf = this_cpu_ci->info_list + index;
27d3a8a2
AH
831
832 for_each_online_cpu(sibling) {
833 apicid = cpu_data(sibling).apicid;
834 if ((apicid < first) || (apicid > last))
ebb682f5 835 continue;
0d55ba46
SH
836 cpumask_set_cpu(sibling,
837 &this_leaf->shared_cpu_map);
ebb682f5 838 }
a326e948 839 }
27d3a8a2
AH
840 } else if (index == 3) {
841 for_each_cpu(i, cpu_llc_shared_mask(cpu)) {
0d55ba46
SH
842 this_cpu_ci = get_cpu_cacheinfo(i);
843 if (!this_cpu_ci->info_list)
32c32338 844 continue;
0d55ba46 845 this_leaf = this_cpu_ci->info_list + index;
27d3a8a2 846 for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) {
32c32338
AH
847 if (!cpu_online(sibling))
848 continue;
0d55ba46
SH
849 cpumask_set_cpu(sibling,
850 &this_leaf->shared_cpu_map);
32c32338
AH
851 }
852 }
27d3a8a2
AH
853 } else
854 return 0;
32c32338 855
27d3a8a2 856 return 1;
32c32338
AH
857}
858
0d55ba46
SH
859static void __cache_cpumap_setup(unsigned int cpu, int index,
860 struct _cpuid4_info_regs *base)
32c32338 861{
0d55ba46
SH
862 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
863 struct cacheinfo *this_leaf, *sibling_leaf;
32c32338
AH
864 unsigned long num_threads_sharing;
865 int index_msb, i;
866 struct cpuinfo_x86 *c = &cpu_data(cpu);
867
868 if (c->x86_vendor == X86_VENDOR_AMD) {
0d55ba46 869 if (__cache_amd_cpumap_setup(cpu, index, base))
32c32338
AH
870 return;
871 }
872
0d55ba46
SH
873 this_leaf = this_cpu_ci->info_list + index;
874 num_threads_sharing = 1 + base->eax.split.num_threads_sharing;
1da177e4 875
0d55ba46 876 cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map);
1da177e4 877 if (num_threads_sharing == 1)
0d55ba46 878 return;
e2cac789 879
0d55ba46 880 index_msb = get_count_order(num_threads_sharing);
b7d11a76 881
0d55ba46
SH
882 for_each_online_cpu(i)
883 if (cpu_data(i).apicid >> index_msb == c->apicid >> index_msb) {
884 struct cpu_cacheinfo *sib_cpu_ci = get_cpu_cacheinfo(i);
ef1d7151 885
0d55ba46
SH
886 if (i == cpu || !sib_cpu_ci->info_list)
887 continue;/* skip if itself or no cacheinfo */
888 sibling_leaf = sib_cpu_ci->info_list + index;
889 cpumask_set_cpu(i, &this_leaf->shared_cpu_map);
890 cpumask_set_cpu(cpu, &sibling_leaf->shared_cpu_map);
ef1d7151 891 }
b2bb8554
MT
892}
893
0d55ba46
SH
894static void ci_leaf_init(struct cacheinfo *this_leaf,
895 struct _cpuid4_info_regs *base)
b2bb8554 896{
0d55ba46
SH
897 this_leaf->level = base->eax.split.level;
898 this_leaf->type = cache_type_map[base->eax.split.type];
899 this_leaf->coherency_line_size =
900 base->ebx.split.coherency_line_size + 1;
901 this_leaf->ways_of_associativity =
902 base->ebx.split.ways_of_associativity + 1;
903 this_leaf->size = base->size;
904 this_leaf->number_of_sets = base->ecx.split.number_of_sets + 1;
905 this_leaf->physical_line_partition =
906 base->ebx.split.physical_line_partition + 1;
907 this_leaf->priv = base->nb;
1da177e4
LT
908}
909
0d55ba46 910static int __init_cache_level(unsigned int cpu)
fb0f330e 911{
0d55ba46 912 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
fb0f330e 913
0d55ba46 914 if (!num_cache_leaves)
1da177e4 915 return -ENOENT;
0d55ba46
SH
916 if (!this_cpu_ci)
917 return -EINVAL;
918 this_cpu_ci->num_levels = 3;
919 this_cpu_ci->num_leaves = num_cache_leaves;
1da177e4 920 return 0;
1da177e4
LT
921}
922
0d55ba46 923static int __populate_cache_leaves(unsigned int cpu)
1da177e4 924{
0d55ba46
SH
925 unsigned int idx, ret;
926 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
927 struct cacheinfo *this_leaf = this_cpu_ci->info_list;
928 struct _cpuid4_info_regs id4_regs = {};
1da177e4 929
0d55ba46
SH
930 for (idx = 0; idx < this_cpu_ci->num_leaves; idx++) {
931 ret = cpuid4_cache_lookup_regs(idx, &id4_regs);
932 if (ret)
933 return ret;
934 ci_leaf_init(this_leaf++, &id4_regs);
935 __cache_cpumap_setup(cpu, idx, &id4_regs);
1da177e4 936 }
8b2b9c1a 937 return 0;
1da177e4
LT
938}
939
0d55ba46
SH
940DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
941DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
This page took 0.753091 seconds and 5 git commands to generate.