summaryrefslogtreecommitdiff
path: root/arch/mips/mm
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2009-10-14 12:16:56 -0700
committerRalf Baechle <ralf@linux-mips.org>2009-12-17 01:57:01 +0000
commit82622284dd2f8791f9759f3cef601520a8bc63b2 (patch)
treeee47f43af373d0c021cc83ff9e22925942e9d001 /arch/mips/mm
parent92078e0618f525e22945040b5daea21d4b6d4a16 (diff)
MIPS: Put PGD in C0_CONTEXT for 64-bit R2 processors.
Processors that support the mips64r2 ISA can in four instructions convert a shifted PGD pointer stored in the upper bits of c0_context into a usable pointer. By doing this we save a memory load and associated potential cache miss in the TLB exception handlers. Since the upper bits of c0_context were holding the CPU number, we move this to the upper bits of c0_xcontext which doesn't have enough bits to hold the PGD pointer, but has plenty for the CPU number. Signed-off-by: David Daney <ddaney@caviumnetworks.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mm')
-rw-r--r--arch/mips/mm/init.c2
-rw-r--r--arch/mips/mm/tlbex.c28
2 files changed, 27 insertions, 3 deletions
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 8d1f4f363049..9e8d00389eef 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -462,7 +462,9 @@ void __init_refok free_initmem(void)
__pa_symbol(&__init_end));
}
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
unsigned long pgd_current[NR_CPUS];
+#endif
/*
* On 64-bit we've got three-level pagetables with a slightly
* different layout ...
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index bb1719a55d22..3d0baa4a842d 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -160,6 +160,12 @@ static u32 tlb_handler[128] __cpuinitdata;
static struct uasm_label labels[128] __cpuinitdata;
static struct uasm_reloc relocs[128] __cpuinitdata;
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+/*
+ * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
+ * we cannot do r3000 under these circumstances.
+ */
+
/*
* The R3000 TLB handler is simple.
*/
@@ -199,6 +205,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void)
dump_handler((u32 *)ebase, 32);
}
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
/*
* The R4000 TLB handler is much more complicated. We have two
@@ -497,8 +504,9 @@ static void __cpuinit
build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
unsigned int tmp, unsigned int ptr)
{
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
long pgdc = (long)pgd_current;
-
+#endif
/*
* The vmalloc handling is not in the hotpath.
*/
@@ -506,7 +514,15 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
uasm_il_bltz(p, r, tmp, label_vmalloc);
/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
-#ifdef CONFIG_SMP
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+ /*
+ * &pgd << 11 stored in CONTEXT [23..63].
+ */
+ UASM_i_MFC0(p, ptr, C0_CONTEXT);
+ uasm_i_dins(p, ptr, 0, 0, 23); /* Clear lower 23 bits of context. */
+ uasm_i_ori(p, ptr, ptr, 0x540); /* 1 0 1 0 1 << 6 xkphys cached */
+ uasm_i_drotr(p, ptr, ptr, 11);
+#elif defined(CONFIG_SMP)
# ifdef CONFIG_MIPS_MT_SMTC
/*
* SMTC uses TCBind value as "CPU" index
@@ -520,7 +536,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
*/
uasm_i_dmfc0(p, ptr, C0_CONTEXT);
uasm_i_dsrl(p, ptr, ptr, 23);
-#endif
+# endif
UASM_i_LA_mostly(p, tmp, pgdc);
uasm_i_daddu(p, ptr, ptr, tmp);
uasm_i_dmfc0(p, tmp, C0_BADVADDR);
@@ -1033,6 +1049,7 @@ build_pte_modifiable(u32 **p, struct uasm_reloc **r,
iPTE_LW(p, pte, ptr);
}
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
/*
* R3000 style TLB load/store/modify handlers.
*/
@@ -1184,6 +1201,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
}
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
/*
* R4000 style TLB load/store/modify handlers.
@@ -1400,6 +1418,7 @@ void __cpuinit build_tlb_refill_handler(void)
case CPU_TX3912:
case CPU_TX3922:
case CPU_TX3927:
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
build_r3000_tlb_refill_handler();
if (!run_once) {
build_r3000_tlb_load_handler();
@@ -1407,6 +1426,9 @@ void __cpuinit build_tlb_refill_handler(void)
build_r3000_tlb_modify_handler();
run_once++;
}
+#else
+ panic("No R3000 TLB refill handler");
+#endif
break;
case CPU_R6000: