diff options
| -rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 115 |
1 files changed, 61 insertions, 54 deletions
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index d6ea50e270e0..a61c9e399ba9 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
| @@ -253,14 +253,16 @@ static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, | |||
| 253 | (ebx->split.ways_of_associativity + 1) - 1; | 253 | (ebx->split.ways_of_associativity + 1) - 1; |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | static void __cpuinit amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) | 256 | static void __cpuinit |
| 257 | amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) | ||
| 257 | { | 258 | { |
| 258 | if (index < 3) | 259 | if (index < 3) |
| 259 | return; | 260 | return; |
| 260 | this_leaf->can_disable = 1; | 261 | this_leaf->can_disable = 1; |
| 261 | } | 262 | } |
| 262 | 263 | ||
| 263 | static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) | 264 | static int |
| 265 | __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) | ||
| 264 | { | 266 | { |
| 265 | union _cpuid4_leaf_eax eax; | 267 | union _cpuid4_leaf_eax eax; |
| 266 | union _cpuid4_leaf_ebx ebx; | 268 | union _cpuid4_leaf_ebx ebx; |
| @@ -271,19 +273,20 @@ static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_le | |||
| 271 | amd_cpuid4(index, &eax, &ebx, &ecx); | 273 | amd_cpuid4(index, &eax, &ebx, &ecx); |
| 272 | if (boot_cpu_data.x86 >= 0x10) | 274 | if (boot_cpu_data.x86 >= 0x10) |
| 273 | amd_check_l3_disable(index, this_leaf); | 275 | amd_check_l3_disable(index, this_leaf); |
| 274 | 276 | } else { | |
| 275 | } else | 277 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); |
| 276 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); | 278 | } |
| 279 | |||
| 277 | if (eax.split.type == CACHE_TYPE_NULL) | 280 | if (eax.split.type == CACHE_TYPE_NULL) |
| 278 | return -EIO; /* better error ? */ | 281 | return -EIO; /* better error ? */ |
| 279 | 282 | ||
| 280 | this_leaf->eax = eax; | 283 | this_leaf->eax = eax; |
| 281 | this_leaf->ebx = ebx; | 284 | this_leaf->ebx = ebx; |
| 282 | this_leaf->ecx = ecx; | 285 | this_leaf->ecx = ecx; |
| 283 | this_leaf->size = (ecx.split.number_of_sets + 1) * | 286 | this_leaf->size = (ecx.split.number_of_sets + 1) * |
| 284 | (ebx.split.coherency_line_size + 1) * | 287 | (ebx.split.coherency_line_size + 1) * |
| 285 | (ebx.split.physical_line_partition + 1) * | 288 | (ebx.split.physical_line_partition + 1) * |
| 286 | (ebx.split.ways_of_associativity + 1); | 289 | (ebx.split.ways_of_associativity + 1); |
| 287 | return 0; | 290 | return 0; |
| 288 | } | 291 | } |
| 289 | 292 | ||
| @@ -649,59 +652,63 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { | |||
| 649 | } | 652 | } |
| 650 | } | 653 | } |
| 651 | 654 | ||
| 652 | #define to_object(k) container_of(k, struct _index_kobject, kobj) | 655 | #define to_object(k) container_of(k, struct _index_kobject, kobj) |
| 653 | #define to_attr(a) container_of(a, struct _cache_attr, attr) | 656 | #define to_attr(a) container_of(a, struct _cache_attr, attr) |
| 654 | 657 | ||
| 655 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) | 658 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) |
| 656 | { | 659 | { |
| 657 | struct pci_dev *dev; | 660 | int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); |
| 658 | if (this_leaf->can_disable) { | 661 | struct pci_dev *dev = k8_northbridges[node]; |
| 659 | int i; | 662 | ssize_t ret = 0; |
| 660 | ssize_t ret = 0; | 663 | int i; |
| 661 | int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); | ||
| 662 | dev = k8_northbridges[node]; | ||
| 663 | |||
| 664 | for (i = 0; i < 2; i++) { | ||
| 665 | unsigned int reg; | ||
| 666 | pci_read_config_dword(dev, 0x1BC + i * 4, ®); | ||
| 667 | ret += sprintf(buf, "%sEntry: %d\n", buf, i); | ||
| 668 | ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n", | ||
| 669 | buf, | ||
| 670 | reg & 0x80000000 ? "Disabled" : "Allowed", | ||
| 671 | reg & 0x40000000 ? "Disabled" : "Allowed"); | ||
| 672 | ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n", buf, | ||
| 673 | (reg & 0x30000) >> 16, reg & 0xfff); | ||
| 674 | 664 | ||
| 675 | } | 665 | if (!this_leaf->can_disable) |
| 676 | return ret; | 666 | return sprintf(buf, "Feature not enabled\n"); |
| 667 | |||
| 668 | for (i = 0; i < 2; i++) { | ||
| 669 | unsigned int reg; | ||
| 670 | |||
| 671 | pci_read_config_dword(dev, 0x1BC + i * 4, ®); | ||
| 672 | |||
| 673 | ret += sprintf(buf, "%sEntry: %d\n", buf, i); | ||
| 674 | ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n", | ||
| 675 | buf, | ||
| 676 | reg & 0x80000000 ? "Disabled" : "Allowed", | ||
| 677 | reg & 0x40000000 ? "Disabled" : "Allowed"); | ||
| 678 | ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n", | ||
| 679 | buf, (reg & 0x30000) >> 16, reg & 0xfff); | ||
| 677 | } | 680 | } |
| 678 | return sprintf(buf, "Feature not enabled\n"); | 681 | return ret; |
| 679 | } | 682 | } |
| 680 | 683 | ||
| 681 | static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count) | 684 | static ssize_t |
| 685 | store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, | ||
| 686 | size_t count) | ||
| 682 | { | 687 | { |
| 683 | struct pci_dev *dev; | 688 | int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); |
| 684 | if (this_leaf->can_disable) { | 689 | struct pci_dev *dev = k8_northbridges[node]; |
| 685 | /* write the MSR value */ | 690 | unsigned int ret, index, val; |
| 686 | unsigned int ret; | 691 | |
| 687 | unsigned int index, val; | 692 | if (!this_leaf->can_disable) |
| 688 | int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); | 693 | return 0; |
| 689 | dev = k8_northbridges[node]; | 694 | |
| 690 | 695 | /* write the MSR value */ | |
| 691 | if (strlen(buf) > 15) | 696 | |
| 692 | return -EINVAL; | 697 | if (strlen(buf) > 15) |
| 693 | ret = sscanf(buf, "%x %x", &index, &val); | 698 | return -EINVAL; |
| 694 | if (ret != 2) | 699 | |
| 695 | return -EINVAL; | 700 | ret = sscanf(buf, "%x %x", &index, &val); |
| 696 | if (index > 1) | 701 | if (ret != 2) |
| 697 | return -EINVAL; | 702 | return -EINVAL; |
| 698 | val |= 0xc0000000; | 703 | if (index > 1) |
| 699 | pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); | 704 | return -EINVAL; |
| 700 | wbinvd(); | 705 | |
| 701 | pci_write_config_dword(dev, 0x1BC + index * 4, val); | 706 | val |= 0xc0000000; |
| 702 | return 1; | 707 | pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000); |
| 703 | } | 708 | wbinvd(); |
| 704 | return 0; | 709 | pci_write_config_dword(dev, 0x1BC + index * 4, val); |
| 710 | |||
| 711 | return 1; | ||
| 705 | } | 712 | } |
| 706 | 713 | ||
| 707 | struct _cache_attr { | 714 | struct _cache_attr { |
