aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2012-08-29 08:12:20 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-09-26 09:45:03 -0400
commit6668022c7bde3fdc96d3d257294a7216c7a46829 (patch)
tree796f5d9eb8d1acc5541c22cd06a674fee1442d95 /arch/s390
parentd35339a42dd1f53b0bb86cf75418a9b7cf5f0f30 (diff)
s390/cache: add cpu cache information to /proc/cpuinfo
Add a line for each cpu cache to /proc/cpuinfo. Since we only have information of private cpu caches in sysfs we add a line for each cpu cache in /proc/cpuinfo which will also contain information about shared caches. For a z196 machine /proc/cpuinfo now looks like: vendor_id : IBM/S390 bogomips per cpu: 14367.00 features : esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs cache0 : level=1 type=Data scope=Private size=64K line_size=256 associativity=4 cache1 : level=1 type=Instruction scope=Private size=128K line_size=256 associativity=8 cache2 : level=2 type=Unified scope=Private size=1536K line_size=256 associativity=12 cache3 : level=3 type=Unified scope=Shared size=24576K line_size=256 associativity=12 cache4 : level=4 type=Unified scope=Shared size=196608K line_size=256 associativity=24 processor 0: version = FF, identification = 000123, machine = 2817 processor 1: version = FF, identification = 100123, machine = 2817 processor 2: version = FF, identification = 200123, machine = 2817 processor 3: version = FF, identification = 200123, machine = 2817 Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/processor.h6
-rw-r--r--arch/s390/kernel/cache.c46
-rw-r--r--arch/s390/kernel/processor.c1
3 files changed, 43 insertions, 10 deletions
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 46fe1fbf91c5..7e81ff17a89b 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -140,6 +140,12 @@ struct task_struct;
140struct mm_struct; 140struct mm_struct;
141struct seq_file; 141struct seq_file;
142 142
143#ifdef CONFIG_64BIT
144extern void show_cacheinfo(struct seq_file *m);
145#else
146static inline void show_cacheinfo(struct seq_file *m) { }
147#endif
148
143/* Free all resources held by a thread. */ 149/* Free all resources held by a thread. */
144extern void release_thread(struct task_struct *); 150extern void release_thread(struct task_struct *);
145extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 151extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c
index 5e20bab4df22..8df8d8a19c98 100644
--- a/arch/s390/kernel/cache.c
+++ b/arch/s390/kernel/cache.c
@@ -6,6 +6,7 @@
6 */ 6 */
7 7
8#include <linux/notifier.h> 8#include <linux/notifier.h>
9#include <linux/seq_file.h>
9#include <linux/init.h> 10#include <linux/init.h>
10#include <linux/list.h> 11#include <linux/list.h>
11#include <linux/slab.h> 12#include <linux/slab.h>
@@ -17,8 +18,9 @@ struct cache {
17 unsigned int line_size; 18 unsigned int line_size;
18 unsigned int associativity; 19 unsigned int associativity;
19 unsigned int nr_sets; 20 unsigned int nr_sets;
20 int level; 21 unsigned int level : 3;
21 int type; 22 unsigned int type : 2;
23 unsigned int private : 1;
22 struct list_head list; 24 struct list_head list;
23}; 25};
24 26
@@ -83,6 +85,24 @@ static const char * const cache_type_string[] = {
83static struct cache_dir *cache_dir_cpu[NR_CPUS]; 85static struct cache_dir *cache_dir_cpu[NR_CPUS];
84static LIST_HEAD(cache_list); 86static LIST_HEAD(cache_list);
85 87
88void show_cacheinfo(struct seq_file *m)
89{
90 struct cache *cache;
91 int index = 0;
92
93 list_for_each_entry(cache, &cache_list, list) {
94 seq_printf(m, "cache%-11d: ", index);
95 seq_printf(m, "level=%d ", cache->level);
96 seq_printf(m, "type=%s ", cache_type_string[cache->type]);
97 seq_printf(m, "scope=%s ", cache->private ? "Private" : "Shared");
98 seq_printf(m, "size=%luK ", cache->size >> 10);
99 seq_printf(m, "line_size=%u ", cache->line_size);
100 seq_printf(m, "associativity=%d", cache->associativity);
101 seq_puts(m, "\n");
102 index++;
103 }
104}
105
86static inline unsigned long ecag(int ai, int li, int ti) 106static inline unsigned long ecag(int ai, int li, int ti)
87{ 107{
88 unsigned long cmd, val; 108 unsigned long cmd, val;
@@ -93,7 +113,7 @@ static inline unsigned long ecag(int ai, int li, int ti)
93 return val; 113 return val;
94} 114}
95 115
96static int __init cache_add(int level, int type) 116static int __init cache_add(int level, int private, int type)
97{ 117{
98 struct cache *cache; 118 struct cache *cache;
99 int ti; 119 int ti;
@@ -107,8 +127,9 @@ static int __init cache_add(int level, int type)
107 cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti); 127 cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti);
108 cache->nr_sets = cache->size / cache->associativity; 128 cache->nr_sets = cache->size / cache->associativity;
109 cache->nr_sets /= cache->line_size; 129 cache->nr_sets /= cache->line_size;
130 cache->private = private;
110 cache->level = level + 1; 131 cache->level = level + 1;
111 cache->type = type; 132 cache->type = type - 1;
112 list_add_tail(&cache->list, &cache_list); 133 list_add_tail(&cache->list, &cache_list);
113 return 0; 134 return 0;
114} 135}
@@ -117,23 +138,26 @@ static void __init cache_build_info(void)
117{ 138{
118 struct cache *cache, *next; 139 struct cache *cache, *next;
119 union cache_topology ct; 140 union cache_topology ct;
120 int level, rc; 141 int level, private, rc;
121 142
122 ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); 143 ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);
123 for (level = 0; level < CACHE_MAX_LEVEL; level++) { 144 for (level = 0; level < CACHE_MAX_LEVEL; level++) {
124 switch (ct.ci[level].scope) { 145 switch (ct.ci[level].scope) {
125 case CACHE_SCOPE_NOTEXISTS: 146 case CACHE_SCOPE_NOTEXISTS:
126 case CACHE_SCOPE_RESERVED: 147 case CACHE_SCOPE_RESERVED:
127 case CACHE_SCOPE_SHARED:
128 return; 148 return;
149 case CACHE_SCOPE_SHARED:
150 private = 0;
151 break;
129 case CACHE_SCOPE_PRIVATE: 152 case CACHE_SCOPE_PRIVATE:
153 private = 1;
130 break; 154 break;
131 } 155 }
132 if (ct.ci[level].type == CACHE_TYPE_SEPARATE) { 156 if (ct.ci[level].type == CACHE_TYPE_SEPARATE) {
133 rc = cache_add(level, CACHE_TYPE_DATA); 157 rc = cache_add(level, private, CACHE_TYPE_DATA);
134 rc |= cache_add(level, CACHE_TYPE_INSTRUCTION); 158 rc |= cache_add(level, private, CACHE_TYPE_INSTRUCTION);
135 } else { 159 } else {
136 rc = cache_add(level, ct.ci[level].type); 160 rc = cache_add(level, private, ct.ci[level].type);
137 } 161 }
138 if (rc) 162 if (rc)
139 goto error; 163 goto error;
@@ -208,7 +232,7 @@ DEFINE_CACHE_ATTR(size, "%luK\n", index->cache->size >> 10);
208DEFINE_CACHE_ATTR(coherency_line_size, "%u\n", index->cache->line_size); 232DEFINE_CACHE_ATTR(coherency_line_size, "%u\n", index->cache->line_size);
209DEFINE_CACHE_ATTR(number_of_sets, "%u\n", index->cache->nr_sets); 233DEFINE_CACHE_ATTR(number_of_sets, "%u\n", index->cache->nr_sets);
210DEFINE_CACHE_ATTR(ways_of_associativity, "%u\n", index->cache->associativity); 234DEFINE_CACHE_ATTR(ways_of_associativity, "%u\n", index->cache->associativity);
211DEFINE_CACHE_ATTR(type, "%s\n", cache_type_string[index->cache->type - 1]); 235DEFINE_CACHE_ATTR(type, "%s\n", cache_type_string[index->cache->type]);
212DEFINE_CACHE_ATTR(level, "%d\n", index->cache->level); 236DEFINE_CACHE_ATTR(level, "%d\n", index->cache->level);
213 237
214static ssize_t shared_cpu_map_func(struct kobject *kobj, int type, char *buf) 238static ssize_t shared_cpu_map_func(struct kobject *kobj, int type, char *buf)
@@ -298,6 +322,8 @@ static int __cpuinit cache_add_cpu(int cpu)
298 if (!cache_dir) 322 if (!cache_dir)
299 return -ENOMEM; 323 return -ENOMEM;
300 list_for_each_entry(cache, &cache_list, list) { 324 list_for_each_entry(cache, &cache_list, list) {
325 if (!cache->private)
326 break;
301 rc = cache_create_index_dir(cache_dir, cache, index, cpu); 327 rc = cache_create_index_dir(cache_dir, cache, index, cpu);
302 if (rc) 328 if (rc)
303 return rc; 329 return rc;
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 22bf8f0ee093..63f3b76e37a9 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -58,6 +58,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
58 if (hwcap_str[i] && (elf_hwcap & (1UL << i))) 58 if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
59 seq_printf(m, "%s ", hwcap_str[i]); 59 seq_printf(m, "%s ", hwcap_str[i]);
60 seq_puts(m, "\n"); 60 seq_puts(m, "\n");
61 show_cacheinfo(m);
61 } 62 }
62 get_online_cpus(); 63 get_online_cpus();
63 if (cpu_online(n)) { 64 if (cpu_online(n)) {