diff options
Diffstat (limited to 'arch/x86/kernel/cpu/intel_cacheinfo.c')
-rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 83 |
1 files changed, 66 insertions, 17 deletions
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 7283e98deaae..1ce1af2899df 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -45,6 +45,7 @@ static const struct _cache_table __cpuinitconst cache_table[] = | |||
45 | { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */ | 45 | { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */ |
46 | { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */ | 46 | { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */ |
47 | { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */ | 47 | { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */ |
48 | { 0x0e, LVL_1_DATA, 24 }, /* 6-way set assoc, 64 byte line size */ | ||
48 | { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */ | 49 | { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */ |
49 | { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ | 50 | { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ |
50 | { 0x23, LVL_3, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 51 | { 0x23, LVL_3, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */ |
@@ -66,6 +67,7 @@ static const struct _cache_table __cpuinitconst cache_table[] = | |||
66 | { 0x45, LVL_2, MB(2) }, /* 4-way set assoc, 32 byte line size */ | 67 | { 0x45, LVL_2, MB(2) }, /* 4-way set assoc, 32 byte line size */ |
67 | { 0x46, LVL_3, MB(4) }, /* 4-way set assoc, 64 byte line size */ | 68 | { 0x46, LVL_3, MB(4) }, /* 4-way set assoc, 64 byte line size */ |
68 | { 0x47, LVL_3, MB(8) }, /* 8-way set assoc, 64 byte line size */ | 69 | { 0x47, LVL_3, MB(8) }, /* 8-way set assoc, 64 byte line size */ |
70 | { 0x48, LVL_2, MB(3) }, /* 12-way set assoc, 64 byte line size */ | ||
69 | { 0x49, LVL_3, MB(4) }, /* 16-way set assoc, 64 byte line size */ | 71 | { 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 */ | 72 | { 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 */ | 73 | { 0x4b, LVL_3, MB(8) }, /* 16-way set assoc, 64 byte line size */ |
@@ -87,6 +89,7 @@ static const struct _cache_table __cpuinitconst cache_table[] = | |||
87 | { 0x7c, LVL_2, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */ | 89 | { 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 */ | 90 | { 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 */ | 91 | { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */ |
92 | { 0x80, LVL_2, 512 }, /* 8-way set assoc, 64 byte line size */ | ||
90 | { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */ | 93 | { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */ |
91 | { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */ | 94 | { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */ |
92 | { 0x84, LVL_2, MB(1) }, /* 8-way set assoc, 32 byte line size */ | 95 | { 0x84, LVL_2, MB(1) }, /* 8-way set assoc, 32 byte line size */ |
@@ -301,8 +304,9 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, | |||
301 | 304 | ||
302 | struct _cache_attr { | 305 | struct _cache_attr { |
303 | struct attribute attr; | 306 | struct attribute attr; |
304 | ssize_t (*show)(struct _cpuid4_info *, char *); | 307 | ssize_t (*show)(struct _cpuid4_info *, char *, unsigned int); |
305 | ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count); | 308 | ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count, |
309 | unsigned int); | ||
306 | }; | 310 | }; |
307 | 311 | ||
308 | #ifdef CONFIG_AMD_NB | 312 | #ifdef CONFIG_AMD_NB |
@@ -397,7 +401,8 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | |||
397 | 401 | ||
398 | #define SHOW_CACHE_DISABLE(slot) \ | 402 | #define SHOW_CACHE_DISABLE(slot) \ |
399 | static ssize_t \ | 403 | static ssize_t \ |
400 | show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf) \ | 404 | show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf, \ |
405 | unsigned int cpu) \ | ||
401 | { \ | 406 | { \ |
402 | return show_cache_disable(this_leaf, buf, slot); \ | 407 | return show_cache_disable(this_leaf, buf, slot); \ |
403 | } | 408 | } |
@@ -509,7 +514,8 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
509 | #define STORE_CACHE_DISABLE(slot) \ | 514 | #define STORE_CACHE_DISABLE(slot) \ |
510 | static ssize_t \ | 515 | static ssize_t \ |
511 | store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \ | 516 | store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \ |
512 | const char *buf, size_t count) \ | 517 | const char *buf, size_t count, \ |
518 | unsigned int cpu) \ | ||
513 | { \ | 519 | { \ |
514 | return store_cache_disable(this_leaf, buf, count, slot); \ | 520 | return store_cache_disable(this_leaf, buf, count, slot); \ |
515 | } | 521 | } |
@@ -521,6 +527,39 @@ static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644, | |||
521 | static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, | 527 | static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, |
522 | show_cache_disable_1, store_cache_disable_1); | 528 | show_cache_disable_1, store_cache_disable_1); |
523 | 529 | ||
530 | static ssize_t | ||
531 | show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu) | ||
532 | { | ||
533 | if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) | ||
534 | return -EINVAL; | ||
535 | |||
536 | return sprintf(buf, "%x\n", amd_get_subcaches(cpu)); | ||
537 | } | ||
538 | |||
539 | static ssize_t | ||
540 | store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count, | ||
541 | unsigned int cpu) | ||
542 | { | ||
543 | unsigned long val; | ||
544 | |||
545 | if (!capable(CAP_SYS_ADMIN)) | ||
546 | return -EPERM; | ||
547 | |||
548 | if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) | ||
549 | return -EINVAL; | ||
550 | |||
551 | if (strict_strtoul(buf, 16, &val) < 0) | ||
552 | return -EINVAL; | ||
553 | |||
554 | if (amd_set_subcaches(cpu, val)) | ||
555 | return -EINVAL; | ||
556 | |||
557 | return count; | ||
558 | } | ||
559 | |||
560 | static struct _cache_attr subcaches = | ||
561 | __ATTR(subcaches, 0644, show_subcaches, store_subcaches); | ||
562 | |||
524 | #else /* CONFIG_AMD_NB */ | 563 | #else /* CONFIG_AMD_NB */ |
525 | #define amd_init_l3_cache(x, y) | 564 | #define amd_init_l3_cache(x, y) |
526 | #endif /* CONFIG_AMD_NB */ | 565 | #endif /* CONFIG_AMD_NB */ |
@@ -529,9 +568,9 @@ static int | |||
529 | __cpuinit cpuid4_cache_lookup_regs(int index, | 568 | __cpuinit cpuid4_cache_lookup_regs(int index, |
530 | struct _cpuid4_info_regs *this_leaf) | 569 | struct _cpuid4_info_regs *this_leaf) |
531 | { | 570 | { |
532 | union _cpuid4_leaf_eax eax; | 571 | union _cpuid4_leaf_eax eax; |
533 | union _cpuid4_leaf_ebx ebx; | 572 | union _cpuid4_leaf_ebx ebx; |
534 | union _cpuid4_leaf_ecx ecx; | 573 | union _cpuid4_leaf_ecx ecx; |
535 | unsigned edx; | 574 | unsigned edx; |
536 | 575 | ||
537 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { | 576 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { |
@@ -729,11 +768,11 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) | |||
729 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 768 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
730 | 769 | ||
731 | if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) { | 770 | if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) { |
732 | for_each_cpu(i, c->llc_shared_map) { | 771 | for_each_cpu(i, cpu_llc_shared_mask(cpu)) { |
733 | if (!per_cpu(ici_cpuid4_info, i)) | 772 | if (!per_cpu(ici_cpuid4_info, i)) |
734 | continue; | 773 | continue; |
735 | this_leaf = CPUID4_INFO_IDX(i, index); | 774 | this_leaf = CPUID4_INFO_IDX(i, index); |
736 | for_each_cpu(sibling, c->llc_shared_map) { | 775 | for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) { |
737 | if (!cpu_online(sibling)) | 776 | if (!cpu_online(sibling)) |
738 | continue; | 777 | continue; |
739 | set_bit(sibling, this_leaf->shared_cpu_map); | 778 | set_bit(sibling, this_leaf->shared_cpu_map); |
@@ -867,8 +906,8 @@ static DEFINE_PER_CPU(struct _index_kobject *, ici_index_kobject); | |||
867 | #define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(ici_index_kobject, x))[y])) | 906 | #define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(ici_index_kobject, x))[y])) |
868 | 907 | ||
869 | #define show_one_plus(file_name, object, val) \ | 908 | #define show_one_plus(file_name, object, val) \ |
870 | static ssize_t show_##file_name \ | 909 | static ssize_t show_##file_name(struct _cpuid4_info *this_leaf, char *buf, \ |
871 | (struct _cpuid4_info *this_leaf, char *buf) \ | 910 | unsigned int cpu) \ |
872 | { \ | 911 | { \ |
873 | return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \ | 912 | return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \ |
874 | } | 913 | } |
@@ -879,7 +918,8 @@ show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1); | |||
879 | show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1); | 918 | show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1); |
880 | show_one_plus(number_of_sets, ecx.split.number_of_sets, 1); | 919 | show_one_plus(number_of_sets, ecx.split.number_of_sets, 1); |
881 | 920 | ||
882 | static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf) | 921 | static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf, |
922 | unsigned int cpu) | ||
883 | { | 923 | { |
884 | return sprintf(buf, "%luK\n", this_leaf->size / 1024); | 924 | return sprintf(buf, "%luK\n", this_leaf->size / 1024); |
885 | } | 925 | } |
@@ -903,17 +943,20 @@ static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf, | |||
903 | return n; | 943 | return n; |
904 | } | 944 | } |
905 | 945 | ||
906 | static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf) | 946 | static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf, |
947 | unsigned int cpu) | ||
907 | { | 948 | { |
908 | return show_shared_cpu_map_func(leaf, 0, buf); | 949 | return show_shared_cpu_map_func(leaf, 0, buf); |
909 | } | 950 | } |
910 | 951 | ||
911 | static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf) | 952 | static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf, |
953 | unsigned int cpu) | ||
912 | { | 954 | { |
913 | return show_shared_cpu_map_func(leaf, 1, buf); | 955 | return show_shared_cpu_map_func(leaf, 1, buf); |
914 | } | 956 | } |
915 | 957 | ||
916 | static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) | 958 | static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf, |
959 | unsigned int cpu) | ||
917 | { | 960 | { |
918 | switch (this_leaf->eax.split.type) { | 961 | switch (this_leaf->eax.split.type) { |
919 | case CACHE_TYPE_DATA: | 962 | case CACHE_TYPE_DATA: |
@@ -971,6 +1014,9 @@ static struct attribute ** __cpuinit amd_l3_attrs(void) | |||
971 | if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | 1014 | if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) |
972 | n += 2; | 1015 | n += 2; |
973 | 1016 | ||
1017 | if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) | ||
1018 | n += 1; | ||
1019 | |||
974 | attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL); | 1020 | attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL); |
975 | if (attrs == NULL) | 1021 | if (attrs == NULL) |
976 | return attrs = default_attrs; | 1022 | return attrs = default_attrs; |
@@ -983,6 +1029,9 @@ static struct attribute ** __cpuinit amd_l3_attrs(void) | |||
983 | attrs[n++] = &cache_disable_1.attr; | 1029 | attrs[n++] = &cache_disable_1.attr; |
984 | } | 1030 | } |
985 | 1031 | ||
1032 | if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) | ||
1033 | attrs[n++] = &subcaches.attr; | ||
1034 | |||
986 | return attrs; | 1035 | return attrs; |
987 | } | 1036 | } |
988 | #endif | 1037 | #endif |
@@ -995,7 +1044,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) | |||
995 | 1044 | ||
996 | ret = fattr->show ? | 1045 | ret = fattr->show ? |
997 | fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), | 1046 | fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), |
998 | buf) : | 1047 | buf, this_leaf->cpu) : |
999 | 0; | 1048 | 0; |
1000 | return ret; | 1049 | return ret; |
1001 | } | 1050 | } |
@@ -1009,7 +1058,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, | |||
1009 | 1058 | ||
1010 | ret = fattr->store ? | 1059 | ret = fattr->store ? |
1011 | fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), | 1060 | fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), |
1012 | buf, count) : | 1061 | buf, count, this_leaf->cpu) : |
1013 | 0; | 1062 | 0; |
1014 | return ret; | 1063 | return ret; |
1015 | } | 1064 | } |