1 | /* |
2 | * debugfs ops for the L1 cache |
3 | * |
4 | * Copyright (C) 2006 Paul Mundt |
5 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public |
7 | * License. See the file "COPYING" in the main directory of this archive |
8 | * for more details. |
9 | */ |
10 | #include <linux/init.h> |
11 | #include <linux/module.h> |
12 | #include <linux/debugfs.h> |
13 | #include <linux/seq_file.h> |
14 | #include <asm/processor.h> |
15 | #include <linux/uaccess.h> |
16 | #include <asm/cache.h> |
17 | #include <asm/io.h> |
18 | |
19 | enum cache_type { |
20 | CACHE_TYPE_ICACHE, |
21 | CACHE_TYPE_DCACHE, |
22 | CACHE_TYPE_UNIFIED, |
23 | }; |
24 | |
25 | static int cache_debugfs_show(struct seq_file *file, void *iter) |
26 | { |
27 | unsigned int cache_type = (unsigned int)file->private; |
28 | struct cache_info *cache; |
29 | unsigned int waysize, way; |
30 | unsigned long ccr; |
31 | unsigned long addrstart = 0; |
32 | |
33 | /* |
34 | * Go uncached immediately so we don't skew the results any |
35 | * more than we already are.. |
36 | */ |
37 | jump_to_uncached(); |
38 | |
39 | ccr = __raw_readl(addr: SH_CCR); |
40 | if ((ccr & CCR_CACHE_ENABLE) == 0) { |
41 | back_to_cached(); |
42 | |
43 | seq_printf(m: file, fmt: "disabled\n" ); |
44 | return 0; |
45 | } |
46 | |
47 | if (cache_type == CACHE_TYPE_DCACHE) { |
48 | addrstart = CACHE_OC_ADDRESS_ARRAY; |
49 | cache = ¤t_cpu_data.dcache; |
50 | } else { |
51 | addrstart = CACHE_IC_ADDRESS_ARRAY; |
52 | cache = ¤t_cpu_data.icache; |
53 | } |
54 | |
55 | waysize = cache->sets; |
56 | |
57 | /* |
58 | * If the OC is already in RAM mode, we only have |
59 | * half of the entries to consider.. |
60 | */ |
61 | if ((ccr & CCR_CACHE_ORA) && cache_type == CACHE_TYPE_DCACHE) |
62 | waysize >>= 1; |
63 | |
64 | waysize <<= cache->entry_shift; |
65 | |
66 | for (way = 0; way < cache->ways; way++) { |
67 | unsigned long addr; |
68 | unsigned int line; |
69 | |
70 | seq_printf(m: file, fmt: "-----------------------------------------\n" ); |
71 | seq_printf(m: file, fmt: "Way %d\n" , way); |
72 | seq_printf(m: file, fmt: "-----------------------------------------\n" ); |
73 | |
74 | for (addr = addrstart, line = 0; |
75 | addr < addrstart + waysize; |
76 | addr += cache->linesz, line++) { |
77 | unsigned long data = __raw_readl(addr); |
78 | |
79 | /* Check the V bit, ignore invalid cachelines */ |
80 | if ((data & 1) == 0) |
81 | continue; |
82 | |
83 | /* U: Dirty, cache tag is 10 bits up */ |
84 | seq_printf(m: file, fmt: "%3d: %c 0x%lx\n" , |
85 | line, data & 2 ? 'U' : ' ', |
86 | data & 0x1ffffc00); |
87 | } |
88 | |
89 | addrstart += cache->way_incr; |
90 | } |
91 | |
92 | back_to_cached(); |
93 | |
94 | return 0; |
95 | } |
96 | |
97 | DEFINE_SHOW_ATTRIBUTE(cache_debugfs); |
98 | |
99 | static int __init cache_debugfs_init(void) |
100 | { |
101 | debugfs_create_file(name: "dcache" , S_IRUSR, parent: arch_debugfs_dir, |
102 | data: (void *)CACHE_TYPE_DCACHE, fops: &cache_debugfs_fops); |
103 | debugfs_create_file(name: "icache" , S_IRUSR, parent: arch_debugfs_dir, |
104 | data: (void *)CACHE_TYPE_ICACHE, fops: &cache_debugfs_fops); |
105 | return 0; |
106 | } |
107 | module_init(cache_debugfs_init); |
108 | |
109 | MODULE_LICENSE("GPL v2" ); |
110 | |