diff options
| -rw-r--r-- | arch/arm/mm/flush.c | 39 | ||||
| -rw-r--r-- | include/asm-arm/cacheflush.h | 10 |
2 files changed, 49 insertions, 0 deletions
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 628348c9f6c5..9df507d36e0b 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
| @@ -202,3 +202,42 @@ void flush_dcache_page(struct page *page) | |||
| 202 | } | 202 | } |
| 203 | } | 203 | } |
| 204 | EXPORT_SYMBOL(flush_dcache_page); | 204 | EXPORT_SYMBOL(flush_dcache_page); |
| 205 | |||
| 206 | /* | ||
| 207 | * Flush an anonymous page so that users of get_user_pages() | ||
| 208 | * can safely access the data. The expected sequence is: | ||
| 209 | * | ||
| 210 | * get_user_pages() | ||
| 211 | * -> flush_anon_page | ||
| 212 | * memcpy() to/from page | ||
| 213 | * if written to page, flush_dcache_page() | ||
| 214 | */ | ||
| 215 | void __flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) | ||
| 216 | { | ||
| 217 | unsigned long pfn; | ||
| 218 | |||
| 219 | /* VIPT non-aliasing caches need do nothing */ | ||
| 220 | if (cache_is_vipt_nonaliasing()) | ||
| 221 | return; | ||
| 222 | |||
| 223 | /* | ||
| 224 | * Write back and invalidate userspace mapping. | ||
| 225 | */ | ||
| 226 | pfn = page_to_pfn(page); | ||
| 227 | if (cache_is_vivt()) { | ||
| 228 | flush_cache_page(vma, vmaddr, pfn); | ||
| 229 | } else { | ||
| 230 | /* | ||
| 231 | * For aliasing VIPT, we can flush an alias of the | ||
| 232 | * userspace address only. | ||
| 233 | */ | ||
| 234 | flush_pfn_alias(pfn, vmaddr); | ||
| 235 | } | ||
| 236 | |||
| 237 | /* | ||
| 238 | * Invalidate kernel mapping. No data should be contained | ||
| 239 | * in this mapping of the page. FIXME: this is overkill | ||
| 240 | * since we actually ask for a write-back and invalidate. | ||
| 241 | */ | ||
| 242 | __cpuc_flush_dcache_page(page_address(page)); | ||
| 243 | } | ||
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index d51049522cd0..5f531ea03059 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h | |||
| @@ -357,6 +357,16 @@ extern void flush_dcache_page(struct page *); | |||
| 357 | 357 | ||
| 358 | extern void __flush_dcache_page(struct address_space *mapping, struct page *page); | 358 | extern void __flush_dcache_page(struct address_space *mapping, struct page *page); |
| 359 | 359 | ||
| 360 | #define ARCH_HAS_FLUSH_ANON_PAGE | ||
| 361 | static inline void flush_anon_page(struct vm_area_struct *vma, | ||
| 362 | struct page *page, unsigned long vmaddr) | ||
| 363 | { | ||
| 364 | extern void __flush_anon_page(struct vm_area_struct *vma, | ||
| 365 | struct page *, unsigned long); | ||
| 366 | if (PageAnon(page)) | ||
| 367 | __flush_anon_page(vma, page, vmaddr); | ||
| 368 | } | ||
| 369 | |||
| 360 | #define flush_dcache_mmap_lock(mapping) \ | 370 | #define flush_dcache_mmap_lock(mapping) \ |
| 361 | write_lock_irq(&(mapping)->tree_lock) | 371 | write_lock_irq(&(mapping)->tree_lock) |
| 362 | #define flush_dcache_mmap_unlock(mapping) \ | 372 | #define flush_dcache_mmap_unlock(mapping) \ |
