aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorSteven J. Hill <Steven.Hill@imgtec.com>2013-03-25 12:58:57 -0400
committerRalf Baechle <ralf@linux-mips.org>2013-05-08 06:30:10 -0400
commitd532f3d26716a39dfd4b88d687bd344fbe77e390 (patch)
tree64bb16ffd8176e0c9e692817b1d17df717c127ed /arch/mips
parent49bffbdc88fdd8f5eac40306a617252625a0fa35 (diff)
MIPS: Allow ASID size to be determined at boot time.
Original patch by Ralf Baechle and removed by Harold Koerfgen with commit f67e4ffc79905482c3b9b8c8dd65197bac7eb508. This allows for more generic kernels since the size of the ASID and corresponding masks can be determined at run-time. This patch is also required for the new Aptiv cores and has been tested on Malta and Malta Aptiv platforms. [ralf@linux-mips.org: Added relevant part of fix https://patchwork.linux-mips.org/patch/5213/] Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/include/asm/mmu_context.h95
-rw-r--r--arch/mips/kernel/genex.S2
-rw-r--r--arch/mips/kernel/smtc.c10
-rw-r--r--arch/mips/kernel/traps.c6
-rw-r--r--arch/mips/lib/dump_tlb.c5
-rw-r--r--arch/mips/lib/r3k_dump_tlb.c7
-rw-r--r--arch/mips/mm/tlb-r3k.c20
-rw-r--r--arch/mips/mm/tlb-r4k.c2
-rw-r--r--arch/mips/mm/tlb-r8k.c2
-rw-r--r--arch/mips/mm/tlbex.c49
10 files changed, 137 insertions, 61 deletions
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index e81d719efcd1..bab1980bbf0d 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -62,45 +62,68 @@ extern unsigned long pgd_current[];
62 TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) 62 TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
63#endif 63#endif
64#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/ 64#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
65#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
66 65
67#define ASID_INC 0x40 66#define ASID_INC(asid) \
68#define ASID_MASK 0xfc0 67({ \
69 68 unsigned long __asid = asid; \
70#elif defined(CONFIG_CPU_R8000) 69 __asm__("1:\taddiu\t%0,1\t\t\t\t# patched\n\t" \
71 70 ".section\t__asid_inc,\"a\"\n\t" \
72#define ASID_INC 0x10 71 ".word\t1b\n\t" \
73#define ASID_MASK 0xff0 72 ".previous" \
74 73 :"=r" (__asid) \
75#elif defined(CONFIG_MIPS_MT_SMTC) 74 :"0" (__asid)); \
76 75 __asid; \
77#define ASID_INC 0x1 76})
78extern unsigned long smtc_asid_mask; 77#define ASID_MASK(asid) \
79#define ASID_MASK (smtc_asid_mask) 78({ \
80#define HW_ASID_MASK 0xff 79 unsigned long __asid = asid; \
81/* End SMTC/34K debug hack */ 80 __asm__("1:\tandi\t%0,%1,0xfc0\t\t\t# patched\n\t" \
82#else /* FIXME: not correct for R6000 */ 81 ".section\t__asid_mask,\"a\"\n\t" \
83 82 ".word\t1b\n\t" \
84#define ASID_INC 0x1 83 ".previous" \
85#define ASID_MASK 0xff 84 :"=r" (__asid) \
85 :"r" (__asid)); \
86 __asid; \
87})
88#define ASID_VERSION_MASK \
89({ \
90 unsigned long __asid; \
91 __asm__("1:\taddiu\t%0,$0,0xff00\t\t\t\t# patched\n\t" \
92 ".section\t__asid_version_mask,\"a\"\n\t" \
93 ".word\t1b\n\t" \
94 ".previous" \
95 :"=r" (__asid)); \
96 __asid; \
97})
98#define ASID_FIRST_VERSION \
99({ \
100 unsigned long __asid = asid; \
101 __asm__("1:\tli\t%0,0x100\t\t\t\t# patched\n\t" \
102 ".section\t__asid_first_version,\"a\"\n\t" \
103 ".word\t1b\n\t" \
104 ".previous" \
105 :"=r" (__asid)); \
106 __asid; \
107})
108
109#define ASID_FIRST_VERSION_R3000 0x1000
110#define ASID_FIRST_VERSION_R4000 0x100
111#define ASID_FIRST_VERSION_R8000 0x1000
112#define ASID_FIRST_VERSION_RM9000 0x1000
86 113
114#ifdef CONFIG_MIPS_MT_SMTC
115#define SMTC_HW_ASID_MASK 0xff
116extern unsigned int smtc_asid_mask;
87#endif 117#endif
88 118
89#define cpu_context(cpu, mm) ((mm)->context.asid[cpu]) 119#define cpu_context(cpu, mm) ((mm)->context.asid[cpu])
90#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK) 120#define cpu_asid(cpu, mm) ASID_MASK(cpu_context((cpu), (mm)))
91#define asid_cache(cpu) (cpu_data[cpu].asid_cache) 121#define asid_cache(cpu) (cpu_data[cpu].asid_cache)
92 122
93static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) 123static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
94{ 124{
95} 125}
96 126
97/*
98 * All unused by hardware upper bits will be considered
99 * as a software asid extension.
100 */
101#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
102#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
103
104#ifndef CONFIG_MIPS_MT_SMTC 127#ifndef CONFIG_MIPS_MT_SMTC
105/* Normal, classic MIPS get_new_mmu_context */ 128/* Normal, classic MIPS get_new_mmu_context */
106static inline void 129static inline void
@@ -108,7 +131,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
108{ 131{
109 unsigned long asid = asid_cache(cpu); 132 unsigned long asid = asid_cache(cpu);
110 133
111 if (! ((asid += ASID_INC) & ASID_MASK) ) { 134 if (!ASID_MASK((asid = ASID_INC(asid)))) {
112 if (cpu_has_vtag_icache) 135 if (cpu_has_vtag_icache)
113 flush_icache_all(); 136 flush_icache_all();
114 local_flush_tlb_all(); /* start new asid cycle */ 137 local_flush_tlb_all(); /* start new asid cycle */
@@ -166,7 +189,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
166 * free up the ASID value for use and flush any old 189 * free up the ASID value for use and flush any old
167 * instances of it from the TLB. 190 * instances of it from the TLB.
168 */ 191 */
169 oldasid = (read_c0_entryhi() & ASID_MASK); 192 oldasid = ASID_MASK(read_c0_entryhi());
170 if(smtc_live_asid[mytlb][oldasid]) { 193 if(smtc_live_asid[mytlb][oldasid]) {
171 smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); 194 smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
172 if(smtc_live_asid[mytlb][oldasid] == 0) 195 if(smtc_live_asid[mytlb][oldasid] == 0)
@@ -177,7 +200,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
177 * having ASID_MASK smaller than the hardware maximum, 200 * having ASID_MASK smaller than the hardware maximum,
178 * make sure no "soft" bits become "hard"... 201 * make sure no "soft" bits become "hard"...
179 */ 202 */
180 write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) | 203 write_c0_entryhi((read_c0_entryhi() & ~SMTC_HW_ASID_MASK) |
181 cpu_asid(cpu, next)); 204 cpu_asid(cpu, next));
182 ehb(); /* Make sure it propagates to TCStatus */ 205 ehb(); /* Make sure it propagates to TCStatus */
183 evpe(mtflags); 206 evpe(mtflags);
@@ -230,15 +253,15 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
230#ifdef CONFIG_MIPS_MT_SMTC 253#ifdef CONFIG_MIPS_MT_SMTC
231 /* See comments for similar code above */ 254 /* See comments for similar code above */
232 mtflags = dvpe(); 255 mtflags = dvpe();
233 oldasid = read_c0_entryhi() & ASID_MASK; 256 oldasid = ASID_MASK(read_c0_entryhi());
234 if(smtc_live_asid[mytlb][oldasid]) { 257 if(smtc_live_asid[mytlb][oldasid]) {
235 smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); 258 smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
236 if(smtc_live_asid[mytlb][oldasid] == 0) 259 if(smtc_live_asid[mytlb][oldasid] == 0)
237 smtc_flush_tlb_asid(oldasid); 260 smtc_flush_tlb_asid(oldasid);
238 } 261 }
239 /* See comments for similar code above */ 262 /* See comments for similar code above */
240 write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) | 263 write_c0_entryhi((read_c0_entryhi() & ~SMTC_HW_ASID_MASK) |
241 cpu_asid(cpu, next)); 264 cpu_asid(cpu, next));
242 ehb(); /* Make sure it propagates to TCStatus */ 265 ehb(); /* Make sure it propagates to TCStatus */
243 evpe(mtflags); 266 evpe(mtflags);
244#else 267#else
@@ -275,14 +298,14 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
275#ifdef CONFIG_MIPS_MT_SMTC 298#ifdef CONFIG_MIPS_MT_SMTC
276 /* See comments for similar code above */ 299 /* See comments for similar code above */
277 prevvpe = dvpe(); 300 prevvpe = dvpe();
278 oldasid = (read_c0_entryhi() & ASID_MASK); 301 oldasid = ASID_MASK(read_c0_entryhi());
279 if (smtc_live_asid[mytlb][oldasid]) { 302 if (smtc_live_asid[mytlb][oldasid]) {
280 smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); 303 smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
281 if(smtc_live_asid[mytlb][oldasid] == 0) 304 if(smtc_live_asid[mytlb][oldasid] == 0)
282 smtc_flush_tlb_asid(oldasid); 305 smtc_flush_tlb_asid(oldasid);
283 } 306 }
284 /* See comments for similar code above */ 307 /* See comments for similar code above */
285 write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) 308 write_c0_entryhi((read_c0_entryhi() & ~SMTC_HW_ASID_MASK)
286 | cpu_asid(cpu, mm)); 309 | cpu_asid(cpu, mm));
287 ehb(); /* Make sure it propagates to TCStatus */ 310 ehb(); /* Make sure it propagates to TCStatus */
288 evpe(prevvpe); 311 evpe(prevvpe);
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index ecb347ce1b3d..5360b1db337d 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -480,7 +480,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
480 .set noreorder 480 .set noreorder
481 /* check if TLB contains a entry for EPC */ 481 /* check if TLB contains a entry for EPC */
482 MFC0 k1, CP0_ENTRYHI 482 MFC0 k1, CP0_ENTRYHI
483 andi k1, 0xff /* ASID_MASK */ 483 andi k1, 0xff /* ASID_MASK patched at run-time!! */
484 MFC0 k0, CP0_EPC 484 MFC0 k0, CP0_EPC
485 PTR_SRL k0, _PAGE_SHIFT + 1 485 PTR_SRL k0, _PAGE_SHIFT + 1
486 PTR_SLL k0, _PAGE_SHIFT + 1 486 PTR_SLL k0, _PAGE_SHIFT + 1
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 7186222dc5bb..31d22f3121c9 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -111,7 +111,7 @@ static int vpe0limit;
111static int ipibuffers; 111static int ipibuffers;
112static int nostlb; 112static int nostlb;
113static int asidmask; 113static int asidmask;
114unsigned long smtc_asid_mask = 0xff; 114unsigned int smtc_asid_mask = 0xff;
115 115
116static int __init vpe0tcs(char *str) 116static int __init vpe0tcs(char *str)
117{ 117{
@@ -1395,7 +1395,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
1395 asid = asid_cache(cpu); 1395 asid = asid_cache(cpu);
1396 1396
1397 do { 1397 do {
1398 if (!((asid += ASID_INC) & ASID_MASK) ) { 1398 if (!ASID_MASK(ASID_INC(asid))) {
1399 if (cpu_has_vtag_icache) 1399 if (cpu_has_vtag_icache)
1400 flush_icache_all(); 1400 flush_icache_all();
1401 /* Traverse all online CPUs (hack requires contiguous range) */ 1401 /* Traverse all online CPUs (hack requires contiguous range) */
@@ -1414,7 +1414,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
1414 mips_ihb(); 1414 mips_ihb();
1415 } 1415 }
1416 tcstat = read_tc_c0_tcstatus(); 1416 tcstat = read_tc_c0_tcstatus();
1417 smtc_live_asid[tlb][(tcstat & ASID_MASK)] |= (asiduse)(0x1 << i); 1417 smtc_live_asid[tlb][ASID_MASK(tcstat)] |= (asiduse)(0x1 << i);
1418 if (!prevhalt) 1418 if (!prevhalt)
1419 write_tc_c0_tchalt(0); 1419 write_tc_c0_tchalt(0);
1420 } 1420 }
@@ -1423,7 +1423,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
1423 asid = ASID_FIRST_VERSION; 1423 asid = ASID_FIRST_VERSION;
1424 local_flush_tlb_all(); /* start new asid cycle */ 1424 local_flush_tlb_all(); /* start new asid cycle */
1425 } 1425 }
1426 } while (smtc_live_asid[tlb][(asid & ASID_MASK)]); 1426 } while (smtc_live_asid[tlb][ASID_MASK(asid)]);
1427 1427
1428 /* 1428 /*
1429 * SMTC shares the TLB within VPEs and possibly across all VPEs. 1429 * SMTC shares the TLB within VPEs and possibly across all VPEs.
@@ -1461,7 +1461,7 @@ void smtc_flush_tlb_asid(unsigned long asid)
1461 tlb_read(); 1461 tlb_read();
1462 ehb(); 1462 ehb();
1463 ehi = read_c0_entryhi(); 1463 ehi = read_c0_entryhi();
1464 if ((ehi & ASID_MASK) == asid) { 1464 if (ASID_MASK(ehi) == asid) {
1465 /* 1465 /*
1466 * Invalidate only entries with specified ASID, 1466 * Invalidate only entries with specified ASID,
1467 * makiing sure all entries differ. 1467 * makiing sure all entries differ.
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index c3abb88170fc..4b6b607b0179 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1547,6 +1547,7 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
1547 unsigned int cpu = smp_processor_id(); 1547 unsigned int cpu = smp_processor_id();
1548 unsigned int status_set = ST0_CU0; 1548 unsigned int status_set = ST0_CU0;
1549 unsigned int hwrena = cpu_hwrena_impl_bits; 1549 unsigned int hwrena = cpu_hwrena_impl_bits;
1550 unsigned long asid = 0;
1550#ifdef CONFIG_MIPS_MT_SMTC 1551#ifdef CONFIG_MIPS_MT_SMTC
1551 int secondaryTC = 0; 1552 int secondaryTC = 0;
1552 int bootTC = (cpu == 0); 1553 int bootTC = (cpu == 0);
@@ -1630,8 +1631,9 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
1630 } 1631 }
1631#endif /* CONFIG_MIPS_MT_SMTC */ 1632#endif /* CONFIG_MIPS_MT_SMTC */
1632 1633
1633 if (!cpu_data[cpu].asid_cache) 1634 asid = ASID_FIRST_VERSION;
1634 cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; 1635 cpu_data[cpu].asid_cache = asid;
1636 TLBMISS_HANDLER_SETUP();
1635 1637
1636 atomic_inc(&init_mm.mm_count); 1638 atomic_inc(&init_mm.mm_count);
1637 current->active_mm = &init_mm; 1639 current->active_mm = &init_mm;
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
index 32b9f21bfd85..8a12d00908e0 100644
--- a/arch/mips/lib/dump_tlb.c
+++ b/arch/mips/lib/dump_tlb.c
@@ -11,6 +11,7 @@
11#include <asm/page.h> 11#include <asm/page.h>
12#include <asm/pgtable.h> 12#include <asm/pgtable.h>
13#include <asm/tlbdebug.h> 13#include <asm/tlbdebug.h>
14#include <asm/mmu_context.h>
14 15
15static inline const char *msk2str(unsigned int mask) 16static inline const char *msk2str(unsigned int mask)
16{ 17{
@@ -55,7 +56,7 @@ static void dump_tlb(int first, int last)
55 s_pagemask = read_c0_pagemask(); 56 s_pagemask = read_c0_pagemask();
56 s_entryhi = read_c0_entryhi(); 57 s_entryhi = read_c0_entryhi();
57 s_index = read_c0_index(); 58 s_index = read_c0_index();
58 asid = s_entryhi & 0xff; 59 asid = ASID_MASK(s_entryhi);
59 60
60 for (i = first; i <= last; i++) { 61 for (i = first; i <= last; i++) {
61 write_c0_index(i); 62 write_c0_index(i);
@@ -85,7 +86,7 @@ static void dump_tlb(int first, int last)
85 86
86 printk("va=%0*lx asid=%02lx\n", 87 printk("va=%0*lx asid=%02lx\n",
87 width, (entryhi & ~0x1fffUL), 88 width, (entryhi & ~0x1fffUL),
88 entryhi & 0xff); 89 ASID_MASK(entryhi));
89 printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ", 90 printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ",
90 width, 91 width,
91 (entrylo0 << 6) & PAGE_MASK, c0, 92 (entrylo0 << 6) & PAGE_MASK, c0,
diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c
index 91615c2ef0cf..8327698b9937 100644
--- a/arch/mips/lib/r3k_dump_tlb.c
+++ b/arch/mips/lib/r3k_dump_tlb.c
@@ -9,6 +9,7 @@
9#include <linux/mm.h> 9#include <linux/mm.h>
10 10
11#include <asm/mipsregs.h> 11#include <asm/mipsregs.h>
12#include <asm/mmu_context.h>
12#include <asm/page.h> 13#include <asm/page.h>
13#include <asm/pgtable.h> 14#include <asm/pgtable.h>
14#include <asm/tlbdebug.h> 15#include <asm/tlbdebug.h>
@@ -21,7 +22,7 @@ static void dump_tlb(int first, int last)
21 unsigned int asid; 22 unsigned int asid;
22 unsigned long entryhi, entrylo0; 23 unsigned long entryhi, entrylo0;
23 24
24 asid = read_c0_entryhi() & 0xfc0; 25 asid = ASID_MASK(read_c0_entryhi());
25 26
26 for (i = first; i <= last; i++) { 27 for (i = first; i <= last; i++) {
27 write_c0_index(i<<8); 28 write_c0_index(i<<8);
@@ -35,7 +36,7 @@ static void dump_tlb(int first, int last)
35 36
36 /* Unused entries have a virtual address of KSEG0. */ 37 /* Unused entries have a virtual address of KSEG0. */
37 if ((entryhi & 0xffffe000) != 0x80000000 38 if ((entryhi & 0xffffe000) != 0x80000000
38 && (entryhi & 0xfc0) == asid) { 39 && (ASID_MASK(entryhi) == asid)) {
39 /* 40 /*
40 * Only print entries in use 41 * Only print entries in use
41 */ 42 */
@@ -44,7 +45,7 @@ static void dump_tlb(int first, int last)
44 printk("va=%08lx asid=%08lx" 45 printk("va=%08lx asid=%08lx"
45 " [pa=%06lx n=%d d=%d v=%d g=%d]", 46 " [pa=%06lx n=%d d=%d v=%d g=%d]",
46 (entryhi & 0xffffe000), 47 (entryhi & 0xffffe000),
47 entryhi & 0xfc0, 48 ASID_MASK(entryhi),
48 entrylo0 & PAGE_MASK, 49 entrylo0 & PAGE_MASK,
49 (entrylo0 & (1 << 11)) ? 1 : 0, 50 (entrylo0 & (1 << 11)) ? 1 : 0,
50 (entrylo0 & (1 << 10)) ? 1 : 0, 51 (entrylo0 & (1 << 10)) ? 1 : 0,
diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c
index a63d1ed0827f..4a13c150f31b 100644
--- a/arch/mips/mm/tlb-r3k.c
+++ b/arch/mips/mm/tlb-r3k.c
@@ -51,7 +51,7 @@ void local_flush_tlb_all(void)
51#endif 51#endif
52 52
53 local_irq_save(flags); 53 local_irq_save(flags);
54 old_ctx = read_c0_entryhi() & ASID_MASK; 54 old_ctx = ASID_MASK(read_c0_entryhi());
55 write_c0_entrylo0(0); 55 write_c0_entrylo0(0);
56 entry = r3k_have_wired_reg ? read_c0_wired() : 8; 56 entry = r3k_have_wired_reg ? read_c0_wired() : 8;
57 for (; entry < current_cpu_data.tlbsize; entry++) { 57 for (; entry < current_cpu_data.tlbsize; entry++) {
@@ -87,13 +87,13 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
87 87
88#ifdef DEBUG_TLB 88#ifdef DEBUG_TLB
89 printk("[tlbrange<%lu,0x%08lx,0x%08lx>]", 89 printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
90 cpu_context(cpu, mm) & ASID_MASK, start, end); 90 ASID_MASK(cpu_context(cpu, mm)), start, end);
91#endif 91#endif
92 local_irq_save(flags); 92 local_irq_save(flags);
93 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 93 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
94 if (size <= current_cpu_data.tlbsize) { 94 if (size <= current_cpu_data.tlbsize) {
95 int oldpid = read_c0_entryhi() & ASID_MASK; 95 int oldpid = ASID_MASK(read_c0_entryhi());
96 int newpid = cpu_context(cpu, mm) & ASID_MASK; 96 int newpid = ASID_MASK(cpu_context(cpu, mm));
97 97
98 start &= PAGE_MASK; 98 start &= PAGE_MASK;
99 end += PAGE_SIZE - 1; 99 end += PAGE_SIZE - 1;
@@ -166,10 +166,10 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
166#ifdef DEBUG_TLB 166#ifdef DEBUG_TLB
167 printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page); 167 printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page);
168#endif 168#endif
169 newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK; 169 newpid = ASID_MASK(cpu_context(cpu, vma->vm_mm));
170 page &= PAGE_MASK; 170 page &= PAGE_MASK;
171 local_irq_save(flags); 171 local_irq_save(flags);
172 oldpid = read_c0_entryhi() & ASID_MASK; 172 oldpid = ASID_MASK(read_c0_entryhi());
173 write_c0_entryhi(page | newpid); 173 write_c0_entryhi(page | newpid);
174 BARRIER; 174 BARRIER;
175 tlb_probe(); 175 tlb_probe();
@@ -197,10 +197,10 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
197 if (current->active_mm != vma->vm_mm) 197 if (current->active_mm != vma->vm_mm)
198 return; 198 return;
199 199
200 pid = read_c0_entryhi() & ASID_MASK; 200 pid = ASID_MASK(read_c0_entryhi());
201 201
202#ifdef DEBUG_TLB 202#ifdef DEBUG_TLB
203 if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) { 203 if ((pid != ASID_MASK(cpu_context(cpu, vma->vm_mm))) || (cpu_context(cpu, vma->vm_mm) == 0)) {
204 printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n", 204 printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
205 (cpu_context(cpu, vma->vm_mm)), pid); 205 (cpu_context(cpu, vma->vm_mm)), pid);
206 } 206 }
@@ -241,7 +241,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
241 241
242 local_irq_save(flags); 242 local_irq_save(flags);
243 /* Save old context and create impossible VPN2 value */ 243 /* Save old context and create impossible VPN2 value */
244 old_ctx = read_c0_entryhi() & ASID_MASK; 244 old_ctx = ASID_MASK(read_c0_entryhi());
245 old_pagemask = read_c0_pagemask(); 245 old_pagemask = read_c0_pagemask();
246 w = read_c0_wired(); 246 w = read_c0_wired();
247 write_c0_wired(w + 1); 247 write_c0_wired(w + 1);
@@ -264,7 +264,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
264#endif 264#endif
265 265
266 local_irq_save(flags); 266 local_irq_save(flags);
267 old_ctx = read_c0_entryhi() & ASID_MASK; 267 old_ctx = ASID_MASK(read_c0_entryhi());
268 write_c0_entrylo0(entrylo0); 268 write_c0_entrylo0(entrylo0);
269 write_c0_entryhi(entryhi); 269 write_c0_entryhi(entryhi);
270 write_c0_index(wired); 270 write_c0_index(wired);
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 493131c81a29..3d03a2ccebaa 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -285,7 +285,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
285 285
286 ENTER_CRITICAL(flags); 286 ENTER_CRITICAL(flags);
287 287
288 pid = read_c0_entryhi() & ASID_MASK; 288 pid = ASID_MASK(read_c0_entryhi());
289 address &= (PAGE_MASK << 1); 289 address &= (PAGE_MASK << 1);
290 write_c0_entryhi(address | pid); 290 write_c0_entryhi(address | pid);
291 pgdp = pgd_offset(vma->vm_mm, address); 291 pgdp = pgd_offset(vma->vm_mm, address);
diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c
index 91c2499f806a..122f9207f49e 100644
--- a/arch/mips/mm/tlb-r8k.c
+++ b/arch/mips/mm/tlb-r8k.c
@@ -195,7 +195,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
195 if (current->active_mm != vma->vm_mm) 195 if (current->active_mm != vma->vm_mm)
196 return; 196 return;
197 197
198 pid = read_c0_entryhi() & ASID_MASK; 198 pid = ASID_MASK(read_c0_entryhi());
199 199
200 local_irq_save(flags); 200 local_irq_save(flags);
201 address &= PAGE_MASK; 201 address &= PAGE_MASK;
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 820e6612d744..e2a9e3687c45 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -29,6 +29,7 @@
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/cache.h> 30#include <linux/cache.h>
31 31
32#include <asm/mmu_context.h>
32#include <asm/cacheflush.h> 33#include <asm/cacheflush.h>
33#include <asm/pgtable.h> 34#include <asm/pgtable.h>
34#include <asm/war.h> 35#include <asm/war.h>
@@ -305,6 +306,48 @@ static struct uasm_reloc relocs[128] __cpuinitdata;
305static int check_for_high_segbits __cpuinitdata; 306static int check_for_high_segbits __cpuinitdata;
306#endif 307#endif
307 308
309static void __cpuinit insn_fixup(unsigned int **start, unsigned int **stop,
310 unsigned int i_const)
311{
312 unsigned int **p, *ip;
313
314 for (p = start; p < stop; p++) {
315 ip = *p;
316 *ip = (*ip & 0xffff0000) | i_const;
317 }
318 local_flush_icache_range((unsigned long)*p, (unsigned long)((*p) + 1));
319}
320
321#define asid_insn_fixup(section, const) \
322do { \
323 extern unsigned int *__start_ ## section; \
324 extern unsigned int *__stop_ ## section; \
325 insn_fixup(&__start_ ## section, &__stop_ ## section, const); \
326} while(0)
327
328/*
329 * Caller is assumed to flush the caches before the first context switch.
330 */
331static void __cpuinit setup_asid(unsigned int inc, unsigned int mask,
332 unsigned int version_mask,
333 unsigned int first_version)
334{
335 extern asmlinkage void handle_ri_rdhwr_vivt(void);
336 unsigned long *vivt_exc;
337
338 asid_insn_fixup(__asid_inc, inc);
339 asid_insn_fixup(__asid_mask, mask);
340 asid_insn_fixup(__asid_version_mask, version_mask);
341 asid_insn_fixup(__asid_first_version, first_version);
342
343 /* Patch up the 'handle_ri_rdhwr_vivt' handler. */
344 vivt_exc = (unsigned long *) &handle_ri_rdhwr_vivt;
345 vivt_exc++;
346 *vivt_exc = (*vivt_exc & ~mask) | mask;
347
348 current_cpu_data.asid_cache = first_version;
349}
350
308static int check_for_high_segbits __cpuinitdata; 351static int check_for_high_segbits __cpuinitdata;
309 352
310static unsigned int kscratch_used_mask __cpuinitdata; 353static unsigned int kscratch_used_mask __cpuinitdata;
@@ -2162,6 +2205,7 @@ void __cpuinit build_tlb_refill_handler(void)
2162 case CPU_TX3922: 2205 case CPU_TX3922:
2163 case CPU_TX3927: 2206 case CPU_TX3927:
2164#ifndef CONFIG_MIPS_PGD_C0_CONTEXT 2207#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
2208 setup_asid(0x40, 0xfc0, 0xf000, ASID_FIRST_VERSION_R3000);
2165 build_r3000_tlb_refill_handler(); 2209 build_r3000_tlb_refill_handler();
2166 if (!run_once) { 2210 if (!run_once) {
2167 build_r3000_tlb_load_handler(); 2211 build_r3000_tlb_load_handler();
@@ -2184,6 +2228,11 @@ void __cpuinit build_tlb_refill_handler(void)
2184 break; 2228 break;
2185 2229
2186 default: 2230 default:
2231#ifndef CONFIG_MIPS_MT_SMTC
2232 setup_asid(0x1, 0xff, 0xff00, ASID_FIRST_VERSION_R4000);
2233#else
2234 setup_asid(0x1, smtc_asid_mask, 0xff00, ASID_FIRST_VERSION_R4000);
2235#endif
2187 if (!run_once) { 2236 if (!run_once) {
2188 scratch_reg = allocate_kscratch(); 2237 scratch_reg = allocate_kscratch();
2189#ifdef CONFIG_MIPS_PGD_C0_CONTEXT 2238#ifdef CONFIG_MIPS_PGD_C0_CONTEXT