提交 95affdda 编写于 作者: D David Daney 提交者: Ralf Baechle

MIPS: Fold the TLB refill at the vmalloc path if possible.

Try to fold the 64-bit TLB refill handler opportunistically at the
beginning of the vmalloc path so as to avoid splitting execution flow in
half and wasting cycles for a branch required at that point then.  Resort
to doing the split if either of the newly created parts would not fit into
its designated slot.
Original-patch-by: NMaciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: NMaciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: NDavid Daney <ddaney@caviumnetworks.com>
Signed-off-by: NRalf Baechle <ralf@linux-mips.org>
上级 e6f72d3a
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Synthesize TLB refill handlers at runtime. * Synthesize TLB refill handlers at runtime.
* *
* Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
* Copyright (C) 2005, 2007 Maciej W. Rozycki * Copyright (C) 2005, 2007, 2008, 2009 Maciej W. Rozycki
* Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
* *
* ... and the days got worse and worse and now you see * ... and the days got worse and worse and now you see
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* (Condolences to Napoleon XIV) * (Condolences to Napoleon XIV)
*/ */
#include <linux/bug.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -732,36 +733,60 @@ static void __cpuinit build_r4000_tlb_refill_handler(void) ...@@ -732,36 +733,60 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
uasm_copy_handler(relocs, labels, tlb_handler, p, f); uasm_copy_handler(relocs, labels, tlb_handler, p, f);
final_len = p - tlb_handler; final_len = p - tlb_handler;
} else { } else {
/* #ifdef MODULE_START
* Split two instructions before the end. One for the const enum label_id ls = label_module_alloc;
* branch and one for the instruction in the delay #else
* slot. const enum label_id ls = label_vmalloc;
*/ #endif
u32 *split = tlb_handler + MIPS64_REFILL_INSNS - 2; u32 *split;
int ov = 0;
int i;
for (i = 0; i < ARRAY_SIZE(labels) && labels[i].lab != ls; i++)
;
BUG_ON(i == ARRAY_SIZE(labels));
split = labels[i].addr;
/* /*
* Find the split point. If the branch would fall in * See if we have overflown one way or the other.
* a delay slot, we must back up an additional
* instruction so that it is no longer in a delay
* slot.
*/ */
if (uasm_insn_has_bdelay(relocs, split - 1)) if (split > tlb_handler + MIPS64_REFILL_INSNS ||
split--; split < p - MIPS64_REFILL_INSNS)
ov = 1;
if (ov) {
/*
* Split two instructions before the end. One
* for the branch and one for the instruction
* in the delay slot.
*/
split = tlb_handler + MIPS64_REFILL_INSNS - 2;
/*
* If the branch would fall in a delay slot,
* we must back up an additional instruction
* so that it is no longer in a delay slot.
*/
if (uasm_insn_has_bdelay(relocs, split - 1))
split--;
}
/* Copy first part of the handler. */ /* Copy first part of the handler. */
uasm_copy_handler(relocs, labels, tlb_handler, split, f); uasm_copy_handler(relocs, labels, tlb_handler, split, f);
f += split - tlb_handler; f += split - tlb_handler;
/* Insert branch. */ if (ov) {
uasm_l_split(&l, final_handler); /* Insert branch. */
uasm_il_b(&f, &r, label_split); uasm_l_split(&l, final_handler);
if (uasm_insn_has_bdelay(relocs, split)) uasm_il_b(&f, &r, label_split);
uasm_i_nop(&f); if (uasm_insn_has_bdelay(relocs, split))
else { uasm_i_nop(&f);
uasm_copy_handler(relocs, labels, split, split + 1, f); else {
uasm_move_labels(labels, f, f + 1, -1); uasm_copy_handler(relocs, labels,
f++; split, split + 1, f);
split++; uasm_move_labels(labels, f, f + 1, -1);
f++;
split++;
}
} }
/* Copy the rest of the handler. */ /* Copy the rest of the handler. */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册