diff options
-rw-r--r-- | arch/parisc/include/asm/cacheflush.h | 5 | ||||
-rw-r--r-- | arch/parisc/kernel/cache.c | 13 |
2 files changed, 16 insertions, 2 deletions
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index d18328b3f938..da601dd34c05 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
5 | #include <linux/uaccess.h> | 5 | #include <linux/uaccess.h> |
6 | #include <asm/tlbflush.h> | ||
6 | 7 | ||
7 | /* The usual comment is "Caches aren't brain-dead on the <architecture>". | 8 | /* The usual comment is "Caches aren't brain-dead on the <architecture>". |
8 | * Unfortunately, that doesn't apply to PA-RISC. */ | 9 | * Unfortunately, that doesn't apply to PA-RISC. */ |
@@ -112,8 +113,10 @@ void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr); | |||
112 | static inline void | 113 | static inline void |
113 | flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) | 114 | flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) |
114 | { | 115 | { |
115 | if (PageAnon(page)) | 116 | if (PageAnon(page)) { |
117 | flush_tlb_page(vma, vmaddr); | ||
116 | flush_dcache_page_asm(page_to_phys(page), vmaddr); | 118 | flush_dcache_page_asm(page_to_phys(page), vmaddr); |
119 | } | ||
117 | } | 120 | } |
118 | 121 | ||
119 | #ifdef CONFIG_DEBUG_RODATA | 122 | #ifdef CONFIG_DEBUG_RODATA |
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 3f11331c2775..83335f3da5fc 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c | |||
@@ -304,10 +304,20 @@ void flush_dcache_page(struct page *page) | |||
304 | offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; | 304 | offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; |
305 | addr = mpnt->vm_start + offset; | 305 | addr = mpnt->vm_start + offset; |
306 | 306 | ||
307 | /* The TLB is the engine of coherence on parisc: The | ||
308 | * CPU is entitled to speculate any page with a TLB | ||
309 | * mapping, so here we kill the mapping then flush the | ||
310 | * page along a special flush only alias mapping. | ||
311 | * This guarantees that the page is no-longer in the | ||
312 | * cache for any process and nor may it be | ||
313 | * speculatively read in (until the user or kernel | ||
314 | * specifically accesses it, of course) */ | ||
315 | |||
316 | flush_tlb_page(mpnt, addr); | ||
307 | if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) { | 317 | if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) { |
308 | __flush_cache_page(mpnt, addr, page_to_phys(page)); | 318 | __flush_cache_page(mpnt, addr, page_to_phys(page)); |
309 | if (old_addr) | 319 | if (old_addr) |
310 | printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? mpnt->vm_file->f_path.dentry->d_name.name : "(null)"); | 320 | printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? (char *)mpnt->vm_file->f_path.dentry->d_name.name : "(null)"); |
311 | old_addr = addr; | 321 | old_addr = addr; |
312 | } | 322 | } |
313 | } | 323 | } |
@@ -499,6 +509,7 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long | |||
499 | { | 509 | { |
500 | BUG_ON(!vma->vm_mm->context); | 510 | BUG_ON(!vma->vm_mm->context); |
501 | 511 | ||
512 | flush_tlb_page(vma, vmaddr); | ||
502 | __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); | 513 | __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); |
503 | 514 | ||
504 | } | 515 | } |