diff options
author | Hans Rosenfeld <hans.rosenfeld@amd.com> | 2010-10-29 11:14:32 -0400 |
---|---|---|
committer | Borislav Petkov <borislav.petkov@amd.com> | 2010-11-18 09:53:06 -0500 |
commit | f658bcfb2607bf0808966a69cf74135ce98e5c2d (patch) | |
tree | a01f768fb6b49acd701f912f426e1fd6ee4f0f56 | |
parent | 9653a5c76c8677b05b45b3b999d3b39988d2a064 (diff) |
x86, cacheinfo: Cleanup L3 cache index disable support
Adaptions to the changes of the AMD northbridge caching code: instead
of a bool in each l3 struct, use a flag in amd_northbridges.flags to
indicate L3 cache index disable support; use a pointer to the whole
northbridge instead of the misc device in the l3 struct; simplify the
initialisation; dynamically generate sysfs attribute array.
Signed-off-by: Hans Rosenfeld <hans.rosenfeld@amd.com>
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
-rw-r--r-- | arch/x86/include/asm/amd_nb.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/amd_nb.c | 10 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 147 |
3 files changed, 74 insertions, 84 deletions
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h index 4d7ec7df7de2..6aee50d655d1 100644 --- a/arch/x86/include/asm/amd_nb.h +++ b/arch/x86/include/asm/amd_nb.h | |||
@@ -25,6 +25,7 @@ struct amd_northbridge_info { | |||
25 | extern struct amd_northbridge_info amd_northbridges; | 25 | extern struct amd_northbridge_info amd_northbridges; |
26 | 26 | ||
27 | #define AMD_NB_GART 0x1 | 27 | #define AMD_NB_GART 0x1 |
28 | #define AMD_NB_L3_INDEX_DISABLE 0x2 | ||
28 | 29 | ||
29 | #ifdef CONFIG_AMD_NB | 30 | #ifdef CONFIG_AMD_NB |
30 | 31 | ||
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 63c8b4f2c1ad..affacb5e0065 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c | |||
@@ -68,6 +68,16 @@ int amd_cache_northbridges(void) | |||
68 | boot_cpu_data.x86 == 0x15) | 68 | boot_cpu_data.x86 == 0x15) |
69 | amd_northbridges.flags |= AMD_NB_GART; | 69 | amd_northbridges.flags |= AMD_NB_GART; |
70 | 70 | ||
71 | /* | ||
72 | * Some CPU families support L3 Cache Index Disable. There are some | ||
73 | * limitations because of E382 and E388 on family 0x10. | ||
74 | */ | ||
75 | if (boot_cpu_data.x86 == 0x10 && | ||
76 | boot_cpu_data.x86_model >= 0x8 && | ||
77 | (boot_cpu_data.x86_model > 0x9 || | ||
78 | boot_cpu_data.x86_mask >= 0x1)) | ||
79 | amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE; | ||
80 | |||
71 | return 0; | 81 | return 0; |
72 | } | 82 | } |
73 | EXPORT_SYMBOL_GPL(amd_cache_northbridges); | 83 | EXPORT_SYMBOL_GPL(amd_cache_northbridges); |
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 6b8ea7434972..9ecf81f9b90f 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -149,8 +149,7 @@ union _cpuid4_leaf_ecx { | |||
149 | }; | 149 | }; |
150 | 150 | ||
151 | struct amd_l3_cache { | 151 | struct amd_l3_cache { |
152 | struct pci_dev *dev; | 152 | struct amd_northbridge *nb; |
153 | bool can_disable; | ||
154 | unsigned indices; | 153 | unsigned indices; |
155 | u8 subcaches[4]; | 154 | u8 subcaches[4]; |
156 | }; | 155 | }; |
@@ -311,14 +310,12 @@ struct _cache_attr { | |||
311 | /* | 310 | /* |
312 | * L3 cache descriptors | 311 | * L3 cache descriptors |
313 | */ | 312 | */ |
314 | static struct amd_l3_cache **__cpuinitdata l3_caches; | ||
315 | |||
316 | static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) | 313 | static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) |
317 | { | 314 | { |
318 | unsigned int sc0, sc1, sc2, sc3; | 315 | unsigned int sc0, sc1, sc2, sc3; |
319 | u32 val = 0; | 316 | u32 val = 0; |
320 | 317 | ||
321 | pci_read_config_dword(l3->dev, 0x1C4, &val); | 318 | pci_read_config_dword(l3->nb->misc, 0x1C4, &val); |
322 | 319 | ||
323 | /* calculate subcache sizes */ | 320 | /* calculate subcache sizes */ |
324 | l3->subcaches[0] = sc0 = !(val & BIT(0)); | 321 | l3->subcaches[0] = sc0 = !(val & BIT(0)); |
@@ -330,47 +327,14 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) | |||
330 | l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1; | 327 | l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1; |
331 | } | 328 | } |
332 | 329 | ||
333 | static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node) | 330 | static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, |
334 | { | 331 | int index) |
335 | struct amd_l3_cache *l3; | ||
336 | struct pci_dev *dev = node_to_amd_nb(node)->misc; | ||
337 | |||
338 | l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC); | ||
339 | if (!l3) { | ||
340 | printk(KERN_WARNING "Error allocating L3 struct\n"); | ||
341 | return NULL; | ||
342 | } | ||
343 | |||
344 | l3->dev = dev; | ||
345 | |||
346 | amd_calc_l3_indices(l3); | ||
347 | |||
348 | return l3; | ||
349 | } | ||
350 | |||
351 | static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, | ||
352 | int index) | ||
353 | { | 332 | { |
333 | static struct amd_l3_cache *__cpuinitdata l3_caches; | ||
354 | int node; | 334 | int node; |
355 | 335 | ||
356 | if (boot_cpu_data.x86 != 0x10) | 336 | /* only for L3, and not in virtualized environments */ |
357 | return; | 337 | if (index < 3 || amd_nb_num() == 0) |
358 | |||
359 | if (index < 3) | ||
360 | return; | ||
361 | |||
362 | /* see errata #382 and #388 */ | ||
363 | if (boot_cpu_data.x86_model < 0x8) | ||
364 | return; | ||
365 | |||
366 | if ((boot_cpu_data.x86_model == 0x8 || | ||
367 | boot_cpu_data.x86_model == 0x9) | ||
368 | && | ||
369 | boot_cpu_data.x86_mask < 0x1) | ||
370 | return; | ||
371 | |||
372 | /* not in virtualized environments */ | ||
373 | if (amd_nb_num() == 0) | ||
374 | return; | 338 | return; |
375 | 339 | ||
376 | /* | 340 | /* |
@@ -378,7 +342,7 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, | |||
378 | * never freed but this is done only on shutdown so it doesn't matter. | 342 | * never freed but this is done only on shutdown so it doesn't matter. |
379 | */ | 343 | */ |
380 | if (!l3_caches) { | 344 | if (!l3_caches) { |
381 | int size = amd_nb_num() * sizeof(struct amd_l3_cache *); | 345 | int size = amd_nb_num() * sizeof(struct amd_l3_cache); |
382 | 346 | ||
383 | l3_caches = kzalloc(size, GFP_ATOMIC); | 347 | l3_caches = kzalloc(size, GFP_ATOMIC); |
384 | if (!l3_caches) | 348 | if (!l3_caches) |
@@ -387,14 +351,12 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, | |||
387 | 351 | ||
388 | node = amd_get_nb_id(smp_processor_id()); | 352 | node = amd_get_nb_id(smp_processor_id()); |
389 | 353 | ||
390 | if (!l3_caches[node]) { | 354 | if (!l3_caches[node].nb) { |
391 | l3_caches[node] = amd_init_l3_cache(node); | 355 | l3_caches[node].nb = node_to_amd_nb(node); |
392 | l3_caches[node]->can_disable = true; | 356 | amd_calc_l3_indices(&l3_caches[node]); |
393 | } | 357 | } |
394 | 358 | ||
395 | WARN_ON(!l3_caches[node]); | 359 | this_leaf->l3 = &l3_caches[node]; |
396 | |||
397 | this_leaf->l3 = l3_caches[node]; | ||
398 | } | 360 | } |
399 | 361 | ||
400 | /* | 362 | /* |
@@ -408,7 +370,7 @@ int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot) | |||
408 | { | 370 | { |
409 | unsigned int reg = 0; | 371 | unsigned int reg = 0; |
410 | 372 | ||
411 | pci_read_config_dword(l3->dev, 0x1BC + slot * 4, ®); | 373 | pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, ®); |
412 | 374 | ||
413 | /* check whether this slot is activated already */ | 375 | /* check whether this slot is activated already */ |
414 | if (reg & (3UL << 30)) | 376 | if (reg & (3UL << 30)) |
@@ -422,7 +384,8 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | |||
422 | { | 384 | { |
423 | int index; | 385 | int index; |
424 | 386 | ||
425 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) | 387 | if (!this_leaf->l3 || |
388 | !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | ||
426 | return -EINVAL; | 389 | return -EINVAL; |
427 | 390 | ||
428 | index = amd_get_l3_disable_slot(this_leaf->l3, slot); | 391 | index = amd_get_l3_disable_slot(this_leaf->l3, slot); |
@@ -457,7 +420,7 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, | |||
457 | if (!l3->subcaches[i]) | 420 | if (!l3->subcaches[i]) |
458 | continue; | 421 | continue; |
459 | 422 | ||
460 | pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg); | 423 | pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); |
461 | 424 | ||
462 | /* | 425 | /* |
463 | * We need to WBINVD on a core on the node containing the L3 | 426 | * We need to WBINVD on a core on the node containing the L3 |
@@ -467,7 +430,7 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, | |||
467 | wbinvd_on_cpu(cpu); | 430 | wbinvd_on_cpu(cpu); |
468 | 431 | ||
469 | reg |= BIT(31); | 432 | reg |= BIT(31); |
470 | pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg); | 433 | pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); |
471 | } | 434 | } |
472 | } | 435 | } |
473 | 436 | ||
@@ -524,7 +487,8 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
524 | if (!capable(CAP_SYS_ADMIN)) | 487 | if (!capable(CAP_SYS_ADMIN)) |
525 | return -EPERM; | 488 | return -EPERM; |
526 | 489 | ||
527 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) | 490 | if (!this_leaf->l3 || |
491 | !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | ||
528 | return -EINVAL; | 492 | return -EINVAL; |
529 | 493 | ||
530 | cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | 494 | cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); |
@@ -545,7 +509,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
545 | #define STORE_CACHE_DISABLE(slot) \ | 509 | #define STORE_CACHE_DISABLE(slot) \ |
546 | static ssize_t \ | 510 | static ssize_t \ |
547 | store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \ | 511 | store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \ |
548 | const char *buf, size_t count) \ | 512 | const char *buf, size_t count) \ |
549 | { \ | 513 | { \ |
550 | return store_cache_disable(this_leaf, buf, count, slot); \ | 514 | return store_cache_disable(this_leaf, buf, count, slot); \ |
551 | } | 515 | } |
@@ -558,10 +522,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, | |||
558 | show_cache_disable_1, store_cache_disable_1); | 522 | show_cache_disable_1, store_cache_disable_1); |
559 | 523 | ||
560 | #else /* CONFIG_AMD_NB */ | 524 | #else /* CONFIG_AMD_NB */ |
561 | static void __cpuinit | 525 | #define amd_init_l3_cache(x, y) |
562 | amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, int index) | ||
563 | { | ||
564 | }; | ||
565 | #endif /* CONFIG_AMD_NB */ | 526 | #endif /* CONFIG_AMD_NB */ |
566 | 527 | ||
567 | static int | 528 | static int |
@@ -575,7 +536,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index, | |||
575 | 536 | ||
576 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { | 537 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { |
577 | amd_cpuid4(index, &eax, &ebx, &ecx); | 538 | amd_cpuid4(index, &eax, &ebx, &ecx); |
578 | amd_check_l3_disable(this_leaf, index); | 539 | amd_init_l3_cache(this_leaf, index); |
579 | } else { | 540 | } else { |
580 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); | 541 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); |
581 | } | 542 | } |
@@ -983,30 +944,48 @@ define_one_ro(size); | |||
983 | define_one_ro(shared_cpu_map); | 944 | define_one_ro(shared_cpu_map); |
984 | define_one_ro(shared_cpu_list); | 945 | define_one_ro(shared_cpu_list); |
985 | 946 | ||
986 | #define DEFAULT_SYSFS_CACHE_ATTRS \ | ||
987 | &type.attr, \ | ||
988 | &level.attr, \ | ||
989 | &coherency_line_size.attr, \ | ||
990 | &physical_line_partition.attr, \ | ||
991 | &ways_of_associativity.attr, \ | ||
992 | &number_of_sets.attr, \ | ||
993 | &size.attr, \ | ||
994 | &shared_cpu_map.attr, \ | ||
995 | &shared_cpu_list.attr | ||
996 | |||
997 | static struct attribute *default_attrs[] = { | 947 | static struct attribute *default_attrs[] = { |
998 | DEFAULT_SYSFS_CACHE_ATTRS, | 948 | &type.attr, |
949 | &level.attr, | ||
950 | &coherency_line_size.attr, | ||
951 | &physical_line_partition.attr, | ||
952 | &ways_of_associativity.attr, | ||
953 | &number_of_sets.attr, | ||
954 | &size.attr, | ||
955 | &shared_cpu_map.attr, | ||
956 | &shared_cpu_list.attr, | ||
999 | NULL | 957 | NULL |
1000 | }; | 958 | }; |
1001 | 959 | ||
1002 | static struct attribute *default_l3_attrs[] = { | ||
1003 | DEFAULT_SYSFS_CACHE_ATTRS, | ||
1004 | #ifdef CONFIG_AMD_NB | 960 | #ifdef CONFIG_AMD_NB |
1005 | &cache_disable_0.attr, | 961 | static struct attribute ** __cpuinit amd_l3_attrs(void) |
1006 | &cache_disable_1.attr, | 962 | { |
963 | static struct attribute **attrs; | ||
964 | int n; | ||
965 | |||
966 | if (attrs) | ||
967 | return attrs; | ||
968 | |||
969 | n = sizeof (default_attrs) / sizeof (struct attribute *); | ||
970 | |||
971 | if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | ||
972 | n += 2; | ||
973 | |||
974 | attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL); | ||
975 | if (attrs == NULL) | ||
976 | return attrs = default_attrs; | ||
977 | |||
978 | for (n = 0; default_attrs[n]; n++) | ||
979 | attrs[n] = default_attrs[n]; | ||
980 | |||
981 | if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) { | ||
982 | attrs[n++] = &cache_disable_0.attr; | ||
983 | attrs[n++] = &cache_disable_1.attr; | ||
984 | } | ||
985 | |||
986 | return attrs; | ||
987 | } | ||
1007 | #endif | 988 | #endif |
1008 | NULL | ||
1009 | }; | ||
1010 | 989 | ||
1011 | static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) | 990 | static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) |
1012 | { | 991 | { |
@@ -1117,11 +1096,11 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) | |||
1117 | 1096 | ||
1118 | this_leaf = CPUID4_INFO_IDX(cpu, i); | 1097 | this_leaf = CPUID4_INFO_IDX(cpu, i); |
1119 | 1098 | ||
1120 | if (this_leaf->l3 && this_leaf->l3->can_disable) | 1099 | ktype_cache.default_attrs = default_attrs; |
1121 | ktype_cache.default_attrs = default_l3_attrs; | 1100 | #ifdef CONFIG_AMD_NB |
1122 | else | 1101 | if (this_leaf->l3) |
1123 | ktype_cache.default_attrs = default_attrs; | 1102 | ktype_cache.default_attrs = amd_l3_attrs(); |
1124 | 1103 | #endif | |
1125 | retval = kobject_init_and_add(&(this_object->kobj), | 1104 | retval = kobject_init_and_add(&(this_object->kobj), |
1126 | &ktype_cache, | 1105 | &ktype_cache, |
1127 | per_cpu(ici_cache_kobject, cpu), | 1106 | per_cpu(ici_cache_kobject, cpu), |