diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-06-20 04:51:03 -0400 |
---|---|---|
committer | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-06-20 04:51:03 -0400 |
commit | 8830f04a092b47f3d246271b24685cd9eab82027 (patch) | |
tree | 8258af450ec736fd0ff3cf0864eb5407b3f8b5ff /arch/arm/mm/fault-armv.c | |
parent | d411b845dcc8e1d97e8b02a345e765af5134700f (diff) |
[PATCH] ARM: Fix delayed dcache flush for ARMv6 non-aliasing caches
flush_dcache_page() did nothing for these caches, but since they
suffer from I/D cache coherency issues, we need to ensure that data
is written back to RAM.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/fault-armv.c')
-rw-r--r-- | arch/arm/mm/fault-armv.c | 31 |
1 files changed, 11 insertions, 20 deletions
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 01967ddeef53..be4ab3d73c91 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -77,9 +77,8 @@ no_pmd: | |||
77 | } | 77 | } |
78 | 78 | ||
79 | static void | 79 | static void |
80 | make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty) | 80 | make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) |
81 | { | 81 | { |
82 | struct address_space *mapping = page_mapping(page); | ||
83 | struct mm_struct *mm = vma->vm_mm; | 82 | struct mm_struct *mm = vma->vm_mm; |
84 | struct vm_area_struct *mpnt; | 83 | struct vm_area_struct *mpnt; |
85 | struct prio_tree_iter iter; | 84 | struct prio_tree_iter iter; |
@@ -87,9 +86,6 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, | |||
87 | pgoff_t pgoff; | 86 | pgoff_t pgoff; |
88 | int aliases = 0; | 87 | int aliases = 0; |
89 | 88 | ||
90 | if (!mapping) | ||
91 | return; | ||
92 | |||
93 | pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT); | 89 | pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT); |
94 | 90 | ||
95 | /* | 91 | /* |
@@ -115,9 +111,11 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, | |||
115 | if (aliases) | 111 | if (aliases) |
116 | adjust_pte(vma, addr); | 112 | adjust_pte(vma, addr); |
117 | else | 113 | else |
118 | flush_cache_page(vma, addr, page_to_pfn(page)); | 114 | flush_cache_page(vma, addr, pfn); |
119 | } | 115 | } |
120 | 116 | ||
117 | void __flush_dcache_page(struct address_space *mapping, struct page *page); | ||
118 | |||
121 | /* | 119 | /* |
122 | * Take care of architecture specific things when placing a new PTE into | 120 | * Take care of architecture specific things when placing a new PTE into |
123 | * a page table, or changing an existing PTE. Basically, there are two | 121 | * a page table, or changing an existing PTE. Basically, there are two |
@@ -134,29 +132,22 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, | |||
134 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) | 132 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) |
135 | { | 133 | { |
136 | unsigned long pfn = pte_pfn(pte); | 134 | unsigned long pfn = pte_pfn(pte); |
135 | struct address_space *mapping; | ||
137 | struct page *page; | 136 | struct page *page; |
138 | 137 | ||
139 | if (!pfn_valid(pfn)) | 138 | if (!pfn_valid(pfn)) |
140 | return; | 139 | return; |
140 | |||
141 | page = pfn_to_page(pfn); | 141 | page = pfn_to_page(pfn); |
142 | if (page_mapping(page)) { | 142 | mapping = page_mapping(page); |
143 | if (mapping) { | ||
143 | int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); | 144 | int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); |
144 | 145 | ||
145 | if (dirty) { | 146 | if (dirty) |
146 | /* | 147 | __flush_dcache_page(mapping, page); |
147 | * This is our first userspace mapping of this page. | ||
148 | * Ensure that the physical page is coherent with | ||
149 | * the kernel mapping. | ||
150 | * | ||
151 | * FIXME: only need to do this on VIVT and aliasing | ||
152 | * VIPT cache architectures. We can do that | ||
153 | * by choosing whether to set this bit... | ||
154 | */ | ||
155 | __cpuc_flush_dcache_page(page_address(page)); | ||
156 | } | ||
157 | 148 | ||
158 | if (cache_is_vivt()) | 149 | if (cache_is_vivt()) |
159 | make_coherent(vma, addr, page, dirty); | 150 | make_coherent(mapping, vma, addr, pfn); |
160 | } | 151 | } |
161 | } | 152 | } |
162 | 153 | ||