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_seq_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(SH_CCR); 40 if ((ccr & CCR_CACHE_ENABLE) == 0) { 41 back_to_cached(); 42 43 seq_printf(file, "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(file, "-----------------------------------------\n"); 71 seq_printf(file, "Way %d\n", way); 72 seq_printf(file, "-----------------------------------------\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(file, "%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 static int cache_debugfs_open(struct inode *inode, struct file *file) 98 { 99 return single_open(file, cache_seq_show, inode->i_private); 100 } 101 102 static const struct file_operations cache_debugfs_fops = { 103 .owner = THIS_MODULE, 104 .open = cache_debugfs_open, 105 .read = seq_read, 106 .llseek = seq_lseek, 107 .release = single_release, 108 }; 109 110 static int __init cache_debugfs_init(void) 111 { 112 struct dentry *dcache_dentry, *icache_dentry; 113 114 dcache_dentry = debugfs_create_file("dcache", S_IRUSR, arch_debugfs_dir, 115 (unsigned int *)CACHE_TYPE_DCACHE, 116 &cache_debugfs_fops); 117 if (!dcache_dentry) 118 return -ENOMEM; 119 120 icache_dentry = debugfs_create_file("icache", S_IRUSR, arch_debugfs_dir, 121 (unsigned int *)CACHE_TYPE_ICACHE, 122 &cache_debugfs_fops); 123 if (!icache_dentry) { 124 debugfs_remove(dcache_dentry); 125 return -ENOMEM; 126 } 127 128 return 0; 129 } 130 module_init(cache_debugfs_init); 131 132 MODULE_LICENSE("GPL v2"); 133