diff options
author | Thiemo Seufer <ths@networkno.de> | 2005-04-02 05:21:56 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:31:01 -0400 |
commit | 172546bf601356f94f8018af7908a9b7c1c4915c (patch) | |
tree | 3b0d93bc5caf6014ef5554b05cad8b41b7c83b94 /arch/mips/mm/tlb-r4k.c | |
parent | 202d0388e747d7e9b70fc0efc2a5637812b722c1 (diff) |
Fix race conditions for read_c0_entryhi. Remove broken ASID masks in
tlb-sb1.c. Make tlb-r4k.c and tlb-sb1.c more similiar and more efficient.
Signed-off-by: Thiemo Seufer <ths@networkno.de>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mm/tlb-r4k.c')
-rw-r--r-- | arch/mips/mm/tlb-r4k.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 08702202758d..316c8a3d6b53 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c | |||
@@ -21,6 +21,12 @@ | |||
21 | 21 | ||
22 | extern void build_tlb_refill_handler(void); | 22 | extern void build_tlb_refill_handler(void); |
23 | 23 | ||
24 | /* | ||
25 | * Make sure all entries differ. If they're not different | ||
26 | * MIPS32 will take revenge ... | ||
27 | */ | ||
28 | #define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) | ||
29 | |||
24 | /* CP0 hazard avoidance. */ | 30 | /* CP0 hazard avoidance. */ |
25 | #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ | 31 | #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ |
26 | "nop; nop; nop; nop; nop; nop;\n\t" \ | 32 | "nop; nop; nop; nop; nop; nop;\n\t" \ |
@@ -42,11 +48,8 @@ void local_flush_tlb_all(void) | |||
42 | 48 | ||
43 | /* Blast 'em all away. */ | 49 | /* Blast 'em all away. */ |
44 | while (entry < current_cpu_data.tlbsize) { | 50 | while (entry < current_cpu_data.tlbsize) { |
45 | /* | 51 | /* Make sure all entries differ. */ |
46 | * Make sure all entries differ. If they're not different | 52 | write_c0_entryhi(UNIQUE_ENTRYHI(entry)); |
47 | * MIPS32 will take revenge ... | ||
48 | */ | ||
49 | write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1))); | ||
50 | write_c0_index(entry); | 53 | write_c0_index(entry); |
51 | mtc0_tlbw_hazard(); | 54 | mtc0_tlbw_hazard(); |
52 | tlb_write_indexed(); | 55 | tlb_write_indexed(); |
@@ -57,12 +60,21 @@ void local_flush_tlb_all(void) | |||
57 | local_irq_restore(flags); | 60 | local_irq_restore(flags); |
58 | } | 61 | } |
59 | 62 | ||
63 | /* All entries common to a mm share an asid. To effectively flush | ||
64 | these entries, we just bump the asid. */ | ||
60 | void local_flush_tlb_mm(struct mm_struct *mm) | 65 | void local_flush_tlb_mm(struct mm_struct *mm) |
61 | { | 66 | { |
62 | int cpu = smp_processor_id(); | 67 | int cpu; |
68 | |||
69 | preempt_disable(); | ||
63 | 70 | ||
64 | if (cpu_context(cpu, mm) != 0) | 71 | cpu = smp_processor_id(); |
65 | drop_mmu_context(mm,cpu); | 72 | |
73 | if (cpu_context(cpu, mm) != 0) { | ||
74 | drop_mmu_context(mm, cpu); | ||
75 | } | ||
76 | |||
77 | preempt_enable(); | ||
66 | } | 78 | } |
67 | 79 | ||
68 | void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | 80 | void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
@@ -75,9 +87,9 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
75 | unsigned long flags; | 87 | unsigned long flags; |
76 | int size; | 88 | int size; |
77 | 89 | ||
78 | local_irq_save(flags); | ||
79 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 90 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; |
80 | size = (size + 1) >> 1; | 91 | size = (size + 1) >> 1; |
92 | local_irq_save(flags); | ||
81 | if (size <= current_cpu_data.tlbsize/2) { | 93 | if (size <= current_cpu_data.tlbsize/2) { |
82 | int oldpid = read_c0_entryhi(); | 94 | int oldpid = read_c0_entryhi(); |
83 | int newpid = cpu_asid(cpu, mm); | 95 | int newpid = cpu_asid(cpu, mm); |
@@ -99,8 +111,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
99 | if (idx < 0) | 111 | if (idx < 0) |
100 | continue; | 112 | continue; |
101 | /* Make sure all entries differ. */ | 113 | /* Make sure all entries differ. */ |
102 | write_c0_entryhi(CKSEG0 + | 114 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); |
103 | (idx << (PAGE_SHIFT + 1))); | ||
104 | mtc0_tlbw_hazard(); | 115 | mtc0_tlbw_hazard(); |
105 | tlb_write_indexed(); | 116 | tlb_write_indexed(); |
106 | } | 117 | } |
@@ -118,9 +129,9 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
118 | unsigned long flags; | 129 | unsigned long flags; |
119 | int size; | 130 | int size; |
120 | 131 | ||
121 | local_irq_save(flags); | ||
122 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 132 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; |
123 | size = (size + 1) >> 1; | 133 | size = (size + 1) >> 1; |
134 | local_irq_save(flags); | ||
124 | if (size <= current_cpu_data.tlbsize / 2) { | 135 | if (size <= current_cpu_data.tlbsize / 2) { |
125 | int pid = read_c0_entryhi(); | 136 | int pid = read_c0_entryhi(); |
126 | 137 | ||
@@ -142,7 +153,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
142 | if (idx < 0) | 153 | if (idx < 0) |
143 | continue; | 154 | continue; |
144 | /* Make sure all entries differ. */ | 155 | /* Make sure all entries differ. */ |
145 | write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1))); | 156 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); |
146 | mtc0_tlbw_hazard(); | 157 | mtc0_tlbw_hazard(); |
147 | tlb_write_indexed(); | 158 | tlb_write_indexed(); |
148 | } | 159 | } |
@@ -176,7 +187,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
176 | if (idx < 0) | 187 | if (idx < 0) |
177 | goto finish; | 188 | goto finish; |
178 | /* Make sure all entries differ. */ | 189 | /* Make sure all entries differ. */ |
179 | write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1))); | 190 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); |
180 | mtc0_tlbw_hazard(); | 191 | mtc0_tlbw_hazard(); |
181 | tlb_write_indexed(); | 192 | tlb_write_indexed(); |
182 | tlbw_use_hazard(); | 193 | tlbw_use_hazard(); |
@@ -197,8 +208,8 @@ void local_flush_tlb_one(unsigned long page) | |||
197 | int oldpid, idx; | 208 | int oldpid, idx; |
198 | 209 | ||
199 | local_irq_save(flags); | 210 | local_irq_save(flags); |
200 | page &= (PAGE_MASK << 1); | ||
201 | oldpid = read_c0_entryhi(); | 211 | oldpid = read_c0_entryhi(); |
212 | page &= (PAGE_MASK << 1); | ||
202 | write_c0_entryhi(page); | 213 | write_c0_entryhi(page); |
203 | mtc0_tlbw_hazard(); | 214 | mtc0_tlbw_hazard(); |
204 | tlb_probe(); | 215 | tlb_probe(); |
@@ -208,7 +219,7 @@ void local_flush_tlb_one(unsigned long page) | |||
208 | write_c0_entrylo1(0); | 219 | write_c0_entrylo1(0); |
209 | if (idx >= 0) { | 220 | if (idx >= 0) { |
210 | /* Make sure all entries differ. */ | 221 | /* Make sure all entries differ. */ |
211 | write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1))); | 222 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); |
212 | mtc0_tlbw_hazard(); | 223 | mtc0_tlbw_hazard(); |
213 | tlb_write_indexed(); | 224 | tlb_write_indexed(); |
214 | tlbw_use_hazard(); | 225 | tlbw_use_hazard(); |
@@ -238,9 +249,9 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) | |||
238 | if (current->active_mm != vma->vm_mm) | 249 | if (current->active_mm != vma->vm_mm) |
239 | return; | 250 | return; |
240 | 251 | ||
241 | pid = read_c0_entryhi() & ASID_MASK; | ||
242 | |||
243 | local_irq_save(flags); | 252 | local_irq_save(flags); |
253 | |||
254 | pid = read_c0_entryhi() & ASID_MASK; | ||
244 | address &= (PAGE_MASK << 1); | 255 | address &= (PAGE_MASK << 1); |
245 | write_c0_entryhi(address | pid); | 256 | write_c0_entryhi(address | pid); |
246 | pgdp = pgd_offset(vma->vm_mm, address); | 257 | pgdp = pgd_offset(vma->vm_mm, address); |
@@ -260,14 +271,12 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) | |||
260 | write_c0_entrylo0(pte_val(*ptep++) >> 6); | 271 | write_c0_entrylo0(pte_val(*ptep++) >> 6); |
261 | write_c0_entrylo1(pte_val(*ptep) >> 6); | 272 | write_c0_entrylo1(pte_val(*ptep) >> 6); |
262 | #endif | 273 | #endif |
263 | write_c0_entryhi(address | pid); | ||
264 | mtc0_tlbw_hazard(); | 274 | mtc0_tlbw_hazard(); |
265 | if (idx < 0) | 275 | if (idx < 0) |
266 | tlb_write_random(); | 276 | tlb_write_random(); |
267 | else | 277 | else |
268 | tlb_write_indexed(); | 278 | tlb_write_indexed(); |
269 | tlbw_use_hazard(); | 279 | tlbw_use_hazard(); |
270 | write_c0_entryhi(pid); | ||
271 | local_irq_restore(flags); | 280 | local_irq_restore(flags); |
272 | } | 281 | } |
273 | 282 | ||