1 |
1276 |
phoenix |
/*
|
2 |
|
|
* linux/include/asm-arm/proc-armv/cache.h
|
3 |
|
|
*
|
4 |
|
|
* Copyright (C) 1999-2001 Russell King
|
5 |
|
|
*
|
6 |
|
|
* This program is free software; you can redistribute it and/or modify
|
7 |
|
|
* it under the terms of the GNU General Public License version 2 as
|
8 |
|
|
* published by the Free Software Foundation.
|
9 |
|
|
*/
|
10 |
|
|
#include <asm/mman.h>
|
11 |
|
|
|
12 |
|
|
/*
|
13 |
|
|
* This flag is used to indicate that the page pointed to by a pte
|
14 |
|
|
* is dirty and requires cleaning before returning it to the user.
|
15 |
|
|
*/
|
16 |
|
|
#define PG_dcache_dirty PG_arch_1
|
17 |
|
|
|
18 |
|
|
/*
|
19 |
|
|
* Cache handling for 32-bit ARM processors.
|
20 |
|
|
*
|
21 |
|
|
* Note that on ARM, we have a more accurate specification than that
|
22 |
|
|
* Linux's "flush". We therefore do not use "flush" here, but instead
|
23 |
|
|
* use:
|
24 |
|
|
*
|
25 |
|
|
* clean: the act of pushing dirty cache entries out to memory.
|
26 |
|
|
* invalidate: the act of discarding data held within the cache,
|
27 |
|
|
* whether it is dirty or not.
|
28 |
|
|
*/
|
29 |
|
|
|
30 |
|
|
/*
|
31 |
|
|
* Generic I + D cache
|
32 |
|
|
*/
|
33 |
|
|
#define flush_cache_all() \
|
34 |
|
|
do { \
|
35 |
|
|
cpu_cache_clean_invalidate_all(); \
|
36 |
|
|
} while (0)
|
37 |
|
|
|
38 |
|
|
/* This is always called for current->mm */
|
39 |
|
|
#define flush_cache_mm(_mm) \
|
40 |
|
|
do { \
|
41 |
|
|
if ((_mm) == current->active_mm) \
|
42 |
|
|
cpu_cache_clean_invalidate_all(); \
|
43 |
|
|
} while (0)
|
44 |
|
|
|
45 |
|
|
#define flush_cache_range(_mm,_start,_end) \
|
46 |
|
|
do { \
|
47 |
|
|
if ((_mm) == current->active_mm) \
|
48 |
|
|
cpu_cache_clean_invalidate_range((_start) & PAGE_MASK, \
|
49 |
|
|
PAGE_ALIGN(_end), 1); \
|
50 |
|
|
} while (0)
|
51 |
|
|
|
52 |
|
|
#define flush_cache_page(_vma,_vmaddr) \
|
53 |
|
|
do { \
|
54 |
|
|
if ((_vma)->vm_mm == current->active_mm) { \
|
55 |
|
|
unsigned long _addr = (_vmaddr) & PAGE_MASK; \
|
56 |
|
|
cpu_cache_clean_invalidate_range(_addr, \
|
57 |
|
|
_addr + PAGE_SIZE, \
|
58 |
|
|
((_vma)->vm_flags & VM_EXEC)); \
|
59 |
|
|
} \
|
60 |
|
|
} while (0)
|
61 |
|
|
|
62 |
|
|
/*
|
63 |
|
|
* This flushes back any buffered write data. We have to clean the entries
|
64 |
|
|
* in the cache for this page. This does not invalidate either I or D caches.
|
65 |
|
|
*
|
66 |
|
|
* Called from:
|
67 |
|
|
* 1. mm/filemap.c:filemap_nopage
|
68 |
|
|
* 2. mm/filemap.c:filemap_nopage
|
69 |
|
|
* [via do_no_page - ok]
|
70 |
|
|
*
|
71 |
|
|
* 3. mm/memory.c:break_cow
|
72 |
|
|
* [copy_cow_page doesn't do anything to the cache; insufficient cache
|
73 |
|
|
* handling. Need to add flush_dcache_page() here]
|
74 |
|
|
*
|
75 |
|
|
* 4. mm/memory.c:do_swap_page
|
76 |
|
|
* [read_swap_cache_async doesn't do anything to the cache: insufficient
|
77 |
|
|
* cache handling. Need to add flush_dcache_page() here]
|
78 |
|
|
*
|
79 |
|
|
* 5. mm/memory.c:do_anonymous_page
|
80 |
|
|
* [zero page, never written by kernel - ok]
|
81 |
|
|
*
|
82 |
|
|
* 6. mm/memory.c:do_no_page
|
83 |
|
|
* [we will be calling update_mmu_cache, which will catch on PG_dcache_dirty]
|
84 |
|
|
*
|
85 |
|
|
* 7. mm/shmem.c:shmem_nopage
|
86 |
|
|
* 8. mm/shmem.c:shmem_nopage
|
87 |
|
|
* [via do_no_page - ok]
|
88 |
|
|
*
|
89 |
|
|
* 9. fs/exec.c:put_dirty_page
|
90 |
|
|
* [we call flush_dcache_page prior to this, which will flush out the
|
91 |
|
|
* kernel virtual addresses from the dcache - ok]
|
92 |
|
|
*/
|
93 |
|
|
static __inline__ void flush_page_to_ram(struct page *page)
|
94 |
|
|
{
|
95 |
|
|
cpu_flush_ram_page(page_address(page));
|
96 |
|
|
}
|
97 |
|
|
|
98 |
|
|
/*
|
99 |
|
|
* D cache only
|
100 |
|
|
*/
|
101 |
|
|
|
102 |
|
|
#define invalidate_dcache_range(_s,_e) cpu_dcache_invalidate_range((_s),(_e))
|
103 |
|
|
#define clean_dcache_range(_s,_e) cpu_dcache_clean_range((_s),(_e))
|
104 |
|
|
#define flush_dcache_range(_s,_e) cpu_cache_clean_invalidate_range((_s),(_e),0)
|
105 |
|
|
|
106 |
|
|
/*
|
107 |
|
|
* flush_dcache_page is used when the kernel has written to the page
|
108 |
|
|
* cache page at virtual address page->virtual.
|
109 |
|
|
*
|
110 |
|
|
* If this page isn't mapped (ie, page->mapping = NULL), or it has
|
111 |
|
|
* userspace mappings (page->mapping->i_mmap or page->mapping->i_mmap_shared)
|
112 |
|
|
* then we _must_ always clean + invalidate the dcache entries associated
|
113 |
|
|
* with the kernel mapping.
|
114 |
|
|
*
|
115 |
|
|
* Otherwise we can defer the operation, and clean the cache when we are
|
116 |
|
|
* about to change to user space. This is the same method as used on SPARC64.
|
117 |
|
|
* See update_mmu_cache for the user space part.
|
118 |
|
|
*/
|
119 |
|
|
#define mapping_mapped(map) ((map)->i_mmap || (map)->i_mmap_shared)
|
120 |
|
|
|
121 |
|
|
static inline void flush_dcache_page(struct page *page)
|
122 |
|
|
{
|
123 |
|
|
if (page->mapping && !mapping_mapped(page->mapping))
|
124 |
|
|
set_bit(PG_dcache_dirty, &page->flags);
|
125 |
|
|
else {
|
126 |
|
|
unsigned long virt = (unsigned long)page_address(page);
|
127 |
|
|
cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
|
128 |
|
|
}
|
129 |
|
|
}
|
130 |
|
|
|
131 |
|
|
#define flush_icache_user_range(vma,page,addr,len) \
|
132 |
|
|
flush_dcache_page(page)
|
133 |
|
|
|
134 |
|
|
#define clean_dcache_entry(_s) cpu_dcache_clean_entry((unsigned long)(_s))
|
135 |
|
|
|
136 |
|
|
/*
|
137 |
|
|
* This function is misnamed IMHO. There are three places where it
|
138 |
|
|
* is called, each of which is preceded immediately by a call to
|
139 |
|
|
* flush_page_to_ram:
|
140 |
|
|
*
|
141 |
|
|
* 1. kernel/ptrace.c:access_one_page
|
142 |
|
|
* called after we have written to the kernel view of a user page.
|
143 |
|
|
* The user page has been expundged from the cache by flush_cache_page.
|
144 |
|
|
* [we don't need to do anything here if we add a call to
|
145 |
|
|
* flush_dcache_page]
|
146 |
|
|
*
|
147 |
|
|
* 2. mm/memory.c:do_swap_page
|
148 |
|
|
* called after we have (possibly) written to the kernel view of a
|
149 |
|
|
* user page, which has previously been removed (ie, has been through
|
150 |
|
|
* the swap cache).
|
151 |
|
|
* [if the flush_page_to_ram() conditions are satisfied, then ok]
|
152 |
|
|
*
|
153 |
|
|
* 3. mm/memory.c:do_no_page
|
154 |
|
|
* [if the flush_page_to_ram() conditions are satisfied, then ok]
|
155 |
|
|
*
|
156 |
|
|
* Invalidating the icache at the kernels virtual page isn't really
|
157 |
|
|
* going to do us much good, since we wouldn't have executed any
|
158 |
|
|
* instructions there.
|
159 |
|
|
*/
|
160 |
|
|
#define flush_icache_page(vma,pg) do { } while (0)
|
161 |
|
|
|
162 |
|
|
/*
|
163 |
|
|
* I cache coherency stuff.
|
164 |
|
|
*
|
165 |
|
|
* This *is not* just icache. It is to make data written to memory
|
166 |
|
|
* consistent such that instructions fetched from the region are what
|
167 |
|
|
* we expect.
|
168 |
|
|
*
|
169 |
|
|
* This generally means that we have to clean out the Dcache and write
|
170 |
|
|
* buffers, and maybe flush the Icache in the specified range.
|
171 |
|
|
*/
|
172 |
|
|
#define flush_icache_range(_s,_e) \
|
173 |
|
|
do { \
|
174 |
|
|
cpu_icache_invalidate_range((_s), (_e)); \
|
175 |
|
|
} while (0)
|
176 |
|
|
|
177 |
|
|
/*
|
178 |
|
|
* TLB flushing.
|
179 |
|
|
*
|
180 |
|
|
* - flush_tlb_all() flushes all processes TLBs
|
181 |
|
|
* - flush_tlb_mm(mm) flushes the specified mm context TLB's
|
182 |
|
|
* - flush_tlb_page(vma, vmaddr) flushes TLB for specified page
|
183 |
|
|
* - flush_tlb_range(mm, start, end) flushes TLB for specified range of pages
|
184 |
|
|
*
|
185 |
|
|
* We drain the write buffer in here to ensure that the page tables in ram
|
186 |
|
|
* are really up to date. It is more efficient to do this here...
|
187 |
|
|
*/
|
188 |
|
|
|
189 |
|
|
/*
|
190 |
|
|
* Notes:
|
191 |
|
|
* current->active_mm is the currently active memory description.
|
192 |
|
|
* current->mm == NULL iff we are lazy.
|
193 |
|
|
*/
|
194 |
|
|
#define flush_tlb_all() \
|
195 |
|
|
do { \
|
196 |
|
|
cpu_tlb_invalidate_all(); \
|
197 |
|
|
} while (0)
|
198 |
|
|
|
199 |
|
|
/*
|
200 |
|
|
* Flush all user virtual address space translations described by `_mm'.
|
201 |
|
|
*
|
202 |
|
|
* Currently, this is always called for current->mm, which should be
|
203 |
|
|
* the same as current->active_mm. This is currently not be called for
|
204 |
|
|
* the lazy TLB case.
|
205 |
|
|
*/
|
206 |
|
|
#define flush_tlb_mm(_mm) \
|
207 |
|
|
do { \
|
208 |
|
|
if ((_mm) == current->active_mm) \
|
209 |
|
|
cpu_tlb_invalidate_all(); \
|
210 |
|
|
} while (0)
|
211 |
|
|
|
212 |
|
|
/*
|
213 |
|
|
* Flush the specified range of user virtual address space translations.
|
214 |
|
|
*
|
215 |
|
|
* _mm may not be current->active_mm, but may not be NULL.
|
216 |
|
|
*/
|
217 |
|
|
#define flush_tlb_range(_mm,_start,_end) \
|
218 |
|
|
do { \
|
219 |
|
|
if ((_mm) == current->active_mm) \
|
220 |
|
|
cpu_tlb_invalidate_range((_start), (_end)); \
|
221 |
|
|
} while (0)
|
222 |
|
|
|
223 |
|
|
/*
|
224 |
|
|
* Flush the specified user virtual address space translation.
|
225 |
|
|
*/
|
226 |
|
|
#define flush_tlb_page(_vma,_page) \
|
227 |
|
|
do { \
|
228 |
|
|
if ((_vma)->vm_mm == current->active_mm) \
|
229 |
|
|
cpu_tlb_invalidate_page((_page), \
|
230 |
|
|
((_vma)->vm_flags & VM_EXEC)); \
|
231 |
|
|
} while (0)
|
232 |
|
|
|
233 |
|
|
/*
|
234 |
|
|
* if PG_dcache_dirty is set for the page, we need to ensure that any
|
235 |
|
|
* cache entries for the kernels virtual memory range are written
|
236 |
|
|
* back to the page.
|
237 |
|
|
*/
|
238 |
|
|
extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte);
|
239 |
|
|
|
240 |
|
|
/*
|
241 |
|
|
* Old ARM MEMC stuff. This supports the reversed mapping handling that
|
242 |
|
|
* we have on the older 26-bit machines. We don't have a MEMC chip, so...
|
243 |
|
|
*/
|
244 |
|
|
#define memc_update_all() do { } while (0)
|
245 |
|
|
#define memc_update_mm(mm) do { } while (0)
|
246 |
|
|
#define memc_update_addr(mm,pte,log) do { } while (0)
|
247 |
|
|
#define memc_clear(mm,physaddr) do { } while (0)
|
248 |
|
|
|