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 | /* |
