aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/include/asm/mmu_context.h6
-rw-r--r--arch/mips/mm/Makefile2
-rw-r--r--arch/mips/mm/tlb-funcs.S37
-rw-r--r--arch/mips/mm/tlbex.c84
4 files changed, 83 insertions, 46 deletions
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 820116067c10..1fed8bdcf2a0 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -28,11 +28,7 @@
28 28
29#define TLBMISS_HANDLER_SETUP_PGD(pgd) \ 29#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
30do { \ 30do { \
31 void (*tlbmiss_handler_setup_pgd)(unsigned long); \ 31 extern void tlbmiss_handler_setup_pgd(unsigned long); \
32 extern u32 tlbmiss_handler_setup_pgd_array[16]; \
33 \
34 tlbmiss_handler_setup_pgd = \
35 (__typeof__(tlbmiss_handler_setup_pgd)) tlbmiss_handler_setup_pgd_array; \
36 tlbmiss_handler_setup_pgd((unsigned long)(pgd)); \ 32 tlbmiss_handler_setup_pgd((unsigned long)(pgd)); \
37} while (0) 33} while (0)
38 34
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index e87aae1f2e80..7f4f93ab22b7 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-y += cache.o dma-default.o extable.o fault.o \ 5obj-y += cache.o dma-default.o extable.o fault.o \
6 gup.o init.o mmap.o page.o page-funcs.o \ 6 gup.o init.o mmap.o page.o page-funcs.o \
7 tlbex.o tlbex-fault.o uasm-mips.o 7 tlbex.o tlbex-fault.o tlb-funcs.o uasm-mips.o
8 8
9obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o 9obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o
10obj-$(CONFIG_64BIT) += pgtable-64.o 10obj-$(CONFIG_64BIT) += pgtable-64.o
diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S
new file mode 100644
index 000000000000..30a494db99c2
--- /dev/null
+++ b/arch/mips/mm/tlb-funcs.S
@@ -0,0 +1,37 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Micro-assembler generated tlb handler functions.
7 *
8 * Copyright (C) 2013 Broadcom Corporation.
9 *
10 * Based on mm/page-funcs.c
11 * Copyright (C) 2012 MIPS Technologies, Inc.
12 * Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org>
13 */
14#include <asm/asm.h>
15#include <asm/regdef.h>
16
17#define FASTPATH_SIZE 128
18
19LEAF(tlbmiss_handler_setup_pgd)
20 .space 16 * 4
21END(tlbmiss_handler_setup_pgd)
22EXPORT(tlbmiss_handler_setup_pgd_end)
23
24LEAF(handle_tlbm)
25 .space FASTPATH_SIZE * 4
26END(handle_tlbm)
27EXPORT(handle_tlbm_end)
28
29LEAF(handle_tlbs)
30 .space FASTPATH_SIZE * 4
31END(handle_tlbs)
32EXPORT(handle_tlbs_end)
33
34LEAF(handle_tlbl)
35 .space FASTPATH_SIZE * 4
36END(handle_tlbl)
37EXPORT(handle_tlbl_end)
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 9b988c050fdd..4712f3cd73b7 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -1455,27 +1455,25 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
1455 dump_handler("r4000_tlb_refill", (u32 *)ebase, 64); 1455 dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
1456} 1456}
1457 1457
1458/* 1458extern u32 handle_tlbl[], handle_tlbl_end[];
1459 * 128 instructions for the fastpath handler is generous and should 1459extern u32 handle_tlbs[], handle_tlbs_end[];
1460 * never be exceeded. 1460extern u32 handle_tlbm[], handle_tlbm_end[];
1461 */
1462#define FASTPATH_SIZE 128
1463 1461
1464u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned;
1465u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned;
1466u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned;
1467#ifdef CONFIG_MIPS_PGD_C0_CONTEXT 1462#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
1468u32 tlbmiss_handler_setup_pgd_array[16] __cacheline_aligned; 1463extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[];
1469 1464
1470static void __cpuinit build_r4000_setup_pgd(void) 1465static void __cpuinit build_r4000_setup_pgd(void)
1471{ 1466{
1472 const int a0 = 4; 1467 const int a0 = 4;
1473 const int a1 = 5; 1468 const int a1 = 5;
1474 u32 *p = tlbmiss_handler_setup_pgd_array; 1469 u32 *p = tlbmiss_handler_setup_pgd_array;
1470 const int tlbmiss_handler_setup_pgd_size =
1471 tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd;
1475 struct uasm_label *l = labels; 1472 struct uasm_label *l = labels;
1476 struct uasm_reloc *r = relocs; 1473 struct uasm_reloc *r = relocs;
1477 1474
1478 memset(tlbmiss_handler_setup_pgd_array, 0, sizeof(tlbmiss_handler_setup_pgd_array)); 1475 memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size *
1476 sizeof(tlbmiss_handler_setup_pgd[0]));
1479 memset(labels, 0, sizeof(labels)); 1477 memset(labels, 0, sizeof(labels));
1480 memset(relocs, 0, sizeof(relocs)); 1478 memset(relocs, 0, sizeof(relocs));
1481 1479
@@ -1503,15 +1501,15 @@ static void __cpuinit build_r4000_setup_pgd(void)
1503 uasm_i_jr(&p, 31); 1501 uasm_i_jr(&p, 31);
1504 UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); 1502 UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
1505 } 1503 }
1506 if (p - tlbmiss_handler_setup_pgd_array > ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)) 1504 if (p >= tlbmiss_handler_setup_pgd_end)
1507 panic("tlbmiss_handler_setup_pgd_array space exceeded"); 1505 panic("tlbmiss_handler_setup_pgd space exceeded");
1506
1508 uasm_resolve_relocs(relocs, labels); 1507 uasm_resolve_relocs(relocs, labels);
1509 pr_debug("Wrote tlbmiss_handler_setup_pgd_array (%u instructions).\n", 1508 pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
1510 (unsigned int)(p - tlbmiss_handler_setup_pgd_array)); 1509 (unsigned int)(p - tlbmiss_handler_setup_pgd));
1511 1510
1512 dump_handler("tlbmiss_handler", 1511 dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd,
1513 tlbmiss_handler_setup_pgd_array, 1512 tlbmiss_handler_setup_pgd_size);
1514 ARRAY_SIZE(tlbmiss_handler_setup_pgd_array));
1515} 1513}
1516#endif 1514#endif
1517 1515
@@ -1756,10 +1754,11 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte,
1756static void __cpuinit build_r3000_tlb_load_handler(void) 1754static void __cpuinit build_r3000_tlb_load_handler(void)
1757{ 1755{
1758 u32 *p = handle_tlbl; 1756 u32 *p = handle_tlbl;
1757 const int handle_tlbl_size = handle_tlbl_end - handle_tlbl;
1759 struct uasm_label *l = labels; 1758 struct uasm_label *l = labels;
1760 struct uasm_reloc *r = relocs; 1759 struct uasm_reloc *r = relocs;
1761 1760
1762 memset(handle_tlbl, 0, sizeof(handle_tlbl)); 1761 memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0]));
1763 memset(labels, 0, sizeof(labels)); 1762 memset(labels, 0, sizeof(labels));
1764 memset(relocs, 0, sizeof(relocs)); 1763 memset(relocs, 0, sizeof(relocs));
1765 1764
@@ -1773,23 +1772,24 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
1773 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); 1772 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
1774 uasm_i_nop(&p); 1773 uasm_i_nop(&p);
1775 1774
1776 if ((p - handle_tlbl) > FASTPATH_SIZE) 1775 if (p >= handle_tlbl_end)
1777 panic("TLB load handler fastpath space exceeded"); 1776 panic("TLB load handler fastpath space exceeded");
1778 1777
1779 uasm_resolve_relocs(relocs, labels); 1778 uasm_resolve_relocs(relocs, labels);
1780 pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", 1779 pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
1781 (unsigned int)(p - handle_tlbl)); 1780 (unsigned int)(p - handle_tlbl));
1782 1781
1783 dump_handler("r3000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl)); 1782 dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_size);
1784} 1783}
1785 1784
1786static void __cpuinit build_r3000_tlb_store_handler(void) 1785static void __cpuinit build_r3000_tlb_store_handler(void)
1787{ 1786{
1788 u32 *p = handle_tlbs; 1787 u32 *p = handle_tlbs;
1788 const int handle_tlbs_size = handle_tlbs_end - handle_tlbs;
1789 struct uasm_label *l = labels; 1789 struct uasm_label *l = labels;
1790 struct uasm_reloc *r = relocs; 1790 struct uasm_reloc *r = relocs;
1791 1791
1792 memset(handle_tlbs, 0, sizeof(handle_tlbs)); 1792 memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0]));
1793 memset(labels, 0, sizeof(labels)); 1793 memset(labels, 0, sizeof(labels));
1794 memset(relocs, 0, sizeof(relocs)); 1794 memset(relocs, 0, sizeof(relocs));
1795 1795
@@ -1803,23 +1803,24 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
1803 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); 1803 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
1804 uasm_i_nop(&p); 1804 uasm_i_nop(&p);
1805 1805
1806 if ((p - handle_tlbs) > FASTPATH_SIZE) 1806 if (p >= handle_tlbs)
1807 panic("TLB store handler fastpath space exceeded"); 1807 panic("TLB store handler fastpath space exceeded");
1808 1808
1809 uasm_resolve_relocs(relocs, labels); 1809 uasm_resolve_relocs(relocs, labels);
1810 pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", 1810 pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
1811 (unsigned int)(p - handle_tlbs)); 1811 (unsigned int)(p - handle_tlbs));
1812 1812
1813 dump_handler("r3000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs)); 1813 dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_size);
1814} 1814}
1815 1815
1816static void __cpuinit build_r3000_tlb_modify_handler(void) 1816static void __cpuinit build_r3000_tlb_modify_handler(void)
1817{ 1817{
1818 u32 *p = handle_tlbm; 1818 u32 *p = handle_tlbm;
1819 const int handle_tlbm_size = handle_tlbm_end - handle_tlbm;
1819 struct uasm_label *l = labels; 1820 struct uasm_label *l = labels;
1820 struct uasm_reloc *r = relocs; 1821 struct uasm_reloc *r = relocs;
1821 1822
1822 memset(handle_tlbm, 0, sizeof(handle_tlbm)); 1823 memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0]));
1823 memset(labels, 0, sizeof(labels)); 1824 memset(labels, 0, sizeof(labels));
1824 memset(relocs, 0, sizeof(relocs)); 1825 memset(relocs, 0, sizeof(relocs));
1825 1826
@@ -1833,14 +1834,14 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
1833 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); 1834 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
1834 uasm_i_nop(&p); 1835 uasm_i_nop(&p);
1835 1836
1836 if ((p - handle_tlbm) > FASTPATH_SIZE) 1837 if (p >= handle_tlbm_end)
1837 panic("TLB modify handler fastpath space exceeded"); 1838 panic("TLB modify handler fastpath space exceeded");
1838 1839
1839 uasm_resolve_relocs(relocs, labels); 1840 uasm_resolve_relocs(relocs, labels);
1840 pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", 1841 pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
1841 (unsigned int)(p - handle_tlbm)); 1842 (unsigned int)(p - handle_tlbm));
1842 1843
1843 dump_handler("r3000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); 1844 dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_size);
1844} 1845}
1845#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ 1846#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
1846 1847
@@ -1904,11 +1905,12 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
1904static void __cpuinit build_r4000_tlb_load_handler(void) 1905static void __cpuinit build_r4000_tlb_load_handler(void)
1905{ 1906{
1906 u32 *p = handle_tlbl; 1907 u32 *p = handle_tlbl;
1908 const int handle_tlbl_size = handle_tlbl_end - handle_tlbl;
1907 struct uasm_label *l = labels; 1909 struct uasm_label *l = labels;
1908 struct uasm_reloc *r = relocs; 1910 struct uasm_reloc *r = relocs;
1909 struct work_registers wr; 1911 struct work_registers wr;
1910 1912
1911 memset(handle_tlbl, 0, sizeof(handle_tlbl)); 1913 memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0]));
1912 memset(labels, 0, sizeof(labels)); 1914 memset(labels, 0, sizeof(labels));
1913 memset(relocs, 0, sizeof(relocs)); 1915 memset(relocs, 0, sizeof(relocs));
1914 1916
@@ -2047,24 +2049,25 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
2047 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); 2049 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
2048 uasm_i_nop(&p); 2050 uasm_i_nop(&p);
2049 2051
2050 if ((p - handle_tlbl) > FASTPATH_SIZE) 2052 if (p >= handle_tlbl_end)
2051 panic("TLB load handler fastpath space exceeded"); 2053 panic("TLB load handler fastpath space exceeded");
2052 2054
2053 uasm_resolve_relocs(relocs, labels); 2055 uasm_resolve_relocs(relocs, labels);
2054 pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", 2056 pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
2055 (unsigned int)(p - handle_tlbl)); 2057 (unsigned int)(p - handle_tlbl));
2056 2058
2057 dump_handler("r4000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl)); 2059 dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_size);
2058} 2060}
2059 2061
2060static void __cpuinit build_r4000_tlb_store_handler(void) 2062static void __cpuinit build_r4000_tlb_store_handler(void)
2061{ 2063{
2062 u32 *p = handle_tlbs; 2064 u32 *p = handle_tlbs;
2065 const int handle_tlbs_size = handle_tlbs_end - handle_tlbs;
2063 struct uasm_label *l = labels; 2066 struct uasm_label *l = labels;
2064 struct uasm_reloc *r = relocs; 2067 struct uasm_reloc *r = relocs;
2065 struct work_registers wr; 2068 struct work_registers wr;
2066 2069
2067 memset(handle_tlbs, 0, sizeof(handle_tlbs)); 2070 memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0]));
2068 memset(labels, 0, sizeof(labels)); 2071 memset(labels, 0, sizeof(labels));
2069 memset(relocs, 0, sizeof(relocs)); 2072 memset(relocs, 0, sizeof(relocs));
2070 2073
@@ -2101,24 +2104,25 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
2101 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); 2104 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
2102 uasm_i_nop(&p); 2105 uasm_i_nop(&p);
2103 2106
2104 if ((p - handle_tlbs) > FASTPATH_SIZE) 2107 if (p >= handle_tlbs_end)
2105 panic("TLB store handler fastpath space exceeded"); 2108 panic("TLB store handler fastpath space exceeded");
2106 2109
2107 uasm_resolve_relocs(relocs, labels); 2110 uasm_resolve_relocs(relocs, labels);
2108 pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", 2111 pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
2109 (unsigned int)(p - handle_tlbs)); 2112 (unsigned int)(p - handle_tlbs));
2110 2113
2111 dump_handler("r4000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs)); 2114 dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_size);
2112} 2115}
2113 2116
2114static void __cpuinit build_r4000_tlb_modify_handler(void) 2117static void __cpuinit build_r4000_tlb_modify_handler(void)
2115{ 2118{
2116 u32 *p = handle_tlbm; 2119 u32 *p = handle_tlbm;
2120 const int handle_tlbm_size = handle_tlbm_end - handle_tlbm;
2117 struct uasm_label *l = labels; 2121 struct uasm_label *l = labels;
2118 struct uasm_reloc *r = relocs; 2122 struct uasm_reloc *r = relocs;
2119 struct work_registers wr; 2123 struct work_registers wr;
2120 2124
2121 memset(handle_tlbm, 0, sizeof(handle_tlbm)); 2125 memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0]));
2122 memset(labels, 0, sizeof(labels)); 2126 memset(labels, 0, sizeof(labels));
2123 memset(relocs, 0, sizeof(relocs)); 2127 memset(relocs, 0, sizeof(relocs));
2124 2128
@@ -2156,14 +2160,14 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
2156 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); 2160 uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
2157 uasm_i_nop(&p); 2161 uasm_i_nop(&p);
2158 2162
2159 if ((p - handle_tlbm) > FASTPATH_SIZE) 2163 if (p >= handle_tlbm_end)
2160 panic("TLB modify handler fastpath space exceeded"); 2164 panic("TLB modify handler fastpath space exceeded");
2161 2165
2162 uasm_resolve_relocs(relocs, labels); 2166 uasm_resolve_relocs(relocs, labels);
2163 pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", 2167 pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
2164 (unsigned int)(p - handle_tlbm)); 2168 (unsigned int)(p - handle_tlbm));
2165 2169
2166 dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); 2170 dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_size);
2167} 2171}
2168 2172
2169void __cpuinit build_tlb_refill_handler(void) 2173void __cpuinit build_tlb_refill_handler(void)
@@ -2235,13 +2239,13 @@ void __cpuinit build_tlb_refill_handler(void)
2235void __cpuinit flush_tlb_handlers(void) 2239void __cpuinit flush_tlb_handlers(void)
2236{ 2240{
2237 local_flush_icache_range((unsigned long)handle_tlbl, 2241 local_flush_icache_range((unsigned long)handle_tlbl,
2238 (unsigned long)handle_tlbl + sizeof(handle_tlbl)); 2242 (unsigned long)handle_tlbl_end);
2239 local_flush_icache_range((unsigned long)handle_tlbs, 2243 local_flush_icache_range((unsigned long)handle_tlbs,
2240 (unsigned long)handle_tlbs + sizeof(handle_tlbs)); 2244 (unsigned long)handle_tlbs_end);
2241 local_flush_icache_range((unsigned long)handle_tlbm, 2245 local_flush_icache_range((unsigned long)handle_tlbm,
2242 (unsigned long)handle_tlbm + sizeof(handle_tlbm)); 2246 (unsigned long)handle_tlbm_end);
2243#ifdef CONFIG_MIPS_PGD_C0_CONTEXT 2247#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
2244 local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array, 2248 local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
2245 (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm)); 2249 (unsigned long)tlbmiss_handler_setup_pgd_end);
2246#endif 2250#endif
2247} 2251}