aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/include/asm
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2011-04-15 13:37:22 -0400
committerJames Bottomley <James.Bottomley@suse.de>2011-04-15 13:55:56 -0400
commitb7d45818444a31948cfc7849136013a0ea54b2fb (patch)
treec24455fe3f41bffabb377fa9c855eaa7cac26a1e /arch/parisc/include/asm
parentd7dd2ff11b7fcd425aca5a875983c862d19a67ae (diff)
[PARISC] prevent speculative re-read on cache flush
According to Appendix F, the TLB is the primary arbiter of speculation. Thus, if a page has a TLB entry, it may be speculatively read into the cache. On linux, this can cause us incoherencies because if we're about to do a disk read, we call get_user_pages() to do the flush/invalidate in user space, but we still potentially have the user TLB entries, and the cache could speculate the lines back into userspace (thus causing stale data to be used). This is fixed by purging the TLB entries before we flush through the tmpalias space. Now, the only way the line could be re-speculated is if the user actually tries to touch it (which is not allowed). Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'arch/parisc/include/asm')
-rw-r--r--arch/parisc/include/asm/cacheflush.h5
1 files changed, 4 insertions, 1 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);
112static inline void 113static inline void
113flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) 114flush_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