r3k_dump_tlb.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Dump R3000 TLB for debugging purposes.
  3. *
  4. * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
  5. * Copyright (C) 1999 by Silicon Graphics, Inc.
  6. * Copyright (C) 1999 by Harald Koerfgen
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/mm.h>
  10. #include <linux/sched.h>
  11. #include <linux/string.h>
  12. #include <asm/bootinfo.h>
  13. #include <asm/cachectl.h>
  14. #include <asm/cpu.h>
  15. #include <asm/mipsregs.h>
  16. #include <asm/page.h>
  17. #include <asm/pgtable.h>
  18. extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
  19. void dump_tlb(int first, int last)
  20. {
  21. int i;
  22. unsigned int asid;
  23. unsigned long entryhi, entrylo0;
  24. asid = read_c0_entryhi() & 0xfc0;
  25. for (i = first; i <= last; i++) {
  26. write_c0_index(i<<8);
  27. __asm__ __volatile__(
  28. ".set\tnoreorder\n\t"
  29. "tlbr\n\t"
  30. "nop\n\t"
  31. ".set\treorder");
  32. entryhi = read_c0_entryhi();
  33. entrylo0 = read_c0_entrylo0();
  34. /* Unused entries have a virtual address of KSEG0. */
  35. if ((entryhi & 0xffffe000) != 0x80000000
  36. && (entryhi & 0xfc0) == asid) {
  37. /*
  38. * Only print entries in use
  39. */
  40. printk("Index: %2d ", i);
  41. printk("va=%08lx asid=%08lx"
  42. " [pa=%06lx n=%d d=%d v=%d g=%d]",
  43. (entryhi & 0xffffe000),
  44. entryhi & 0xfc0,
  45. entrylo0 & PAGE_MASK,
  46. (entrylo0 & (1 << 11)) ? 1 : 0,
  47. (entrylo0 & (1 << 10)) ? 1 : 0,
  48. (entrylo0 & (1 << 9)) ? 1 : 0,
  49. (entrylo0 & (1 << 8)) ? 1 : 0);
  50. }
  51. }
  52. printk("\n");
  53. write_c0_entryhi(asid);
  54. }
  55. void dump_tlb_all(void)
  56. {
  57. dump_tlb(0, current_cpu_data.tlbsize - 1);
  58. }
  59. void dump_tlb_wired(void)
  60. {
  61. int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
  62. printk("Wired: %d", wired);
  63. dump_tlb(0, wired - 1);
  64. }
  65. void dump_tlb_addr(unsigned long addr)
  66. {
  67. unsigned long flags, oldpid;
  68. int index;
  69. local_irq_save(flags);
  70. oldpid = read_c0_entryhi() & 0xff;
  71. write_c0_entryhi((addr & PAGE_MASK) | oldpid);
  72. tlb_probe();
  73. index = read_c0_index();
  74. write_c0_entryhi(oldpid);
  75. local_irq_restore(flags);
  76. if (index < 0) {
  77. printk("No entry for address 0x%08lx in TLB\n", addr);
  78. return;
  79. }
  80. printk("Entry %d maps address 0x%08lx\n", index, addr);
  81. dump_tlb(index, index);
  82. }
  83. void dump_tlb_nonwired(void)
  84. {
  85. int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
  86. dump_tlb(wired, current_cpu_data.tlbsize - 1);
  87. }
  88. void dump_list_process(struct task_struct *t, void *address)
  89. {
  90. pgd_t *page_dir, *pgd;
  91. pmd_t *pmd;
  92. pte_t *pte, page;
  93. unsigned int addr;
  94. unsigned long val;
  95. addr = (unsigned int) address;
  96. printk("Addr == %08x\n", addr);
  97. printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
  98. page_dir = pgd_offset(t->mm, 0);
  99. printk("page_dir == %08x\n", (unsigned int) page_dir);
  100. pgd = pgd_offset(t->mm, addr);
  101. printk("pgd == %08x, ", (unsigned int) pgd);
  102. pmd = pmd_offset(pgd, addr);
  103. printk("pmd == %08x, ", (unsigned int) pmd);
  104. pte = pte_offset(pmd, addr);
  105. printk("pte == %08x, ", (unsigned int) pte);
  106. page = *pte;
  107. printk("page == %08x\n", (unsigned int) pte_val(page));
  108. val = pte_val(page);
  109. if (val & _PAGE_PRESENT) printk("present ");
  110. if (val & _PAGE_READ) printk("read ");
  111. if (val & _PAGE_WRITE) printk("write ");
  112. if (val & _PAGE_ACCESSED) printk("accessed ");
  113. if (val & _PAGE_MODIFIED) printk("modified ");
  114. if (val & _PAGE_GLOBAL) printk("global ");
  115. if (val & _PAGE_VALID) printk("valid ");
  116. printk("\n");
  117. }
  118. void dump_list_current(void *address)
  119. {
  120. dump_list_process(current, address);
  121. }
  122. unsigned int vtop(void *address)
  123. {
  124. pgd_t *pgd;
  125. pmd_t *pmd;
  126. pte_t *pte;
  127. unsigned int addr, paddr;
  128. addr = (unsigned long) address;
  129. pgd = pgd_offset(current->mm, addr);
  130. pmd = pmd_offset(pgd, addr);
  131. pte = pte_offset(pmd, addr);
  132. paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
  133. paddr |= (addr & ~PAGE_MASK);
  134. return paddr;
  135. }
  136. void dump16(unsigned long *p)
  137. {
  138. int i;
  139. for (i = 0; i < 8; i++) {
  140. printk("*%08lx == %08lx, ", (unsigned long)p, *p);
  141. p++;
  142. printk("*%08lx == %08lx\n", (unsigned long)p, *p);
  143. p++;
  144. }
  145. }