tlb-debugfs.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * arch/sh/mm/tlb-debugfs.c
  3. *
  4. * debugfs ops for SH-4 ITLB/UTLBs.
  5. *
  6. * Copyright (C) 2010 Matt Fleming
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. */
  12. #include <linux/init.h>
  13. #include <linux/module.h>
  14. #include <linux/debugfs.h>
  15. #include <linux/seq_file.h>
  16. #include <asm/processor.h>
  17. #include <asm/mmu_context.h>
  18. #include <asm/tlbflush.h>
  19. enum tlb_type {
  20. TLB_TYPE_ITLB,
  21. TLB_TYPE_UTLB,
  22. };
  23. static struct {
  24. int bits;
  25. const char *size;
  26. } tlb_sizes[] = {
  27. { 0x0, " 1KB" },
  28. { 0x1, " 4KB" },
  29. { 0x2, " 8KB" },
  30. { 0x4, " 64KB" },
  31. { 0x5, "256KB" },
  32. { 0x7, " 1MB" },
  33. { 0x8, " 4MB" },
  34. { 0xc, " 64MB" },
  35. };
  36. static int tlb_seq_show(struct seq_file *file, void *iter)
  37. {
  38. unsigned int tlb_type = (unsigned int)file->private;
  39. unsigned long addr1, addr2, data1, data2;
  40. unsigned long flags;
  41. unsigned long mmucr;
  42. unsigned int nentries, entry;
  43. unsigned int urb;
  44. mmucr = __raw_readl(MMUCR);
  45. if ((mmucr & 0x1) == 0) {
  46. seq_printf(file, "address translation disabled\n");
  47. return 0;
  48. }
  49. if (tlb_type == TLB_TYPE_ITLB) {
  50. addr1 = MMU_ITLB_ADDRESS_ARRAY;
  51. addr2 = MMU_ITLB_ADDRESS_ARRAY2;
  52. data1 = MMU_ITLB_DATA_ARRAY;
  53. data2 = MMU_ITLB_DATA_ARRAY2;
  54. nentries = 4;
  55. } else {
  56. addr1 = MMU_UTLB_ADDRESS_ARRAY;
  57. addr2 = MMU_UTLB_ADDRESS_ARRAY2;
  58. data1 = MMU_UTLB_DATA_ARRAY;
  59. data2 = MMU_UTLB_DATA_ARRAY2;
  60. nentries = 64;
  61. }
  62. local_irq_save(flags);
  63. jump_to_uncached();
  64. urb = (mmucr & MMUCR_URB) >> MMUCR_URB_SHIFT;
  65. /* Make the "entry >= urb" test fail. */
  66. if (urb == 0)
  67. urb = MMUCR_URB_NENTRIES + 1;
  68. if (tlb_type == TLB_TYPE_ITLB) {
  69. addr1 = MMU_ITLB_ADDRESS_ARRAY;
  70. addr2 = MMU_ITLB_ADDRESS_ARRAY2;
  71. data1 = MMU_ITLB_DATA_ARRAY;
  72. data2 = MMU_ITLB_DATA_ARRAY2;
  73. nentries = 4;
  74. } else {
  75. addr1 = MMU_UTLB_ADDRESS_ARRAY;
  76. addr2 = MMU_UTLB_ADDRESS_ARRAY2;
  77. data1 = MMU_UTLB_DATA_ARRAY;
  78. data2 = MMU_UTLB_DATA_ARRAY2;
  79. nentries = 64;
  80. }
  81. seq_printf(file, "entry: vpn ppn asid size valid wired\n");
  82. for (entry = 0; entry < nentries; entry++) {
  83. unsigned long vpn, ppn, asid, size;
  84. unsigned long valid;
  85. unsigned long val;
  86. const char *sz = " ?";
  87. int i;
  88. val = __raw_readl(addr1 | (entry << MMU_TLB_ENTRY_SHIFT));
  89. ctrl_barrier();
  90. vpn = val & 0xfffffc00;
  91. valid = val & 0x100;
  92. val = __raw_readl(addr2 | (entry << MMU_TLB_ENTRY_SHIFT));
  93. ctrl_barrier();
  94. asid = val & MMU_CONTEXT_ASID_MASK;
  95. val = __raw_readl(data1 | (entry << MMU_TLB_ENTRY_SHIFT));
  96. ctrl_barrier();
  97. ppn = (val & 0x0ffffc00) << 4;
  98. val = __raw_readl(data2 | (entry << MMU_TLB_ENTRY_SHIFT));
  99. ctrl_barrier();
  100. size = (val & 0xf0) >> 4;
  101. for (i = 0; i < ARRAY_SIZE(tlb_sizes); i++) {
  102. if (tlb_sizes[i].bits == size)
  103. break;
  104. }
  105. if (i != ARRAY_SIZE(tlb_sizes))
  106. sz = tlb_sizes[i].size;
  107. seq_printf(file, "%2d: 0x%08lx 0x%08lx %5lu %s %s %s\n",
  108. entry, vpn, ppn, asid,
  109. sz, valid ? "V" : "-",
  110. (urb <= entry) ? "W" : "-");
  111. }
  112. back_to_cached();
  113. local_irq_restore(flags);
  114. return 0;
  115. }
  116. static int tlb_debugfs_open(struct inode *inode, struct file *file)
  117. {
  118. return single_open(file, tlb_seq_show, inode->i_private);
  119. }
  120. static const struct file_operations tlb_debugfs_fops = {
  121. .owner = THIS_MODULE,
  122. .open = tlb_debugfs_open,
  123. .read = seq_read,
  124. .llseek = seq_lseek,
  125. .release = single_release,
  126. };
  127. static int __init tlb_debugfs_init(void)
  128. {
  129. struct dentry *itlb, *utlb;
  130. itlb = debugfs_create_file("itlb", S_IRUSR, arch_debugfs_dir,
  131. (unsigned int *)TLB_TYPE_ITLB,
  132. &tlb_debugfs_fops);
  133. if (unlikely(!itlb))
  134. return -ENOMEM;
  135. utlb = debugfs_create_file("utlb", S_IRUSR, arch_debugfs_dir,
  136. (unsigned int *)TLB_TYPE_UTLB,
  137. &tlb_debugfs_fops);
  138. if (unlikely(!utlb)) {
  139. debugfs_remove(itlb);
  140. return -ENOMEM;
  141. }
  142. return 0;
  143. }
  144. module_init(tlb_debugfs_init);
  145. MODULE_LICENSE("GPL v2");