cache-debugfs.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 <asm/uaccess.h>
  16. #include <asm/cache.h>
  17. #include <asm/io.h>
  18. enum cache_type {
  19. CACHE_TYPE_ICACHE,
  20. CACHE_TYPE_DCACHE,
  21. CACHE_TYPE_UNIFIED,
  22. };
  23. static int __uses_jump_to_uncached cache_seq_show(struct seq_file *file,
  24. void *iter)
  25. {
  26. unsigned int cache_type = (unsigned int)file->private;
  27. struct cache_info *cache;
  28. unsigned int waysize, way, cache_size;
  29. unsigned long ccr, base;
  30. static unsigned long addrstart = 0;
  31. /*
  32. * Go uncached immediately so we don't skew the results any
  33. * more than we already are..
  34. */
  35. jump_to_uncached();
  36. ccr = ctrl_inl(CCR);
  37. if ((ccr & CCR_CACHE_ENABLE) == 0) {
  38. back_to_cached();
  39. seq_printf(file, "disabled\n");
  40. return 0;
  41. }
  42. if (cache_type == CACHE_TYPE_DCACHE) {
  43. base = CACHE_OC_ADDRESS_ARRAY;
  44. cache = &current_cpu_data.dcache;
  45. } else {
  46. base = CACHE_IC_ADDRESS_ARRAY;
  47. cache = &current_cpu_data.icache;
  48. }
  49. /*
  50. * Due to the amount of data written out (depending on the cache size),
  51. * we may be iterated over multiple times. In this case, keep track of
  52. * the entry position in addrstart, and rewind it when we've hit the
  53. * end of the cache.
  54. *
  55. * Likewise, the same code is used for multiple caches, so care must
  56. * be taken for bouncing addrstart back and forth so the appropriate
  57. * cache is hit.
  58. */
  59. cache_size = cache->ways * cache->sets * cache->linesz;
  60. if (((addrstart & 0xff000000) != base) ||
  61. (addrstart & 0x00ffffff) > cache_size)
  62. addrstart = base;
  63. waysize = cache->sets;
  64. /*
  65. * If the OC is already in RAM mode, we only have
  66. * half of the entries to consider..
  67. */
  68. if ((ccr & CCR_CACHE_ORA) && cache_type == CACHE_TYPE_DCACHE)
  69. waysize >>= 1;
  70. waysize <<= cache->entry_shift;
  71. for (way = 0; way < cache->ways; way++) {
  72. unsigned long addr;
  73. unsigned int line;
  74. seq_printf(file, "-----------------------------------------\n");
  75. seq_printf(file, "Way %d\n", way);
  76. seq_printf(file, "-----------------------------------------\n");
  77. for (addr = addrstart, line = 0;
  78. addr < addrstart + waysize;
  79. addr += cache->linesz, line++) {
  80. unsigned long data = ctrl_inl(addr);
  81. /* Check the V bit, ignore invalid cachelines */
  82. if ((data & 1) == 0)
  83. continue;
  84. /* U: Dirty, cache tag is 10 bits up */
  85. seq_printf(file, "%3d: %c 0x%lx\n",
  86. line, data & 2 ? 'U' : ' ',
  87. data & 0x1ffffc00);
  88. }
  89. addrstart += cache->way_incr;
  90. }
  91. back_to_cached();
  92. return 0;
  93. }
  94. static int cache_debugfs_open(struct inode *inode, struct file *file)
  95. {
  96. return single_open(file, cache_seq_show, inode->i_private);
  97. }
  98. static const struct file_operations cache_debugfs_fops = {
  99. .owner = THIS_MODULE,
  100. .open = cache_debugfs_open,
  101. .read = seq_read,
  102. .llseek = seq_lseek,
  103. .release = single_release,
  104. };
  105. static int __init cache_debugfs_init(void)
  106. {
  107. struct dentry *dcache_dentry, *icache_dentry;
  108. dcache_dentry = debugfs_create_file("dcache", S_IRUSR, sh_debugfs_root,
  109. (unsigned int *)CACHE_TYPE_DCACHE,
  110. &cache_debugfs_fops);
  111. if (!dcache_dentry)
  112. return -ENOMEM;
  113. if (IS_ERR(dcache_dentry))
  114. return PTR_ERR(dcache_dentry);
  115. icache_dentry = debugfs_create_file("icache", S_IRUSR, sh_debugfs_root,
  116. (unsigned int *)CACHE_TYPE_ICACHE,
  117. &cache_debugfs_fops);
  118. if (!icache_dentry) {
  119. debugfs_remove(dcache_dentry);
  120. return -ENOMEM;
  121. }
  122. if (IS_ERR(icache_dentry)) {
  123. debugfs_remove(dcache_dentry);
  124. return PTR_ERR(icache_dentry);
  125. }
  126. return 0;
  127. }
  128. module_init(cache_debugfs_init);
  129. MODULE_LICENSE("GPL v2");