#endif /* SMTC */
#include <asm-generic/mm_hooks.h>
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+
+#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
+ tlbmiss_handler_setup_pgd((unsigned long)(pgd))
+
+static inline void tlbmiss_handler_setup_pgd(unsigned long pgd)
+{
+ /* Check for swapper_pg_dir and convert to physical address. */
+ if ((pgd & CKSEG3) == CKSEG0)
+ pgd = CPHYSADDR(pgd);
+ write_c0_context(pgd << 11);
+}
+
+#define TLBMISS_HANDLER_SETUP() \
+ do { \
+ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); \
+ write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
+ } while (0)
+
+
+static inline unsigned long get_current_pgd(void)
+{
+ return PHYS_TO_XKSEG_CACHED((read_c0_context() >> 11) & ~0xfffUL);
+}
+
+#else /* CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/
+
/*
* For the fast tlb miss handlers, we keep a per cpu array of pointers
* to the current pgd for each processor. Also, the proc. id is stuffed
back_to_back_c0_hazard(); \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
#endif
-
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
#define ASID_INC 0x40
#ifdef CONFIG_SMP
#ifdef CONFIG_MIPS_MT_SMTC
#define PTEBASE_SHIFT 19 /* TCBIND */
+#define CPU_ID_REG CP0_TCBIND
+#define CPU_ID_MFC0 mfc0
+#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
+#define PTEBASE_SHIFT 48 /* XCONTEXT */
+#define CPU_ID_REG CP0_XCONTEXT
+#define CPU_ID_MFC0 MFC0
#else
#define PTEBASE_SHIFT 23 /* CONTEXT */
+#define CPU_ID_REG CP0_CONTEXT
+#define CPU_ID_MFC0 MFC0
#endif
.macro get_saved_sp /* SMP variation */
-#ifdef CONFIG_MIPS_MT_SMTC
- mfc0 k0, CP0_TCBIND
-#else
- MFC0 k0, CP0_CONTEXT
-#endif
+ CPU_ID_MFC0 k0, CPU_ID_REG
#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
lui k1, %hi(kernelsp)
#else
.endm
.macro set_saved_sp stackp temp temp2
-#ifdef CONFIG_MIPS_MT_SMTC
- mfc0 \temp, CP0_TCBIND
-#else
- MFC0 \temp, CP0_CONTEXT
-#endif
+ CPU_ID_MFC0 \temp, CPU_ID_REG
LONG_SRL \temp, PTEBASE_SHIFT
LONG_S \stackp, kernelsp(\temp)
.endm
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.
*/
dump_handler((u32 *)ebase, 32);
}
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
/*
* The R4000 TLB handler is much more complicated. We have two
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.
*/
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
*/
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);
iPTE_LW(p, pte, ptr);
}
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
/*
* R3000 style TLB load/store/modify handlers.
*/
dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
}
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
/*
* R4000 style TLB load/store/modify handlers.
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();
build_r3000_tlb_modify_handler();
run_once++;
}
+#else
+ panic("No R3000 TLB refill handler");
+#endif
break;
case CPU_R6000: