diff options
author | David Daney <ddaney@caviumnetworks.com> | 2009-10-14 15:16:56 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2009-12-16 20:57:01 -0500 |
commit | 82622284dd2f8791f9759f3cef601520a8bc63b2 (patch) | |
tree | ee47f43af373d0c021cc83ff9e22925942e9d001 /arch/mips/mm | |
parent | 92078e0618f525e22945040b5daea21d4b6d4a16 (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.c | 2 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 28 |
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) | |||
462 | __pa_symbol(&__init_end)); | 462 | __pa_symbol(&__init_end)); |
463 | } | 463 | } |
464 | 464 | ||
465 | #ifndef CONFIG_MIPS_PGD_C0_CONTEXT | ||
465 | unsigned long pgd_current[NR_CPUS]; | 466 | unsigned 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; | |||
160 | static struct uasm_label labels[128] __cpuinitdata; | 160 | static struct uasm_label labels[128] __cpuinitdata; |
161 | static struct uasm_reloc relocs[128] __cpuinitdata; | 161 | static 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 | |||
497 | build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, | 504 | build_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: |