aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-03-31 15:34:58 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-03-31 15:34:58 -0500
commit86579dd06deecfa6ac88d5e84e4d63c397cd6f6d (patch)
treeb4475d3ccde53015ad84a06e4e55e64591171b75 /arch/mips/mm
parent7ea9ea832212c4a755650f7c7cc1ff0b63292a41 (diff)
parenta0f067802576d4eb4c65d40b8ee7d6ea3c81dd61 (diff)
Merge branch 'master'
Diffstat (limited to 'arch/mips/mm')
-rw-r--r--arch/mips/mm/Makefile2
-rw-r--r--arch/mips/mm/c-r3k.c18
-rw-r--r--arch/mips/mm/c-r4k.c1
-rw-r--r--arch/mips/mm/dma-ip32.c6
-rw-r--r--arch/mips/mm/init.c15
-rw-r--r--arch/mips/mm/pg-r4k.c10
-rw-r--r--arch/mips/mm/sc-rm7k.c25
-rw-r--r--arch/mips/mm/tlb-andes.c259
-rw-r--r--arch/mips/mm/tlb-r4k.c5
-rw-r--r--arch/mips/mm/tlbex.c13
10 files changed, 43 insertions, 311 deletions
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index b0178da019f0..4a6220116c96 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_HIGHMEM) += highmem.o
12obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o 12obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
13obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o 13obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
14obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o 14obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
15obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o pg-r4k.o tlb-andes.o 15obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
16obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o pg-r4k.o 16obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o pg-r4k.o
17obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o 17obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
18obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o 18obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 27f4fa25e8c9..9dd1352d5748 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -129,7 +129,7 @@ static void r3k_flush_icache_range(unsigned long start, unsigned long end)
129 "sb\t$0, 0x014(%0)\n\t" 129 "sb\t$0, 0x014(%0)\n\t"
130 "sb\t$0, 0x018(%0)\n\t" 130 "sb\t$0, 0x018(%0)\n\t"
131 "sb\t$0, 0x01c(%0)\n\t" 131 "sb\t$0, 0x01c(%0)\n\t"
132 "sb\t$0, 0x020(%0)\n\t" 132 "sb\t$0, 0x020(%0)\n\t"
133 "sb\t$0, 0x024(%0)\n\t" 133 "sb\t$0, 0x024(%0)\n\t"
134 "sb\t$0, 0x028(%0)\n\t" 134 "sb\t$0, 0x028(%0)\n\t"
135 "sb\t$0, 0x02c(%0)\n\t" 135 "sb\t$0, 0x02c(%0)\n\t"
@@ -145,7 +145,7 @@ static void r3k_flush_icache_range(unsigned long start, unsigned long end)
145 "sb\t$0, 0x054(%0)\n\t" 145 "sb\t$0, 0x054(%0)\n\t"
146 "sb\t$0, 0x058(%0)\n\t" 146 "sb\t$0, 0x058(%0)\n\t"
147 "sb\t$0, 0x05c(%0)\n\t" 147 "sb\t$0, 0x05c(%0)\n\t"
148 "sb\t$0, 0x060(%0)\n\t" 148 "sb\t$0, 0x060(%0)\n\t"
149 "sb\t$0, 0x064(%0)\n\t" 149 "sb\t$0, 0x064(%0)\n\t"
150 "sb\t$0, 0x068(%0)\n\t" 150 "sb\t$0, 0x068(%0)\n\t"
151 "sb\t$0, 0x06c(%0)\n\t" 151 "sb\t$0, 0x06c(%0)\n\t"
@@ -182,31 +182,31 @@ static void r3k_flush_dcache_range(unsigned long start, unsigned long end)
182 "sb\t$0, 0x004(%0)\n\t" 182 "sb\t$0, 0x004(%0)\n\t"
183 "sb\t$0, 0x008(%0)\n\t" 183 "sb\t$0, 0x008(%0)\n\t"
184 "sb\t$0, 0x00c(%0)\n\t" 184 "sb\t$0, 0x00c(%0)\n\t"
185 "sb\t$0, 0x010(%0)\n\t" 185 "sb\t$0, 0x010(%0)\n\t"
186 "sb\t$0, 0x014(%0)\n\t" 186 "sb\t$0, 0x014(%0)\n\t"
187 "sb\t$0, 0x018(%0)\n\t" 187 "sb\t$0, 0x018(%0)\n\t"
188 "sb\t$0, 0x01c(%0)\n\t" 188 "sb\t$0, 0x01c(%0)\n\t"
189 "sb\t$0, 0x020(%0)\n\t" 189 "sb\t$0, 0x020(%0)\n\t"
190 "sb\t$0, 0x024(%0)\n\t" 190 "sb\t$0, 0x024(%0)\n\t"
191 "sb\t$0, 0x028(%0)\n\t" 191 "sb\t$0, 0x028(%0)\n\t"
192 "sb\t$0, 0x02c(%0)\n\t" 192 "sb\t$0, 0x02c(%0)\n\t"
193 "sb\t$0, 0x030(%0)\n\t" 193 "sb\t$0, 0x030(%0)\n\t"
194 "sb\t$0, 0x034(%0)\n\t" 194 "sb\t$0, 0x034(%0)\n\t"
195 "sb\t$0, 0x038(%0)\n\t" 195 "sb\t$0, 0x038(%0)\n\t"
196 "sb\t$0, 0x03c(%0)\n\t" 196 "sb\t$0, 0x03c(%0)\n\t"
197 "sb\t$0, 0x040(%0)\n\t" 197 "sb\t$0, 0x040(%0)\n\t"
198 "sb\t$0, 0x044(%0)\n\t" 198 "sb\t$0, 0x044(%0)\n\t"
199 "sb\t$0, 0x048(%0)\n\t" 199 "sb\t$0, 0x048(%0)\n\t"
200 "sb\t$0, 0x04c(%0)\n\t" 200 "sb\t$0, 0x04c(%0)\n\t"
201 "sb\t$0, 0x050(%0)\n\t" 201 "sb\t$0, 0x050(%0)\n\t"
202 "sb\t$0, 0x054(%0)\n\t" 202 "sb\t$0, 0x054(%0)\n\t"
203 "sb\t$0, 0x058(%0)\n\t" 203 "sb\t$0, 0x058(%0)\n\t"
204 "sb\t$0, 0x05c(%0)\n\t" 204 "sb\t$0, 0x05c(%0)\n\t"
205 "sb\t$0, 0x060(%0)\n\t" 205 "sb\t$0, 0x060(%0)\n\t"
206 "sb\t$0, 0x064(%0)\n\t" 206 "sb\t$0, 0x064(%0)\n\t"
207 "sb\t$0, 0x068(%0)\n\t" 207 "sb\t$0, 0x068(%0)\n\t"
208 "sb\t$0, 0x06c(%0)\n\t" 208 "sb\t$0, 0x06c(%0)\n\t"
209 "sb\t$0, 0x070(%0)\n\t" 209 "sb\t$0, 0x070(%0)\n\t"
210 "sb\t$0, 0x074(%0)\n\t" 210 "sb\t$0, 0x074(%0)\n\t"
211 "sb\t$0, 0x078(%0)\n\t" 211 "sb\t$0, 0x078(%0)\n\t"
212 "sb\t$0, 0x07c(%0)\n\t" 212 "sb\t$0, 0x07c(%0)\n\t"
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 9572ed44f0d5..32b7f6aeb983 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -786,6 +786,7 @@ static void __init probe_pcache(void)
786 c->dcache.waybit = 0; 786 c->dcache.waybit = 0;
787 787
788 c->options |= MIPS_CPU_CACHE_CDEX_P; 788 c->options |= MIPS_CPU_CACHE_CDEX_P;
789 c->options |= MIPS_CPU_PREFETCH;
789 break; 790 break;
790 791
791 case CPU_R4000PC: 792 case CPU_R4000PC:
diff --git a/arch/mips/mm/dma-ip32.c b/arch/mips/mm/dma-ip32.c
index a7e3072ff78d..ec54ed0d26ff 100644
--- a/arch/mips/mm/dma-ip32.c
+++ b/arch/mips/mm/dma-ip32.c
@@ -138,7 +138,7 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
138 BUG(); 138 BUG();
139 } 139 }
140 140
141 addr = virt_to_phys(ptr)&RAM_OFFSET_MASK;; 141 addr = virt_to_phys(ptr)&RAM_OFFSET_MASK;
142 if(dev == NULL) 142 if(dev == NULL)
143 addr+=CRIME_HI_MEM_BASE; 143 addr+=CRIME_HI_MEM_BASE;
144 return (dma_addr_t)addr; 144 return (dma_addr_t)addr;
@@ -179,7 +179,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
179 addr = (unsigned long) page_address(sg->page)+sg->offset; 179 addr = (unsigned long) page_address(sg->page)+sg->offset;
180 if (addr) 180 if (addr)
181 __dma_sync(addr, sg->length, direction); 181 __dma_sync(addr, sg->length, direction);
182 addr = __pa(addr)&RAM_OFFSET_MASK;; 182 addr = __pa(addr)&RAM_OFFSET_MASK;
183 if(dev == NULL) 183 if(dev == NULL)
184 addr += CRIME_HI_MEM_BASE; 184 addr += CRIME_HI_MEM_BASE;
185 sg->dma_address = (dma_addr_t)addr; 185 sg->dma_address = (dma_addr_t)addr;
@@ -199,7 +199,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
199 199
200 addr = (unsigned long) page_address(page) + offset; 200 addr = (unsigned long) page_address(page) + offset;
201 dma_cache_wback_inv(addr, size); 201 dma_cache_wback_inv(addr, size);
202 addr = __pa(addr)&RAM_OFFSET_MASK;; 202 addr = __pa(addr)&RAM_OFFSET_MASK;
203 if(dev == NULL) 203 if(dev == NULL)
204 addr += CRIME_HI_MEM_BASE; 204 addr += CRIME_HI_MEM_BASE;
205 205
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 0ff9a348b843..ad89c442f299 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -25,6 +25,7 @@
25#include <linux/highmem.h> 25#include <linux/highmem.h>
26#include <linux/swap.h> 26#include <linux/swap.h>
27#include <linux/proc_fs.h> 27#include <linux/proc_fs.h>
28#include <linux/pfn.h>
28 29
29#include <asm/bootinfo.h> 30#include <asm/bootinfo.h>
30#include <asm/cachectl.h> 31#include <asm/cachectl.h>
@@ -54,7 +55,8 @@ unsigned long empty_zero_page, zero_page_mask;
54 */ 55 */
55unsigned long setup_zero_pages(void) 56unsigned long setup_zero_pages(void)
56{ 57{
57 unsigned long order, size; 58 unsigned int order;
59 unsigned long size;
58 struct page *page; 60 struct page *page;
59 61
60 if (cpu_has_vce) 62 if (cpu_has_vce)
@@ -67,9 +69,9 @@ unsigned long setup_zero_pages(void)
67 panic("Oh boy, that early out of memory?"); 69 panic("Oh boy, that early out of memory?");
68 70
69 page = virt_to_page(empty_zero_page); 71 page = virt_to_page(empty_zero_page);
72 split_page(page, order);
70 while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { 73 while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) {
71 SetPageReserved(page); 74 SetPageReserved(page);
72 set_page_count(page, 1);
73 page++; 75 page++;
74 } 76 }
75 77
@@ -176,9 +178,6 @@ void __init paging_init(void)
176 free_area_init(zones_size); 178 free_area_init(zones_size);
177} 179}
178 180
179#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
180#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
181
182static inline int page_is_ram(unsigned long pagenr) 181static inline int page_is_ram(unsigned long pagenr)
183{ 182{
184 int i; 183 int i;
@@ -244,7 +243,7 @@ void __init mem_init(void)
244#ifdef CONFIG_LIMITED_DMA 243#ifdef CONFIG_LIMITED_DMA
245 set_page_address(page, lowmem_page_address(page)); 244 set_page_address(page, lowmem_page_address(page));
246#endif 245#endif
247 set_page_count(page, 1); 246 init_page_count(page);
248 __free_page(page); 247 __free_page(page);
249 totalhigh_pages++; 248 totalhigh_pages++;
250 } 249 }
@@ -291,7 +290,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
291 290
292 for (; start < end; start += PAGE_SIZE) { 291 for (; start < end; start += PAGE_SIZE) {
293 ClearPageReserved(virt_to_page(start)); 292 ClearPageReserved(virt_to_page(start));
294 set_page_count(virt_to_page(start), 1); 293 init_page_count(virt_to_page(start));
295 free_page(start); 294 free_page(start);
296 totalram_pages++; 295 totalram_pages++;
297 } 296 }
@@ -314,7 +313,7 @@ void free_initmem(void)
314 page = addr; 313 page = addr;
315#endif 314#endif
316 ClearPageReserved(virt_to_page(page)); 315 ClearPageReserved(virt_to_page(page));
317 set_page_count(virt_to_page(page), 1); 316 init_page_count(virt_to_page(page));
318 free_page(page); 317 free_page(page);
319 totalram_pages++; 318 totalram_pages++;
320 freed += PAGE_SIZE; 319 freed += PAGE_SIZE;
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
index f51e180072e3..e4390dc3eb48 100644
--- a/arch/mips/mm/pg-r4k.c
+++ b/arch/mips/mm/pg-r4k.c
@@ -124,7 +124,7 @@ static inline void build_nop(void)
124 124
125static inline void build_src_pref(int advance) 125static inline void build_src_pref(int advance)
126{ 126{
127 if (!(load_offset & (cpu_dcache_line_size() - 1))) { 127 if (!(load_offset & (cpu_dcache_line_size() - 1)) && advance) {
128 union mips_instruction mi; 128 union mips_instruction mi;
129 129
130 mi.i_format.opcode = pref_op; 130 mi.i_format.opcode = pref_op;
@@ -166,7 +166,7 @@ static inline void build_load_reg(int reg)
166 166
167static inline void build_dst_pref(int advance) 167static inline void build_dst_pref(int advance)
168{ 168{
169 if (!(store_offset & (cpu_dcache_line_size() - 1))) { 169 if (!(store_offset & (cpu_dcache_line_size() - 1)) && advance) {
170 union mips_instruction mi; 170 union mips_instruction mi;
171 171
172 mi.i_format.opcode = pref_op; 172 mi.i_format.opcode = pref_op;
@@ -340,6 +340,12 @@ void __init build_clear_page(void)
340 340
341 if (cpu_has_prefetch) { 341 if (cpu_has_prefetch) {
342 switch (current_cpu_data.cputype) { 342 switch (current_cpu_data.cputype) {
343 case CPU_TX49XX:
344 /* TX49 supports only Pref_Load */
345 pref_offset_clear = 0;
346 pref_offset_copy = 0;
347 break;
348
343 case CPU_RM9000: 349 case CPU_RM9000:
344 /* 350 /*
345 * As a workaround for erratum G105 which make the 351 * As a workaround for erratum G105 which make the
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index 9e8ff8badb19..3b6cc9ba1b05 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -9,6 +9,7 @@
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/mm.h> 11#include <linux/mm.h>
12#include <linux/bitops.h>
12 13
13#include <asm/addrspace.h> 14#include <asm/addrspace.h>
14#include <asm/bcache.h> 15#include <asm/bcache.h>
@@ -43,14 +44,7 @@ static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size)
43 /* Catch bad driver code */ 44 /* Catch bad driver code */
44 BUG_ON(size == 0); 45 BUG_ON(size == 0);
45 46
46 a = addr & ~(sc_lsize - 1); 47 blast_scache_range(addr, addr + size);
47 end = (addr + size - 1) & ~(sc_lsize - 1);
48 while (1) {
49 flush_scache_line(a); /* Hit_Writeback_Inv_SD */
50 if (a == end)
51 break;
52 a += sc_lsize;
53 }
54 48
55 if (!rm7k_tcache_enabled) 49 if (!rm7k_tcache_enabled)
56 return; 50 return;
@@ -74,14 +68,7 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size)
74 /* Catch bad driver code */ 68 /* Catch bad driver code */
75 BUG_ON(size == 0); 69 BUG_ON(size == 0);
76 70
77 a = addr & ~(sc_lsize - 1); 71 blast_inv_scache_range(addr, addr + size);
78 end = (addr + size - 1) & ~(sc_lsize - 1);
79 while (1) {
80 invalidate_scache_line(a); /* Hit_Invalidate_SD */
81 if (a == end)
82 break;
83 a += sc_lsize;
84 }
85 72
86 if (!rm7k_tcache_enabled) 73 if (!rm7k_tcache_enabled)
87 return; 74 return;
@@ -143,11 +130,17 @@ struct bcache_ops rm7k_sc_ops = {
143 130
144void __init rm7k_sc_init(void) 131void __init rm7k_sc_init(void)
145{ 132{
133 struct cpuinfo_mips *c = &current_cpu_data;
146 unsigned int config = read_c0_config(); 134 unsigned int config = read_c0_config();
147 135
148 if ((config & RM7K_CONF_SC)) 136 if ((config & RM7K_CONF_SC))
149 return; 137 return;
150 138
139 c->scache.linesz = sc_lsize;
140 c->scache.ways = 4;
141 c->scache.waybit= ffs(scache_size / c->scache.ways) - 1;
142 c->scache.waysize = scache_size / c->scache.ways;
143 c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
151 printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n", 144 printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
152 (scache_size >> 10), sc_lsize); 145 (scache_size >> 10), sc_lsize);
153 146
diff --git a/arch/mips/mm/tlb-andes.c b/arch/mips/mm/tlb-andes.c
deleted file mode 100644
index 3f422a849c41..000000000000
--- a/arch/mips/mm/tlb-andes.c
+++ /dev/null
@@ -1,259 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1997, 1998, 1999 Ralf Baechle (ralf@gnu.org)
7 * Copyright (C) 1999 Silicon Graphics, Inc.
8 * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com)
9 */
10#include <linux/init.h>
11#include <linux/kernel.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <asm/page.h>
15#include <asm/pgtable.h>
16#include <asm/system.h>
17#include <asm/mmu_context.h>
18
19extern void build_tlb_refill_handler(void);
20
21#define NTLB_ENTRIES 64
22#define NTLB_ENTRIES_HALF 32
23
24void local_flush_tlb_all(void)
25{
26 unsigned long flags;
27 unsigned long old_ctx;
28 unsigned long entry;
29
30 local_irq_save(flags);
31 /* Save old context and create impossible VPN2 value */
32 old_ctx = read_c0_entryhi() & ASID_MASK;
33 write_c0_entryhi(CKSEG0);
34 write_c0_entrylo0(0);
35 write_c0_entrylo1(0);
36
37 entry = read_c0_wired();
38
39 /* Blast 'em all away. */
40 while (entry < NTLB_ENTRIES) {
41 write_c0_index(entry);
42 tlb_write_indexed();
43 entry++;
44 }
45 write_c0_entryhi(old_ctx);
46 local_irq_restore(flags);
47}
48
49void local_flush_tlb_mm(struct mm_struct *mm)
50{
51 int cpu = smp_processor_id();
52 if (cpu_context(cpu, mm) != 0) {
53 drop_mmu_context(mm,cpu);
54 }
55}
56
57void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
58 unsigned long end)
59{
60 struct mm_struct *mm = vma->vm_mm;
61 int cpu = smp_processor_id();
62
63 if (cpu_context(cpu, mm) != 0) {
64 unsigned long flags;
65 int size;
66
67 local_irq_save(flags);
68 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
69 size = (size + 1) >> 1;
70 if (size <= NTLB_ENTRIES_HALF) {
71 int oldpid = (read_c0_entryhi() & ASID_MASK);
72 int newpid = (cpu_context(smp_processor_id(), mm)
73 & ASID_MASK);
74
75 start &= (PAGE_MASK << 1);
76 end += ((PAGE_SIZE << 1) - 1);
77 end &= (PAGE_MASK << 1);
78 while(start < end) {
79 int idx;
80
81 write_c0_entryhi(start | newpid);
82 start += (PAGE_SIZE << 1);
83 tlb_probe();
84 idx = read_c0_index();
85 write_c0_entrylo0(0);
86 write_c0_entrylo1(0);
87 write_c0_entryhi(CKSEG0);
88 if(idx < 0)
89 continue;
90 tlb_write_indexed();
91 }
92 write_c0_entryhi(oldpid);
93 } else {
94 drop_mmu_context(mm, cpu);
95 }
96 local_irq_restore(flags);
97 }
98}
99
100void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
101{
102 unsigned long flags;
103 int size;
104
105 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
106 size = (size + 1) >> 1;
107
108 local_irq_save(flags);
109 if (size <= NTLB_ENTRIES_HALF) {
110 int pid = read_c0_entryhi();
111
112 start &= (PAGE_MASK << 1);
113 end += ((PAGE_SIZE << 1) - 1);
114 end &= (PAGE_MASK << 1);
115
116 while (start < end) {
117 int idx;
118
119 write_c0_entryhi(start);
120 start += (PAGE_SIZE << 1);
121 tlb_probe();
122 idx = read_c0_index();
123 write_c0_entrylo0(0);
124 write_c0_entrylo1(0);
125 write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT+1)));
126 if (idx < 0)
127 continue;
128 tlb_write_indexed();
129 }
130 write_c0_entryhi(pid);
131 } else {
132 local_flush_tlb_all();
133 }
134 local_irq_restore(flags);
135}
136
137void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
138{
139 if (cpu_context(smp_processor_id(), vma->vm_mm) != 0) {
140 unsigned long flags;
141 int oldpid, newpid, idx;
142
143 newpid = (cpu_context(smp_processor_id(), vma->vm_mm) &
144 ASID_MASK);
145 page &= (PAGE_MASK << 1);
146 local_irq_save(flags);
147 oldpid = (read_c0_entryhi() & ASID_MASK);
148 write_c0_entryhi(page | newpid);
149 tlb_probe();
150 idx = read_c0_index();
151 write_c0_entrylo0(0);
152 write_c0_entrylo1(0);
153 write_c0_entryhi(CKSEG0);
154 if (idx < 0)
155 goto finish;
156 tlb_write_indexed();
157
158 finish:
159 write_c0_entryhi(oldpid);
160 local_irq_restore(flags);
161 }
162}
163
164/*
165 * This one is only used for pages with the global bit set so we don't care
166 * much about the ASID.
167 */
168void local_flush_tlb_one(unsigned long page)
169{
170 unsigned long flags;
171 int oldpid, idx;
172
173 local_irq_save(flags);
174 page &= (PAGE_MASK << 1);
175 oldpid = read_c0_entryhi() & 0xff;
176 write_c0_entryhi(page);
177 tlb_probe();
178 idx = read_c0_index();
179 write_c0_entrylo0(0);
180 write_c0_entrylo1(0);
181 if (idx >= 0) {
182 /* Make sure all entries differ. */
183 write_c0_entryhi(CKSEG0+(idx<<(PAGE_SHIFT+1)));
184 tlb_write_indexed();
185 }
186 write_c0_entryhi(oldpid);
187
188 local_irq_restore(flags);
189}
190
191/* XXX Simplify this. On the R10000 writing a TLB entry for an virtual
192 address that already exists will overwrite the old entry and not result
193 in TLB malfunction or TLB shutdown. */
194void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
195{
196 unsigned long flags;
197 pgd_t *pgdp;
198 pud_t *pudp;
199 pmd_t *pmdp;
200 pte_t *ptep;
201 int idx, pid;
202
203 /*
204 * Handle debugger faulting in for debugee.
205 */
206 if (current->active_mm != vma->vm_mm)
207 return;
208
209 pid = read_c0_entryhi() & ASID_MASK;
210
211 if ((pid != (cpu_context(smp_processor_id(), vma->vm_mm) & ASID_MASK))
212 || (cpu_context(smp_processor_id(), vma->vm_mm) == 0)) {
213 printk(KERN_WARNING
214 "%s: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n",
215 __FUNCTION__, (int) (cpu_context(smp_processor_id(),
216 vma->vm_mm) & ASID_MASK), pid);
217 }
218
219 local_irq_save(flags);
220 address &= (PAGE_MASK << 1);
221 write_c0_entryhi(address | (pid));
222 pgdp = pgd_offset(vma->vm_mm, address);
223 tlb_probe();
224 pudp = pud_offset(pgdp, address);
225 pmdp = pmd_offset(pudp, address);
226 idx = read_c0_index();
227 ptep = pte_offset_map(pmdp, address);
228 write_c0_entrylo0(pte_val(*ptep++) >> 6);
229 write_c0_entrylo1(pte_val(*ptep) >> 6);
230 write_c0_entryhi(address | pid);
231 if (idx < 0) {
232 tlb_write_random();
233 } else {
234 tlb_write_indexed();
235 }
236 write_c0_entryhi(pid);
237 local_irq_restore(flags);
238}
239
240void __init tlb_init(void)
241{
242 /*
243 * You should never change this register:
244 * - On R4600 1.7 the tlbp never hits for pages smaller than
245 * the value in the c0_pagemask register.
246 * - The entire mm handling assumes the c0_pagemask register to
247 * be set for 4kb pages.
248 */
249 write_c0_pagemask(PM_4K);
250 write_c0_wired(0);
251 write_c0_framemask(0);
252
253 /* From this point on the ARC firmware is dead. */
254 local_flush_tlb_all();
255
256 /* Did I tell you that ARC SUCKS? */
257
258 build_tlb_refill_handler();
259}
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 8297970f0bb1..a865f2394cb0 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -424,8 +424,13 @@ void __init tlb_init(void)
424 probe_tlb(config); 424 probe_tlb(config);
425 write_c0_pagemask(PM_DEFAULT_MASK); 425 write_c0_pagemask(PM_DEFAULT_MASK);
426 write_c0_wired(0); 426 write_c0_wired(0);
427 write_c0_framemask(0);
427 temp_tlb_entry = current_cpu_data.tlbsize - 1; 428 temp_tlb_entry = current_cpu_data.tlbsize - 1;
429
430 /* From this point on the ARC firmware is dead. */
428 local_flush_tlb_all(); 431 local_flush_tlb_all();
429 432
433 /* Did I tell you that ARC SUCKS? */
434
430 build_tlb_refill_handler(); 435 build_tlb_refill_handler();
431} 436}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index ac4f4bfaae50..599b3c297186 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -951,7 +951,6 @@ 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. */ 951 /* No i_nop needed here, since the next insn doesn't touch TMP. */
952 952
953#ifdef CONFIG_SMP 953#ifdef CONFIG_SMP
954# ifdef CONFIG_BUILD_ELF64
955 /* 954 /*
956 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3 955 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
957 * stored in CONTEXT. 956 * stored in CONTEXT.
@@ -962,18 +961,6 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
962 i_daddu(p, ptr, ptr, tmp); 961 i_daddu(p, ptr, ptr, tmp);
963 i_dmfc0(p, tmp, C0_BADVADDR); 962 i_dmfc0(p, tmp, C0_BADVADDR);
964 i_ld(p, ptr, rel_lo(pgdc), ptr); 963 i_ld(p, ptr, rel_lo(pgdc), ptr);
965# else
966 /*
967 * 64 bit SMP running in compat space has the lower part of
968 * &pgd_current[smp_processor_id()] stored in CONTEXT.
969 */
970 if (!in_compat_space_p(pgdc))
971 panic("Invalid page directory address!");
972
973 i_dmfc0(p, ptr, C0_CONTEXT);
974 i_dsra(p, ptr, ptr, 23);
975 i_ld(p, ptr, 0, ptr);
976# endif
977#else 964#else
978 i_LA_mostly(p, ptr, pgdc); 965 i_LA_mostly(p, ptr, pgdc);
979 i_ld(p, ptr, rel_lo(pgdc), ptr); 966 i_ld(p, ptr, rel_lo(pgdc), ptr);