*
* Synthesize TLB refill handlers at runtime.
*
- * Copyright (C) 2004,2005 by Thiemo Seufer
+ * Copyright (C) 2004,2005,2006 by Thiemo Seufer
* Copyright (C) 2005 Maciej W. Rozycki
* Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
*
#include <stdarg.h>
-#include <linux/config.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/smp.h>
#include <asm/war.h>
-/* #define DEBUG_TLB */
-
static __init int __attribute__((unused)) r45k_bvahwbug(void)
{
/* XXX: We should probe for the presence of this bug, but we don't. */
insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
- insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
+ insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32,
insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
{ insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
{ insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
{ insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE },
+ { insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE },
{ insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD },
{ insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 },
{ insn_j, M(j_op,0,0,0,0,0), JIMM },
I_u2u1u3(_dsll32);
I_u2u1u3(_dsra);
I_u2u1u3(_dsrl);
+I_u2u1u3(_dsrl32);
I_u3u1u2(_dsubu);
I_0(_eret);
I_u1(_j);
{
long pgdc = (long)pgd_current;
u32 *p;
+ int i;
memset(tlb_handler, 0, sizeof(tlb_handler));
p = tlb_handler;
if (p > tlb_handler + 32)
panic("TLB refill handler space exceeded");
- printk("Synthesized TLB refill handler (%u instructions).\n",
- (unsigned int)(p - tlb_handler));
-#ifdef DEBUG_TLB
- {
- int i;
+ pr_info("Synthesized TLB refill handler (%u instructions).\n",
+ (unsigned int)(p - tlb_handler));
- for (i = 0; i < (p - tlb_handler); i++)
- printk("%08x\n", tlb_handler[i]);
- }
-#endif
+ pr_debug("\t.set push\n");
+ pr_debug("\t.set noreorder\n");
+ for (i = 0; i < (p - tlb_handler); i++)
+ pr_debug("\t.word 0x%08x\n", tlb_handler[i]);
+ pr_debug("\t.set pop\n");
memcpy((void *)ebase, tlb_handler, 0x80);
}
#endif
l_vmalloc_done(l, *p);
- i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */
+
+ if (PGDIR_SHIFT - 3 < 32) /* get pgd offset in bytes */
+ i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3);
+ else
+ i_dsrl32(p, tmp, tmp, PGDIR_SHIFT - 3 - 32);
+
i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
static __init void build_adjust_context(u32 **p, unsigned int ctx)
{
- unsigned int shift = 4 - (PTE_T_LOG2 + 1);
+ unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12;
unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1);
switch (current_cpu_data.cputype) {
struct reloc *r = relocs;
u32 *f;
unsigned int final_len;
+ int i;
memset(tlb_handler, 0, sizeof(tlb_handler));
memset(labels, 0, sizeof(labels));
* Overflow check: For the 64bit handler, we need at least one
* free instruction slot for the wrap-around branch. In worst
* case, if the intended insertion point is a delay slot, we
- * need three, with the the second nop'ed and the third being
+ * need three, with the second nop'ed and the third being
* unused.
*/
#ifdef CONFIG_32BIT
#endif /* CONFIG_64BIT */
resolve_relocs(relocs, labels);
- printk("Synthesized TLB refill handler (%u instructions).\n",
- final_len);
+ pr_info("Synthesized TLB refill handler (%u instructions).\n",
+ final_len);
-#ifdef DEBUG_TLB
- {
- int i;
-
- f = final_handler;
+ f = final_handler;
#ifdef CONFIG_64BIT
- if (final_len > 32)
- final_len = 64;
- else
- f = final_handler + 32;
+ if (final_len > 32)
+ final_len = 64;
+ else
+ f = final_handler + 32;
#endif /* CONFIG_64BIT */
- for (i = 0; i < final_len; i++)
- printk("%08x\n", f[i]);
- }
-#endif
+ pr_debug("\t.set push\n");
+ pr_debug("\t.set noreorder\n");
+ for (i = 0; i < final_len; i++)
+ pr_debug("\t.word 0x%08x\n", f[i]);
+ pr_debug("\t.set pop\n");
memcpy((void *)ebase, final_handler, 0x100);
}
u32 *p = handle_tlbl;
struct label *l = labels;
struct reloc *r = relocs;
+ int i;
memset(handle_tlbl, 0, sizeof(handle_tlbl));
memset(labels, 0, sizeof(labels));
panic("TLB load handler fastpath space exceeded");
resolve_relocs(relocs, labels);
- printk("Synthesized TLB load handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbl));
-
-#ifdef DEBUG_TLB
- {
- int i;
+ pr_info("Synthesized TLB load handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbl));
- for (i = 0; i < (p - handle_tlbl); i++)
- printk("%08x\n", handle_tlbl[i]);
- }
-#endif
+ pr_debug("\t.set push\n");
+ pr_debug("\t.set noreorder\n");
+ for (i = 0; i < (p - handle_tlbl); i++)
+ pr_debug("\t.word 0x%08x\n", handle_tlbl[i]);
+ pr_debug("\t.set pop\n");
}
static void __init build_r3000_tlb_store_handler(void)
u32 *p = handle_tlbs;
struct label *l = labels;
struct reloc *r = relocs;
+ int i;
memset(handle_tlbs, 0, sizeof(handle_tlbs));
memset(labels, 0, sizeof(labels));
panic("TLB store handler fastpath space exceeded");
resolve_relocs(relocs, labels);
- printk("Synthesized TLB store handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbs));
-
-#ifdef DEBUG_TLB
- {
- int i;
+ pr_info("Synthesized TLB store handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbs));
- for (i = 0; i < (p - handle_tlbs); i++)
- printk("%08x\n", handle_tlbs[i]);
- }
-#endif
+ pr_debug("\t.set push\n");
+ pr_debug("\t.set noreorder\n");
+ for (i = 0; i < (p - handle_tlbs); i++)
+ pr_debug("\t.word 0x%08x\n", handle_tlbs[i]);
+ pr_debug("\t.set pop\n");
}
static void __init build_r3000_tlb_modify_handler(void)
u32 *p = handle_tlbm;
struct label *l = labels;
struct reloc *r = relocs;
+ int i;
memset(handle_tlbm, 0, sizeof(handle_tlbm));
memset(labels, 0, sizeof(labels));
panic("TLB modify handler fastpath space exceeded");
resolve_relocs(relocs, labels);
- printk("Synthesized TLB modify handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbm));
+ pr_info("Synthesized TLB modify handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbm));
-#ifdef DEBUG_TLB
- {
- int i;
-
- for (i = 0; i < (p - handle_tlbm); i++)
- printk("%08x\n", handle_tlbm[i]);
- }
-#endif
+ pr_debug("\t.set push\n");
+ pr_debug("\t.set noreorder\n");
+ for (i = 0; i < (p - handle_tlbm); i++)
+ pr_debug("\t.word 0x%08x\n", handle_tlbm[i]);
+ pr_debug("\t.set pop\n");
}
/*
u32 *p = handle_tlbl;
struct label *l = labels;
struct reloc *r = relocs;
+ int i;
memset(handle_tlbl, 0, sizeof(handle_tlbl));
memset(labels, 0, sizeof(labels));
panic("TLB load handler fastpath space exceeded");
resolve_relocs(relocs, labels);
- printk("Synthesized TLB load handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbl));
-
-#ifdef DEBUG_TLB
- {
- int i;
+ pr_info("Synthesized TLB load handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbl));
- for (i = 0; i < (p - handle_tlbl); i++)
- printk("%08x\n", handle_tlbl[i]);
- }
-#endif
+ pr_debug("\t.set push\n");
+ pr_debug("\t.set noreorder\n");
+ for (i = 0; i < (p - handle_tlbl); i++)
+ pr_debug("\t.word 0x%08x\n", handle_tlbl[i]);
+ pr_debug("\t.set pop\n");
}
static void __init build_r4000_tlb_store_handler(void)
u32 *p = handle_tlbs;
struct label *l = labels;
struct reloc *r = relocs;
+ int i;
memset(handle_tlbs, 0, sizeof(handle_tlbs));
memset(labels, 0, sizeof(labels));
panic("TLB store handler fastpath space exceeded");
resolve_relocs(relocs, labels);
- printk("Synthesized TLB store handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbs));
+ pr_info("Synthesized TLB store handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbs));
-#ifdef DEBUG_TLB
- {
- int i;
-
- for (i = 0; i < (p - handle_tlbs); i++)
- printk("%08x\n", handle_tlbs[i]);
- }
-#endif
+ pr_debug("\t.set push\n");
+ pr_debug("\t.set noreorder\n");
+ for (i = 0; i < (p - handle_tlbs); i++)
+ pr_debug("\t.word 0x%08x\n", handle_tlbs[i]);
+ pr_debug("\t.set pop\n");
}
static void __init build_r4000_tlb_modify_handler(void)
u32 *p = handle_tlbm;
struct label *l = labels;
struct reloc *r = relocs;
+ int i;
memset(handle_tlbm, 0, sizeof(handle_tlbm));
memset(labels, 0, sizeof(labels));
panic("TLB modify handler fastpath space exceeded");
resolve_relocs(relocs, labels);
- printk("Synthesized TLB modify handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbm));
-
-#ifdef DEBUG_TLB
- {
- int i;
-
- for (i = 0; i < (p - handle_tlbm); i++)
- printk("%08x\n", handle_tlbm[i]);
- }
-#endif
+ pr_info("Synthesized TLB modify handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbm));
+
+ pr_debug("\t.set push\n");
+ pr_debug("\t.set noreorder\n");
+ for (i = 0; i < (p - handle_tlbm); i++)
+ pr_debug("\t.word 0x%08x\n", handle_tlbm[i]);
+ pr_debug("\t.set pop\n");
}
void __init build_tlb_refill_handler(void)