Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sh: Revert lazy dcache writeback changes.

These ended up causing too many problems on older parts,
revert for now..

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

+194 -85
-4
arch/sh/boards/renesas/r7780rp/io.c
··· 156 156 157 157 while (count--) 158 158 *buf++ = *p; 159 - 160 - flush_dcache_all(); 161 159 } 162 160 163 161 void r7780rp_insl(unsigned long port, void *dst, unsigned long count) ··· 202 204 203 205 while (count--) 204 206 *p = *buf++; 205 - 206 - flush_dcache_all(); 207 207 } 208 208 209 209 void r7780rp_outsl(unsigned long port, const void *src, unsigned long count)
-3
arch/sh/kernel/io_generic.c
··· 14 14 #include <linux/module.h> 15 15 #include <linux/io.h> 16 16 #include <asm/machvec.h> 17 - #include <asm/cacheflush.h> 18 17 19 18 #ifdef CONFIG_CPU_SH3 20 19 /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a ··· 95 96 while (count--) 96 97 *buf++ = *port_addr; 97 98 98 - flush_dcache_all(); 99 99 dummy_read(); 100 100 } 101 101 ··· 169 171 while (count--) 170 172 *port_addr = *buf++; 171 173 172 - flush_dcache_all(); 173 174 dummy_read(); 174 175 } 175 176
+1 -11
arch/sh/mm/cache-sh4.c
··· 237 237 /* 238 238 * Write back & invalidate the D-cache of the page. 239 239 * (To avoid "alias" issues) 240 - * 241 - * This uses a lazy write-back on UP, which is explicitly 242 - * disabled on SMP. 243 240 */ 244 241 void flush_dcache_page(struct page *page) 245 242 { 246 - #ifndef CONFIG_SMP 247 - struct address_space *mapping = page_mapping(page); 248 - 249 - if (mapping && !mapping_mapped(mapping)) 250 - set_bit(PG_dcache_dirty, &page->flags); 251 - else 252 - #endif 253 - { 243 + if (test_bit(PG_mapped, &page->flags)) { 254 244 unsigned long phys = PHYSADDR(page_address(page)); 255 245 unsigned long addr = CACHE_OC_ADDRESS_ARRAY; 256 246 int i, n;
+3 -6
arch/sh/mm/cache-sh7705.c
··· 3 3 * 4 4 * Copyright (C) 1999, 2000 Niibe Yutaka 5 5 * Copyright (C) 2004 Alex Song 6 - * Copyright (C) 2006 Paul Mundt 7 6 * 8 7 * This file is subject to the terms and conditions of the GNU General Public 9 8 * License. See the file "COPYING" in the main directory of this archive 10 9 * for more details. 10 + * 11 11 */ 12 12 #include <linux/init.h> 13 13 #include <linux/mman.h> ··· 51 51 52 52 if ((data & v) == v) 53 53 ctrl_outl(data & ~v, addr); 54 + 54 55 } 55 56 56 57 addrstart += current_cpu_data.dcache.way_incr; ··· 128 127 */ 129 128 void flush_dcache_page(struct page *page) 130 129 { 131 - struct address_space *mapping = page_mapping(page); 132 - 133 - if (mapping && !mapping_mapped(mapping)) 134 - set_bit(PG_dcache_dirty, &page->flags); 135 - else 130 + if (test_bit(PG_mapped, &page->flags)) 136 131 __flush_dcache_page(PHYSADDR(page_address(page))); 137 132 } 138 133
+22
arch/sh/mm/pg-sh4.c
··· 23 23 */ 24 24 void clear_user_page(void *to, unsigned long address, struct page *page) 25 25 { 26 + __set_bit(PG_mapped, &page->flags); 26 27 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) 27 28 clear_page(to); 28 29 else { ··· 59 58 void copy_user_page(void *to, void *from, unsigned long address, 60 59 struct page *page) 61 60 { 61 + __set_bit(PG_mapped, &page->flags); 62 62 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) 63 63 copy_page(to, from); 64 64 else { ··· 83 81 pte_clear(&init_mm, p3_addr, pte); 84 82 mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); 85 83 } 84 + } 85 + 86 + /* 87 + * For SH-4, we have our own implementation for ptep_get_and_clear 88 + */ 89 + inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 90 + { 91 + pte_t pte = *ptep; 92 + 93 + pte_clear(mm, addr, ptep); 94 + if (!pte_not_present(pte)) { 95 + unsigned long pfn = pte_pfn(pte); 96 + if (pfn_valid(pfn)) { 97 + struct page *page = pfn_to_page(pfn); 98 + struct address_space *mapping = page_mapping(page); 99 + if (!mapping || !mapping_writably_mapped(mapping)) 100 + __clear_bit(PG_mapped, &page->flags); 101 + } 102 + } 103 + return pte; 86 104 }
+29 -2
arch/sh/mm/pg-sh7705.c
··· 7 7 * This file is subject to the terms and conditions of the GNU General Public 8 8 * License. See the file "COPYING" in the main directory of this archive 9 9 * for more details. 10 + * 10 11 */ 12 + 11 13 #include <linux/init.h> 12 14 #include <linux/mman.h> 13 15 #include <linux/mm.h> ··· 76 74 { 77 75 struct page *page = virt_to_page(to); 78 76 77 + __set_bit(PG_mapped, &page->flags); 79 78 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { 80 79 clear_page(to); 81 80 __flush_wback_region(to, PAGE_SIZE); ··· 95 92 * @from: P1 address 96 93 * @address: U0 address to be mapped 97 94 */ 98 - void copy_user_page(void *to, void *from, unsigned long address, 99 - struct page *pg) 95 + void copy_user_page(void *to, void *from, unsigned long address, struct page *pg) 100 96 { 101 97 struct page *page = virt_to_page(to); 102 98 99 + 100 + __set_bit(PG_mapped, &page->flags); 103 101 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { 104 102 copy_page(to, from); 105 103 __flush_wback_region(to, PAGE_SIZE); ··· 112 108 __flush_wback_region(to, PAGE_SIZE); 113 109 } 114 110 } 111 + 112 + /* 113 + * For SH7705, we have our own implementation for ptep_get_and_clear 114 + * Copied from pg-sh4.c 115 + */ 116 + inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 117 + { 118 + pte_t pte = *ptep; 119 + 120 + pte_clear(mm, addr, ptep); 121 + if (!pte_not_present(pte)) { 122 + unsigned long pfn = pte_pfn(pte); 123 + if (pfn_valid(pfn)) { 124 + struct page *page = pfn_to_page(pfn); 125 + struct address_space *mapping = page_mapping(page); 126 + if (!mapping || !mapping_writably_mapped(mapping)) 127 + __clear_bit(PG_mapped, &page->flags); 128 + } 129 + } 130 + 131 + return pte; 132 + } 133 +
+1 -54
arch/sh/mm/tlb-flush.c
··· 2 2 * TLB flushing operations for SH with an MMU. 3 3 * 4 4 * Copyright (C) 1999 Niibe Yutaka 5 - * Copyright (C) 2003 - 2006 Paul Mundt 5 + * Copyright (C) 2003 Paul Mundt 6 6 * 7 7 * This file is subject to the terms and conditions of the GNU General Public 8 8 * License. See the file "COPYING" in the main directory of this archive 9 9 * for more details. 10 10 */ 11 11 #include <linux/mm.h> 12 - #include <linux/io.h> 13 12 #include <asm/mmu_context.h> 14 13 #include <asm/tlbflush.h> 15 - #include <asm/cacheflush.h> 16 14 17 15 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) 18 16 { ··· 136 138 status |= 0x04; 137 139 ctrl_outl(status, MMUCR); 138 140 ctrl_barrier(); 139 - local_irq_restore(flags); 140 - } 141 - 142 - void update_mmu_cache(struct vm_area_struct *vma, 143 - unsigned long address, pte_t pte) 144 - { 145 - unsigned long flags; 146 - unsigned long pteval; 147 - unsigned long vpn; 148 - struct page *page; 149 - unsigned long pfn = pte_pfn(pte); 150 - struct address_space *mapping; 151 - 152 - if (!pfn_valid(pfn)) 153 - return; 154 - 155 - page = pfn_to_page(pfn); 156 - mapping = page_mapping(page); 157 - if (mapping) { 158 - unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; 159 - int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); 160 - 161 - if (dirty) 162 - __flush_wback_region((void *)P1SEGADDR(phys), 163 - PAGE_SIZE); 164 - } 165 - 166 - local_irq_save(flags); 167 - 168 - /* Set PTEH register */ 169 - vpn = (address & MMU_VPN_MASK) | get_asid(); 170 - ctrl_outl(vpn, MMU_PTEH); 171 - 172 - pteval = pte_val(pte); 173 - 174 - #ifdef CONFIG_CPU_HAS_PTEA 175 - /* Set PTEA register */ 176 - /* TODO: make this look less hacky */ 177 - ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA); 178 - #endif 179 - 180 - /* Set PTEL register */ 181 - pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ 182 - #if defined(CONFIG_SH_WRITETHROUGH) && defined(CONFIG_CPU_SH4) 183 - pteval |= _PAGE_WT; 184 - #endif 185 - /* conveniently, we want all the software flags to be 0 anyway */ 186 - ctrl_outl(pteval, MMU_PTEL); 187 - 188 - /* Load the TLB */ 189 - asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); 190 141 local_irq_restore(flags); 191 142 }
+62 -1
arch/sh/mm/tlb-sh3.c
··· 8 8 * 9 9 * Released under the terms of the GNU GPL v2.0. 10 10 */ 11 - #include <linux/io.h> 11 + #include <linux/signal.h> 12 + #include <linux/sched.h> 13 + #include <linux/kernel.h> 14 + #include <linux/errno.h> 15 + #include <linux/string.h> 16 + #include <linux/types.h> 17 + #include <linux/ptrace.h> 18 + #include <linux/mman.h> 19 + #include <linux/mm.h> 20 + #include <linux/smp.h> 21 + #include <linux/smp_lock.h> 22 + #include <linux/interrupt.h> 23 + 12 24 #include <asm/system.h> 25 + #include <asm/io.h> 26 + #include <asm/uaccess.h> 27 + #include <asm/pgalloc.h> 13 28 #include <asm/mmu_context.h> 29 + #include <asm/cacheflush.h> 30 + 31 + void update_mmu_cache(struct vm_area_struct * vma, 32 + unsigned long address, pte_t pte) 33 + { 34 + unsigned long flags; 35 + unsigned long pteval; 36 + unsigned long vpn; 37 + 38 + /* Ptrace may call this routine. */ 39 + if (vma && current->active_mm != vma->vm_mm) 40 + return; 41 + 42 + #if defined(CONFIG_SH7705_CACHE_32KB) 43 + { 44 + struct page *page = pte_page(pte); 45 + unsigned long pfn = pte_pfn(pte); 46 + 47 + if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) { 48 + unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; 49 + 50 + __flush_wback_region((void *)P1SEGADDR(phys), 51 + PAGE_SIZE); 52 + __set_bit(PG_mapped, &page->flags); 53 + } 54 + } 55 + #endif 56 + 57 + local_irq_save(flags); 58 + 59 + /* Set PTEH register */ 60 + vpn = (address & MMU_VPN_MASK) | get_asid(); 61 + ctrl_outl(vpn, MMU_PTEH); 62 + 63 + pteval = pte_val(pte); 64 + 65 + /* Set PTEL register */ 66 + pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ 67 + /* conveniently, we want all the software flags to be 0 anyway */ 68 + ctrl_outl(pteval, MMU_PTEL); 69 + 70 + /* Load the TLB */ 71 + asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); 72 + local_irq_restore(flags); 73 + } 14 74 15 75 void local_flush_tlb_one(unsigned long asid, unsigned long page) 16 76 { ··· 94 34 for (i = 0; i < ways; i++) 95 35 ctrl_outl(data, addr + (i << 8)); 96 36 } 37 +
+67 -1
arch/sh/mm/tlb-sh4.c
··· 8 8 * 9 9 * Released under the terms of the GNU GPL v2.0. 10 10 */ 11 - #include <linux/io.h> 11 + #include <linux/signal.h> 12 + #include <linux/sched.h> 13 + #include <linux/kernel.h> 14 + #include <linux/errno.h> 15 + #include <linux/string.h> 16 + #include <linux/types.h> 17 + #include <linux/ptrace.h> 18 + #include <linux/mman.h> 19 + #include <linux/mm.h> 20 + #include <linux/smp.h> 21 + #include <linux/smp_lock.h> 22 + #include <linux/interrupt.h> 23 + 12 24 #include <asm/system.h> 25 + #include <asm/io.h> 26 + #include <asm/uaccess.h> 27 + #include <asm/pgalloc.h> 13 28 #include <asm/mmu_context.h> 29 + #include <asm/cacheflush.h> 30 + 31 + void update_mmu_cache(struct vm_area_struct * vma, 32 + unsigned long address, pte_t pte) 33 + { 34 + unsigned long flags; 35 + unsigned long pteval; 36 + unsigned long vpn; 37 + struct page *page; 38 + unsigned long pfn; 39 + 40 + /* Ptrace may call this routine. */ 41 + if (vma && current->active_mm != vma->vm_mm) 42 + return; 43 + 44 + pfn = pte_pfn(pte); 45 + if (pfn_valid(pfn)) { 46 + page = pfn_to_page(pfn); 47 + if (!test_bit(PG_mapped, &page->flags)) { 48 + unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; 49 + __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE); 50 + __set_bit(PG_mapped, &page->flags); 51 + } 52 + } 53 + 54 + local_irq_save(flags); 55 + 56 + /* Set PTEH register */ 57 + vpn = (address & MMU_VPN_MASK) | get_asid(); 58 + ctrl_outl(vpn, MMU_PTEH); 59 + 60 + pteval = pte_val(pte); 61 + 62 + /* Set PTEA register */ 63 + if (cpu_data->flags & CPU_HAS_PTEA) 64 + /* TODO: make this look less hacky */ 65 + ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA); 66 + 67 + /* Set PTEL register */ 68 + pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ 69 + #ifdef CONFIG_SH_WRITETHROUGH 70 + pteval |= _PAGE_WT; 71 + #endif 72 + /* conveniently, we want all the software flags to be 0 anyway */ 73 + ctrl_outl(pteval, MMU_PTEL); 74 + 75 + /* Load the TLB */ 76 + asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); 77 + local_irq_restore(flags); 78 + } 14 79 15 80 void local_flush_tlb_one(unsigned long asid, unsigned long page) 16 81 { ··· 93 28 ctrl_outl(data, addr); 94 29 back_to_P1(); 95 30 } 31 +
-3
include/asm-sh/cacheflush.h
··· 30 30 31 31 #define HAVE_ARCH_UNMAPPED_AREA 32 32 33 - /* Page flag for lazy dcache write-back for the aliasing UP caches */ 34 - #define PG_dcache_dirty PG_arch_1 35 - 36 33 #endif /* __KERNEL__ */ 37 34 #endif /* __ASM_SH_CACHEFLUSH_H */
+2
include/asm-sh/cpu-sh3/cacheflush.h
··· 36 36 /* 32KB cache, 4kb PAGE sizes need to check bit 12 */ 37 37 #define CACHE_ALIAS 0x00001000 38 38 39 + #define PG_mapped PG_arch_1 40 + 39 41 void flush_cache_all(void); 40 42 void flush_cache_mm(struct mm_struct *mm); 41 43 #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+2
include/asm-sh/cpu-sh4/cacheflush.h
··· 39 39 /* Initialization of P3 area for copy_user_page */ 40 40 void p3_cache_init(void); 41 41 42 + #define PG_mapped PG_arch_1 43 + 42 44 #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
+5
include/asm-sh/pgtable.h
··· 583 583 extern unsigned int kobjsize(const void *objp); 584 584 #endif /* !CONFIG_MMU */ 585 585 586 + #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) 587 + #define __HAVE_ARCH_PTEP_GET_AND_CLEAR 588 + extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); 589 + #endif 590 + 586 591 extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; 587 592 extern void paging_init(void); 588 593