0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/mm.h>
0010
0011 #include <asm/hazards.h>
0012 #include <asm/mipsregs.h>
0013 #include <asm/mmu_context.h>
0014 #include <asm/page.h>
0015 #include <asm/tlbdebug.h>
0016
0017 void dump_tlb_regs(void)
0018 {
0019 const int field = 2 * sizeof(unsigned long);
0020
0021 pr_info("Index : %0x\n", read_c0_index());
0022 pr_info("PageMask : %0x\n", read_c0_pagemask());
0023 if (cpu_has_guestid)
0024 pr_info("GuestCtl1: %0x\n", read_c0_guestctl1());
0025 pr_info("EntryHi : %0*lx\n", field, read_c0_entryhi());
0026 pr_info("EntryLo0 : %0*lx\n", field, read_c0_entrylo0());
0027 pr_info("EntryLo1 : %0*lx\n", field, read_c0_entrylo1());
0028 pr_info("Wired : %0x\n", read_c0_wired());
0029 switch (current_cpu_type()) {
0030 case CPU_R10000:
0031 case CPU_R12000:
0032 case CPU_R14000:
0033 case CPU_R16000:
0034 pr_info("FrameMask: %0x\n", read_c0_framemask());
0035 break;
0036 }
0037 if (cpu_has_small_pages || cpu_has_rixi || cpu_has_xpa)
0038 pr_info("PageGrain: %0x\n", read_c0_pagegrain());
0039 if (cpu_has_htw) {
0040 pr_info("PWField : %0*lx\n", field, read_c0_pwfield());
0041 pr_info("PWSize : %0*lx\n", field, read_c0_pwsize());
0042 pr_info("PWCtl : %0x\n", read_c0_pwctl());
0043 }
0044 }
0045
0046 static inline const char *msk2str(unsigned int mask)
0047 {
0048 switch (mask) {
0049 case PM_4K: return "4kb";
0050 case PM_16K: return "16kb";
0051 case PM_64K: return "64kb";
0052 case PM_256K: return "256kb";
0053 #ifdef CONFIG_CPU_CAVIUM_OCTEON
0054 case PM_8K: return "8kb";
0055 case PM_32K: return "32kb";
0056 case PM_128K: return "128kb";
0057 case PM_512K: return "512kb";
0058 case PM_2M: return "2Mb";
0059 case PM_8M: return "8Mb";
0060 case PM_32M: return "32Mb";
0061 #endif
0062 }
0063 return "";
0064 }
0065
0066 static void dump_tlb(int first, int last)
0067 {
0068 unsigned long s_entryhi, entryhi, asid, mmid;
0069 unsigned long long entrylo0, entrylo1, pa;
0070 unsigned int s_index, s_pagemask, s_guestctl1 = 0;
0071 unsigned int pagemask, guestctl1 = 0, c0, c1, i;
0072 unsigned long asidmask = cpu_asid_mask(¤t_cpu_data);
0073 int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4);
0074 unsigned long s_mmid;
0075 #ifdef CONFIG_32BIT
0076 bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA);
0077 int pwidth = xpa ? 11 : 8;
0078 int vwidth = 8;
0079 #else
0080 bool xpa = false;
0081 int pwidth = 11;
0082 int vwidth = 11;
0083 #endif
0084
0085 s_pagemask = read_c0_pagemask();
0086 s_entryhi = read_c0_entryhi();
0087 s_index = read_c0_index();
0088
0089 if (cpu_has_mmid)
0090 asid = s_mmid = read_c0_memorymapid();
0091 else
0092 asid = s_entryhi & asidmask;
0093
0094 if (cpu_has_guestid)
0095 s_guestctl1 = read_c0_guestctl1();
0096
0097 for (i = first; i <= last; i++) {
0098 write_c0_index(i);
0099 mtc0_tlbr_hazard();
0100 tlb_read();
0101 tlb_read_hazard();
0102 pagemask = read_c0_pagemask();
0103 entryhi = read_c0_entryhi();
0104 entrylo0 = read_c0_entrylo0();
0105 entrylo1 = read_c0_entrylo1();
0106
0107 if (cpu_has_mmid)
0108 mmid = read_c0_memorymapid();
0109 else
0110 mmid = entryhi & asidmask;
0111
0112 if (cpu_has_guestid)
0113 guestctl1 = read_c0_guestctl1();
0114
0115
0116 if (cpu_has_tlbinv && entryhi & MIPS_ENTRYHI_EHINV)
0117 continue;
0118
0119
0120
0121
0122 if ((entryhi & ~0x1ffffUL) == CKSEG0)
0123 continue;
0124
0125
0126
0127
0128
0129
0130
0131 if (!((entrylo0 | entrylo1) & ENTRYLO_G) && (mmid != asid))
0132 continue;
0133
0134
0135
0136
0137 printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
0138
0139 c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
0140 c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
0141
0142 pr_cont("va=%0*lx asid=%0*lx",
0143 vwidth, (entryhi & ~0x1fffUL),
0144 asidwidth, mmid);
0145 if (cpu_has_guestid)
0146 pr_cont(" gid=%02lx",
0147 (guestctl1 & MIPS_GCTL1_RID)
0148 >> MIPS_GCTL1_RID_SHIFT);
0149
0150 pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
0151 if (xpa)
0152 pa |= (unsigned long long)readx_c0_entrylo0() << 30;
0153 pa = (pa << 6) & PAGE_MASK;
0154 pr_cont("\n\t[");
0155 if (cpu_has_rixi)
0156 pr_cont("ri=%d xi=%d ",
0157 (entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0,
0158 (entrylo0 & MIPS_ENTRYLO_XI) ? 1 : 0);
0159 pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d] [",
0160 pwidth, pa, c0,
0161 (entrylo0 & ENTRYLO_D) ? 1 : 0,
0162 (entrylo0 & ENTRYLO_V) ? 1 : 0,
0163 (entrylo0 & ENTRYLO_G) ? 1 : 0);
0164
0165 pa = entrylo1 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
0166 if (xpa)
0167 pa |= (unsigned long long)readx_c0_entrylo1() << 30;
0168 pa = (pa << 6) & PAGE_MASK;
0169 if (cpu_has_rixi)
0170 pr_cont("ri=%d xi=%d ",
0171 (entrylo1 & MIPS_ENTRYLO_RI) ? 1 : 0,
0172 (entrylo1 & MIPS_ENTRYLO_XI) ? 1 : 0);
0173 pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d]\n",
0174 pwidth, pa, c1,
0175 (entrylo1 & ENTRYLO_D) ? 1 : 0,
0176 (entrylo1 & ENTRYLO_V) ? 1 : 0,
0177 (entrylo1 & ENTRYLO_G) ? 1 : 0);
0178 }
0179 printk("\n");
0180
0181 write_c0_entryhi(s_entryhi);
0182 write_c0_index(s_index);
0183 write_c0_pagemask(s_pagemask);
0184 if (cpu_has_guestid)
0185 write_c0_guestctl1(s_guestctl1);
0186 }
0187
0188 void dump_tlb_all(void)
0189 {
0190 dump_tlb(0, current_cpu_data.tlbsize - 1);
0191 }