diff options
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/init.c | 11 | ||||
| -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 |
9 files changed, 39 insertions, 305 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/init.c b/arch/mips/mm/init.c index 0ff9a348b843..52f7d59fe612 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c | |||
| @@ -54,7 +54,8 @@ unsigned long empty_zero_page, zero_page_mask; | |||
| 54 | */ | 54 | */ |
| 55 | unsigned long setup_zero_pages(void) | 55 | unsigned long setup_zero_pages(void) |
| 56 | { | 56 | { |
| 57 | unsigned long order, size; | 57 | unsigned int order; |
| 58 | unsigned long size; | ||
| 58 | struct page *page; | 59 | struct page *page; |
| 59 | 60 | ||
| 60 | if (cpu_has_vce) | 61 | if (cpu_has_vce) |
| @@ -67,9 +68,9 @@ unsigned long setup_zero_pages(void) | |||
| 67 | panic("Oh boy, that early out of memory?"); | 68 | panic("Oh boy, that early out of memory?"); |
| 68 | 69 | ||
| 69 | page = virt_to_page(empty_zero_page); | 70 | page = virt_to_page(empty_zero_page); |
| 71 | split_page(page, order); | ||
| 70 | while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { | 72 | while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { |
| 71 | SetPageReserved(page); | 73 | SetPageReserved(page); |
| 72 | set_page_count(page, 1); | ||
| 73 | page++; | 74 | page++; |
| 74 | } | 75 | } |
| 75 | 76 | ||
| @@ -244,7 +245,7 @@ void __init mem_init(void) | |||
| 244 | #ifdef CONFIG_LIMITED_DMA | 245 | #ifdef CONFIG_LIMITED_DMA |
| 245 | set_page_address(page, lowmem_page_address(page)); | 246 | set_page_address(page, lowmem_page_address(page)); |
| 246 | #endif | 247 | #endif |
| 247 | set_page_count(page, 1); | 248 | init_page_count(page); |
| 248 | __free_page(page); | 249 | __free_page(page); |
| 249 | totalhigh_pages++; | 250 | totalhigh_pages++; |
| 250 | } | 251 | } |
| @@ -291,7 +292,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) | |||
| 291 | 292 | ||
| 292 | for (; start < end; start += PAGE_SIZE) { | 293 | for (; start < end; start += PAGE_SIZE) { |
| 293 | ClearPageReserved(virt_to_page(start)); | 294 | ClearPageReserved(virt_to_page(start)); |
| 294 | set_page_count(virt_to_page(start), 1); | 295 | init_page_count(virt_to_page(start)); |
| 295 | free_page(start); | 296 | free_page(start); |
| 296 | totalram_pages++; | 297 | totalram_pages++; |
| 297 | } | 298 | } |
| @@ -314,7 +315,7 @@ void free_initmem(void) | |||
| 314 | page = addr; | 315 | page = addr; |
| 315 | #endif | 316 | #endif |
| 316 | ClearPageReserved(virt_to_page(page)); | 317 | ClearPageReserved(virt_to_page(page)); |
| 317 | set_page_count(virt_to_page(page), 1); | 318 | init_page_count(virt_to_page(page)); |
| 318 | free_page(page); | 319 | free_page(page); |
| 319 | totalram_pages++; | 320 | totalram_pages++; |
| 320 | freed += PAGE_SIZE; | 321 | 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); |
