diff options
Diffstat (limited to 'arch/sh/mm/tlb-flush.c')
-rw-r--r-- | arch/sh/mm/tlb-flush.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/arch/sh/mm/tlb-flush.c b/arch/sh/mm/tlb-flush.c index 73ec7f6084fa..9347534aa894 100644 --- a/arch/sh/mm/tlb-flush.c +++ b/arch/sh/mm/tlb-flush.c | |||
@@ -2,15 +2,17 @@ | |||
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 Paul Mundt | 5 | * Copyright (C) 2003 - 2006 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> | ||
12 | #include <asm/mmu_context.h> | 13 | #include <asm/mmu_context.h> |
13 | #include <asm/tlbflush.h> | 14 | #include <asm/tlbflush.h> |
15 | #include <asm/cacheflush.h> | ||
14 | 16 | ||
15 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | 17 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) |
16 | { | 18 | { |
@@ -132,3 +134,54 @@ void flush_tlb_all(void) | |||
132 | ctrl_barrier(); | 134 | ctrl_barrier(); |
133 | local_irq_restore(flags); | 135 | local_irq_restore(flags); |
134 | } | 136 | } |
137 | |||
138 | void update_mmu_cache(struct vm_area_struct *vma, | ||
139 | unsigned long address, pte_t pte) | ||
140 | { | ||
141 | unsigned long flags; | ||
142 | unsigned long pteval; | ||
143 | unsigned long vpn; | ||
144 | struct page *page; | ||
145 | unsigned long pfn = pte_pfn(pte); | ||
146 | struct address_space *mapping; | ||
147 | |||
148 | if (!pfn_valid(pfn)) | ||
149 | return; | ||
150 | |||
151 | page = pfn_to_page(pfn); | ||
152 | mapping = page_mapping(page); | ||
153 | if (mapping) { | ||
154 | unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; | ||
155 | int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); | ||
156 | |||
157 | if (dirty) | ||
158 | __flush_wback_region((void *)P1SEGADDR(phys), | ||
159 | PAGE_SIZE); | ||
160 | } | ||
161 | |||
162 | local_irq_save(flags); | ||
163 | |||
164 | /* Set PTEH register */ | ||
165 | vpn = (address & MMU_VPN_MASK) | get_asid(); | ||
166 | ctrl_outl(vpn, MMU_PTEH); | ||
167 | |||
168 | pteval = pte_val(pte); | ||
169 | |||
170 | #ifdef CONFIG_CPU_HAS_PTEA | ||
171 | /* Set PTEA register */ | ||
172 | /* TODO: make this look less hacky */ | ||
173 | ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA); | ||
174 | #endif | ||
175 | |||
176 | /* Set PTEL register */ | ||
177 | pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ | ||
178 | #ifdef CONFIG_SH_WRITETHROUGH | ||
179 | pteval |= _PAGE_WT; | ||
180 | #endif | ||
181 | /* conveniently, we want all the software flags to be 0 anyway */ | ||
182 | ctrl_outl(pteval, MMU_PTEL); | ||
183 | |||
184 | /* Load the TLB */ | ||
185 | asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); | ||
186 | local_irq_restore(flags); | ||
187 | } | ||