aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2009-10-14 15:16:56 -0400
committerRalf Baechle <ralf@linux-mips.org>2009-12-16 20:57:01 -0500
commit82622284dd2f8791f9759f3cef601520a8bc63b2 (patch)
treeee47f43af373d0c021cc83ff9e22925942e9d001
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>
-rw-r--r--arch/mips/Kconfig3
-rw-r--r--arch/mips/include/asm/mmu_context.h29
-rw-r--r--arch/mips/include/asm/stackframe.h20
-rw-r--r--arch/mips/mm/init.c2
-rw-r--r--arch/mips/mm/tlbex.c28
5 files changed, 68 insertions, 14 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f6f3b990d837..20b223ba654d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1427,6 +1427,9 @@ config CPU_SUPPORTS_64BIT_KERNEL
1427 bool 1427 bool
1428config CPU_SUPPORTS_HUGEPAGES 1428config CPU_SUPPORTS_HUGEPAGES
1429 bool 1429 bool
1430config MIPS_PGD_C0_CONTEXT
1431 bool
1432 default y if 64BIT && CPU_MIPSR2
1430 1433
1431# 1434#
1432# Set to y for ptrace access to watch registers. 1435# Set to y for ptrace access to watch registers.
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 6083db586500..145bb81ccaa5 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -24,6 +24,33 @@
24#endif /* SMTC */ 24#endif /* SMTC */
25#include <asm-generic/mm_hooks.h> 25#include <asm-generic/mm_hooks.h>
26 26
27#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
28
29#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
30 tlbmiss_handler_setup_pgd((unsigned long)(pgd))
31
32static inline void tlbmiss_handler_setup_pgd(unsigned long pgd)
33{
34 /* Check for swapper_pg_dir and convert to physical address. */
35 if ((pgd & CKSEG3) == CKSEG0)
36 pgd = CPHYSADDR(pgd);
37 write_c0_context(pgd << 11);
38}
39
40#define TLBMISS_HANDLER_SETUP() \
41 do { \
42 TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); \
43 write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
44 } while (0)
45
46
47static inline unsigned long get_current_pgd(void)
48{
49 return PHYS_TO_XKSEG_CACHED((read_c0_context() >> 11) & ~0xfffUL);
50}
51
52#else /* CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/
53
27/* 54/*
28 * For the fast tlb miss handlers, we keep a per cpu array of pointers 55 * For the fast tlb miss handlers, we keep a per cpu array of pointers
29 * to the current pgd for each processor. Also, the proc. id is stuffed 56 * to the current pgd for each processor. Also, the proc. id is stuffed
@@ -46,7 +73,7 @@ extern unsigned long pgd_current[];
46 back_to_back_c0_hazard(); \ 73 back_to_back_c0_hazard(); \
47 TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) 74 TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
48#endif 75#endif
49 76#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
50#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) 77#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
51 78
52#define ASID_INC 0x40 79#define ASID_INC 0x40
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index dd7e220e087b..3b6da3330e32 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -87,15 +87,19 @@
87#ifdef CONFIG_SMP 87#ifdef CONFIG_SMP
88#ifdef CONFIG_MIPS_MT_SMTC 88#ifdef CONFIG_MIPS_MT_SMTC
89#define PTEBASE_SHIFT 19 /* TCBIND */ 89#define PTEBASE_SHIFT 19 /* TCBIND */
90#define CPU_ID_REG CP0_TCBIND
91#define CPU_ID_MFC0 mfc0
92#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
93#define PTEBASE_SHIFT 48 /* XCONTEXT */
94#define CPU_ID_REG CP0_XCONTEXT
95#define CPU_ID_MFC0 MFC0
90#else 96#else
91#define PTEBASE_SHIFT 23 /* CONTEXT */ 97#define PTEBASE_SHIFT 23 /* CONTEXT */
98#define CPU_ID_REG CP0_CONTEXT
99#define CPU_ID_MFC0 MFC0
92#endif 100#endif
93 .macro get_saved_sp /* SMP variation */ 101 .macro get_saved_sp /* SMP variation */
94#ifdef CONFIG_MIPS_MT_SMTC 102 CPU_ID_MFC0 k0, CPU_ID_REG
95 mfc0 k0, CP0_TCBIND
96#else
97 MFC0 k0, CP0_CONTEXT
98#endif
99#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) 103#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
100 lui k1, %hi(kernelsp) 104 lui k1, %hi(kernelsp)
101#else 105#else
@@ -111,11 +115,7 @@
111 .endm 115 .endm
112 116
113 .macro set_saved_sp stackp temp temp2 117 .macro set_saved_sp stackp temp temp2
114#ifdef CONFIG_MIPS_MT_SMTC 118 CPU_ID_MFC0 \temp, CPU_ID_REG
115 mfc0 \temp, CP0_TCBIND
116#else
117 MFC0 \temp, CP0_CONTEXT
118#endif
119 LONG_SRL \temp, PTEBASE_SHIFT 119 LONG_SRL \temp, PTEBASE_SHIFT
120 LONG_S \stackp, kernelsp(\temp) 120 LONG_S \stackp, kernelsp(\temp)
121 .endm 121 .endm
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)
462 __pa_symbol(&__init_end)); 462 __pa_symbol(&__init_end));
463} 463}
464 464
465#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
465unsigned long pgd_current[NR_CPUS]; 466unsigned long pgd_current[NR_CPUS];
467#endif
466/* 468/*
467 * On 64-bit we've got three-level pagetables with a slightly 469 * On 64-bit we've got three-level pagetables with a slightly
468 * different layout ... 470 * 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;
160static struct uasm_label labels[128] __cpuinitdata; 160static struct uasm_label labels[128] __cpuinitdata;
161static struct uasm_reloc relocs[128] __cpuinitdata; 161static struct uasm_reloc relocs[128] __cpuinitdata;
162 162
163#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
164/*
165 * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
166 * we cannot do r3000 under these circumstances.
167 */
168
163/* 169/*
164 * The R3000 TLB handler is simple. 170 * The R3000 TLB handler is simple.
165 */ 171 */
@@ -199,6 +205,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void)
199 205
200 dump_handler((u32 *)ebase, 32); 206 dump_handler((u32 *)ebase, 32);
201} 207}
208#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
202 209
203/* 210/*
204 * The R4000 TLB handler is much more complicated. We have two 211 * The R4000 TLB handler is much more complicated. We have two
@@ -497,8 +504,9 @@ static void __cpuinit
497build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, 504build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
498 unsigned int tmp, unsigned int ptr) 505 unsigned int tmp, unsigned int ptr)
499{ 506{
507#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
500 long pgdc = (long)pgd_current; 508 long pgdc = (long)pgd_current;
501 509#endif
502 /* 510 /*
503 * The vmalloc handling is not in the hotpath. 511 * The vmalloc handling is not in the hotpath.
504 */ 512 */
@@ -506,7 +514,15 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
506 uasm_il_bltz(p, r, tmp, label_vmalloc); 514 uasm_il_bltz(p, r, tmp, label_vmalloc);
507 /* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */ 515 /* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
508 516
509#ifdef CONFIG_SMP 517#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
518 /*
519 * &pgd << 11 stored in CONTEXT [23..63].
520 */
521 UASM_i_MFC0(p, ptr, C0_CONTEXT);
522 uasm_i_dins(p, ptr, 0, 0, 23); /* Clear lower 23 bits of context. */
523 uasm_i_ori(p, ptr, ptr, 0x540); /* 1 0 1 0 1 << 6 xkphys cached */
524 uasm_i_drotr(p, ptr, ptr, 11);
525#elif defined(CONFIG_SMP)
510# ifdef CONFIG_MIPS_MT_SMTC 526# ifdef CONFIG_MIPS_MT_SMTC
511 /* 527 /*
512 * SMTC uses TCBind value as "CPU" index 528 * SMTC uses TCBind value as "CPU" index
@@ -520,7 +536,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
520 */ 536 */
521 uasm_i_dmfc0(p, ptr, C0_CONTEXT); 537 uasm_i_dmfc0(p, ptr, C0_CONTEXT);
522 uasm_i_dsrl(p, ptr, ptr, 23); 538 uasm_i_dsrl(p, ptr, ptr, 23);
523#endif 539# endif
524 UASM_i_LA_mostly(p, tmp, pgdc); 540 UASM_i_LA_mostly(p, tmp, pgdc);
525 uasm_i_daddu(p, ptr, ptr, tmp); 541 uasm_i_daddu(p, ptr, ptr, tmp);
526 uasm_i_dmfc0(p, tmp, C0_BADVADDR); 542 uasm_i_dmfc0(p, tmp, C0_BADVADDR);
@@ -1033,6 +1049,7 @@ build_pte_modifiable(u32 **p, struct uasm_reloc **r,
1033 iPTE_LW(p, pte, ptr); 1049 iPTE_LW(p, pte, ptr);
1034} 1050}
1035 1051
1052#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
1036/* 1053/*
1037 * R3000 style TLB load/store/modify handlers. 1054 * R3000 style TLB load/store/modify handlers.
1038 */ 1055 */
@@ -1184,6 +1201,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
1184 1201
1185 dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); 1202 dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
1186} 1203}
1204#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
1187 1205
1188/* 1206/*
1189 * R4000 style TLB load/store/modify handlers. 1207 * R4000 style TLB load/store/modify handlers.
@@ -1400,6 +1418,7 @@ void __cpuinit build_tlb_refill_handler(void)
1400 case CPU_TX3912: 1418 case CPU_TX3912:
1401 case CPU_TX3922: 1419 case CPU_TX3922:
1402 case CPU_TX3927: 1420 case CPU_TX3927:
1421#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
1403 build_r3000_tlb_refill_handler(); 1422 build_r3000_tlb_refill_handler();
1404 if (!run_once) { 1423 if (!run_once) {
1405 build_r3000_tlb_load_handler(); 1424 build_r3000_tlb_load_handler();
@@ -1407,6 +1426,9 @@ void __cpuinit build_tlb_refill_handler(void)
1407 build_r3000_tlb_modify_handler(); 1426 build_r3000_tlb_modify_handler();
1408 run_once++; 1427 run_once++;
1409 } 1428 }
1429#else
1430 panic("No R3000 TLB refill handler");
1431#endif
1410 break; 1432 break;
1411 1433
1412 case CPU_R6000: 1434 case CPU_R6000: