summaryrefslogtreecommitdiffstats
path: root/arch/mips/lib/dump_tlb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-27 12:44:34 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-27 12:44:34 -0700
commit78c10e556ed904d5bfbd71e9cadd8ce8f25d6982 (patch)
treef73c802d60e81ff9e9fd2465eab096834d0227cd /arch/mips/lib/dump_tlb.c
parentd2c3ac7e7e39ec6d37e4114ae7444948561e59af (diff)
parent9ff897c4e8d5bd05ad7009f84a395596d4953858 (diff)
downloadblackbird-op-linux-78c10e556ed904d5bfbd71e9cadd8ce8f25d6982.tar.gz
blackbird-op-linux-78c10e556ed904d5bfbd71e9cadd8ce8f25d6982.zip
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle: - Improvements to the tlb_dump code - KVM fixes - Add support for appended DTB - Minor improvements to the R12000 support - Minor improvements to the R12000 support - Various platform improvments for BCM47xx - The usual pile of minor cleanups - A number of BPF fixes and improvments - Some improvments to the support for R3000 and DECstations - Some improvments to the ATH79 platform support - A major patchset for the JZ4740 SOC adding support for the CI20 platform - Add support for the Pistachio SOC - Minor BMIPS/BCM63xx platform support improvments. - Avoid "SYNC 0" as memory barrier when unlocking spinlocks - Add support for the XWR-1750 board. - Paul's __cpuinit/__cpuinitdata cleanups. - New Malta CPU board support large memory so enable ZONE_DMA32. * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (131 commits) MIPS: spinlock: Adjust arch_spin_lock back-off time MIPS: asmmacro: Ensure 64-bit FP registers are used with MSA MIPS: BCM47xx: Simplify handling SPROM revisions MIPS: Cobalt Don't use module_init in non-modular MTD registration. MIPS: BCM47xx: Move NVRAM driver to the drivers/firmware/ MIPS: use for_each_sg() MIPS: BCM47xx: Don't select BCMA_HOST_PCI MIPS: BCM47xx: Add helper variable for storing NVRAM length MIPS: IRQ/IP27: Move IRQ allocation API to platform code. MIPS: Replace smp_mb with release barrier function in unlocks. MIPS: i8259: DT support MIPS: Malta: Basic DT plumbing MIPS: include errno.h for ENODEV in mips-cm.h MIPS: Define GCR_GIC_STATUS register fields MIPS: BPF: Introduce BPF ASM helpers MIPS: BPF: Use BPF register names to describe the ABI MIPS: BPF: Move register definition to the BPF header MIPS: net: BPF: Replace RSIZE with SZREG MIPS: BPF: Free up some callee-saved registers MIPS: Xtalk: Update xwidget.h with known Xtalk device numbers ...
Diffstat (limited to 'arch/mips/lib/dump_tlb.c')
-rw-r--r--arch/mips/lib/dump_tlb.c110
1 files changed, 71 insertions, 39 deletions
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
index 32b9f21bfd85..167f35634709 100644
--- a/arch/mips/lib/dump_tlb.c
+++ b/arch/mips/lib/dump_tlb.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <asm/hazards.h>
#include <asm/mipsregs.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -40,17 +41,20 @@ static inline const char *msk2str(unsigned int mask)
return "";
}
-#define BARRIER() \
- __asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- "nop;nop;nop;nop;nop;nop;nop\n\t" \
- ".set\treorder");
-
static void dump_tlb(int first, int last)
{
unsigned long s_entryhi, entryhi, asid;
- unsigned long long entrylo0, entrylo1;
+ unsigned long long entrylo0, entrylo1, pa;
unsigned int s_index, s_pagemask, pagemask, c0, c1, i;
+#ifdef CONFIG_32BIT
+ bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA);
+ int pwidth = xpa ? 11 : 8;
+ int vwidth = 8;
+#else
+ bool xpa = false;
+ int pwidth = 11;
+ int vwidth = 11;
+#endif
s_pagemask = read_c0_pagemask();
s_entryhi = read_c0_entryhi();
@@ -59,46 +63,74 @@ static void dump_tlb(int first, int last)
for (i = first; i <= last; i++) {
write_c0_index(i);
- BARRIER();
+ mtc0_tlbr_hazard();
tlb_read();
- BARRIER();
+ tlb_read_hazard();
pagemask = read_c0_pagemask();
entryhi = read_c0_entryhi();
entrylo0 = read_c0_entrylo0();
entrylo1 = read_c0_entrylo1();
- /* Unused entries have a virtual address of CKSEG0. */
- if ((entryhi & ~0x1ffffUL) != CKSEG0
- && (entryhi & 0xff) == asid) {
-#ifdef CONFIG_32BIT
- int width = 8;
-#else
- int width = 11;
-#endif
- /*
- * Only print entries in use
- */
- printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
+ /* EHINV bit marks entire entry as invalid */
+ if (cpu_has_tlbinv && entryhi & MIPS_ENTRYHI_EHINV)
+ continue;
+ /*
+ * Prior to tlbinv, unused entries have a virtual address of
+ * CKSEG0.
+ */
+ if ((entryhi & ~0x1ffffUL) == CKSEG0)
+ continue;
+ /*
+ * 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.
+ */
+ if (!((entrylo0 | entrylo1) & MIPS_ENTRYLO_G) &&
+ (entryhi & 0xff) != asid)
+ continue;
+
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
- c0 = (entrylo0 >> 3) & 7;
- c1 = (entrylo1 >> 3) & 7;
+ c0 = (entrylo0 & MIPS_ENTRYLO_C) >> MIPS_ENTRYLO_C_SHIFT;
+ c1 = (entrylo1 & MIPS_ENTRYLO_C) >> MIPS_ENTRYLO_C_SHIFT;
- printk("va=%0*lx asid=%02lx\n",
- width, (entryhi & ~0x1fffUL),
- entryhi & 0xff);
- printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ",
- width,
- (entrylo0 << 6) & PAGE_MASK, c0,
- (entrylo0 & 4) ? 1 : 0,
- (entrylo0 & 2) ? 1 : 0,
- (entrylo0 & 1) ? 1 : 0);
- printk("[pa=%0*llx c=%d d=%d v=%d g=%d]\n",
- width,
- (entrylo1 << 6) & PAGE_MASK, c1,
- (entrylo1 & 4) ? 1 : 0,
- (entrylo1 & 2) ? 1 : 0,
- (entrylo1 & 1) ? 1 : 0);
- }
+ printk("va=%0*lx asid=%02lx\n",
+ vwidth, (entryhi & ~0x1fffUL),
+ entryhi & 0xff);
+ /* RI/XI are in awkward places, so mask them off separately */
+ pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
+ if (xpa)
+ pa |= (unsigned long long)readx_c0_entrylo0() << 30;
+ pa = (pa << 6) & PAGE_MASK;
+ printk("\t[");
+ 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] [",
+ pwidth, pa, c0,
+ (entrylo0 & MIPS_ENTRYLO_D) ? 1 : 0,
+ (entrylo0 & MIPS_ENTRYLO_V) ? 1 : 0,
+ (entrylo0 & MIPS_ENTRYLO_G) ? 1 : 0);
+ /* RI/XI are in awkward places, so mask them off separately */
+ pa = entrylo1 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
+ if (xpa)
+ pa |= (unsigned long long)readx_c0_entrylo1() << 30;
+ 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",
+ pwidth, pa, c1,
+ (entrylo1 & MIPS_ENTRYLO_D) ? 1 : 0,
+ (entrylo1 & MIPS_ENTRYLO_V) ? 1 : 0,
+ (entrylo1 & MIPS_ENTRYLO_G) ? 1 : 0);
}
printk("\n");
OpenPOWER on IntegriCloud