summaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/include/asm/mmu_context.h1
-rw-r--r--arch/mips/include/asm/tlbex.h9
-rw-r--r--arch/mips/kernel/traps.c4
-rw-r--r--arch/mips/mm/tlb-funcs.S1
-rw-r--r--arch/mips/mm/tlbex.c100
5 files changed, 51 insertions, 64 deletions
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index b509371a6b0c..94414561de0e 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -32,6 +32,7 @@ do { \
} while (0)
extern void tlbmiss_handler_setup_pgd(unsigned long);
+extern char tlbmiss_handler_setup_pgd_end[];
/* Note: This is also implemented with uasm in arch/mips/kvm/entry.c */
#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
diff --git a/arch/mips/include/asm/tlbex.h b/arch/mips/include/asm/tlbex.h
index 4ed7ebed3bf1..6d97e23f30ab 100644
--- a/arch/mips/include/asm/tlbex.h
+++ b/arch/mips/include/asm/tlbex.h
@@ -24,4 +24,13 @@ void build_tlb_write_entry(u32 **p, struct uasm_label **l,
struct uasm_reloc **r,
enum tlb_write_entry wmode);
+extern void handle_tlbl(void);
+extern char handle_tlbl_end[];
+
+extern void handle_tlbs(void);
+extern char handle_tlbs_end[];
+
+extern void handle_tlbm(void);
+extern char handle_tlbm_end[];
+
#endif /* __ASM_TLBEX_H */
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 4d9ca9b465ae..5e1e580dd164 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -67,14 +67,12 @@
#include <asm/mmu_context.h>
#include <asm/types.h>
#include <asm/stacktrace.h>
+#include <asm/tlbex.h>
#include <asm/uasm.h>
extern void check_wait(void);
extern asmlinkage void rollback_handle_int(void);
extern asmlinkage void handle_int(void);
-extern u32 handle_tlbl[];
-extern u32 handle_tlbs[];
-extern u32 handle_tlbm[];
extern asmlinkage void handle_adel(void);
extern asmlinkage void handle_ades(void);
extern asmlinkage void handle_ibe(void);
diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S
index ae34361b6060..00fef578c8cd 100644
--- a/arch/mips/mm/tlb-funcs.S
+++ b/arch/mips/mm/tlb-funcs.S
@@ -17,7 +17,6 @@
#define FASTPATH_SIZE 128
-EXPORT(tlbmiss_handler_setup_pgd_start)
LEAF(tlbmiss_handler_setup_pgd)
1: j 1b /* Dummy, will be replaced. */
.space 64
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 2223620fb573..067714291643 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -31,6 +31,7 @@
#include <asm/cacheflush.h>
#include <asm/cpu-type.h>
+#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/war.h>
#include <asm/uasm.h>
@@ -253,8 +254,10 @@ static void output_pgtable_bits_defines(void)
pr_debug("\n");
}
-static inline void dump_handler(const char *symbol, const u32 *handler, int count)
+static inline void dump_handler(const char *symbol, const void *start, const void *end)
{
+ unsigned int count = (end - start) / sizeof(u32);
+ const u32 *handler = start;
int i;
pr_debug("LEAF(%s)\n", symbol);
@@ -402,12 +405,6 @@ static void build_restore_work_registers(u32 **p)
* CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
* we cannot do r3000 under these circumstances.
*
- * Declare pgd_current here instead of including mmu_context.h to avoid type
- * conflicts for tlbmiss_handler_setup_pgd
- */
-extern unsigned long pgd_current[];
-
-/*
* The R3000 TLB handler is simple.
*/
static void build_r3000_tlb_refill_handler(void)
@@ -444,8 +441,7 @@ static void build_r3000_tlb_refill_handler(void)
memcpy((void *)ebase, tlb_handler, 0x80);
local_flush_icache_range(ebase, ebase + 0x80);
-
- dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
+ dump_handler("r3000_tlb_refill", (u32 *)ebase, (u32 *)(ebase + 0x80));
}
#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
@@ -1465,8 +1461,7 @@ static void build_r4000_tlb_refill_handler(void)
memcpy((void *)ebase, final_handler, 0x100);
local_flush_icache_range(ebase, ebase + 0x100);
-
- dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
+ dump_handler("r4000_tlb_refill", (u32 *)ebase, (u32 *)(ebase + 0x100));
}
static void setup_pw(void)
@@ -1568,30 +1563,21 @@ static void build_loongson3_tlb_refill_handler(void)
uasm_resolve_relocs(relocs, labels);
memcpy((void *)(ebase + 0x80), tlb_handler, 0x80);
local_flush_icache_range(ebase + 0x80, ebase + 0x100);
- dump_handler("loongson3_tlb_refill", (u32 *)(ebase + 0x80), 32);
+ dump_handler("loongson3_tlb_refill",
+ (u32 *)(ebase + 0x80), (u32 *)(ebase + 0x100));
}
-extern u32 handle_tlbl[], handle_tlbl_end[];
-extern u32 handle_tlbs[], handle_tlbs_end[];
-extern u32 handle_tlbm[], handle_tlbm_end[];
-extern u32 tlbmiss_handler_setup_pgd_start[];
-extern u32 tlbmiss_handler_setup_pgd[];
-extern u32 tlbmiss_handler_setup_pgd_end[];
-
static void build_setup_pgd(void)
{
const int a0 = 4;
const int __maybe_unused a1 = 5;
const int __maybe_unused a2 = 6;
- u32 *p = tlbmiss_handler_setup_pgd_start;
- const int tlbmiss_handler_setup_pgd_size =
- tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd_start;
+ u32 *p = (u32 *)msk_isa16_mode((ulong)tlbmiss_handler_setup_pgd);
#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
long pgdc = (long)pgd_current;
#endif
- memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size *
- sizeof(tlbmiss_handler_setup_pgd[0]));
+ memset(p, 0, tlbmiss_handler_setup_pgd_end - (char *)p);
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
pgd_reg = allocate_kscratch();
@@ -1644,15 +1630,15 @@ static void build_setup_pgd(void)
else
uasm_i_nop(&p);
#endif
- if (p >= tlbmiss_handler_setup_pgd_end)
+ if (p >= (u32 *)tlbmiss_handler_setup_pgd_end)
panic("tlbmiss_handler_setup_pgd space exceeded");
uasm_resolve_relocs(relocs, labels);
pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
- (unsigned int)(p - tlbmiss_handler_setup_pgd));
+ (unsigned int)(p - (u32 *)tlbmiss_handler_setup_pgd));
dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd,
- tlbmiss_handler_setup_pgd_size);
+ tlbmiss_handler_setup_pgd_end);
}
static void
@@ -1921,12 +1907,11 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte,
static void build_r3000_tlb_load_handler(void)
{
- u32 *p = handle_tlbl;
- const int handle_tlbl_size = handle_tlbl_end - handle_tlbl;
+ u32 *p = (u32 *)handle_tlbl;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
- memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0]));
+ memset(p, 0, handle_tlbl_end - (char *)p);
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
@@ -1940,24 +1925,23 @@ static void build_r3000_tlb_load_handler(void)
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
uasm_i_nop(&p);
- if (p >= handle_tlbl_end)
+ if (p >= (u32 *)handle_tlbl_end)
panic("TLB load handler fastpath space exceeded");
uasm_resolve_relocs(relocs, labels);
pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbl));
+ (unsigned int)(p - (u32 *)handle_tlbl));
- dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_size);
+ dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_end);
}
static void build_r3000_tlb_store_handler(void)
{
- u32 *p = handle_tlbs;
- const int handle_tlbs_size = handle_tlbs_end - handle_tlbs;
+ u32 *p = (u32 *)handle_tlbs;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
- memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0]));
+ memset(p, 0, handle_tlbs_end - (char *)p);
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
@@ -1971,24 +1955,23 @@ static void build_r3000_tlb_store_handler(void)
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
uasm_i_nop(&p);
- if (p >= handle_tlbs_end)
+ if (p >= (u32 *)handle_tlbs_end)
panic("TLB store handler fastpath space exceeded");
uasm_resolve_relocs(relocs, labels);
pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbs));
+ (unsigned int)(p - (u32 *)handle_tlbs));
- dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_size);
+ dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_end);
}
static void build_r3000_tlb_modify_handler(void)
{
- u32 *p = handle_tlbm;
- const int handle_tlbm_size = handle_tlbm_end - handle_tlbm;
+ u32 *p = (u32 *)handle_tlbm;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
- memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0]));
+ memset(p, 0, handle_tlbm_end - (char *)p);
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
@@ -2002,14 +1985,14 @@ static void build_r3000_tlb_modify_handler(void)
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
uasm_i_nop(&p);
- if (p >= handle_tlbm_end)
+ if (p >= (u32 *)handle_tlbm_end)
panic("TLB modify handler fastpath space exceeded");
uasm_resolve_relocs(relocs, labels);
pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbm));
+ (unsigned int)(p - (u32 *)handle_tlbm));
- dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_size);
+ dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_end);
}
#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
@@ -2101,12 +2084,11 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
static void build_r4000_tlb_load_handler(void)
{
u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbl);
- const int handle_tlbl_size = handle_tlbl_end - handle_tlbl;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
struct work_registers wr;
- memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0]));
+ memset(p, 0, handle_tlbl_end - (char *)p);
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
@@ -2287,25 +2269,24 @@ static void build_r4000_tlb_load_handler(void)
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
uasm_i_nop(&p);
- if (p >= handle_tlbl_end)
+ if (p >= (u32 *)handle_tlbl_end)
panic("TLB load handler fastpath space exceeded");
uasm_resolve_relocs(relocs, labels);
pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbl));
+ (unsigned int)(p - (u32 *)handle_tlbl));
- dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_size);
+ dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_end);
}
static void build_r4000_tlb_store_handler(void)
{
u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbs);
- const int handle_tlbs_size = handle_tlbs_end - handle_tlbs;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
struct work_registers wr;
- memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0]));
+ memset(p, 0, handle_tlbs_end - (char *)p);
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
@@ -2342,25 +2323,24 @@ static void build_r4000_tlb_store_handler(void)
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
uasm_i_nop(&p);
- if (p >= handle_tlbs_end)
+ if (p >= (u32 *)handle_tlbs_end)
panic("TLB store handler fastpath space exceeded");
uasm_resolve_relocs(relocs, labels);
pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbs));
+ (unsigned int)(p - (u32 *)handle_tlbs));
- dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_size);
+ dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_end);
}
static void build_r4000_tlb_modify_handler(void)
{
u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbm);
- const int handle_tlbm_size = handle_tlbm_end - handle_tlbm;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
struct work_registers wr;
- memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0]));
+ memset(p, 0, handle_tlbm_end - (char *)p);
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
@@ -2398,14 +2378,14 @@ static void build_r4000_tlb_modify_handler(void)
uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
uasm_i_nop(&p);
- if (p >= handle_tlbm_end)
+ if (p >= (u32 *)handle_tlbm_end)
panic("TLB modify handler fastpath space exceeded");
uasm_resolve_relocs(relocs, labels);
pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
- (unsigned int)(p - handle_tlbm));
+ (unsigned int)(p - (u32 *)handle_tlbm));
- dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_size);
+ dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_end);
}
static void flush_tlb_handlers(void)