diff options
Diffstat (limited to 'arch/mips/mm')
-rw-r--r-- | arch/mips/mm/c-r3k.c | 5 | ||||
-rw-r--r-- | arch/mips/mm/c-r4k.c | 20 | ||||
-rw-r--r-- | arch/mips/mm/c-sb1.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/c-tx39.c | 7 | ||||
-rw-r--r-- | arch/mips/mm/cache.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/fault.c | 13 | ||||
-rw-r--r-- | arch/mips/mm/highmem.c | 2 | ||||
-rw-r--r-- | arch/mips/mm/init.c | 48 | ||||
-rw-r--r-- | arch/mips/mm/sc-rm7k.c | 2 | ||||
-rw-r--r-- | arch/mips/mm/tlb-r4k.c | 85 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 87 |
11 files changed, 194 insertions, 77 deletions
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 9dd1352d5748..bb041a22f20a 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c | |||
@@ -260,6 +260,10 @@ static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, | |||
260 | { | 260 | { |
261 | } | 261 | } |
262 | 262 | ||
263 | static void local_r3k_flush_data_cache_page(unsigned long addr) | ||
264 | { | ||
265 | } | ||
266 | |||
263 | static void r3k_flush_data_cache_page(unsigned long addr) | 267 | static void r3k_flush_data_cache_page(unsigned long addr) |
264 | { | 268 | { |
265 | } | 269 | } |
@@ -335,6 +339,7 @@ void __init r3k_cache_init(void) | |||
335 | flush_icache_range = r3k_flush_icache_range; | 339 | flush_icache_range = r3k_flush_icache_range; |
336 | 340 | ||
337 | flush_cache_sigtramp = r3k_flush_cache_sigtramp; | 341 | flush_cache_sigtramp = r3k_flush_cache_sigtramp; |
342 | local_flush_data_cache_page = local_r3k_flush_data_cache_page; | ||
338 | flush_data_cache_page = r3k_flush_data_cache_page; | 343 | flush_data_cache_page = r3k_flush_data_cache_page; |
339 | 344 | ||
340 | _dma_cache_wback_inv = r3k_dma_cache_wback_inv; | 345 | _dma_cache_wback_inv = r3k_dma_cache_wback_inv; |
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 32b7f6aeb983..4182e1176fae 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
@@ -154,7 +154,8 @@ static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page) | |||
154 | 154 | ||
155 | static inline void tx49_blast_icache32_page_indexed(unsigned long page) | 155 | static inline void tx49_blast_icache32_page_indexed(unsigned long page) |
156 | { | 156 | { |
157 | unsigned long start = page; | 157 | unsigned long indexmask = current_cpu_data.icache.waysize - 1; |
158 | unsigned long start = INDEX_BASE + (page & indexmask); | ||
158 | unsigned long end = start + PAGE_SIZE; | 159 | unsigned long end = start + PAGE_SIZE; |
159 | unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; | 160 | unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; |
160 | unsigned long ws_end = current_cpu_data.icache.ways << | 161 | unsigned long ws_end = current_cpu_data.icache.ways << |
@@ -749,12 +750,12 @@ static void __init probe_pcache(void) | |||
749 | icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); | 750 | icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); |
750 | c->icache.linesz = 16 << ((config & CONF_IB) >> 5); | 751 | c->icache.linesz = 16 << ((config & CONF_IB) >> 5); |
751 | c->icache.ways = 2; | 752 | c->icache.ways = 2; |
752 | c->icache.waybit = ffs(icache_size/2) - 1; | 753 | c->icache.waybit = __ffs(icache_size/2); |
753 | 754 | ||
754 | dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); | 755 | dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); |
755 | c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); | 756 | c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); |
756 | c->dcache.ways = 2; | 757 | c->dcache.ways = 2; |
757 | c->dcache.waybit= ffs(dcache_size/2) - 1; | 758 | c->dcache.waybit= __ffs(dcache_size/2); |
758 | 759 | ||
759 | c->options |= MIPS_CPU_CACHE_CDEX_P; | 760 | c->options |= MIPS_CPU_CACHE_CDEX_P; |
760 | break; | 761 | break; |
@@ -837,12 +838,12 @@ static void __init probe_pcache(void) | |||
837 | icache_size = 1 << (10 + ((config & CONF_IC) >> 9)); | 838 | icache_size = 1 << (10 + ((config & CONF_IC) >> 9)); |
838 | c->icache.linesz = 16 << ((config & CONF_IB) >> 5); | 839 | c->icache.linesz = 16 << ((config & CONF_IB) >> 5); |
839 | c->icache.ways = 2; | 840 | c->icache.ways = 2; |
840 | c->icache.waybit = ffs(icache_size/2) - 1; | 841 | c->icache.waybit = __ffs(icache_size/2); |
841 | 842 | ||
842 | dcache_size = 1 << (10 + ((config & CONF_DC) >> 6)); | 843 | dcache_size = 1 << (10 + ((config & CONF_DC) >> 6)); |
843 | c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); | 844 | c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); |
844 | c->dcache.ways = 2; | 845 | c->dcache.ways = 2; |
845 | c->dcache.waybit = ffs(dcache_size/2) - 1; | 846 | c->dcache.waybit = __ffs(dcache_size/2); |
846 | 847 | ||
847 | c->options |= MIPS_CPU_CACHE_CDEX_P; | 848 | c->options |= MIPS_CPU_CACHE_CDEX_P; |
848 | break; | 849 | break; |
@@ -873,12 +874,12 @@ static void __init probe_pcache(void) | |||
873 | icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); | 874 | icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); |
874 | c->icache.linesz = 16 << ((config & CONF_IB) >> 5); | 875 | c->icache.linesz = 16 << ((config & CONF_IB) >> 5); |
875 | c->icache.ways = 4; | 876 | c->icache.ways = 4; |
876 | c->icache.waybit = ffs(icache_size / c->icache.ways) - 1; | 877 | c->icache.waybit = __ffs(icache_size / c->icache.ways); |
877 | 878 | ||
878 | dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); | 879 | dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); |
879 | c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); | 880 | c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); |
880 | c->dcache.ways = 4; | 881 | c->dcache.ways = 4; |
881 | c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1; | 882 | c->dcache.waybit = __ffs(dcache_size / c->dcache.ways); |
882 | 883 | ||
883 | #if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR) | 884 | #if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR) |
884 | c->options |= MIPS_CPU_CACHE_CDEX_P; | 885 | c->options |= MIPS_CPU_CACHE_CDEX_P; |
@@ -906,7 +907,7 @@ static void __init probe_pcache(void) | |||
906 | icache_size = c->icache.sets * | 907 | icache_size = c->icache.sets * |
907 | c->icache.ways * | 908 | c->icache.ways * |
908 | c->icache.linesz; | 909 | c->icache.linesz; |
909 | c->icache.waybit = ffs(icache_size/c->icache.ways) - 1; | 910 | c->icache.waybit = __ffs(icache_size/c->icache.ways); |
910 | 911 | ||
911 | if (config & 0x8) /* VI bit */ | 912 | if (config & 0x8) /* VI bit */ |
912 | c->icache.flags |= MIPS_CACHE_VTAG; | 913 | c->icache.flags |= MIPS_CACHE_VTAG; |
@@ -926,7 +927,7 @@ static void __init probe_pcache(void) | |||
926 | dcache_size = c->dcache.sets * | 927 | dcache_size = c->dcache.sets * |
927 | c->dcache.ways * | 928 | c->dcache.ways * |
928 | c->dcache.linesz; | 929 | c->dcache.linesz; |
929 | c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1; | 930 | c->dcache.waybit = __ffs(dcache_size/c->dcache.ways); |
930 | 931 | ||
931 | c->options |= MIPS_CPU_PREFETCH; | 932 | c->options |= MIPS_CPU_PREFETCH; |
932 | break; | 933 | break; |
@@ -1198,6 +1199,7 @@ void __init r4k_cache_init(void) | |||
1198 | 1199 | ||
1199 | flush_cache_sigtramp = r4k_flush_cache_sigtramp; | 1200 | flush_cache_sigtramp = r4k_flush_cache_sigtramp; |
1200 | flush_icache_all = r4k_flush_icache_all; | 1201 | flush_icache_all = r4k_flush_icache_all; |
1202 | local_flush_data_cache_page = local_r4k_flush_data_cache_page; | ||
1201 | flush_data_cache_page = r4k_flush_data_cache_page; | 1203 | flush_data_cache_page = r4k_flush_data_cache_page; |
1202 | flush_icache_range = r4k_flush_icache_range; | 1204 | flush_icache_range = r4k_flush_icache_range; |
1203 | 1205 | ||
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c index 2f08b535f20e..f9b129491b1e 100644 --- a/arch/mips/mm/c-sb1.c +++ b/arch/mips/mm/c-sb1.c | |||
@@ -528,6 +528,7 @@ void sb1_cache_init(void) | |||
528 | flush_cache_page = sb1_flush_cache_page; | 528 | flush_cache_page = sb1_flush_cache_page; |
529 | 529 | ||
530 | flush_cache_sigtramp = sb1_flush_cache_sigtramp; | 530 | flush_cache_sigtramp = sb1_flush_cache_sigtramp; |
531 | local_flush_data_cache_page = (void *) sb1_nop; | ||
531 | flush_data_cache_page = (void *) sb1_nop; | 532 | flush_data_cache_page = (void *) sb1_nop; |
532 | 533 | ||
533 | /* Full flush */ | 534 | /* Full flush */ |
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index fe232e3988e3..5dfc9b1901f6 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c | |||
@@ -216,6 +216,11 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page | |||
216 | tx39_blast_icache_page_indexed(page); | 216 | tx39_blast_icache_page_indexed(page); |
217 | } | 217 | } |
218 | 218 | ||
219 | static void local_tx39_flush_data_cache_page(void * addr) | ||
220 | { | ||
221 | tx39_blast_dcache_page(addr); | ||
222 | } | ||
223 | |||
219 | static void tx39_flush_data_cache_page(unsigned long addr) | 224 | static void tx39_flush_data_cache_page(unsigned long addr) |
220 | { | 225 | { |
221 | tx39_blast_dcache_page(addr); | 226 | tx39_blast_dcache_page(addr); |
@@ -381,6 +386,7 @@ void __init tx39_cache_init(void) | |||
381 | flush_icache_range = (void *) tx39h_flush_icache_all; | 386 | flush_icache_range = (void *) tx39h_flush_icache_all; |
382 | 387 | ||
383 | flush_cache_sigtramp = (void *) tx39h_flush_icache_all; | 388 | flush_cache_sigtramp = (void *) tx39h_flush_icache_all; |
389 | local_flush_data_cache_page = (void *) tx39h_flush_icache_all; | ||
384 | flush_data_cache_page = (void *) tx39h_flush_icache_all; | 390 | flush_data_cache_page = (void *) tx39h_flush_icache_all; |
385 | 391 | ||
386 | _dma_cache_wback_inv = tx39h_dma_cache_wback_inv; | 392 | _dma_cache_wback_inv = tx39h_dma_cache_wback_inv; |
@@ -406,6 +412,7 @@ void __init tx39_cache_init(void) | |||
406 | flush_icache_range = tx39_flush_icache_range; | 412 | flush_icache_range = tx39_flush_icache_range; |
407 | 413 | ||
408 | flush_cache_sigtramp = tx39_flush_cache_sigtramp; | 414 | flush_cache_sigtramp = tx39_flush_cache_sigtramp; |
415 | local_flush_data_cache_page = local_tx39_flush_data_cache_page; | ||
409 | flush_data_cache_page = tx39_flush_data_cache_page; | 416 | flush_data_cache_page = tx39_flush_data_cache_page; |
410 | 417 | ||
411 | _dma_cache_wback_inv = tx39_dma_cache_wback_inv; | 418 | _dma_cache_wback_inv = tx39_dma_cache_wback_inv; |
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 591c22b080e4..83a56296be86 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c | |||
@@ -30,6 +30,7 @@ void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); | |||
30 | 30 | ||
31 | /* MIPS specific cache operations */ | 31 | /* MIPS specific cache operations */ |
32 | void (*flush_cache_sigtramp)(unsigned long addr); | 32 | void (*flush_cache_sigtramp)(unsigned long addr); |
33 | void (*local_flush_data_cache_page)(void * addr); | ||
33 | void (*flush_data_cache_page)(unsigned long addr); | 34 | void (*flush_data_cache_page)(unsigned long addr); |
34 | void (*flush_icache_all)(void); | 35 | void (*flush_icache_all)(void); |
35 | 36 | ||
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 2d9624fd10ec..e3a617224868 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c | |||
@@ -157,7 +157,6 @@ no_context: | |||
157 | * Oops. The kernel tried to access some bad page. We'll have to | 157 | * Oops. The kernel tried to access some bad page. We'll have to |
158 | * terminate things with extreme prejudice. | 158 | * terminate things with extreme prejudice. |
159 | */ | 159 | */ |
160 | |||
161 | bust_spinlocks(1); | 160 | bust_spinlocks(1); |
162 | 161 | ||
163 | printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " | 162 | printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " |
@@ -188,11 +187,20 @@ do_sigbus: | |||
188 | /* Kernel mode? Handle exceptions or die */ | 187 | /* Kernel mode? Handle exceptions or die */ |
189 | if (!user_mode(regs)) | 188 | if (!user_mode(regs)) |
190 | goto no_context; | 189 | goto no_context; |
191 | 190 | else | |
192 | /* | 191 | /* |
193 | * Send a sigbus, regardless of whether we were in kernel | 192 | * Send a sigbus, regardless of whether we were in kernel |
194 | * or user mode. | 193 | * or user mode. |
195 | */ | 194 | */ |
195 | #if 0 | ||
196 | printk("do_page_fault() #3: sending SIGBUS to %s for " | ||
197 | "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n", | ||
198 | tsk->comm, | ||
199 | write ? "write access to" : "read access from", | ||
200 | field, address, | ||
201 | field, (unsigned long) regs->cp0_epc, | ||
202 | field, (unsigned long) regs->regs[31]); | ||
203 | #endif | ||
196 | tsk->thread.cp0_badvaddr = address; | 204 | tsk->thread.cp0_badvaddr = address; |
197 | info.si_signo = SIGBUS; | 205 | info.si_signo = SIGBUS; |
198 | info.si_errno = 0; | 206 | info.si_errno = 0; |
@@ -201,7 +209,6 @@ do_sigbus: | |||
201 | force_sig_info(SIGBUS, &info, tsk); | 209 | force_sig_info(SIGBUS, &info, tsk); |
202 | 210 | ||
203 | return; | 211 | return; |
204 | |||
205 | vmalloc_fault: | 212 | vmalloc_fault: |
206 | { | 213 | { |
207 | /* | 214 | /* |
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c index 1f7b37b38f5c..0c544375b856 100644 --- a/arch/mips/mm/highmem.c +++ b/arch/mips/mm/highmem.c | |||
@@ -83,6 +83,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type) | |||
83 | preempt_check_resched(); | 83 | preempt_check_resched(); |
84 | } | 84 | } |
85 | 85 | ||
86 | #ifndef CONFIG_LIMITED_DMA | ||
86 | /* | 87 | /* |
87 | * This is the same as kmap_atomic() but can map memory that doesn't | 88 | * This is the same as kmap_atomic() but can map memory that doesn't |
88 | * have a struct page associated with it. | 89 | * have a struct page associated with it. |
@@ -101,6 +102,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | |||
101 | 102 | ||
102 | return (void*) vaddr; | 103 | return (void*) vaddr; |
103 | } | 104 | } |
105 | #endif /* CONFIG_LIMITED_DMA */ | ||
104 | 106 | ||
105 | struct page *__kmap_atomic_to_page(void *ptr) | 107 | struct page *__kmap_atomic_to_page(void *ptr) |
106 | { | 108 | { |
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index ad89c442f299..c22308b93ff0 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c | |||
@@ -276,6 +276,20 @@ void __init mem_init(void) | |||
276 | } | 276 | } |
277 | #endif /* !CONFIG_NEED_MULTIPLE_NODES */ | 277 | #endif /* !CONFIG_NEED_MULTIPLE_NODES */ |
278 | 278 | ||
279 | void free_init_pages(char *what, unsigned long begin, unsigned long end) | ||
280 | { | ||
281 | unsigned long addr; | ||
282 | |||
283 | for (addr = begin; addr < end; addr += PAGE_SIZE) { | ||
284 | ClearPageReserved(virt_to_page(addr)); | ||
285 | init_page_count(virt_to_page(addr)); | ||
286 | memset((void *)addr, 0xcc, PAGE_SIZE); | ||
287 | free_page(addr); | ||
288 | totalram_pages++; | ||
289 | } | ||
290 | printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10); | ||
291 | } | ||
292 | |||
279 | #ifdef CONFIG_BLK_DEV_INITRD | 293 | #ifdef CONFIG_BLK_DEV_INITRD |
280 | void free_initrd_mem(unsigned long start, unsigned long end) | 294 | void free_initrd_mem(unsigned long start, unsigned long end) |
281 | { | 295 | { |
@@ -284,16 +298,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) | |||
284 | start = (unsigned long)phys_to_virt(CPHYSADDR(start)); | 298 | start = (unsigned long)phys_to_virt(CPHYSADDR(start)); |
285 | end = (unsigned long)phys_to_virt(CPHYSADDR(end)); | 299 | end = (unsigned long)phys_to_virt(CPHYSADDR(end)); |
286 | #endif | 300 | #endif |
287 | if (start < end) | 301 | free_init_pages("initrd memory", start, end); |
288 | printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", | ||
289 | (end - start) >> 10); | ||
290 | |||
291 | for (; start < end; start += PAGE_SIZE) { | ||
292 | ClearPageReserved(virt_to_page(start)); | ||
293 | init_page_count(virt_to_page(start)); | ||
294 | free_page(start); | ||
295 | totalram_pages++; | ||
296 | } | ||
297 | } | 302 | } |
298 | #endif | 303 | #endif |
299 | 304 | ||
@@ -301,24 +306,17 @@ extern unsigned long prom_free_prom_memory(void); | |||
301 | 306 | ||
302 | void free_initmem(void) | 307 | void free_initmem(void) |
303 | { | 308 | { |
304 | unsigned long addr, page, freed; | 309 | unsigned long start, end, freed; |
305 | 310 | ||
306 | freed = prom_free_prom_memory(); | 311 | freed = prom_free_prom_memory(); |
312 | if (freed) | ||
313 | printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed); | ||
307 | 314 | ||
308 | addr = (unsigned long) &__init_begin; | 315 | start = (unsigned long)(&__init_begin); |
309 | while (addr < (unsigned long) &__init_end) { | 316 | end = (unsigned long)(&__init_end); |
310 | #ifdef CONFIG_64BIT | 317 | #ifdef CONFIG_64BIT |
311 | page = PAGE_OFFSET | CPHYSADDR(addr); | 318 | start = PAGE_OFFSET | CPHYSADDR(start); |
312 | #else | 319 | end = PAGE_OFFSET | CPHYSADDR(end); |
313 | page = addr; | ||
314 | #endif | 320 | #endif |
315 | ClearPageReserved(virt_to_page(page)); | 321 | free_init_pages("unused kernel memory", start, end); |
316 | init_page_count(virt_to_page(page)); | ||
317 | free_page(page); | ||
318 | totalram_pages++; | ||
319 | freed += PAGE_SIZE; | ||
320 | addr += PAGE_SIZE; | ||
321 | } | ||
322 | printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n", | ||
323 | freed >> 10); | ||
324 | } | 322 | } |
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index 3b6cc9ba1b05..31ec73052423 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c | |||
@@ -138,7 +138,7 @@ void __init rm7k_sc_init(void) | |||
138 | 138 | ||
139 | c->scache.linesz = sc_lsize; | 139 | c->scache.linesz = sc_lsize; |
140 | c->scache.ways = 4; | 140 | c->scache.ways = 4; |
141 | c->scache.waybit= ffs(scache_size / c->scache.ways) - 1; | 141 | c->scache.waybit= __ffs(scache_size / c->scache.ways); |
142 | c->scache.waysize = scache_size / c->scache.ways; | 142 | c->scache.waysize = scache_size / c->scache.ways; |
143 | c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways); | 143 | c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways); |
144 | printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n", | 144 | printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n", |
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index a865f2394cb0..9dca099ba16b 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c | |||
@@ -32,13 +32,35 @@ extern void build_tlb_refill_handler(void); | |||
32 | "nop; nop; nop; nop; nop; nop;\n\t" \ | 32 | "nop; nop; nop; nop; nop; nop;\n\t" \ |
33 | ".set reorder\n\t") | 33 | ".set reorder\n\t") |
34 | 34 | ||
35 | /* Atomicity and interruptability */ | ||
36 | #ifdef CONFIG_MIPS_MT_SMTC | ||
37 | |||
38 | #include <asm/smtc.h> | ||
39 | #include <asm/mipsmtregs.h> | ||
40 | |||
41 | #define ENTER_CRITICAL(flags) \ | ||
42 | { \ | ||
43 | unsigned int mvpflags; \ | ||
44 | local_irq_save(flags);\ | ||
45 | mvpflags = dvpe() | ||
46 | #define EXIT_CRITICAL(flags) \ | ||
47 | evpe(mvpflags); \ | ||
48 | local_irq_restore(flags); \ | ||
49 | } | ||
50 | #else | ||
51 | |||
52 | #define ENTER_CRITICAL(flags) local_irq_save(flags) | ||
53 | #define EXIT_CRITICAL(flags) local_irq_restore(flags) | ||
54 | |||
55 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
56 | |||
35 | void local_flush_tlb_all(void) | 57 | void local_flush_tlb_all(void) |
36 | { | 58 | { |
37 | unsigned long flags; | 59 | unsigned long flags; |
38 | unsigned long old_ctx; | 60 | unsigned long old_ctx; |
39 | int entry; | 61 | int entry; |
40 | 62 | ||
41 | local_irq_save(flags); | 63 | ENTER_CRITICAL(flags); |
42 | /* Save old context and create impossible VPN2 value */ | 64 | /* Save old context and create impossible VPN2 value */ |
43 | old_ctx = read_c0_entryhi(); | 65 | old_ctx = read_c0_entryhi(); |
44 | write_c0_entrylo0(0); | 66 | write_c0_entrylo0(0); |
@@ -57,7 +79,7 @@ void local_flush_tlb_all(void) | |||
57 | } | 79 | } |
58 | tlbw_use_hazard(); | 80 | tlbw_use_hazard(); |
59 | write_c0_entryhi(old_ctx); | 81 | write_c0_entryhi(old_ctx); |
60 | local_irq_restore(flags); | 82 | EXIT_CRITICAL(flags); |
61 | } | 83 | } |
62 | 84 | ||
63 | /* All entries common to a mm share an asid. To effectively flush | 85 | /* All entries common to a mm share an asid. To effectively flush |
@@ -87,6 +109,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
87 | unsigned long flags; | 109 | unsigned long flags; |
88 | int size; | 110 | int size; |
89 | 111 | ||
112 | ENTER_CRITICAL(flags); | ||
90 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 113 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; |
91 | size = (size + 1) >> 1; | 114 | size = (size + 1) >> 1; |
92 | local_irq_save(flags); | 115 | local_irq_save(flags); |
@@ -120,7 +143,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
120 | } else { | 143 | } else { |
121 | drop_mmu_context(mm, cpu); | 144 | drop_mmu_context(mm, cpu); |
122 | } | 145 | } |
123 | local_irq_restore(flags); | 146 | EXIT_CRITICAL(flags); |
124 | } | 147 | } |
125 | } | 148 | } |
126 | 149 | ||
@@ -129,9 +152,9 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
129 | unsigned long flags; | 152 | unsigned long flags; |
130 | int size; | 153 | int size; |
131 | 154 | ||
155 | ENTER_CRITICAL(flags); | ||
132 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 156 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; |
133 | size = (size + 1) >> 1; | 157 | size = (size + 1) >> 1; |
134 | local_irq_save(flags); | ||
135 | if (size <= current_cpu_data.tlbsize / 2) { | 158 | if (size <= current_cpu_data.tlbsize / 2) { |
136 | int pid = read_c0_entryhi(); | 159 | int pid = read_c0_entryhi(); |
137 | 160 | ||
@@ -162,7 +185,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
162 | } else { | 185 | } else { |
163 | local_flush_tlb_all(); | 186 | local_flush_tlb_all(); |
164 | } | 187 | } |
165 | local_irq_restore(flags); | 188 | EXIT_CRITICAL(flags); |
166 | } | 189 | } |
167 | 190 | ||
168 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | 191 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) |
@@ -175,7 +198,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
175 | 198 | ||
176 | newpid = cpu_asid(cpu, vma->vm_mm); | 199 | newpid = cpu_asid(cpu, vma->vm_mm); |
177 | page &= (PAGE_MASK << 1); | 200 | page &= (PAGE_MASK << 1); |
178 | local_irq_save(flags); | 201 | ENTER_CRITICAL(flags); |
179 | oldpid = read_c0_entryhi(); | 202 | oldpid = read_c0_entryhi(); |
180 | write_c0_entryhi(page | newpid); | 203 | write_c0_entryhi(page | newpid); |
181 | mtc0_tlbw_hazard(); | 204 | mtc0_tlbw_hazard(); |
@@ -194,7 +217,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
194 | 217 | ||
195 | finish: | 218 | finish: |
196 | write_c0_entryhi(oldpid); | 219 | write_c0_entryhi(oldpid); |
197 | local_irq_restore(flags); | 220 | EXIT_CRITICAL(flags); |
198 | } | 221 | } |
199 | } | 222 | } |
200 | 223 | ||
@@ -207,7 +230,7 @@ void local_flush_tlb_one(unsigned long page) | |||
207 | unsigned long flags; | 230 | unsigned long flags; |
208 | int oldpid, idx; | 231 | int oldpid, idx; |
209 | 232 | ||
210 | local_irq_save(flags); | 233 | ENTER_CRITICAL(flags); |
211 | oldpid = read_c0_entryhi(); | 234 | oldpid = read_c0_entryhi(); |
212 | page &= (PAGE_MASK << 1); | 235 | page &= (PAGE_MASK << 1); |
213 | write_c0_entryhi(page); | 236 | write_c0_entryhi(page); |
@@ -226,7 +249,7 @@ void local_flush_tlb_one(unsigned long page) | |||
226 | } | 249 | } |
227 | write_c0_entryhi(oldpid); | 250 | write_c0_entryhi(oldpid); |
228 | 251 | ||
229 | local_irq_restore(flags); | 252 | EXIT_CRITICAL(flags); |
230 | } | 253 | } |
231 | 254 | ||
232 | /* | 255 | /* |
@@ -249,7 +272,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) | |||
249 | if (current->active_mm != vma->vm_mm) | 272 | if (current->active_mm != vma->vm_mm) |
250 | return; | 273 | return; |
251 | 274 | ||
252 | local_irq_save(flags); | 275 | ENTER_CRITICAL(flags); |
253 | 276 | ||
254 | pid = read_c0_entryhi() & ASID_MASK; | 277 | pid = read_c0_entryhi() & ASID_MASK; |
255 | address &= (PAGE_MASK << 1); | 278 | address &= (PAGE_MASK << 1); |
@@ -277,7 +300,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) | |||
277 | else | 300 | else |
278 | tlb_write_indexed(); | 301 | tlb_write_indexed(); |
279 | tlbw_use_hazard(); | 302 | tlbw_use_hazard(); |
280 | local_irq_restore(flags); | 303 | EXIT_CRITICAL(flags); |
281 | } | 304 | } |
282 | 305 | ||
283 | #if 0 | 306 | #if 0 |
@@ -291,7 +314,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma, | |||
291 | pte_t *ptep; | 314 | pte_t *ptep; |
292 | int idx; | 315 | int idx; |
293 | 316 | ||
294 | local_irq_save(flags); | 317 | ENTER_CRITICAL(flags); |
295 | address &= (PAGE_MASK << 1); | 318 | address &= (PAGE_MASK << 1); |
296 | asid = read_c0_entryhi() & ASID_MASK; | 319 | asid = read_c0_entryhi() & ASID_MASK; |
297 | write_c0_entryhi(address | asid); | 320 | write_c0_entryhi(address | asid); |
@@ -310,7 +333,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma, | |||
310 | else | 333 | else |
311 | tlb_write_indexed(); | 334 | tlb_write_indexed(); |
312 | tlbw_use_hazard(); | 335 | tlbw_use_hazard(); |
313 | local_irq_restore(flags); | 336 | EXIT_CRITICAL(flags); |
314 | } | 337 | } |
315 | #endif | 338 | #endif |
316 | 339 | ||
@@ -322,7 +345,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, | |||
322 | unsigned long old_pagemask; | 345 | unsigned long old_pagemask; |
323 | unsigned long old_ctx; | 346 | unsigned long old_ctx; |
324 | 347 | ||
325 | local_irq_save(flags); | 348 | ENTER_CRITICAL(flags); |
326 | /* Save old context and create impossible VPN2 value */ | 349 | /* Save old context and create impossible VPN2 value */ |
327 | old_ctx = read_c0_entryhi(); | 350 | old_ctx = read_c0_entryhi(); |
328 | old_pagemask = read_c0_pagemask(); | 351 | old_pagemask = read_c0_pagemask(); |
@@ -342,7 +365,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, | |||
342 | BARRIER; | 365 | BARRIER; |
343 | write_c0_pagemask(old_pagemask); | 366 | write_c0_pagemask(old_pagemask); |
344 | local_flush_tlb_all(); | 367 | local_flush_tlb_all(); |
345 | local_irq_restore(flags); | 368 | EXIT_CRITICAL(flags); |
346 | } | 369 | } |
347 | 370 | ||
348 | /* | 371 | /* |
@@ -362,7 +385,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, | |||
362 | unsigned long old_pagemask; | 385 | unsigned long old_pagemask; |
363 | unsigned long old_ctx; | 386 | unsigned long old_ctx; |
364 | 387 | ||
365 | local_irq_save(flags); | 388 | ENTER_CRITICAL(flags); |
366 | /* Save old context and create impossible VPN2 value */ | 389 | /* Save old context and create impossible VPN2 value */ |
367 | old_ctx = read_c0_entryhi(); | 390 | old_ctx = read_c0_entryhi(); |
368 | old_pagemask = read_c0_pagemask(); | 391 | old_pagemask = read_c0_pagemask(); |
@@ -386,10 +409,11 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, | |||
386 | write_c0_entryhi(old_ctx); | 409 | write_c0_entryhi(old_ctx); |
387 | write_c0_pagemask(old_pagemask); | 410 | write_c0_pagemask(old_pagemask); |
388 | out: | 411 | out: |
389 | local_irq_restore(flags); | 412 | EXIT_CRITICAL(flags); |
390 | return ret; | 413 | return ret; |
391 | } | 414 | } |
392 | 415 | ||
416 | extern void __init sanitize_tlb_entries(void); | ||
393 | static void __init probe_tlb(unsigned long config) | 417 | static void __init probe_tlb(unsigned long config) |
394 | { | 418 | { |
395 | struct cpuinfo_mips *c = ¤t_cpu_data; | 419 | struct cpuinfo_mips *c = ¤t_cpu_data; |
@@ -402,6 +426,14 @@ static void __init probe_tlb(unsigned long config) | |||
402 | */ | 426 | */ |
403 | if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY) | 427 | if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY) |
404 | return; | 428 | return; |
429 | #ifdef CONFIG_MIPS_MT_SMTC | ||
430 | /* | ||
431 | * If TLB is shared in SMTC system, total size already | ||
432 | * has been calculated and written into cpu_data tlbsize | ||
433 | */ | ||
434 | if((smtc_status & SMTC_TLB_SHARED) == SMTC_TLB_SHARED) | ||
435 | return; | ||
436 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
405 | 437 | ||
406 | reg = read_c0_config1(); | 438 | reg = read_c0_config1(); |
407 | if (!((config >> 7) & 3)) | 439 | if (!((config >> 7) & 3)) |
@@ -410,6 +442,15 @@ static void __init probe_tlb(unsigned long config) | |||
410 | c->tlbsize = ((reg >> 25) & 0x3f) + 1; | 442 | c->tlbsize = ((reg >> 25) & 0x3f) + 1; |
411 | } | 443 | } |
412 | 444 | ||
445 | static int __initdata ntlb = 0; | ||
446 | static int __init set_ntlb(char *str) | ||
447 | { | ||
448 | get_option(&str, &ntlb); | ||
449 | return 1; | ||
450 | } | ||
451 | |||
452 | __setup("ntlb=", set_ntlb); | ||
453 | |||
413 | void __init tlb_init(void) | 454 | void __init tlb_init(void) |
414 | { | 455 | { |
415 | unsigned int config = read_c0_config(); | 456 | unsigned int config = read_c0_config(); |
@@ -432,5 +473,15 @@ void __init tlb_init(void) | |||
432 | 473 | ||
433 | /* Did I tell you that ARC SUCKS? */ | 474 | /* Did I tell you that ARC SUCKS? */ |
434 | 475 | ||
476 | if (ntlb) { | ||
477 | if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) { | ||
478 | int wired = current_cpu_data.tlbsize - ntlb; | ||
479 | write_c0_wired(wired); | ||
480 | write_c0_index(wired-1); | ||
481 | printk ("Restricting TLB to %d entries\n", ntlb); | ||
482 | } else | ||
483 | printk("Ignoring invalid argument ntlb=%d\n", ntlb); | ||
484 | } | ||
485 | |||
435 | build_tlb_refill_handler(); | 486 | build_tlb_refill_handler(); |
436 | } | 487 | } |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 599b3c297186..053dbacac56b 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -7,6 +7,16 @@ | |||
7 | * | 7 | * |
8 | * Copyright (C) 2004,2005 by Thiemo Seufer | 8 | * Copyright (C) 2004,2005 by Thiemo Seufer |
9 | * Copyright (C) 2005 Maciej W. Rozycki | 9 | * Copyright (C) 2005 Maciej W. Rozycki |
10 | * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) | ||
11 | * | ||
12 | * ... and the days got worse and worse and now you see | ||
13 | * I've gone completly out of my mind. | ||
14 | * | ||
15 | * They're coming to take me a away haha | ||
16 | * they're coming to take me a away hoho hihi haha | ||
17 | * to the funny farm where code is beautiful all the time ... | ||
18 | * | ||
19 | * (Condolences to Napoleon XIV) | ||
10 | */ | 20 | */ |
11 | 21 | ||
12 | #include <stdarg.h> | 22 | #include <stdarg.h> |
@@ -68,6 +78,7 @@ enum fields | |||
68 | BIMM = 0x040, | 78 | BIMM = 0x040, |
69 | JIMM = 0x080, | 79 | JIMM = 0x080, |
70 | FUNC = 0x100, | 80 | FUNC = 0x100, |
81 | SET = 0x200 | ||
71 | }; | 82 | }; |
72 | 83 | ||
73 | #define OP_MASK 0x2f | 84 | #define OP_MASK 0x2f |
@@ -86,6 +97,8 @@ enum fields | |||
86 | #define JIMM_SH 0 | 97 | #define JIMM_SH 0 |
87 | #define FUNC_MASK 0x2f | 98 | #define FUNC_MASK 0x2f |
88 | #define FUNC_SH 0 | 99 | #define FUNC_SH 0 |
100 | #define SET_MASK 0x7 | ||
101 | #define SET_SH 0 | ||
89 | 102 | ||
90 | enum opcode { | 103 | enum opcode { |
91 | insn_invalid, | 104 | insn_invalid, |
@@ -129,8 +142,8 @@ static __initdata struct insn insn_table[] = { | |||
129 | { insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM }, | 142 | { insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM }, |
130 | { insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM }, | 143 | { insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM }, |
131 | { insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD }, | 144 | { insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD }, |
132 | { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD }, | 145 | { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD | SET}, |
133 | { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD }, | 146 | { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD | SET}, |
134 | { insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE }, | 147 | { insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE }, |
135 | { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, | 148 | { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, |
136 | { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, | 149 | { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, |
@@ -145,8 +158,8 @@ static __initdata struct insn insn_table[] = { | |||
145 | { insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM }, | 158 | { insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM }, |
146 | { insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM }, | 159 | { insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM }, |
147 | { insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM }, | 160 | { insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM }, |
148 | { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD }, | 161 | { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD | SET}, |
149 | { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD }, | 162 | { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD | SET}, |
150 | { insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM }, | 163 | { insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM }, |
151 | { insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 }, | 164 | { insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 }, |
152 | { insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM }, | 165 | { insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM }, |
@@ -242,6 +255,14 @@ static __init u32 build_func(u32 arg) | |||
242 | return arg & FUNC_MASK; | 255 | return arg & FUNC_MASK; |
243 | } | 256 | } |
244 | 257 | ||
258 | static __init u32 build_set(u32 arg) | ||
259 | { | ||
260 | if (arg & ~SET_MASK) | ||
261 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | ||
262 | |||
263 | return arg & SET_MASK; | ||
264 | } | ||
265 | |||
245 | /* | 266 | /* |
246 | * The order of opcode arguments is implicitly left to right, | 267 | * The order of opcode arguments is implicitly left to right, |
247 | * starting with RS and ending with FUNC or IMM. | 268 | * starting with RS and ending with FUNC or IMM. |
@@ -273,6 +294,7 @@ static void __init build_insn(u32 **buf, enum opcode opc, ...) | |||
273 | if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32)); | 294 | if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32)); |
274 | if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32)); | 295 | if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32)); |
275 | if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32)); | 296 | if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32)); |
297 | if (ip->fields & SET) op |= build_set(va_arg(ap, u32)); | ||
276 | va_end(ap); | 298 | va_end(ap); |
277 | 299 | ||
278 | **buf = op; | 300 | **buf = op; |
@@ -358,8 +380,8 @@ I_u1s2(_bgezl); | |||
358 | I_u1s2(_bltz); | 380 | I_u1s2(_bltz); |
359 | I_u1s2(_bltzl); | 381 | I_u1s2(_bltzl); |
360 | I_u1u2s3(_bne); | 382 | I_u1u2s3(_bne); |
361 | I_u1u2(_dmfc0); | 383 | I_u1u2u3(_dmfc0); |
362 | I_u1u2(_dmtc0); | 384 | I_u1u2u3(_dmtc0); |
363 | I_u2u1s3(_daddiu); | 385 | I_u2u1s3(_daddiu); |
364 | I_u3u1u2(_daddu); | 386 | I_u3u1u2(_daddu); |
365 | I_u2u1u3(_dsll); | 387 | I_u2u1u3(_dsll); |
@@ -376,8 +398,8 @@ I_u2s3u1(_ll); | |||
376 | I_u2s3u1(_lld); | 398 | I_u2s3u1(_lld); |
377 | I_u1s2(_lui); | 399 | I_u1s2(_lui); |
378 | I_u2s3u1(_lw); | 400 | I_u2s3u1(_lw); |
379 | I_u1u2(_mfc0); | 401 | I_u1u2u3(_mfc0); |
380 | I_u1u2(_mtc0); | 402 | I_u1u2u3(_mtc0); |
381 | I_u2u1u3(_ori); | 403 | I_u2u1u3(_ori); |
382 | I_0(_rfe); | 404 | I_0(_rfe); |
383 | I_u2s3u1(_sc); | 405 | I_u2s3u1(_sc); |
@@ -451,8 +473,8 @@ L_LA(_r3000_write_probe_fail) | |||
451 | # define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh) | 473 | # define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh) |
452 | # define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh) | 474 | # define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh) |
453 | # define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh) | 475 | # define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh) |
454 | # define i_MFC0(buf, rt, rd) i_dmfc0(buf, rt, rd) | 476 | # define i_MFC0(buf, rt, rd...) i_dmfc0(buf, rt, rd) |
455 | # define i_MTC0(buf, rt, rd) i_dmtc0(buf, rt, rd) | 477 | # define i_MTC0(buf, rt, rd...) i_dmtc0(buf, rt, rd) |
456 | # define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val) | 478 | # define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val) |
457 | # define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd) | 479 | # define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd) |
458 | # define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd) | 480 | # define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd) |
@@ -464,8 +486,8 @@ L_LA(_r3000_write_probe_fail) | |||
464 | # define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh) | 486 | # define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh) |
465 | # define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh) | 487 | # define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh) |
466 | # define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh) | 488 | # define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh) |
467 | # define i_MFC0(buf, rt, rd) i_mfc0(buf, rt, rd) | 489 | # define i_MFC0(buf, rt, rd...) i_mfc0(buf, rt, rd) |
468 | # define i_MTC0(buf, rt, rd) i_mtc0(buf, rt, rd) | 490 | # define i_MTC0(buf, rt, rd...) i_mtc0(buf, rt, rd) |
469 | # define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val) | 491 | # define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val) |
470 | # define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd) | 492 | # define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd) |
471 | # define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd) | 493 | # define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd) |
@@ -670,14 +692,15 @@ static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg, | |||
670 | #define K1 27 | 692 | #define K1 27 |
671 | 693 | ||
672 | /* Some CP0 registers */ | 694 | /* Some CP0 registers */ |
673 | #define C0_INDEX 0 | 695 | #define C0_INDEX 0, 0 |
674 | #define C0_ENTRYLO0 2 | 696 | #define C0_ENTRYLO0 2, 0 |
675 | #define C0_ENTRYLO1 3 | 697 | #define C0_TCBIND 2, 2 |
676 | #define C0_CONTEXT 4 | 698 | #define C0_ENTRYLO1 3, 0 |
677 | #define C0_BADVADDR 8 | 699 | #define C0_CONTEXT 4, 0 |
678 | #define C0_ENTRYHI 10 | 700 | #define C0_BADVADDR 8, 0 |
679 | #define C0_EPC 14 | 701 | #define C0_ENTRYHI 10, 0 |
680 | #define C0_XCONTEXT 20 | 702 | #define C0_EPC 14, 0 |
703 | #define C0_XCONTEXT 20, 0 | ||
681 | 704 | ||
682 | #ifdef CONFIG_64BIT | 705 | #ifdef CONFIG_64BIT |
683 | # define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT) | 706 | # define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT) |
@@ -742,7 +765,7 @@ static void __init build_r3000_tlb_refill_handler(void) | |||
742 | } | 765 | } |
743 | #endif | 766 | #endif |
744 | 767 | ||
745 | memcpy((void *)CAC_BASE, tlb_handler, 0x80); | 768 | memcpy((void *)ebase, tlb_handler, 0x80); |
746 | } | 769 | } |
747 | 770 | ||
748 | /* | 771 | /* |
@@ -951,12 +974,20 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r, | |||
951 | /* No i_nop needed here, since the next insn doesn't touch TMP. */ | 974 | /* No i_nop needed here, since the next insn doesn't touch TMP. */ |
952 | 975 | ||
953 | #ifdef CONFIG_SMP | 976 | #ifdef CONFIG_SMP |
977 | # ifdef CONFIG_MIPS_MT_SMTC | ||
978 | /* | ||
979 | * SMTC uses TCBind value as "CPU" index | ||
980 | */ | ||
981 | i_mfc0(p, ptr, C0_TCBIND); | ||
982 | i_dsrl(p, ptr, ptr, 19); | ||
983 | # else | ||
954 | /* | 984 | /* |
955 | * 64 bit SMP running in XKPHYS has smp_processor_id() << 3 | 985 | * 64 bit SMP running in XKPHYS has smp_processor_id() << 3 |
956 | * stored in CONTEXT. | 986 | * stored in CONTEXT. |
957 | */ | 987 | */ |
958 | i_dmfc0(p, ptr, C0_CONTEXT); | 988 | i_dmfc0(p, ptr, C0_CONTEXT); |
959 | i_dsrl(p, ptr, ptr, 23); | 989 | i_dsrl(p, ptr, ptr, 23); |
990 | #endif | ||
960 | i_LA_mostly(p, tmp, pgdc); | 991 | i_LA_mostly(p, tmp, pgdc); |
961 | i_daddu(p, ptr, ptr, tmp); | 992 | i_daddu(p, ptr, ptr, tmp); |
962 | i_dmfc0(p, tmp, C0_BADVADDR); | 993 | i_dmfc0(p, tmp, C0_BADVADDR); |
@@ -1014,9 +1045,21 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) | |||
1014 | 1045 | ||
1015 | /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */ | 1046 | /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */ |
1016 | #ifdef CONFIG_SMP | 1047 | #ifdef CONFIG_SMP |
1048 | #ifdef CONFIG_MIPS_MT_SMTC | ||
1049 | /* | ||
1050 | * SMTC uses TCBind value as "CPU" index | ||
1051 | */ | ||
1052 | i_mfc0(p, ptr, C0_TCBIND); | ||
1053 | i_LA_mostly(p, tmp, pgdc); | ||
1054 | i_srl(p, ptr, ptr, 19); | ||
1055 | #else | ||
1056 | /* | ||
1057 | * smp_processor_id() << 3 is stored in CONTEXT. | ||
1058 | */ | ||
1017 | i_mfc0(p, ptr, C0_CONTEXT); | 1059 | i_mfc0(p, ptr, C0_CONTEXT); |
1018 | i_LA_mostly(p, tmp, pgdc); | 1060 | i_LA_mostly(p, tmp, pgdc); |
1019 | i_srl(p, ptr, ptr, 23); | 1061 | i_srl(p, ptr, ptr, 23); |
1062 | #endif | ||
1020 | i_addu(p, ptr, tmp, ptr); | 1063 | i_addu(p, ptr, tmp, ptr); |
1021 | #else | 1064 | #else |
1022 | i_LA_mostly(p, ptr, pgdc); | 1065 | i_LA_mostly(p, ptr, pgdc); |
@@ -1247,7 +1290,7 @@ static void __init build_r4000_tlb_refill_handler(void) | |||
1247 | } | 1290 | } |
1248 | #endif | 1291 | #endif |
1249 | 1292 | ||
1250 | memcpy((void *)CAC_BASE, final_handler, 0x100); | 1293 | memcpy((void *)ebase, final_handler, 0x100); |
1251 | } | 1294 | } |
1252 | 1295 | ||
1253 | /* | 1296 | /* |