diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2012-08-29 08:12:20 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-09-26 09:45:03 -0400 |
commit | 6668022c7bde3fdc96d3d257294a7216c7a46829 (patch) | |
tree | 796f5d9eb8d1acc5541c22cd06a674fee1442d95 /arch/s390 | |
parent | d35339a42dd1f53b0bb86cf75418a9b7cf5f0f30 (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.h | 6 | ||||
-rw-r--r-- | arch/s390/kernel/cache.c | 46 | ||||
-rw-r--r-- | arch/s390/kernel/processor.c | 1 |
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; | |||
140 | struct mm_struct; | 140 | struct mm_struct; |
141 | struct seq_file; | 141 | struct seq_file; |
142 | 142 | ||
143 | #ifdef CONFIG_64BIT | ||
144 | extern void show_cacheinfo(struct seq_file *m); | ||
145 | #else | ||
146 | static 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. */ |
144 | extern void release_thread(struct task_struct *); | 150 | extern void release_thread(struct task_struct *); |
145 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 151 | extern 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[] = { | |||
83 | static struct cache_dir *cache_dir_cpu[NR_CPUS]; | 85 | static struct cache_dir *cache_dir_cpu[NR_CPUS]; |
84 | static LIST_HEAD(cache_list); | 86 | static LIST_HEAD(cache_list); |
85 | 87 | ||
88 | void 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 | |||
86 | static inline unsigned long ecag(int ai, int li, int ti) | 106 | static 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 | ||
96 | static int __init cache_add(int level, int type) | 116 | static 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); | |||
208 | DEFINE_CACHE_ATTR(coherency_line_size, "%u\n", index->cache->line_size); | 232 | DEFINE_CACHE_ATTR(coherency_line_size, "%u\n", index->cache->line_size); |
209 | DEFINE_CACHE_ATTR(number_of_sets, "%u\n", index->cache->nr_sets); | 233 | DEFINE_CACHE_ATTR(number_of_sets, "%u\n", index->cache->nr_sets); |
210 | DEFINE_CACHE_ATTR(ways_of_associativity, "%u\n", index->cache->associativity); | 234 | DEFINE_CACHE_ATTR(ways_of_associativity, "%u\n", index->cache->associativity); |
211 | DEFINE_CACHE_ATTR(type, "%s\n", cache_type_string[index->cache->type - 1]); | 235 | DEFINE_CACHE_ATTR(type, "%s\n", cache_type_string[index->cache->type]); |
212 | DEFINE_CACHE_ATTR(level, "%d\n", index->cache->level); | 236 | DEFINE_CACHE_ATTR(level, "%d\n", index->cache->level); |
213 | 237 | ||
214 | static ssize_t shared_cpu_map_func(struct kobject *kobj, int type, char *buf) | 238 | static 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)) { |