* Synthesize TLB refill handlers at runtime.
*
* Copyright (C) 2004,2005,2006 by Thiemo Seufer
- * Copyright (C) 2005 Maciej W. Rozycki
+ * Copyright (C) 2005, 2007 Maciej W. Rozycki
* Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
*
* ... and the days got worse and worse and now you see
* (Condolences to Napoleon XIV)
*/
-#include <stdarg.h>
-
-#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <asm/pgtable.h>
-#include <asm/cacheflush.h>
+#include <asm/bugs.h>
#include <asm/mmu_context.h>
#include <asm/inst.h>
#include <asm/elf.h>
-#include <asm/smp.h>
#include <asm/war.h>
-static __init int __maybe_unused r45k_bvahwbug(void)
+static inline int r45k_bvahwbug(void)
{
/* XXX: We should probe for the presence of this bug, but we don't. */
return 0;
}
-static __init int __maybe_unused r4k_250MHZhwbug(void)
+static inline int r4k_250MHZhwbug(void)
{
/* XXX: We should probe for the presence of this bug, but we don't. */
return 0;
}
-static __init int __maybe_unused bcm1250_m3_war(void)
+static inline int __maybe_unused bcm1250_m3_war(void)
{
return BCM1250_M3_WAR;
}
-static __init int __maybe_unused r10000_llsc_war(void)
+static inline int __maybe_unused r10000_llsc_war(void)
{
return R10000_LLSC_WAR;
}
* why; it's not an issue caused by the core RTL.
*
*/
-static __init int __attribute__((unused)) m4kc_tlbp_war(void)
+static int __init m4kc_tlbp_war(void)
{
return (current_cpu_data.processor_id & 0xffff00) ==
(PRID_COMP_MIPS | PRID_IMP_4KC);
| (e) << RE_SH \
| (f) << FUNC_SH)
-static __initdata struct insn insn_table[] = {
- { insn_addiu, M(addiu_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_addu, M(spec_op,0,0,0,0,addu_op), RS | RT | RD },
- { insn_and, M(spec_op,0,0,0,0,and_op), RS | RT | RD },
- { insn_andi, M(andi_op,0,0,0,0,0), RS | RT | UIMM },
- { insn_beq, M(beq_op,0,0,0,0,0), RS | RT | BIMM },
- { insn_beql, M(beql_op,0,0,0,0,0), RS | RT | BIMM },
- { insn_bgez, M(bcond_op,0,bgez_op,0,0,0), RS | BIMM },
- { insn_bgezl, M(bcond_op,0,bgezl_op,0,0,0), RS | BIMM },
- { insn_bltz, M(bcond_op,0,bltz_op,0,0,0), RS | BIMM },
- { insn_bltzl, M(bcond_op,0,bltzl_op,0,0,0), RS | BIMM },
- { insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM },
- { insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD },
- { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD | SET},
- { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD | SET},
- { insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE },
- { 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 },
- { insn_jal, M(jal_op,0,0,0,0,0), JIMM },
- { insn_jr, M(spec_op,0,0,0,0,jr_op), RS },
- { insn_ld, M(ld_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_ll, M(ll_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM },
- { insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD | SET},
- { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD | SET},
- { insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM },
- { insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 },
- { insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_scd, M(scd_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_sd, M(sd_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_sll, M(spec_op,0,0,0,0,sll_op), RT | RD | RE },
- { insn_sra, M(spec_op,0,0,0,0,sra_op), RT | RD | RE },
- { insn_srl, M(spec_op,0,0,0,0,srl_op), RT | RD | RE },
- { insn_subu, M(spec_op,0,0,0,0,subu_op), RS | RT | RD },
- { insn_sw, M(sw_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_tlbp, M(cop0_op,cop_op,0,0,0,tlbp_op), 0 },
- { insn_tlbwi, M(cop0_op,cop_op,0,0,0,tlbwi_op), 0 },
- { insn_tlbwr, M(cop0_op,cop_op,0,0,0,tlbwr_op), 0 },
- { insn_xor, M(spec_op,0,0,0,0,xor_op), RS | RT | RD },
- { insn_xori, M(xori_op,0,0,0,0,0), RS | RT | UIMM },
+static struct insn insn_table[] __initdata = {
+ { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
+ { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
+ { insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
+ { insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+ { insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+ { insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
+ { insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
+ { insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
+ { insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
+ { insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+ { insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
+ { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
+ { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
+ { insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
+ { 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 },
+ { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
+ { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
+ { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
+ { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
+ { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
+ { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
+ { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
+ { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
+ { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE },
+ { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE },
+ { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD },
+ { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 },
+ { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 },
+ { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 },
+ { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
+ { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
{ insn_invalid, 0, 0 }
};
#undef M
-static __init u32 build_rs(u32 arg)
+static u32 __init build_rs(u32 arg)
{
if (arg & ~RS_MASK)
printk(KERN_WARNING "TLB synthesizer field overflow\n");
return (arg & RS_MASK) << RS_SH;
}
-static __init u32 build_rt(u32 arg)
+static u32 __init build_rt(u32 arg)
{
if (arg & ~RT_MASK)
printk(KERN_WARNING "TLB synthesizer field overflow\n");
return (arg & RT_MASK) << RT_SH;
}
-static __init u32 build_rd(u32 arg)
+static u32 __init build_rd(u32 arg)
{
if (arg & ~RD_MASK)
printk(KERN_WARNING "TLB synthesizer field overflow\n");
return (arg & RD_MASK) << RD_SH;
}
-static __init u32 build_re(u32 arg)
+static u32 __init build_re(u32 arg)
{
if (arg & ~RE_MASK)
printk(KERN_WARNING "TLB synthesizer field overflow\n");
return (arg & RE_MASK) << RE_SH;
}
-static __init u32 build_simm(s32 arg)
+static u32 __init build_simm(s32 arg)
{
if (arg > 0x7fff || arg < -0x8000)
printk(KERN_WARNING "TLB synthesizer field overflow\n");
return arg & 0xffff;
}
-static __init u32 build_uimm(u32 arg)
+static u32 __init build_uimm(u32 arg)
{
if (arg & ~IMM_MASK)
printk(KERN_WARNING "TLB synthesizer field overflow\n");
return arg & IMM_MASK;
}
-static __init u32 build_bimm(s32 arg)
+static u32 __init build_bimm(s32 arg)
{
if (arg > 0x1ffff || arg < -0x20000)
printk(KERN_WARNING "TLB synthesizer field overflow\n");
return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
}
-static __init u32 build_jimm(u32 arg)
+static u32 __init build_jimm(u32 arg)
{
if (arg & ~((JIMM_MASK) << 2))
printk(KERN_WARNING "TLB synthesizer field overflow\n");
return (arg >> 2) & JIMM_MASK;
}
-static __init u32 build_func(u32 arg)
+static u32 __init build_func(u32 arg)
{
if (arg & ~FUNC_MASK)
printk(KERN_WARNING "TLB synthesizer field overflow\n");
return arg & FUNC_MASK;
}
-static __init u32 build_set(u32 arg)
+static u32 __init build_set(u32 arg)
{
if (arg & ~SET_MASK)
printk(KERN_WARNING "TLB synthesizer field overflow\n");
break;
}
- if (!ip)
+ if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
panic("Unsupported TLB synthesizer instruction %d", opc);
op = ip->match;
}
#define I_u1u2u3(op) \
- static inline void __init i##op(u32 **buf, unsigned int a, \
+ static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
unsigned int b, unsigned int c) \
{ \
build_insn(buf, insn##op, a, b, c); \
}
#define I_u2u1u3(op) \
- static inline void __init i##op(u32 **buf, unsigned int a, \
+ static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
unsigned int b, unsigned int c) \
{ \
build_insn(buf, insn##op, b, a, c); \
}
#define I_u3u1u2(op) \
- static inline void __init i##op(u32 **buf, unsigned int a, \
+ static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
unsigned int b, unsigned int c) \
{ \
build_insn(buf, insn##op, b, c, a); \
}
#define I_u1u2s3(op) \
- static inline void __init i##op(u32 **buf, unsigned int a, \
+ static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
unsigned int b, signed int c) \
{ \
build_insn(buf, insn##op, a, b, c); \
}
#define I_u2s3u1(op) \
- static inline void __init i##op(u32 **buf, unsigned int a, \
+ static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
signed int b, unsigned int c) \
{ \
build_insn(buf, insn##op, c, a, b); \
}
#define I_u2u1s3(op) \
- static inline void __init i##op(u32 **buf, unsigned int a, \
+ static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
unsigned int b, signed int c) \
{ \
build_insn(buf, insn##op, b, a, c); \
}
#define I_u1u2(op) \
- static inline void __init i##op(u32 **buf, unsigned int a, \
+ static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
unsigned int b) \
{ \
build_insn(buf, insn##op, a, b); \
}
#define I_u1s2(op) \
- static inline void __init i##op(u32 **buf, unsigned int a, \
+ static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
signed int b) \
{ \
build_insn(buf, insn##op, a, b); \
}
#define I_u1(op) \
- static inline void __init i##op(u32 **buf, unsigned int a) \
+ static void __init __maybe_unused i##op(u32 **buf, unsigned int a) \
{ \
build_insn(buf, insn##op, a); \
}
#define I_0(op) \
- static inline void __init i##op(u32 **buf) \
+ static void __init __maybe_unused i##op(u32 **buf) \
{ \
build_insn(buf, insn##op); \
}
enum label_id lab;
};
-static __init void build_label(struct label **lab, u32 *addr,
+static void __init build_label(struct label **lab, u32 *addr,
enum label_id l)
{
(*lab)->addr = addr;
}
#define L_LA(lb) \
- static inline void l##lb(struct label **lab, u32 *addr) \
+ static inline void __init l##lb(struct label **lab, u32 *addr) \
{ \
build_label(lab, addr, label##lb); \
}
#define i_ssnop(buf) i_sll(buf, 0, 0, 1)
#define i_ehb(buf) i_sll(buf, 0, 0, 3)
-#ifdef CONFIG_64BIT
-static __init int __maybe_unused in_compat_space_p(long addr)
+static int __init __maybe_unused in_compat_space_p(long addr)
{
/* Is this address in 32bit compat space? */
+#ifdef CONFIG_64BIT
return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L);
+#else
+ return 1;
+#endif
}
-static __init int __maybe_unused rel_highest(long val)
+static int __init __maybe_unused rel_highest(long val)
{
+#ifdef CONFIG_64BIT
return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000;
+#else
+ return 0;
+#endif
}
-static __init int __maybe_unused rel_higher(long val)
+static int __init __maybe_unused rel_higher(long val)
{
+#ifdef CONFIG_64BIT
return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000;
-}
+#else
+ return 0;
#endif
+}
-static __init int rel_hi(long val)
+static int __init rel_hi(long val)
{
return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
}
-static __init int rel_lo(long val)
+static int __init rel_lo(long val)
{
return ((val & 0xffff) ^ 0x8000) - 0x8000;
}
-static __init void i_LA_mostly(u32 **buf, unsigned int rs, long addr)
+static void __init i_LA_mostly(u32 **buf, unsigned int rs, long addr)
{
-#ifdef CONFIG_64BIT
if (!in_compat_space_p(addr)) {
i_lui(buf, rs, rel_highest(addr));
if (rel_higher(addr))
} else
i_dsll32(buf, rs, rs, 0);
} else
-#endif
i_lui(buf, rs, rel_hi(addr));
}
-static __init void __maybe_unused i_LA(u32 **buf, unsigned int rs,
- long addr)
+static void __init __maybe_unused i_LA(u32 **buf, unsigned int rs, long addr)
{
i_LA_mostly(buf, rs, addr);
- if (rel_lo(addr))
- i_ADDIU(buf, rs, rs, rel_lo(addr));
+ if (rel_lo(addr)) {
+ if (!in_compat_space_p(addr))
+ i_daddiu(buf, rs, rs, rel_lo(addr));
+ else
+ i_addiu(buf, rs, rs, rel_lo(addr));
+ }
}
/*
enum label_id lab;
};
-static __init void r_mips_pc16(struct reloc **rel, u32 *addr,
+static void __init r_mips_pc16(struct reloc **rel, u32 *addr,
enum label_id l)
{
(*rel)->addr = addr;
}
}
-static __init void resolve_relocs(struct reloc *rel, struct label *lab)
+static void __init resolve_relocs(struct reloc *rel, struct label *lab)
{
struct label *l;
__resolve_relocs(rel, l);
}
-static __init void move_relocs(struct reloc *rel, u32 *first, u32 *end,
+static void __init move_relocs(struct reloc *rel, u32 *first, u32 *end,
long off)
{
for (; rel->lab != label_invalid; rel++)
rel->addr += off;
}
-static __init void move_labels(struct label *lab, u32 *first, u32 *end,
+static void __init move_labels(struct label *lab, u32 *first, u32 *end,
long off)
{
for (; lab->lab != label_invalid; lab++)
lab->addr += off;
}
-static __init void copy_handler(struct reloc *rel, struct label *lab,
+static void __init copy_handler(struct reloc *rel, struct label *lab,
u32 *first, u32 *end, u32 *target)
{
long off = (long)(target - first);
move_labels(lab, first, end, off);
}
-static __init int __maybe_unused insn_has_bdelay(struct reloc *rel,
+static int __init __maybe_unused insn_has_bdelay(struct reloc *rel,
u32 *addr)
{
for (; rel->lab != label_invalid; rel++) {
i_bgez(p, reg, 0);
}
+/*
+ * For debug purposes.
+ */
+static inline void dump_handler(const u32 *handler, int count)
+{
+ int i;
+
+ pr_debug("\t.set push\n");
+ pr_debug("\t.set noreorder\n");
+
+ for (i = 0; i < count; i++)
+ pr_debug("\t%p\t.word 0x%08x\n", &handler[i], handler[i]);
+
+ pr_debug("\t.set pop\n");
+}
+
/* The only general purpose registers allowed in TLB handlers. */
#define K0 26
#define K1 27
* We deliberately chose a buffer size of 128, so we won't scribble
* over anything important on overflow before we panic.
*/
-static __initdata u32 tlb_handler[128];
+static u32 tlb_handler[128] __initdata;
/* simply assume worst case size for labels and relocs */
-static __initdata struct label labels[128];
-static __initdata struct reloc relocs[128];
+static struct label labels[128] __initdata;
+static struct reloc relocs[128] __initdata;
/*
* The R3000 TLB handler is simple.
{
long pgdc = (long)pgd_current;
u32 *p;
- int i;
memset(tlb_handler, 0, sizeof(tlb_handler));
p = tlb_handler;
pr_info("Synthesized TLB refill handler (%u instructions).\n",
(unsigned int)(p - tlb_handler));
- 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);
+
+ dump_handler((u32 *)ebase, 32);
}
/*
* other one.To keep things simple, we first assume linear space,
* then we relocate it to the final handler layout as needed.
*/
-static __initdata u32 final_handler[64];
+static u32 final_handler[64] __initdata;
/*
* Hazards
*
* As if we MIPS hackers wouldn't know how to nop pipelines happy ...
*/
-static __init void __maybe_unused build_tlb_probe_entry(u32 **p)
+static void __init __maybe_unused build_tlb_probe_entry(u32 **p)
{
- switch (current_cpu_data.cputype) {
+ switch (current_cpu_type()) {
/* Found by experiment: R4600 v2.0 needs this, too. */
case CPU_R4600:
case CPU_R5000:
*/
enum tlb_write_entry { tlb_random, tlb_indexed };
-static __init void build_tlb_write_entry(u32 **p, struct label **l,
+static void __init build_tlb_write_entry(u32 **p, struct label **l,
struct reloc **r,
enum tlb_write_entry wmode)
{
case tlb_indexed: tlbw = i_tlbwi; break;
}
- switch (current_cpu_data.cputype) {
+ if (cpu_has_mips_r2) {
+ i_ehb(p);
+ tlbw(p);
+ return;
+ }
+
+ switch (current_cpu_type()) {
case CPU_R4000PC:
case CPU_R4000SC:
case CPU_R4000MC:
case CPU_AU1500:
case CPU_AU1550:
case CPU_AU1200:
+ case CPU_AU1210:
+ case CPU_AU1250:
case CPU_PR4450:
i_nop(p);
tlbw(p);
case CPU_4KSC:
case CPU_20KC:
case CPU_25KF:
+ case CPU_BCM3302:
+ case CPU_BCM4710:
case CPU_LOONGSON2:
if (m4kc_tlbp_war())
i_nop(p);
tlbw(p);
break;
- case CPU_4KEC:
- case CPU_24K:
- case CPU_34K:
- case CPU_74K:
- i_ehb(p);
- tlbw(p);
- break;
-
case CPU_RM9000:
/*
* When the JTLB is updated by tlbwi or tlbwr, a subsequent
* TMP and PTR are scratch.
* TMP will be clobbered, PTR will hold the pmd entry.
*/
-static __init void
+static void __init
build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
unsigned int tmp, unsigned int ptr)
{
* BVADDR is the faulting address, PTR is scratch.
* PTR will hold the pgd for vmalloc.
*/
-static __init void
+static void __init
build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r,
unsigned int bvaddr, unsigned int ptr)
{
} else {
i_LA_mostly(p, ptr, modd);
il_b(p, r, label_vmalloc_done);
- i_daddiu(p, ptr, ptr, rel_lo(modd));
+ if (in_compat_space_p(modd))
+ i_addiu(p, ptr, ptr, rel_lo(modd));
+ else
+ i_daddiu(p, ptr, ptr, rel_lo(modd));
}
l_vmalloc(l, *p);
} else {
i_LA_mostly(p, ptr, swpd);
il_b(p, r, label_vmalloc_done);
- i_daddiu(p, ptr, ptr, rel_lo(swpd));
+ if (in_compat_space_p(swpd))
+ i_addiu(p, ptr, ptr, rel_lo(swpd));
+ else
+ i_daddiu(p, ptr, ptr, rel_lo(swpd));
}
}
* TMP and PTR are scratch.
* TMP will be clobbered, PTR will hold the pgd entry.
*/
-static __init void __maybe_unused
+static void __init __maybe_unused
build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
{
long pgdc = (long)pgd_current;
#endif /* !CONFIG_64BIT */
-static __init void build_adjust_context(u32 **p, unsigned int ctx)
+static void __init build_adjust_context(u32 **p, unsigned int ctx)
{
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) {
+ switch (current_cpu_type()) {
case CPU_VR41XX:
case CPU_VR4111:
case CPU_VR4121:
i_andi(p, ctx, ctx, mask);
}
-static __init void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr)
+static void __init build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr)
{
/*
* Bug workaround for the Nevada. It seems as if under certain
* in a different cacheline or a load instruction, probably any
* memory reference, is between them.
*/
- switch (current_cpu_data.cputype) {
+ switch (current_cpu_type()) {
case CPU_NEVADA:
i_LW(p, ptr, 0, ptr);
GET_CONTEXT(p, tmp); /* get context reg */
i_ADDU(p, ptr, ptr, tmp); /* add in offset */
}
-static __init void build_update_entries(u32 **p, unsigned int tmp,
+static void __init build_update_entries(u32 **p, unsigned int tmp,
unsigned int ptep)
{
/*
struct reloc *r = relocs;
u32 *f;
unsigned int final_len;
- int i;
memset(tlb_handler, 0, sizeof(tlb_handler));
memset(labels, 0, sizeof(labels));
pr_info("Synthesized TLB refill handler (%u instructions).\n",
final_len);
- f = final_handler;
-#if defined(CONFIG_64BIT) && !defined(CONFIG_CPU_LOONGSON2)
- if (final_len > 32)
- final_len = 64;
- else
- f = final_handler + 32;
-#endif /* CONFIG_64BIT */
- 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);
+
+ dump_handler((u32 *)ebase, 64);
}
/*
extern void tlb_do_page_fault_0(void);
extern void tlb_do_page_fault_1(void);
-#define __tlb_handler_align \
- __attribute__((__aligned__(1 << CONFIG_MIPS_L1_CACHE_SHIFT)))
-
/*
* 128 instructions for the fastpath handler is generous and should
* never be exceeded.
*/
#define FASTPATH_SIZE 128
-u32 __tlb_handler_align handle_tlbl[FASTPATH_SIZE];
-u32 __tlb_handler_align handle_tlbs[FASTPATH_SIZE];
-u32 __tlb_handler_align handle_tlbm[FASTPATH_SIZE];
+u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned;
+u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned;
+u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned;
static void __init
iPTE_LW(u32 **p, struct label **l, unsigned int pte, unsigned int ptr)
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));
pr_info("Synthesized TLB load handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbl));
- 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");
+ dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
}
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));
pr_info("Synthesized TLB store handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbs));
- 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");
+ dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
}
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));
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");
+ dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
}
/*
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));
pr_info("Synthesized TLB load handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbl));
- 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");
+ dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
}
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));
pr_info("Synthesized TLB store handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbs));
- 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");
+ dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
}
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));
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");
+ dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
}
void __init build_tlb_refill_handler(void)
*/
static int run_once = 0;
- switch (current_cpu_data.cputype) {
+ switch (current_cpu_type()) {
case CPU_R2000:
case CPU_R3000:
case CPU_R3000A: