diff options
Diffstat (limited to 'arch/arm/mm')
| -rw-r--r-- | arch/arm/mm/flush.c | 39 |
1 files changed, 39 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 | } | ||
