diff options
Diffstat (limited to 'arch/arm64/mm/flush.c')
-rw-r--r-- | arch/arm64/mm/flush.c | 37 |
1 files changed, 8 insertions, 29 deletions
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c index 88611c3a421a..e4193e3adc7f 100644 --- a/arch/arm64/mm/flush.c +++ b/arch/arm64/mm/flush.c | |||
@@ -70,23 +70,16 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | |||
70 | #endif | 70 | #endif |
71 | } | 71 | } |
72 | 72 | ||
73 | void __flush_dcache_page(struct page *page) | ||
74 | { | ||
75 | __flush_dcache_area(page_address(page), PAGE_SIZE); | ||
76 | } | ||
77 | |||
78 | void __sync_icache_dcache(pte_t pte, unsigned long addr) | 73 | void __sync_icache_dcache(pte_t pte, unsigned long addr) |
79 | { | 74 | { |
80 | unsigned long pfn; | 75 | struct page *page = pte_page(pte); |
81 | struct page *page; | ||
82 | 76 | ||
83 | pfn = pte_pfn(pte); | 77 | /* no flushing needed for anonymous pages */ |
84 | if (!pfn_valid(pfn)) | 78 | if (!page_mapping(page)) |
85 | return; | 79 | return; |
86 | 80 | ||
87 | page = pfn_to_page(pfn); | ||
88 | if (!test_and_set_bit(PG_dcache_clean, &page->flags)) { | 81 | if (!test_and_set_bit(PG_dcache_clean, &page->flags)) { |
89 | __flush_dcache_page(page); | 82 | __flush_dcache_area(page_address(page), PAGE_SIZE); |
90 | __flush_icache_all(); | 83 | __flush_icache_all(); |
91 | } else if (icache_is_aivivt()) { | 84 | } else if (icache_is_aivivt()) { |
92 | __flush_icache_all(); | 85 | __flush_icache_all(); |
@@ -94,28 +87,14 @@ void __sync_icache_dcache(pte_t pte, unsigned long addr) | |||
94 | } | 87 | } |
95 | 88 | ||
96 | /* | 89 | /* |
97 | * Ensure cache coherency between kernel mapping and userspace mapping of this | 90 | * This function is called when a page has been modified by the kernel. Mark |
98 | * page. | 91 | * it as dirty for later flushing when mapped in user space (if executable, |
92 | * see __sync_icache_dcache). | ||
99 | */ | 93 | */ |
100 | void flush_dcache_page(struct page *page) | 94 | void flush_dcache_page(struct page *page) |
101 | { | 95 | { |
102 | struct address_space *mapping; | 96 | if (test_bit(PG_dcache_clean, &page->flags)) |
103 | |||
104 | /* | ||
105 | * The zero page is never written to, so never has any dirty cache | ||
106 | * lines, and therefore never needs to be flushed. | ||
107 | */ | ||
108 | if (page == ZERO_PAGE(0)) | ||
109 | return; | ||
110 | |||
111 | mapping = page_mapping(page); | ||
112 | if (mapping && mapping_mapped(mapping)) { | ||
113 | __flush_dcache_page(page); | ||
114 | __flush_icache_all(); | ||
115 | set_bit(PG_dcache_clean, &page->flags); | ||
116 | } else { | ||
117 | clear_bit(PG_dcache_clean, &page->flags); | 97 | clear_bit(PG_dcache_clean, &page->flags); |
118 | } | ||
119 | } | 98 | } |
120 | EXPORT_SYMBOL(flush_dcache_page); | 99 | EXPORT_SYMBOL(flush_dcache_page); |
121 | 100 | ||