2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Dump R4x00 TLB for debugging purposes.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
|
|
|
|
* Copyright (C) 1999 by Silicon Graphics, Inc.
|
|
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
|
2015-05-19 16:50:32 +08:00
|
|
|
#include <asm/hazards.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <asm/mipsregs.h>
|
|
|
|
#include <asm/page.h>
|
|
|
|
#include <asm/pgtable.h>
|
2007-07-11 23:51:00 +08:00
|
|
|
#include <asm/tlbdebug.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2015-07-15 23:17:43 +08:00
|
|
|
void dump_tlb_regs(void)
|
|
|
|
{
|
|
|
|
const int field = 2 * sizeof(unsigned long);
|
|
|
|
|
|
|
|
pr_info("Index : %0x\n", read_c0_index());
|
|
|
|
pr_info("PageMask : %0x\n", read_c0_pagemask());
|
2016-05-11 22:50:32 +08:00
|
|
|
if (cpu_has_guestid)
|
|
|
|
pr_info("GuestCtl1: %0x\n", read_c0_guestctl1());
|
2015-07-15 23:17:43 +08:00
|
|
|
pr_info("EntryHi : %0*lx\n", field, read_c0_entryhi());
|
|
|
|
pr_info("EntryLo0 : %0*lx\n", field, read_c0_entrylo0());
|
|
|
|
pr_info("EntryLo1 : %0*lx\n", field, read_c0_entrylo1());
|
|
|
|
pr_info("Wired : %0x\n", read_c0_wired());
|
2015-07-15 23:17:46 +08:00
|
|
|
switch (current_cpu_type()) {
|
|
|
|
case CPU_R10000:
|
|
|
|
case CPU_R12000:
|
|
|
|
case CPU_R14000:
|
|
|
|
case CPU_R16000:
|
|
|
|
pr_info("FrameMask: %0x\n", read_c0_framemask());
|
|
|
|
break;
|
|
|
|
}
|
2015-07-15 23:17:45 +08:00
|
|
|
if (cpu_has_small_pages || cpu_has_rixi || cpu_has_xpa)
|
|
|
|
pr_info("PageGrain: %0x\n", read_c0_pagegrain());
|
2015-07-15 23:17:43 +08:00
|
|
|
if (cpu_has_htw) {
|
|
|
|
pr_info("PWField : %0*lx\n", field, read_c0_pwfield());
|
|
|
|
pr_info("PWSize : %0*lx\n", field, read_c0_pwsize());
|
|
|
|
pr_info("PWCtl : %0x\n", read_c0_pwctl());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static inline const char *msk2str(unsigned int mask)
|
|
|
|
{
|
|
|
|
switch (mask) {
|
|
|
|
case PM_4K: return "4kb";
|
|
|
|
case PM_16K: return "16kb";
|
|
|
|
case PM_64K: return "64kb";
|
|
|
|
case PM_256K: return "256kb";
|
2009-04-02 20:07:10 +08:00
|
|
|
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
|
|
|
case PM_8K: return "8kb";
|
|
|
|
case PM_32K: return "32kb";
|
|
|
|
case PM_128K: return "128kb";
|
|
|
|
case PM_512K: return "512kb";
|
|
|
|
case PM_2M: return "2Mb";
|
|
|
|
case PM_8M: return "8Mb";
|
|
|
|
case PM_32M: return "32Mb";
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
#ifndef CONFIG_CPU_VR41XX
|
|
|
|
case PM_1M: return "1Mb";
|
|
|
|
case PM_4M: return "4Mb";
|
|
|
|
case PM_16M: return "16Mb";
|
|
|
|
case PM_64M: return "64Mb";
|
|
|
|
case PM_256M: return "256Mb";
|
2008-10-24 00:27:57 +08:00
|
|
|
case PM_1G: return "1Gb";
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
|
|
|
}
|
2007-06-01 23:21:30 +08:00
|
|
|
return "";
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2007-06-01 23:30:25 +08:00
|
|
|
static void dump_tlb(int first, int last)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-06-01 23:21:30 +08:00
|
|
|
unsigned long s_entryhi, entryhi, asid;
|
MIPS: dump_tlb: Take RI/XI bits into account
The RI/XI bits when present are above the PFN field in the EntryLo
registers, at bits 63,62 when read with dmfc0, and bits 31,30 when read
with mfc0. This makes them appear as part of the physical address, since
the other bits are masked with PAGE_MASK, for example:
Index: 253 pgmask=16kb va=77b18000 asid=75
[pa=1000744000 c=5 d=1 v=1 g=0] [pa=100134c000 c=5 d=1 v=1 g=0]
The physical addresses have bit 36 set, which corresponds to bit 30 of
EntryLo1, the XI bit.
Explicitly mask off the RI and XI bits from the printed physical
address, and print the RI and XI bits separately if they exist, giving
output more like this:
Index: 226 pgmask=16kb va=77be0000 asid=79
[ri=0 xi=1 pa=01288000 c=5 d=1 v=1 g=0] [ri=0 xi=0 pa=010e4000 c=5 d=0 v=1 g=0]
Cc: linux-mips@linux-mips.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: David Daney <ddaney@caviumnetworks.com>
Patchwork: https://patchwork.linux-mips.org/patch/10080/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2015-05-19 16:50:37 +08:00
|
|
|
unsigned long long entrylo0, entrylo1, pa;
|
2016-05-11 22:50:31 +08:00
|
|
|
unsigned int s_index, s_pagemask, s_guestctl1 = 0;
|
|
|
|
unsigned int pagemask, guestctl1 = 0, c0, c1, i;
|
2016-05-06 21:36:23 +08:00
|
|
|
unsigned long asidmask = cpu_asid_mask(¤t_cpu_data);
|
|
|
|
int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4);
|
2015-05-19 16:50:33 +08:00
|
|
|
#ifdef CONFIG_32BIT
|
2015-05-19 16:50:38 +08:00
|
|
|
bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA);
|
|
|
|
int pwidth = xpa ? 11 : 8;
|
|
|
|
int vwidth = 8;
|
2015-05-19 16:50:33 +08:00
|
|
|
#else
|
2015-05-19 16:50:38 +08:00
|
|
|
bool xpa = false;
|
|
|
|
int pwidth = 11;
|
|
|
|
int vwidth = 11;
|
2015-05-19 16:50:33 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-10-17 07:01:20 +08:00
|
|
|
s_pagemask = read_c0_pagemask();
|
2005-04-17 06:20:36 +08:00
|
|
|
s_entryhi = read_c0_entryhi();
|
|
|
|
s_index = read_c0_index();
|
2016-05-06 21:36:23 +08:00
|
|
|
asid = s_entryhi & asidmask;
|
2016-05-11 22:50:31 +08:00
|
|
|
if (cpu_has_guestid)
|
|
|
|
s_guestctl1 = read_c0_guestctl1();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
for (i = first; i <= last; i++) {
|
|
|
|
write_c0_index(i);
|
2015-05-19 16:50:32 +08:00
|
|
|
mtc0_tlbr_hazard();
|
2005-04-17 06:20:36 +08:00
|
|
|
tlb_read();
|
2015-05-19 16:50:32 +08:00
|
|
|
tlb_read_hazard();
|
2005-04-17 06:20:36 +08:00
|
|
|
pagemask = read_c0_pagemask();
|
2013-01-22 19:59:30 +08:00
|
|
|
entryhi = read_c0_entryhi();
|
2005-04-17 06:20:36 +08:00
|
|
|
entrylo0 = read_c0_entrylo0();
|
|
|
|
entrylo1 = read_c0_entrylo1();
|
2016-05-11 22:50:31 +08:00
|
|
|
if (cpu_has_guestid)
|
|
|
|
guestctl1 = read_c0_guestctl1();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2015-05-19 16:50:36 +08:00
|
|
|
/* EHINV bit marks entire entry as invalid */
|
|
|
|
if (cpu_has_tlbinv && entryhi & MIPS_ENTRYHI_EHINV)
|
|
|
|
continue;
|
2015-05-19 16:50:33 +08:00
|
|
|
/*
|
|
|
|
* Prior to tlbinv, unused entries have a virtual address of
|
|
|
|
* CKSEG0.
|
|
|
|
*/
|
|
|
|
if ((entryhi & ~0x1ffffUL) == CKSEG0)
|
|
|
|
continue;
|
2015-05-19 16:50:35 +08:00
|
|
|
/*
|
|
|
|
* ASID takes effect in absence of G (global) bit.
|
|
|
|
* We check both G bits, even though architecturally they should
|
|
|
|
* match one another, because some revisions of the SB1 core may
|
|
|
|
* leave only a single G bit set after a machine check exception
|
|
|
|
* due to duplicate TLB entry.
|
|
|
|
*/
|
2015-07-15 23:17:47 +08:00
|
|
|
if (!((entrylo0 | entrylo1) & ENTRYLO_G) &&
|
2016-05-06 21:36:23 +08:00
|
|
|
(entryhi & asidmask) != asid)
|
2015-05-19 16:50:33 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Only print entries in use
|
|
|
|
*/
|
|
|
|
printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2015-07-15 23:17:47 +08:00
|
|
|
c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
|
|
|
|
c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-05-11 22:50:31 +08:00
|
|
|
printk("va=%0*lx asid=%0*lx",
|
2015-05-19 16:50:38 +08:00
|
|
|
vwidth, (entryhi & ~0x1fffUL),
|
2016-05-06 21:36:23 +08:00
|
|
|
asidwidth, entryhi & asidmask);
|
2016-05-11 22:50:31 +08:00
|
|
|
if (cpu_has_guestid)
|
|
|
|
printk(" gid=%02lx",
|
|
|
|
(guestctl1 & MIPS_GCTL1_RID)
|
|
|
|
>> MIPS_GCTL1_RID_SHIFT);
|
MIPS: dump_tlb: Take RI/XI bits into account
The RI/XI bits when present are above the PFN field in the EntryLo
registers, at bits 63,62 when read with dmfc0, and bits 31,30 when read
with mfc0. This makes them appear as part of the physical address, since
the other bits are masked with PAGE_MASK, for example:
Index: 253 pgmask=16kb va=77b18000 asid=75
[pa=1000744000 c=5 d=1 v=1 g=0] [pa=100134c000 c=5 d=1 v=1 g=0]
The physical addresses have bit 36 set, which corresponds to bit 30 of
EntryLo1, the XI bit.
Explicitly mask off the RI and XI bits from the printed physical
address, and print the RI and XI bits separately if they exist, giving
output more like this:
Index: 226 pgmask=16kb va=77be0000 asid=79
[ri=0 xi=1 pa=01288000 c=5 d=1 v=1 g=0] [ri=0 xi=0 pa=010e4000 c=5 d=0 v=1 g=0]
Cc: linux-mips@linux-mips.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: David Daney <ddaney@caviumnetworks.com>
Patchwork: https://patchwork.linux-mips.org/patch/10080/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2015-05-19 16:50:37 +08:00
|
|
|
/* RI/XI are in awkward places, so mask them off separately */
|
|
|
|
pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
|
2015-05-19 16:50:38 +08:00
|
|
|
if (xpa)
|
|
|
|
pa |= (unsigned long long)readx_c0_entrylo0() << 30;
|
MIPS: dump_tlb: Take RI/XI bits into account
The RI/XI bits when present are above the PFN field in the EntryLo
registers, at bits 63,62 when read with dmfc0, and bits 31,30 when read
with mfc0. This makes them appear as part of the physical address, since
the other bits are masked with PAGE_MASK, for example:
Index: 253 pgmask=16kb va=77b18000 asid=75
[pa=1000744000 c=5 d=1 v=1 g=0] [pa=100134c000 c=5 d=1 v=1 g=0]
The physical addresses have bit 36 set, which corresponds to bit 30 of
EntryLo1, the XI bit.
Explicitly mask off the RI and XI bits from the printed physical
address, and print the RI and XI bits separately if they exist, giving
output more like this:
Index: 226 pgmask=16kb va=77be0000 asid=79
[ri=0 xi=1 pa=01288000 c=5 d=1 v=1 g=0] [ri=0 xi=0 pa=010e4000 c=5 d=0 v=1 g=0]
Cc: linux-mips@linux-mips.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: David Daney <ddaney@caviumnetworks.com>
Patchwork: https://patchwork.linux-mips.org/patch/10080/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2015-05-19 16:50:37 +08:00
|
|
|
pa = (pa << 6) & PAGE_MASK;
|
2016-05-11 22:50:31 +08:00
|
|
|
printk("\n\t[");
|
MIPS: dump_tlb: Take RI/XI bits into account
The RI/XI bits when present are above the PFN field in the EntryLo
registers, at bits 63,62 when read with dmfc0, and bits 31,30 when read
with mfc0. This makes them appear as part of the physical address, since
the other bits are masked with PAGE_MASK, for example:
Index: 253 pgmask=16kb va=77b18000 asid=75
[pa=1000744000 c=5 d=1 v=1 g=0] [pa=100134c000 c=5 d=1 v=1 g=0]
The physical addresses have bit 36 set, which corresponds to bit 30 of
EntryLo1, the XI bit.
Explicitly mask off the RI and XI bits from the printed physical
address, and print the RI and XI bits separately if they exist, giving
output more like this:
Index: 226 pgmask=16kb va=77be0000 asid=79
[ri=0 xi=1 pa=01288000 c=5 d=1 v=1 g=0] [ri=0 xi=0 pa=010e4000 c=5 d=0 v=1 g=0]
Cc: linux-mips@linux-mips.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: David Daney <ddaney@caviumnetworks.com>
Patchwork: https://patchwork.linux-mips.org/patch/10080/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2015-05-19 16:50:37 +08:00
|
|
|
if (cpu_has_rixi)
|
|
|
|
printk("ri=%d xi=%d ",
|
|
|
|
(entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0,
|
|
|
|
(entrylo0 & MIPS_ENTRYLO_XI) ? 1 : 0);
|
|
|
|
printk("pa=%0*llx c=%d d=%d v=%d g=%d] [",
|
2015-05-19 16:50:38 +08:00
|
|
|
pwidth, pa, c0,
|
2015-07-15 23:17:47 +08:00
|
|
|
(entrylo0 & ENTRYLO_D) ? 1 : 0,
|
|
|
|
(entrylo0 & ENTRYLO_V) ? 1 : 0,
|
|
|
|
(entrylo0 & ENTRYLO_G) ? 1 : 0);
|
MIPS: dump_tlb: Take RI/XI bits into account
The RI/XI bits when present are above the PFN field in the EntryLo
registers, at bits 63,62 when read with dmfc0, and bits 31,30 when read
with mfc0. This makes them appear as part of the physical address, since
the other bits are masked with PAGE_MASK, for example:
Index: 253 pgmask=16kb va=77b18000 asid=75
[pa=1000744000 c=5 d=1 v=1 g=0] [pa=100134c000 c=5 d=1 v=1 g=0]
The physical addresses have bit 36 set, which corresponds to bit 30 of
EntryLo1, the XI bit.
Explicitly mask off the RI and XI bits from the printed physical
address, and print the RI and XI bits separately if they exist, giving
output more like this:
Index: 226 pgmask=16kb va=77be0000 asid=79
[ri=0 xi=1 pa=01288000 c=5 d=1 v=1 g=0] [ri=0 xi=0 pa=010e4000 c=5 d=0 v=1 g=0]
Cc: linux-mips@linux-mips.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: David Daney <ddaney@caviumnetworks.com>
Patchwork: https://patchwork.linux-mips.org/patch/10080/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2015-05-19 16:50:37 +08:00
|
|
|
/* RI/XI are in awkward places, so mask them off separately */
|
|
|
|
pa = entrylo1 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
|
2015-05-19 16:50:38 +08:00
|
|
|
if (xpa)
|
|
|
|
pa |= (unsigned long long)readx_c0_entrylo1() << 30;
|
MIPS: dump_tlb: Take RI/XI bits into account
The RI/XI bits when present are above the PFN field in the EntryLo
registers, at bits 63,62 when read with dmfc0, and bits 31,30 when read
with mfc0. This makes them appear as part of the physical address, since
the other bits are masked with PAGE_MASK, for example:
Index: 253 pgmask=16kb va=77b18000 asid=75
[pa=1000744000 c=5 d=1 v=1 g=0] [pa=100134c000 c=5 d=1 v=1 g=0]
The physical addresses have bit 36 set, which corresponds to bit 30 of
EntryLo1, the XI bit.
Explicitly mask off the RI and XI bits from the printed physical
address, and print the RI and XI bits separately if they exist, giving
output more like this:
Index: 226 pgmask=16kb va=77be0000 asid=79
[ri=0 xi=1 pa=01288000 c=5 d=1 v=1 g=0] [ri=0 xi=0 pa=010e4000 c=5 d=0 v=1 g=0]
Cc: linux-mips@linux-mips.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: David Daney <ddaney@caviumnetworks.com>
Patchwork: https://patchwork.linux-mips.org/patch/10080/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2015-05-19 16:50:37 +08:00
|
|
|
pa = (pa << 6) & PAGE_MASK;
|
|
|
|
if (cpu_has_rixi)
|
|
|
|
printk("ri=%d xi=%d ",
|
|
|
|
(entrylo1 & MIPS_ENTRYLO_RI) ? 1 : 0,
|
|
|
|
(entrylo1 & MIPS_ENTRYLO_XI) ? 1 : 0);
|
|
|
|
printk("pa=%0*llx c=%d d=%d v=%d g=%d]\n",
|
2015-05-19 16:50:38 +08:00
|
|
|
pwidth, pa, c1,
|
2015-07-15 23:17:47 +08:00
|
|
|
(entrylo1 & ENTRYLO_D) ? 1 : 0,
|
|
|
|
(entrylo1 & ENTRYLO_V) ? 1 : 0,
|
|
|
|
(entrylo1 & ENTRYLO_G) ? 1 : 0);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
printk("\n");
|
|
|
|
|
|
|
|
write_c0_entryhi(s_entryhi);
|
|
|
|
write_c0_index(s_index);
|
2012-10-17 07:01:20 +08:00
|
|
|
write_c0_pagemask(s_pagemask);
|
2016-05-11 22:50:31 +08:00
|
|
|
if (cpu_has_guestid)
|
|
|
|
write_c0_guestctl1(s_guestctl1);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void dump_tlb_all(void)
|
|
|
|
{
|
|
|
|
dump_tlb(0, current_cpu_data.tlbsize - 1);
|
|
|
|
}
|