2006-09-27 17:51:01 +09:00
/*
* debugfs ops for the L1 cache
*
* Copyright ( C ) 2006 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
# include <linux/init.h>
# include <linux/module.h>
# include <linux/debugfs.h>
# include <linux/seq_file.h>
# include <asm/processor.h>
# include <asm/uaccess.h>
# include <asm/cache.h>
# include <asm/io.h>
enum cache_type {
CACHE_TYPE_ICACHE ,
CACHE_TYPE_DCACHE ,
CACHE_TYPE_UNIFIED ,
} ;
2010-01-21 16:05:25 +09:00
static int cache_seq_show ( struct seq_file * file , void * iter )
2006-09-27 17:51:01 +09:00
{
unsigned int cache_type = ( unsigned int ) file - > private ;
struct cache_info * cache ;
2011-06-02 10:30:44 +00:00
unsigned int waysize , way ;
unsigned long ccr ;
unsigned long addrstart = 0 ;
2006-09-27 17:51:01 +09:00
/*
* Go uncached immediately so we don ' t skew the results any
* more than we already are . .
*/
2007-11-30 17:06:36 +09:00
jump_to_uncached ( ) ;
2006-09-27 17:51:01 +09:00
2014-03-03 15:38:33 -08:00
ccr = __raw_readl ( SH_CCR ) ;
2006-09-27 17:51:01 +09:00
if ( ( ccr & CCR_CACHE_ENABLE ) = = 0 ) {
2007-11-30 17:06:36 +09:00
back_to_cached ( ) ;
2006-09-27 17:51:01 +09:00
seq_printf ( file , " disabled \n " ) ;
return 0 ;
}
if ( cache_type = = CACHE_TYPE_DCACHE ) {
2011-06-02 10:30:44 +00:00
addrstart = CACHE_OC_ADDRESS_ARRAY ;
2006-12-25 10:19:56 +09:00
cache = & current_cpu_data . dcache ;
2006-09-27 17:51:01 +09:00
} else {
2011-06-02 10:30:44 +00:00
addrstart = CACHE_IC_ADDRESS_ARRAY ;
2006-12-25 10:19:56 +09:00
cache = & current_cpu_data . icache ;
2006-09-27 17:51:01 +09:00
}
waysize = cache - > sets ;
/*
* If the OC is already in RAM mode , we only have
* half of the entries to consider . .
*/
if ( ( ccr & CCR_CACHE_ORA ) & & cache_type = = CACHE_TYPE_DCACHE )
waysize > > = 1 ;
waysize < < = cache - > entry_shift ;
for ( way = 0 ; way < cache - > ways ; way + + ) {
unsigned long addr ;
unsigned int line ;
seq_printf ( file , " ----------------------------------------- \n " ) ;
seq_printf ( file , " Way %d \n " , way ) ;
seq_printf ( file , " ----------------------------------------- \n " ) ;
for ( addr = addrstart , line = 0 ;
addr < addrstart + waysize ;
addr + = cache - > linesz , line + + ) {
2010-01-26 12:58:40 +09:00
unsigned long data = __raw_readl ( addr ) ;
2006-09-27 17:51:01 +09:00
/* Check the V bit, ignore invalid cachelines */
if ( ( data & 1 ) = = 0 )
continue ;
/* U: Dirty, cache tag is 10 bits up */
seq_printf ( file , " %3d: %c 0x%lx \n " ,
line , data & 2 ? ' U ' : ' ' ,
data & 0x1ffffc00 ) ;
}
addrstart + = cache - > way_incr ;
}
2007-11-30 17:06:36 +09:00
back_to_cached ( ) ;
2006-09-27 17:51:01 +09:00
return 0 ;
}
static int cache_debugfs_open ( struct inode * inode , struct file * file )
{
2006-10-03 13:14:04 +09:00
return single_open ( file , cache_seq_show , inode - > i_private ) ;
2006-09-27 17:51:01 +09:00
}
2007-02-12 00:55:31 -08:00
static const struct file_operations cache_debugfs_fops = {
2006-09-27 17:51:01 +09:00
. owner = THIS_MODULE ,
. open = cache_debugfs_open ,
. read = seq_read ,
. llseek = seq_lseek ,
2008-06-24 13:30:23 +08:00
. release = single_release ,
2006-09-27 17:51:01 +09:00
} ;
static int __init cache_debugfs_init ( void )
{
struct dentry * dcache_dentry , * icache_dentry ;
2010-09-24 04:04:26 +09:00
dcache_dentry = debugfs_create_file ( " dcache " , S_IRUSR , arch_debugfs_dir ,
2006-09-27 17:51:01 +09:00
( unsigned int * ) CACHE_TYPE_DCACHE ,
& cache_debugfs_fops ) ;
2008-10-17 19:25:09 +08:00
if ( ! dcache_dentry )
return - ENOMEM ;
2006-09-27 17:51:01 +09:00
2010-09-24 04:04:26 +09:00
icache_dentry = debugfs_create_file ( " icache " , S_IRUSR , arch_debugfs_dir ,
2006-09-27 17:51:01 +09:00
( unsigned int * ) CACHE_TYPE_ICACHE ,
& cache_debugfs_fops ) ;
2008-10-17 19:25:09 +08:00
if ( ! icache_dentry ) {
debugfs_remove ( dcache_dentry ) ;
return - ENOMEM ;
}
2006-09-27 17:51:01 +09:00
return 0 ;
}
module_init ( cache_debugfs_init ) ;
MODULE_LICENSE ( " GPL v2 " ) ;