diff options
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap2-git/beagleboard/cache-display-fix.patch')
-rw-r--r-- | meta/recipes-kernel/linux/linux-omap2-git/beagleboard/cache-display-fix.patch | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/cache-display-fix.patch b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/cache-display-fix.patch new file mode 100644 index 0000000000..c96b95f2f4 --- /dev/null +++ b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/cache-display-fix.patch | |||
@@ -0,0 +1,238 @@ | |||
1 | On Tue, 2008-07-01 at 06:23 +0100, Dirk Behme wrote: | ||
2 | > Catalin Marinas wrote: | ||
3 | > > But, anyway, if you want a patch, Harry is updating it to a recent | ||
4 | > > kernel. | ||
5 | > | ||
6 | > Any news on this? I think there are some people wanting a patch ;) | ||
7 | |||
8 | See below for a preliminary patch updated to 2.6.26-rc8. Note that I | ||
9 | don't plan to submit it in its current form but clean it up a bit first. | ||
10 | |||
11 | |||
12 | Show the cache type of ARMv7 CPUs | ||
13 | |||
14 | From: Catalin Marinas <catalin.marinas@arm.com> | ||
15 | |||
16 | Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> | ||
17 | --- | ||
18 | |||
19 | arch/arm/kernel/setup.c | 137 +++++++++++++++++++++++++++++++++++++++++++++- | ||
20 | include/asm-arm/system.h | 18 ++++++ | ||
21 | 2 files changed, 153 insertions(+), 2 deletions(-) | ||
22 | |||
23 | |||
24 | diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c | ||
25 | index 5ae0eb2..0cd238d 100644 | ||
26 | --- a/arch/arm/kernel/setup.c | ||
27 | +++ b/arch/arm/kernel/setup.c | ||
28 | @@ -256,6 +256,24 @@ static const char *proc_arch[] = { | ||
29 | "?(17)", | ||
30 | }; | ||
31 | |||
32 | +static const char *v7_cache_policy[4] = { | ||
33 | + "reserved", | ||
34 | + "AVIVT", | ||
35 | + "VIPT", | ||
36 | + "PIPT", | ||
37 | +}; | ||
38 | + | ||
39 | +static const char *v7_cache_type[8] = { | ||
40 | + "none", | ||
41 | + "instruction only", | ||
42 | + "data only", | ||
43 | + "separate instruction and data", | ||
44 | + "unified", | ||
45 | + "unknown type", | ||
46 | + "unknown type", | ||
47 | + "unknown type", | ||
48 | +}; | ||
49 | + | ||
50 | #define CACHE_TYPE(x) (((x) >> 25) & 15) | ||
51 | #define CACHE_S(x) ((x) & (1 << 24)) | ||
52 | #define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */ | ||
53 | @@ -266,6 +284,22 @@ static const char *proc_arch[] = { | ||
54 | #define CACHE_M(y) ((y) & (1 << 2)) | ||
55 | #define CACHE_LINE(y) ((y) & 3) | ||
56 | |||
57 | +#define CACHE_TYPE_V7(x) (((x) >> 14) & 3) | ||
58 | +#define CACHE_UNIFIED(x) ((((x) >> 27) & 7)+1) | ||
59 | +#define CACHE_COHERENT(x) ((((x) >> 24) & 7)+1) | ||
60 | + | ||
61 | +#define CACHE_ID_LEVEL_MASK 7 | ||
62 | +#define CACHE_ID_LEVEL_BITS 3 | ||
63 | + | ||
64 | +#define CACHE_LINE_V7(v) ((1 << (((v) & 7)+4))) | ||
65 | +#define CACHE_ASSOC_V7(v) ((((v) >> 3) & ((1<<10)-1))+1) | ||
66 | +#define CACHE_SETS_V7(v) ((((v) >> 13) & ((1<<15)-1))+1) | ||
67 | +#define CACHE_SIZE_V7(v) (CACHE_LINE_V7(v)*CACHE_ASSOC_V7(v)*CACHE_SETS_V7(v)) | ||
68 | +#define CACHE_WA_V7(v) (((v) & (1<<28)) != 0) | ||
69 | +#define CACHE_RA_V7(v) (((v) & (1<<29)) != 0) | ||
70 | +#define CACHE_WB_V7(v) (((v) & (1<<30)) != 0) | ||
71 | +#define CACHE_WT_V7(v) (((v) & (1<<31)) != 0) | ||
72 | + | ||
73 | static inline void dump_cache(const char *prefix, int cpu, unsigned int cache) | ||
74 | { | ||
75 | unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0); | ||
76 | @@ -279,11 +313,57 @@ static inline void dump_cache(const char *prefix, int cpu, unsigned int cache) | ||
77 | CACHE_LINE(cache))); | ||
78 | } | ||
79 | |||
80 | +static void dump_v7_cache(const char *type, int cpu, unsigned int level) | ||
81 | +{ | ||
82 | + unsigned int cachesize; | ||
83 | + | ||
84 | + write_extended_cpuid(2,0,0,0,level); /* Set the cache size selection register */ | ||
85 | + write_extended_cpuid(0,7,5,4,0); /* Prefetch flush to wait for above */ | ||
86 | + cachesize = read_extended_cpuid(1,0,0,0); | ||
87 | + | ||
88 | + printk("CPU%u: %s cache: %d bytes, associativity %d, %d byte lines, %d sets,\n supports%s%s%s%s\n", | ||
89 | + cpu, type, | ||
90 | + CACHE_SIZE_V7(cachesize),CACHE_ASSOC_V7(cachesize), | ||
91 | + CACHE_LINE_V7(cachesize),CACHE_SETS_V7(cachesize), | ||
92 | + CACHE_WA_V7(cachesize) ? " WA" : "", | ||
93 | + CACHE_RA_V7(cachesize) ? " RA" : "", | ||
94 | + CACHE_WB_V7(cachesize) ? " WB" : "", | ||
95 | + CACHE_WT_V7(cachesize) ? " WT" : ""); | ||
96 | +} | ||
97 | + | ||
98 | static void __init dump_cpu_info(int cpu) | ||
99 | { | ||
100 | unsigned int info = read_cpuid(CPUID_CACHETYPE); | ||
101 | |||
102 | - if (info != processor_id) { | ||
103 | + if (info != processor_id && (info & (1 << 31))) { | ||
104 | + /* ARMv7 style of cache info register */ | ||
105 | + unsigned int id = read_extended_cpuid(1,0,0,1); | ||
106 | + unsigned int level = 0; | ||
107 | + printk("CPU%u: L1 I %s cache. Caches unified at level %u, coherent at level %u\n", | ||
108 | + cpu, | ||
109 | + v7_cache_policy[CACHE_TYPE_V7(info)], | ||
110 | + CACHE_UNIFIED(id), | ||
111 | + CACHE_COHERENT(id)); | ||
112 | + | ||
113 | + while (id & CACHE_ID_LEVEL_MASK) { | ||
114 | + printk("CPU%u: Level %u cache is %s\n", | ||
115 | + cpu, (level >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]); | ||
116 | + | ||
117 | + if (id & 1) { | ||
118 | + /* Dump I at this level */ | ||
119 | + dump_v7_cache("I", cpu, level | 1); | ||
120 | + } | ||
121 | + | ||
122 | + if (id & (4 | 2)) { | ||
123 | + /* Dump D or unified at this level */ | ||
124 | + dump_v7_cache((id & 4) ? "unified" : "D", cpu, level); | ||
125 | + } | ||
126 | + | ||
127 | + /* Next level out */ | ||
128 | + level += 2; | ||
129 | + id >>= CACHE_ID_LEVEL_BITS; | ||
130 | + } | ||
131 | + } else if (info != processor_id) { | ||
132 | printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT", | ||
133 | cache_types[CACHE_TYPE(info)]); | ||
134 | if (CACHE_S(info)) { | ||
135 | @@ -916,6 +996,30 @@ c_show_cache(struct seq_file *m, const char *type, unsigned int cache) | ||
136 | CACHE_LINE(cache))); | ||
137 | } | ||
138 | |||
139 | +static void c_show_v7_cache(struct seq_file *m, const char *type, unsigned int levelselect) | ||
140 | +{ | ||
141 | + unsigned int cachesize; | ||
142 | + unsigned int level = (levelselect >> 1) + 1; | ||
143 | + | ||
144 | + write_extended_cpuid(2,0,0,0,levelselect); /* Set the cache size selection register */ | ||
145 | + write_extended_cpuid(0,7,5,4,0); /* Prefetch flush to wait for above */ | ||
146 | + cachesize = read_extended_cpuid(1,0,0,0); | ||
147 | + | ||
148 | + seq_printf(m, "L%u %s size\t\t: %d bytes\n" | ||
149 | + "L%u %s assoc\t\t: %d\n" | ||
150 | + "L%u %s line length\t: %d\n" | ||
151 | + "L%u %s sets\t\t: %d\n" | ||
152 | + "L%u %s supports\t\t:%s%s%s%s\n", | ||
153 | + level, type, CACHE_SIZE_V7(cachesize), | ||
154 | + level, type, CACHE_ASSOC_V7(cachesize), | ||
155 | + level, type, CACHE_LINE_V7(cachesize), | ||
156 | + level, type, CACHE_SETS_V7(cachesize), | ||
157 | + level, type, CACHE_WA_V7(cachesize) ? " WA" : "", | ||
158 | + CACHE_RA_V7(cachesize) ? " RA" : "", | ||
159 | + CACHE_WB_V7(cachesize) ? " WB" : "", | ||
160 | + CACHE_WT_V7(cachesize) ? " WT" : ""); | ||
161 | +} | ||
162 | + | ||
163 | static int c_show(struct seq_file *m, void *v) | ||
164 | { | ||
165 | int i; | ||
166 | @@ -971,7 +1075,36 @@ static int c_show(struct seq_file *m, void *v) | ||
167 | |||
168 | { | ||
169 | unsigned int cache_info = read_cpuid(CPUID_CACHETYPE); | ||
170 | - if (cache_info != processor_id) { | ||
171 | + if (cache_info != processor_id && (cache_info & (1<<31))) { | ||
172 | + /* V7 style of cache info register */ | ||
173 | + unsigned int id = read_extended_cpuid(1,0,0,1); | ||
174 | + unsigned int levelselect = 0; | ||
175 | + seq_printf(m, "L1 I cache\t:%s\n" | ||
176 | + "Cache unification level\t: %u\n" | ||
177 | + "Cache coherency level\t: %u\n", | ||
178 | + v7_cache_policy[CACHE_TYPE_V7(cache_info)], | ||
179 | + CACHE_UNIFIED(id), | ||
180 | + CACHE_COHERENT(id)); | ||
181 | + | ||
182 | + while (id & CACHE_ID_LEVEL_MASK) { | ||
183 | + seq_printf(m, "Level %u cache\t\t: %s\n", | ||
184 | + (levelselect >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]); | ||
185 | + | ||
186 | + if (id & 1) { | ||
187 | + /* Dump I at this level */ | ||
188 | + c_show_v7_cache(m, "I", levelselect | 1); | ||
189 | + } | ||
190 | + | ||
191 | + if (id & (4 | 2)) { | ||
192 | + /* Dump D or unified at this level */ | ||
193 | + c_show_v7_cache(m, (id & 4) ? "cache" : "D", levelselect); | ||
194 | + } | ||
195 | + | ||
196 | + /* Next level out */ | ||
197 | + levelselect += 2; | ||
198 | + id >>= CACHE_ID_LEVEL_BITS; | ||
199 | + } | ||
200 | + } else if (cache_info != processor_id) { | ||
201 | seq_printf(m, "Cache type\t: %s\n" | ||
202 | "Cache clean\t: %s\n" | ||
203 | "Cache lockdown\t: %s\n" | ||
204 | diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h | ||
205 | index 514af79..704738e 100644 | ||
206 | --- a/include/asm-arm/system.h | ||
207 | +++ b/include/asm-arm/system.h | ||
208 | @@ -74,6 +74,24 @@ | ||
209 | : "cc"); \ | ||
210 | __val; \ | ||
211 | }) | ||
212 | +#define read_extended_cpuid(op1,op2,op3,op4) \ | ||
213 | + ({ \ | ||
214 | + unsigned int __val; \ | ||
215 | + asm("mrc p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4) \ | ||
216 | + : "=r" (__val) \ | ||
217 | + : \ | ||
218 | + : "cc"); \ | ||
219 | + __val; \ | ||
220 | + }) | ||
221 | + | ||
222 | +#define write_extended_cpuid(op1,op2,op3,op4,v) \ | ||
223 | + ({ \ | ||
224 | + unsigned int __val = v; \ | ||
225 | + asm("mcr p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4) \ | ||
226 | + : \ | ||
227 | + : "r" (__val) \ | ||
228 | + : "cc"); \ | ||
229 | + }) | ||
230 | #else | ||
231 | extern unsigned int processor_id; | ||
232 | #define read_cpuid(reg) (processor_id) | ||
233 | |||
234 | |||
235 | -- | ||
236 | Catalin | ||
237 | |||
238 | |||