diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-31 15:34:58 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-31 15:34:58 -0500 |
commit | 86579dd06deecfa6ac88d5e84e4d63c397cd6f6d (patch) | |
tree | b4475d3ccde53015ad84a06e4e55e64591171b75 /arch/mips/mm | |
parent | 7ea9ea832212c4a755650f7c7cc1ff0b63292a41 (diff) | |
parent | a0f067802576d4eb4c65d40b8ee7d6ea3c81dd61 (diff) |
Merge branch 'master'
Diffstat (limited to 'arch/mips/mm')
-rw-r--r-- | arch/mips/mm/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/mm/c-r3k.c | 18 | ||||
-rw-r--r-- | arch/mips/mm/c-r4k.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/dma-ip32.c | 6 | ||||
-rw-r--r-- | arch/mips/mm/init.c | 15 | ||||
-rw-r--r-- | arch/mips/mm/pg-r4k.c | 10 | ||||
-rw-r--r-- | arch/mips/mm/sc-rm7k.c | 25 | ||||
-rw-r--r-- | arch/mips/mm/tlb-andes.c | 259 | ||||
-rw-r--r-- | arch/mips/mm/tlb-r4k.c | 5 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 13 |
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 | |||
12 | obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o | 12 | obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o |
13 | obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o | 13 | obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o |
14 | obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o | 14 | obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o |
15 | obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o pg-r4k.o tlb-andes.o | 15 | obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o |
16 | obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o pg-r4k.o | 16 | obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o pg-r4k.o |
17 | obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o | 17 | obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o |
18 | obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o | 18 | obj-$(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 | */ |
55 | unsigned long setup_zero_pages(void) | 56 | unsigned 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 | |||
182 | static inline int page_is_ram(unsigned long pagenr) | 181 | static 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 | ||
125 | static inline void build_src_pref(int advance) | 125 | static 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 | ||
167 | static inline void build_dst_pref(int advance) | 167 | static 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 | ||
144 | void __init rm7k_sc_init(void) | 131 | void __init rm7k_sc_init(void) |
145 | { | 132 | { |
133 | struct cpuinfo_mips *c = ¤t_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 | |||
19 | extern void build_tlb_refill_handler(void); | ||
20 | |||
21 | #define NTLB_ENTRIES 64 | ||
22 | #define NTLB_ENTRIES_HALF 32 | ||
23 | |||
24 | void 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 | |||
49 | void 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 | |||
57 | void 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 | |||
100 | void 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 | |||
137 | void 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 | */ | ||
168 | void 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. */ | ||
194 | void __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 | |||
240 | void __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); |