diff options
| author | Paul Mundt <lethal@linux-sh.org> | 2007-03-05 05:46:47 -0500 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2007-03-05 05:46:47 -0500 |
| commit | 39e688a94b94eaba768b1494e19e96f828fc2688 (patch) | |
| tree | 706ce255a95d0705241beafb8354fb7253a24af4 | |
| parent | c87a7111349891043cb0a62b0ba745264d4b600a (diff) | |
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>
| -rw-r--r-- | arch/sh/boards/renesas/r7780rp/io.c | 4 | ||||
| -rw-r--r-- | arch/sh/kernel/io_generic.c | 3 | ||||
| -rw-r--r-- | arch/sh/mm/cache-sh4.c | 12 | ||||
| -rw-r--r-- | arch/sh/mm/cache-sh7705.c | 9 | ||||
| -rw-r--r-- | arch/sh/mm/pg-sh4.c | 22 | ||||
| -rw-r--r-- | arch/sh/mm/pg-sh7705.c | 31 | ||||
| -rw-r--r-- | arch/sh/mm/tlb-flush.c | 55 | ||||
| -rw-r--r-- | arch/sh/mm/tlb-sh3.c | 63 | ||||
| -rw-r--r-- | arch/sh/mm/tlb-sh4.c | 68 | ||||
| -rw-r--r-- | include/asm-sh/cacheflush.h | 3 | ||||
| -rw-r--r-- | include/asm-sh/cpu-sh3/cacheflush.h | 2 | ||||
| -rw-r--r-- | include/asm-sh/cpu-sh4/cacheflush.h | 2 | ||||
| -rw-r--r-- | include/asm-sh/pgtable.h | 5 |
13 files changed, 194 insertions, 85 deletions
diff --git a/arch/sh/boards/renesas/r7780rp/io.c b/arch/sh/boards/renesas/r7780rp/io.c index f74d2ffb3851..86dfe85ec440 100644 --- a/arch/sh/boards/renesas/r7780rp/io.c +++ b/arch/sh/boards/renesas/r7780rp/io.c | |||
| @@ -156,8 +156,6 @@ void r7780rp_insw(unsigned long port, void *dst, unsigned long count) | |||
| 156 | 156 | ||
| 157 | while (count--) | 157 | while (count--) |
| 158 | *buf++ = *p; | 158 | *buf++ = *p; |
| 159 | |||
| 160 | flush_dcache_all(); | ||
| 161 | } | 159 | } |
| 162 | 160 | ||
| 163 | void r7780rp_insl(unsigned long port, void *dst, unsigned long count) | 161 | void r7780rp_insl(unsigned long port, void *dst, unsigned long count) |
| @@ -204,8 +202,6 @@ void r7780rp_outsw(unsigned long port, const void *src, unsigned long count) | |||
| 204 | 202 | ||
| 205 | while (count--) | 203 | while (count--) |
| 206 | *p = *buf++; | 204 | *p = *buf++; |
| 207 | |||
| 208 | flush_dcache_all(); | ||
| 209 | } | 205 | } |
| 210 | 206 | ||
| 211 | void r7780rp_outsl(unsigned long port, const void *src, unsigned long count) | 207 | void r7780rp_outsl(unsigned long port, const void *src, unsigned long count) |
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index 66626c03e1ee..771ea4230441 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| 16 | #include <asm/machvec.h> | 16 | #include <asm/machvec.h> |
| 17 | #include <asm/cacheflush.h> | ||
| 18 | 17 | ||
| 19 | #ifdef CONFIG_CPU_SH3 | 18 | #ifdef CONFIG_CPU_SH3 |
| 20 | /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a | 19 | /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a |
| @@ -96,7 +95,6 @@ void generic_insw(unsigned long port, void *dst, unsigned long count) | |||
| 96 | while (count--) | 95 | while (count--) |
| 97 | *buf++ = *port_addr; | 96 | *buf++ = *port_addr; |
| 98 | 97 | ||
| 99 | flush_dcache_all(); | ||
| 100 | dummy_read(); | 98 | dummy_read(); |
| 101 | } | 99 | } |
| 102 | 100 | ||
| @@ -171,7 +169,6 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count) | |||
| 171 | while (count--) | 169 | while (count--) |
| 172 | *port_addr = *buf++; | 170 | *port_addr = *buf++; |
| 173 | 171 | ||
| 174 | flush_dcache_all(); | ||
| 175 | dummy_read(); | 172 | dummy_read(); |
| 176 | } | 173 | } |
| 177 | 174 | ||
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index e0cd4b7f4aeb..981b04089055 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c | |||
| @@ -237,20 +237,10 @@ static inline void flush_cache_4096(unsigned long start, | |||
| 237 | /* | 237 | /* |
| 238 | * Write back & invalidate the D-cache of the page. | 238 | * Write back & invalidate the D-cache of the page. |
| 239 | * (To avoid "alias" issues) | 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 | void flush_dcache_page(struct page *page) | 241 | void flush_dcache_page(struct page *page) |
| 245 | { | 242 | { |
| 246 | #ifndef CONFIG_SMP | 243 | if (test_bit(PG_mapped, &page->flags)) { |
| 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 | { | ||
| 254 | unsigned long phys = PHYSADDR(page_address(page)); | 244 | unsigned long phys = PHYSADDR(page_address(page)); |
| 255 | unsigned long addr = CACHE_OC_ADDRESS_ARRAY; | 245 | unsigned long addr = CACHE_OC_ADDRESS_ARRAY; |
| 256 | int i, n; | 246 | int i, n; |
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c index 31f8deb7a158..4896d7376926 100644 --- a/arch/sh/mm/cache-sh7705.c +++ b/arch/sh/mm/cache-sh7705.c | |||
| @@ -3,11 +3,11 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1999, 2000 Niibe Yutaka | 4 | * Copyright (C) 1999, 2000 Niibe Yutaka |
| 5 | * Copyright (C) 2004 Alex Song | 5 | * Copyright (C) 2004 Alex Song |
| 6 | * Copyright (C) 2006 Paul Mundt | ||
| 7 | * | 6 | * |
| 8 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
| 9 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
| 10 | * for more details. | 9 | * for more details. |
| 10 | * | ||
| 11 | */ | 11 | */ |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/mman.h> | 13 | #include <linux/mman.h> |
| @@ -51,6 +51,7 @@ static inline void cache_wback_all(void) | |||
| 51 | 51 | ||
| 52 | if ((data & v) == v) | 52 | if ((data & v) == v) |
| 53 | ctrl_outl(data & ~v, addr); | 53 | ctrl_outl(data & ~v, addr); |
| 54 | |||
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | addrstart += current_cpu_data.dcache.way_incr; | 57 | addrstart += current_cpu_data.dcache.way_incr; |
| @@ -127,11 +128,7 @@ static void __flush_dcache_page(unsigned long phys) | |||
| 127 | */ | 128 | */ |
| 128 | void flush_dcache_page(struct page *page) | 129 | void flush_dcache_page(struct page *page) |
| 129 | { | 130 | { |
| 130 | struct address_space *mapping = page_mapping(page); | 131 | if (test_bit(PG_mapped, &page->flags)) |
| 131 | |||
| 132 | if (mapping && !mapping_mapped(mapping)) | ||
| 133 | set_bit(PG_dcache_dirty, &page->flags); | ||
| 134 | else | ||
| 135 | __flush_dcache_page(PHYSADDR(page_address(page))); | 132 | __flush_dcache_page(PHYSADDR(page_address(page))); |
| 136 | } | 133 | } |
| 137 | 134 | ||
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index 969efeceb928..df69da9ca69c 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c | |||
| @@ -23,6 +23,7 @@ extern struct mutex p3map_mutex[]; | |||
| 23 | */ | 23 | */ |
| 24 | void clear_user_page(void *to, unsigned long address, struct page *page) | 24 | void clear_user_page(void *to, unsigned long address, struct page *page) |
| 25 | { | 25 | { |
| 26 | __set_bit(PG_mapped, &page->flags); | ||
| 26 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) | 27 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) |
| 27 | clear_page(to); | 28 | clear_page(to); |
| 28 | else { | 29 | else { |
| @@ -58,6 +59,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page) | |||
| 58 | void copy_user_page(void *to, void *from, unsigned long address, | 59 | void copy_user_page(void *to, void *from, unsigned long address, |
| 59 | struct page *page) | 60 | struct page *page) |
| 60 | { | 61 | { |
| 62 | __set_bit(PG_mapped, &page->flags); | ||
| 61 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) | 63 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) |
| 62 | copy_page(to, from); | 64 | copy_page(to, from); |
| 63 | else { | 65 | else { |
| @@ -82,3 +84,23 @@ void copy_user_page(void *to, void *from, unsigned long address, | |||
| 82 | mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); | 84 | mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); |
| 83 | } | 85 | } |
| 84 | } | 86 | } |
| 87 | |||
| 88 | /* | ||
| 89 | * For SH-4, we have our own implementation for ptep_get_and_clear | ||
| 90 | */ | ||
| 91 | inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | ||
| 92 | { | ||
| 93 | pte_t pte = *ptep; | ||
| 94 | |||
| 95 | pte_clear(mm, addr, ptep); | ||
| 96 | if (!pte_not_present(pte)) { | ||
| 97 | unsigned long pfn = pte_pfn(pte); | ||
| 98 | if (pfn_valid(pfn)) { | ||
| 99 | struct page *page = pfn_to_page(pfn); | ||
| 100 | struct address_space *mapping = page_mapping(page); | ||
| 101 | if (!mapping || !mapping_writably_mapped(mapping)) | ||
| 102 | __clear_bit(PG_mapped, &page->flags); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | return pte; | ||
| 106 | } | ||
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c index 887ab9d18ccd..a4b015f95a3a 100644 --- a/arch/sh/mm/pg-sh7705.c +++ b/arch/sh/mm/pg-sh7705.c | |||
| @@ -7,7 +7,9 @@ | |||
| 7 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
| 8 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
| 9 | * for more details. | 9 | * for more details. |
| 10 | * | ||
| 10 | */ | 11 | */ |
| 12 | |||
| 11 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 12 | #include <linux/mman.h> | 14 | #include <linux/mman.h> |
| 13 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
| @@ -74,6 +76,7 @@ void clear_user_page(void *to, unsigned long address, struct page *pg) | |||
| 74 | { | 76 | { |
| 75 | struct page *page = virt_to_page(to); | 77 | struct page *page = virt_to_page(to); |
| 76 | 78 | ||
| 79 | __set_bit(PG_mapped, &page->flags); | ||
| 77 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { | 80 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { |
| 78 | clear_page(to); | 81 | clear_page(to); |
| 79 | __flush_wback_region(to, PAGE_SIZE); | 82 | __flush_wback_region(to, PAGE_SIZE); |
| @@ -92,11 +95,12 @@ void clear_user_page(void *to, unsigned long address, struct page *pg) | |||
| 92 | * @from: P1 address | 95 | * @from: P1 address |
| 93 | * @address: U0 address to be mapped | 96 | * @address: U0 address to be mapped |
| 94 | */ | 97 | */ |
| 95 | void copy_user_page(void *to, void *from, unsigned long address, | 98 | void copy_user_page(void *to, void *from, unsigned long address, struct page *pg) |
| 96 | struct page *pg) | ||
| 97 | { | 99 | { |
| 98 | struct page *page = virt_to_page(to); | 100 | struct page *page = virt_to_page(to); |
| 99 | 101 | ||
| 102 | |||
| 103 | __set_bit(PG_mapped, &page->flags); | ||
| 100 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { | 104 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { |
| 101 | copy_page(to, from); | 105 | copy_page(to, from); |
| 102 | __flush_wback_region(to, PAGE_SIZE); | 106 | __flush_wback_region(to, PAGE_SIZE); |
| @@ -108,3 +112,26 @@ void copy_user_page(void *to, void *from, unsigned long address, | |||
| 108 | __flush_wback_region(to, PAGE_SIZE); | 112 | __flush_wback_region(to, PAGE_SIZE); |
| 109 | } | 113 | } |
| 110 | } | 114 | } |
| 115 | |||
| 116 | /* | ||
| 117 | * For SH7705, we have our own implementation for ptep_get_and_clear | ||
| 118 | * Copied from pg-sh4.c | ||
| 119 | */ | ||
| 120 | inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | ||
| 121 | { | ||
| 122 | pte_t pte = *ptep; | ||
| 123 | |||
| 124 | pte_clear(mm, addr, ptep); | ||
| 125 | if (!pte_not_present(pte)) { | ||
| 126 | unsigned long pfn = pte_pfn(pte); | ||
| 127 | if (pfn_valid(pfn)) { | ||
| 128 | struct page *page = pfn_to_page(pfn); | ||
| 129 | struct address_space *mapping = page_mapping(page); | ||
| 130 | if (!mapping || !mapping_writably_mapped(mapping)) | ||
| 131 | __clear_bit(PG_mapped, &page->flags); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | return pte; | ||
| 136 | } | ||
| 137 | |||
diff --git a/arch/sh/mm/tlb-flush.c b/arch/sh/mm/tlb-flush.c index d2f7b4a2eb05..6f45c1f8a7fe 100644 --- a/arch/sh/mm/tlb-flush.c +++ b/arch/sh/mm/tlb-flush.c | |||
| @@ -2,17 +2,15 @@ | |||
| 2 | * TLB flushing operations for SH with an MMU. | 2 | * TLB flushing operations for SH with an MMU. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1999 Niibe Yutaka | 4 | * Copyright (C) 1999 Niibe Yutaka |
| 5 | * Copyright (C) 2003 - 2006 Paul Mundt | 5 | * Copyright (C) 2003 Paul Mundt |
| 6 | * | 6 | * |
| 7 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
| 8 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
| 9 | * for more details. | 9 | * for more details. |
| 10 | */ | 10 | */ |
| 11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
| 12 | #include <linux/io.h> | ||
| 13 | #include <asm/mmu_context.h> | 12 | #include <asm/mmu_context.h> |
| 14 | #include <asm/tlbflush.h> | 13 | #include <asm/tlbflush.h> |
| 15 | #include <asm/cacheflush.h> | ||
| 16 | 14 | ||
| 17 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | 15 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) |
| 18 | { | 16 | { |
| @@ -140,54 +138,3 @@ void local_flush_tlb_all(void) | |||
| 140 | ctrl_barrier(); | 138 | ctrl_barrier(); |
| 141 | local_irq_restore(flags); | 139 | local_irq_restore(flags); |
| 142 | } | 140 | } |
| 143 | |||
| 144 | void update_mmu_cache(struct vm_area_struct *vma, | ||
| 145 | unsigned long address, pte_t pte) | ||
| 146 | { | ||
| 147 | unsigned long flags; | ||
| 148 | unsigned long pteval; | ||
| 149 | unsigned long vpn; | ||
| 150 | struct page *page; | ||
| 151 | unsigned long pfn = pte_pfn(pte); | ||
| 152 | struct address_space *mapping; | ||
| 153 | |||
| 154 | if (!pfn_valid(pfn)) | ||
| 155 | return; | ||
| 156 | |||
| 157 | page = pfn_to_page(pfn); | ||
| 158 | mapping = page_mapping(page); | ||
| 159 | if (mapping) { | ||
| 160 | unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; | ||
| 161 | int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); | ||
| 162 | |||
| 163 | if (dirty) | ||
| 164 | __flush_wback_region((void *)P1SEGADDR(phys), | ||
| 165 | PAGE_SIZE); | ||
| 166 | } | ||
| 167 | |||
| 168 | local_irq_save(flags); | ||
| 169 | |||
| 170 | /* Set PTEH register */ | ||
| 171 | vpn = (address & MMU_VPN_MASK) | get_asid(); | ||
| 172 | ctrl_outl(vpn, MMU_PTEH); | ||
| 173 | |||
| 174 | pteval = pte_val(pte); | ||
| 175 | |||
| 176 | #ifdef CONFIG_CPU_HAS_PTEA | ||
| 177 | /* Set PTEA register */ | ||
| 178 | /* TODO: make this look less hacky */ | ||
| 179 | ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA); | ||
| 180 | #endif | ||
| 181 | |||
| 182 | /* Set PTEL register */ | ||
| 183 | pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ | ||
| 184 | #if defined(CONFIG_SH_WRITETHROUGH) && defined(CONFIG_CPU_SH4) | ||
| 185 | pteval |= _PAGE_WT; | ||
| 186 | #endif | ||
| 187 | /* conveniently, we want all the software flags to be 0 anyway */ | ||
| 188 | ctrl_outl(pteval, MMU_PTEL); | ||
| 189 | |||
| 190 | /* Load the TLB */ | ||
| 191 | asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); | ||
| 192 | local_irq_restore(flags); | ||
| 193 | } | ||
diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c index e5e76eb7ee09..7fbfd5a11ffa 100644 --- a/arch/sh/mm/tlb-sh3.c +++ b/arch/sh/mm/tlb-sh3.c | |||
| @@ -8,9 +8,69 @@ | |||
| 8 | * | 8 | * |
| 9 | * Released under the terms of the GNU GPL v2.0. | 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 | #include <asm/system.h> | 24 | #include <asm/system.h> |
| 25 | #include <asm/io.h> | ||
| 26 | #include <asm/uaccess.h> | ||
| 27 | #include <asm/pgalloc.h> | ||
| 13 | #include <asm/mmu_context.h> | 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 | void local_flush_tlb_one(unsigned long asid, unsigned long page) | 75 | void local_flush_tlb_one(unsigned long asid, unsigned long page) |
| 16 | { | 76 | { |
| @@ -34,3 +94,4 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page) | |||
| 34 | for (i = 0; i < ways; i++) | 94 | for (i = 0; i < ways; i++) |
| 35 | ctrl_outl(data, addr + (i << 8)); | 95 | ctrl_outl(data, addr + (i << 8)); |
| 36 | } | 96 | } |
| 97 | |||
diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c index 221e7095473d..f74cf667c8fa 100644 --- a/arch/sh/mm/tlb-sh4.c +++ b/arch/sh/mm/tlb-sh4.c | |||
| @@ -8,9 +8,74 @@ | |||
| 8 | * | 8 | * |
| 9 | * Released under the terms of the GNU GPL v2.0. | 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 | #include <asm/system.h> | 24 | #include <asm/system.h> |
| 25 | #include <asm/io.h> | ||
| 26 | #include <asm/uaccess.h> | ||
| 27 | #include <asm/pgalloc.h> | ||
| 13 | #include <asm/mmu_context.h> | 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 | void local_flush_tlb_one(unsigned long asid, unsigned long page) | 80 | void local_flush_tlb_one(unsigned long asid, unsigned long page) |
| 16 | { | 81 | { |
| @@ -28,3 +93,4 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page) | |||
| 28 | ctrl_outl(data, addr); | 93 | ctrl_outl(data, addr); |
| 29 | back_to_P1(); | 94 | back_to_P1(); |
| 30 | } | 95 | } |
| 96 | |||
diff --git a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h index 22f12634975b..07f62ec9ff0c 100644 --- a/include/asm-sh/cacheflush.h +++ b/include/asm-sh/cacheflush.h | |||
| @@ -30,8 +30,5 @@ extern void __flush_invalidate_region(void *start, int size); | |||
| 30 | 30 | ||
| 31 | #define HAVE_ARCH_UNMAPPED_AREA | 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 | #endif /* __KERNEL__ */ | 33 | #endif /* __KERNEL__ */ |
| 37 | #endif /* __ASM_SH_CACHEFLUSH_H */ | 34 | #endif /* __ASM_SH_CACHEFLUSH_H */ |
diff --git a/include/asm-sh/cpu-sh3/cacheflush.h b/include/asm-sh/cpu-sh3/cacheflush.h index 6fabbba228de..f70d8ef76a15 100644 --- a/include/asm-sh/cpu-sh3/cacheflush.h +++ b/include/asm-sh/cpu-sh3/cacheflush.h | |||
| @@ -36,6 +36,8 @@ | |||
| 36 | /* 32KB cache, 4kb PAGE sizes need to check bit 12 */ | 36 | /* 32KB cache, 4kb PAGE sizes need to check bit 12 */ |
| 37 | #define CACHE_ALIAS 0x00001000 | 37 | #define CACHE_ALIAS 0x00001000 |
| 38 | 38 | ||
| 39 | #define PG_mapped PG_arch_1 | ||
| 40 | |||
| 39 | void flush_cache_all(void); | 41 | void flush_cache_all(void); |
| 40 | void flush_cache_mm(struct mm_struct *mm); | 42 | void flush_cache_mm(struct mm_struct *mm); |
| 41 | #define flush_cache_dup_mm(mm) flush_cache_mm(mm) | 43 | #define flush_cache_dup_mm(mm) flush_cache_mm(mm) |
diff --git a/include/asm-sh/cpu-sh4/cacheflush.h b/include/asm-sh/cpu-sh4/cacheflush.h index b3746a936a09..5fd5c89ef86a 100644 --- a/include/asm-sh/cpu-sh4/cacheflush.h +++ b/include/asm-sh/cpu-sh4/cacheflush.h | |||
| @@ -39,4 +39,6 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, | |||
| 39 | /* Initialization of P3 area for copy_user_page */ | 39 | /* Initialization of P3 area for copy_user_page */ |
| 40 | void p3_cache_init(void); | 40 | void p3_cache_init(void); |
| 41 | 41 | ||
| 42 | #define PG_mapped PG_arch_1 | ||
| 43 | |||
| 42 | #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */ | 44 | #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */ |
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index 9214c015fe14..184d7fcaaf10 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h | |||
| @@ -583,6 +583,11 @@ struct mm_struct; | |||
| 583 | extern unsigned int kobjsize(const void *objp); | 583 | extern unsigned int kobjsize(const void *objp); |
| 584 | #endif /* !CONFIG_MMU */ | 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 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | 591 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
| 587 | extern void paging_init(void); | 592 | extern void paging_init(void); |
| 588 | 593 | ||
