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